Commit | Line | Data |
---|---|---|
a2e2876a | 1 | /* |
2 | * max98926.c -- ALSA SoC MAX98926 driver | |
3 | * Copyright 2013-15 Maxim Integrated Products | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License version 2 as | |
6 | * published by the Free Software Foundation. | |
7 | */ | |
8 | #include <linux/delay.h> | |
9 | #include <linux/i2c.h> | |
10 | #include <linux/module.h> | |
11 | #include <linux/regmap.h> | |
12 | #include <linux/slab.h> | |
13 | #include <linux/cdev.h> | |
14 | #include <sound/pcm.h> | |
15 | #include <sound/pcm_params.h> | |
16 | #include <sound/soc.h> | |
17 | #include <sound/tlv.h> | |
18 | #include "max98926.h" | |
19 | ||
20 | static const char * const max98926_boost_voltage_txt[] = { | |
21 | "8.5V", "8.25V", "8.0V", "7.75V", "7.5V", "7.25V", "7.0V", "6.75V", | |
22 | "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V" | |
23 | }; | |
24 | ||
25 | static const char * const max98926_boost_current_txt[] = { | |
26 | "0.6", "0.8", "1.0", "1.2", "1.4", "1.6", "1.8", "2.0", | |
27 | "2.2", "2.4", "2.6", "2.8", "3.2", "3.6", "4.0", "4.4" | |
28 | }; | |
29 | ||
30 | static const char *const max98926_dai_txt[] = { | |
31 | "Left", "Right", "LeftRight", "LeftRightDiv2", | |
32 | }; | |
33 | ||
34 | static const char *const max98926_pdm_ch_text[] = { | |
35 | "Current", "Voltage", | |
36 | }; | |
37 | ||
38 | static const char *const max98926_hpf_cutoff_txt[] = { | |
39 | "Disable", "DC Block", "100Hz", | |
40 | "200Hz", "400Hz", "800Hz", | |
41 | }; | |
42 | ||
e354d86e | 43 | static const struct reg_default max98926_reg[] = { |
a2e2876a | 44 | { 0x0B, 0x00 }, /* IRQ Enable0 */ |
45 | { 0x0C, 0x00 }, /* IRQ Enable1 */ | |
46 | { 0x0D, 0x00 }, /* IRQ Enable2 */ | |
47 | { 0x0E, 0x00 }, /* IRQ Clear0 */ | |
48 | { 0x0F, 0x00 }, /* IRQ Clear1 */ | |
49 | { 0x10, 0x00 }, /* IRQ Clear2 */ | |
50 | { 0x11, 0xC0 }, /* Map0 */ | |
51 | { 0x12, 0x00 }, /* Map1 */ | |
52 | { 0x13, 0x00 }, /* Map2 */ | |
53 | { 0x14, 0xF0 }, /* Map3 */ | |
54 | { 0x15, 0x00 }, /* Map4 */ | |
55 | { 0x16, 0xAB }, /* Map5 */ | |
56 | { 0x17, 0x89 }, /* Map6 */ | |
57 | { 0x18, 0x00 }, /* Map7 */ | |
58 | { 0x19, 0x00 }, /* Map8 */ | |
59 | { 0x1A, 0x04 }, /* DAI Clock Mode 1 */ | |
60 | { 0x1B, 0x00 }, /* DAI Clock Mode 2 */ | |
61 | { 0x1C, 0x00 }, /* DAI Clock Divider Denominator MSBs */ | |
62 | { 0x1D, 0x00 }, /* DAI Clock Divider Denominator LSBs */ | |
63 | { 0x1E, 0xF0 }, /* DAI Clock Divider Numerator MSBs */ | |
64 | { 0x1F, 0x00 }, /* DAI Clock Divider Numerator LSBs */ | |
65 | { 0x20, 0x50 }, /* Format */ | |
66 | { 0x21, 0x00 }, /* TDM Slot Select */ | |
67 | { 0x22, 0x00 }, /* DOUT Configuration VMON */ | |
68 | { 0x23, 0x00 }, /* DOUT Configuration IMON */ | |
69 | { 0x24, 0x00 }, /* DOUT Configuration VBAT */ | |
70 | { 0x25, 0x00 }, /* DOUT Configuration VBST */ | |
71 | { 0x26, 0x00 }, /* DOUT Configuration FLAG */ | |
72 | { 0x27, 0xFF }, /* DOUT HiZ Configuration 1 */ | |
73 | { 0x28, 0xFF }, /* DOUT HiZ Configuration 2 */ | |
74 | { 0x29, 0xFF }, /* DOUT HiZ Configuration 3 */ | |
75 | { 0x2A, 0xFF }, /* DOUT HiZ Configuration 4 */ | |
76 | { 0x2B, 0x02 }, /* DOUT Drive Strength */ | |
77 | { 0x2C, 0x90 }, /* Filters */ | |
78 | { 0x2D, 0x00 }, /* Gain */ | |
79 | { 0x2E, 0x02 }, /* Gain Ramping */ | |
80 | { 0x2F, 0x00 }, /* Speaker Amplifier */ | |
81 | { 0x30, 0x0A }, /* Threshold */ | |
82 | { 0x31, 0x00 }, /* ALC Attack */ | |
83 | { 0x32, 0x80 }, /* ALC Atten and Release */ | |
84 | { 0x33, 0x00 }, /* ALC Infinite Hold Release */ | |
85 | { 0x34, 0x92 }, /* ALC Configuration */ | |
86 | { 0x35, 0x01 }, /* Boost Converter */ | |
87 | { 0x36, 0x00 }, /* Block Enable */ | |
88 | { 0x37, 0x00 }, /* Configuration */ | |
89 | { 0x38, 0x00 }, /* Global Enable */ | |
90 | { 0x3A, 0x00 }, /* Boost Limiter */ | |
91 | }; | |
92 | ||
93 | static const struct soc_enum max98926_voltage_enum[] = { | |
94 | SOC_ENUM_SINGLE(MAX98926_DAI_CLK_DIV_N_LSBS, 0, | |
95 | ARRAY_SIZE(max98926_pdm_ch_text), | |
96 | max98926_pdm_ch_text), | |
97 | }; | |
98 | ||
99 | static const struct snd_kcontrol_new max98926_voltage_control = | |
100 | SOC_DAPM_ENUM("Route", max98926_voltage_enum); | |
101 | ||
102 | static const struct soc_enum max98926_current_enum[] = { | |
103 | SOC_ENUM_SINGLE(MAX98926_DAI_CLK_DIV_N_LSBS, | |
104 | MAX98926_PDM_SOURCE_1_SHIFT, | |
105 | ARRAY_SIZE(max98926_pdm_ch_text), | |
106 | max98926_pdm_ch_text), | |
107 | }; | |
108 | ||
109 | static const struct snd_kcontrol_new max98926_current_control = | |
110 | SOC_DAPM_ENUM("Route", max98926_current_enum); | |
111 | ||
112 | static const struct snd_kcontrol_new max98926_mixer_controls[] = { | |
113 | SOC_DAPM_SINGLE("PCM Single Switch", MAX98926_SPK_AMP, | |
114 | MAX98926_INSELECT_MODE_SHIFT, 0, 0), | |
115 | SOC_DAPM_SINGLE("PDM Single Switch", MAX98926_SPK_AMP, | |
116 | MAX98926_INSELECT_MODE_SHIFT, 1, 0), | |
117 | }; | |
118 | ||
119 | static const struct snd_kcontrol_new max98926_dai_controls[] = { | |
120 | SOC_DAPM_SINGLE("Left", MAX98926_GAIN, | |
121 | MAX98926_DAC_IN_SEL_SHIFT, 0, 0), | |
122 | SOC_DAPM_SINGLE("Right", MAX98926_GAIN, | |
123 | MAX98926_DAC_IN_SEL_SHIFT, 1, 0), | |
124 | SOC_DAPM_SINGLE("LeftRight", MAX98926_GAIN, | |
125 | MAX98926_DAC_IN_SEL_SHIFT, 2, 0), | |
126 | SOC_DAPM_SINGLE("(Left+Right)/2 Switch", MAX98926_GAIN, | |
127 | MAX98926_DAC_IN_SEL_SHIFT, 3, 0), | |
128 | }; | |
129 | ||
130 | static const struct snd_soc_dapm_widget max98926_dapm_widgets[] = { | |
131 | SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, | |
132 | SND_SOC_NOPM, 0, 0), | |
133 | SND_SOC_DAPM_DAC("Amp Enable", NULL, MAX98926_BLOCK_ENABLE, | |
134 | MAX98926_SPK_EN_SHIFT, 0), | |
135 | SND_SOC_DAPM_SUPPLY("Global Enable", MAX98926_GLOBAL_ENABLE, | |
136 | MAX98926_EN_SHIFT, 0, NULL, 0), | |
137 | SND_SOC_DAPM_SUPPLY("VI Enable", MAX98926_BLOCK_ENABLE, | |
138 | MAX98926_ADC_IMON_EN_WIDTH | | |
139 | MAX98926_ADC_VMON_EN_SHIFT, | |
140 | 0, NULL, 0), | |
141 | SND_SOC_DAPM_PGA("BST Enable", MAX98926_BLOCK_ENABLE, | |
142 | MAX98926_BST_EN_SHIFT, 0, NULL, 0), | |
143 | SND_SOC_DAPM_OUTPUT("BE_OUT"), | |
144 | SND_SOC_DAPM_MIXER("PCM Sel", MAX98926_SPK_AMP, | |
145 | MAX98926_INSELECT_MODE_SHIFT, 0, | |
146 | &max98926_mixer_controls[0], | |
147 | ARRAY_SIZE(max98926_mixer_controls)), | |
148 | SND_SOC_DAPM_MIXER("DAI Sel", | |
149 | MAX98926_GAIN, MAX98926_DAC_IN_SEL_SHIFT, 0, | |
150 | &max98926_dai_controls[0], | |
151 | ARRAY_SIZE(max98926_dai_controls)), | |
152 | SND_SOC_DAPM_MUX("PDM CH1 Source", | |
153 | MAX98926_DAI_CLK_DIV_N_LSBS, | |
154 | MAX98926_PDM_CURRENT_SHIFT, | |
155 | 0, &max98926_current_control), | |
156 | SND_SOC_DAPM_MUX("PDM CH0 Source", | |
157 | MAX98926_DAI_CLK_DIV_N_LSBS, | |
158 | MAX98926_PDM_VOLTAGE_SHIFT, | |
159 | 0, &max98926_voltage_control), | |
160 | }; | |
161 | ||
162 | static const struct snd_soc_dapm_route max98926_audio_map[] = { | |
163 | {"VI Enable", NULL, "DAI_OUT"}, | |
164 | {"DAI Sel", "Left", "VI Enable"}, | |
165 | {"DAI Sel", "Right", "VI Enable"}, | |
166 | {"DAI Sel", "LeftRight", "VI Enable"}, | |
167 | {"DAI Sel", "LeftRightDiv2", "VI Enable"}, | |
168 | {"PCM Sel", "PCM", "DAI Sel"}, | |
169 | ||
170 | {"PDM CH1 Source", "Current", "DAI_OUT"}, | |
171 | {"PDM CH1 Source", "Voltage", "DAI_OUT"}, | |
172 | {"PDM CH0 Source", "Current", "DAI_OUT"}, | |
173 | {"PDM CH0 Source", "Voltage", "DAI_OUT"}, | |
174 | {"PCM Sel", "Analog", "PDM CH1 Source"}, | |
175 | {"PCM Sel", "Analog", "PDM CH0 Source"}, | |
176 | {"Amp Enable", NULL, "PCM Sel"}, | |
177 | ||
178 | {"BST Enable", NULL, "Amp Enable"}, | |
179 | {"BE_OUT", NULL, "BST Enable"}, | |
180 | }; | |
181 | ||
182 | static bool max98926_volatile_register(struct device *dev, unsigned int reg) | |
183 | { | |
184 | switch (reg) { | |
185 | case MAX98926_VBAT_DATA: | |
186 | case MAX98926_VBST_DATA: | |
187 | case MAX98926_LIVE_STATUS0: | |
188 | case MAX98926_LIVE_STATUS1: | |
189 | case MAX98926_LIVE_STATUS2: | |
190 | case MAX98926_STATE0: | |
191 | case MAX98926_STATE1: | |
192 | case MAX98926_STATE2: | |
193 | case MAX98926_FLAG0: | |
194 | case MAX98926_FLAG1: | |
195 | case MAX98926_FLAG2: | |
196 | case MAX98926_VERSION: | |
197 | return true; | |
198 | default: | |
199 | return false; | |
200 | } | |
201 | } | |
202 | ||
203 | static bool max98926_readable_register(struct device *dev, unsigned int reg) | |
204 | { | |
205 | switch (reg) { | |
206 | case MAX98926_IRQ_CLEAR0: | |
207 | case MAX98926_IRQ_CLEAR1: | |
208 | case MAX98926_IRQ_CLEAR2: | |
209 | case MAX98926_ALC_HOLD_RLS: | |
210 | return false; | |
211 | default: | |
212 | return true; | |
213 | } | |
214 | }; | |
215 | ||
216 | DECLARE_TLV_DB_SCALE(max98926_spk_tlv, -600, 100, 0); | |
217 | DECLARE_TLV_DB_RANGE(max98926_current_tlv, | |
218 | 0, 11, TLV_DB_SCALE_ITEM(20, 20, 0), | |
219 | 12, 15, TLV_DB_SCALE_ITEM(320, 40, 0), | |
220 | ); | |
221 | ||
222 | static SOC_ENUM_SINGLE_DECL(max98926_dac_hpf_cutoff, | |
223 | MAX98926_FILTERS, MAX98926_DAC_HPF_SHIFT, | |
224 | max98926_hpf_cutoff_txt); | |
225 | ||
226 | static SOC_ENUM_SINGLE_DECL(max98926_boost_voltage, | |
227 | MAX98926_CONFIGURATION, MAX98926_BST_VOUT_SHIFT, | |
228 | max98926_boost_voltage_txt); | |
229 | ||
230 | static const struct snd_kcontrol_new max98926_snd_controls[] = { | |
231 | SOC_SINGLE_TLV("Speaker Volume", MAX98926_GAIN, | |
232 | MAX98926_SPK_GAIN_SHIFT, | |
233 | (1<<MAX98926_SPK_GAIN_WIDTH)-1, 0, | |
234 | max98926_spk_tlv), | |
235 | SOC_SINGLE("Ramp Switch", MAX98926_GAIN_RAMPING, | |
236 | MAX98926_SPK_RMP_EN_SHIFT, 1, 0), | |
237 | SOC_SINGLE("ZCD Switch", MAX98926_GAIN_RAMPING, | |
238 | MAX98926_SPK_ZCD_EN_SHIFT, 1, 0), | |
239 | SOC_SINGLE("ALC Switch", MAX98926_THRESHOLD, | |
240 | MAX98926_ALC_EN_SHIFT, 1, 0), | |
241 | SOC_SINGLE("ALC Threshold", MAX98926_THRESHOLD, | |
242 | MAX98926_ALC_TH_SHIFT, | |
243 | (1<<MAX98926_ALC_TH_WIDTH)-1, 0), | |
244 | SOC_ENUM("Boost Output Voltage", max98926_boost_voltage), | |
245 | SOC_SINGLE_TLV("Boost Current Limit", MAX98926_BOOST_LIMITER, | |
246 | MAX98926_BST_ILIM_SHIFT, | |
247 | (1<<MAX98926_BST_ILIM_SHIFT)-1, 0, | |
248 | max98926_current_tlv), | |
249 | SOC_ENUM("DAC HPF Cutoff", max98926_dac_hpf_cutoff), | |
250 | SOC_DOUBLE("PDM Channel One", MAX98926_DAI_CLK_DIV_N_LSBS, | |
251 | MAX98926_PDM_CHANNEL_1_SHIFT, | |
252 | MAX98926_PDM_CHANNEL_1_HIZ, 1, 0), | |
253 | SOC_DOUBLE("PDM Channel Zero", MAX98926_DAI_CLK_DIV_N_LSBS, | |
254 | MAX98926_PDM_CHANNEL_0_SHIFT, | |
255 | MAX98926_PDM_CHANNEL_0_HIZ, 1, 0), | |
256 | }; | |
257 | ||
258 | static const struct { | |
259 | int rate; | |
260 | int sr; | |
261 | } rate_table[] = { | |
262 | { | |
263 | .rate = 8000, | |
264 | .sr = 0, | |
265 | }, | |
266 | { | |
267 | .rate = 11025, | |
268 | .sr = 1, | |
269 | }, | |
270 | { | |
271 | .rate = 12000, | |
272 | .sr = 2, | |
273 | }, | |
274 | { | |
275 | .rate = 16000, | |
276 | .sr = 3, | |
277 | }, | |
278 | { | |
279 | .rate = 22050, | |
280 | .sr = 4, | |
281 | }, | |
282 | { | |
283 | .rate = 24000, | |
284 | .sr = 5, | |
285 | }, | |
286 | { | |
287 | .rate = 32000, | |
288 | .sr = 6, | |
289 | }, | |
290 | { | |
291 | .rate = 44100, | |
292 | .sr = 7, | |
293 | }, | |
294 | { | |
295 | .rate = 48000, | |
296 | .sr = 8, | |
297 | }, | |
298 | }; | |
299 | ||
300 | static void max98926_set_sense_data(struct max98926_priv *max98926) | |
301 | { | |
302 | regmap_update_bits(max98926->regmap, | |
303 | MAX98926_DOUT_CFG_VMON, | |
304 | MAX98926_DAI_VMON_EN_MASK, | |
305 | MAX98926_DAI_VMON_EN_MASK); | |
306 | regmap_update_bits(max98926->regmap, | |
307 | MAX98926_DOUT_CFG_IMON, | |
308 | MAX98926_DAI_IMON_EN_MASK, | |
309 | MAX98926_DAI_IMON_EN_MASK); | |
310 | ||
311 | if (!max98926->interleave_mode) { | |
312 | /* set VMON slots */ | |
313 | regmap_update_bits(max98926->regmap, | |
314 | MAX98926_DOUT_CFG_VMON, | |
315 | MAX98926_DAI_VMON_SLOT_MASK, | |
316 | max98926->v_slot); | |
317 | /* set IMON slots */ | |
318 | regmap_update_bits(max98926->regmap, | |
319 | MAX98926_DOUT_CFG_IMON, | |
320 | MAX98926_DAI_IMON_SLOT_MASK, | |
321 | max98926->i_slot); | |
322 | } else { | |
323 | /* enable interleave mode */ | |
324 | regmap_update_bits(max98926->regmap, | |
325 | MAX98926_FORMAT, | |
326 | MAX98926_DAI_INTERLEAVE_MASK, | |
327 | MAX98926_DAI_INTERLEAVE_MASK); | |
328 | /* set interleave slots */ | |
329 | regmap_update_bits(max98926->regmap, | |
330 | MAX98926_DOUT_CFG_VBAT, | |
331 | MAX98926_DAI_INTERLEAVE_SLOT_MASK, | |
332 | max98926->v_slot); | |
333 | } | |
334 | } | |
335 | ||
336 | static int max98926_dai_set_fmt(struct snd_soc_dai *codec_dai, | |
337 | unsigned int fmt) | |
338 | { | |
339 | struct snd_soc_codec *codec = codec_dai->codec; | |
340 | struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec); | |
341 | unsigned int invert = 0; | |
342 | ||
343 | dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt); | |
344 | ||
345 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | |
346 | case SND_SOC_DAIFMT_CBS_CFS: | |
347 | max98926_set_sense_data(max98926); | |
348 | break; | |
349 | default: | |
350 | dev_err(codec->dev, "DAI clock mode unsupported"); | |
351 | return -EINVAL; | |
352 | } | |
353 | ||
354 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | |
355 | case SND_SOC_DAIFMT_NB_NF: | |
356 | break; | |
357 | case SND_SOC_DAIFMT_NB_IF: | |
358 | invert = MAX98926_DAI_WCI_MASK; | |
359 | break; | |
360 | case SND_SOC_DAIFMT_IB_NF: | |
361 | invert = MAX98926_DAI_BCI_MASK; | |
362 | break; | |
363 | case SND_SOC_DAIFMT_IB_IF: | |
364 | invert = MAX98926_DAI_BCI_MASK | MAX98926_DAI_WCI_MASK; | |
365 | break; | |
366 | default: | |
367 | dev_err(codec->dev, "DAI invert mode unsupported"); | |
368 | return -EINVAL; | |
369 | } | |
370 | ||
371 | regmap_write(max98926->regmap, | |
372 | MAX98926_FORMAT, MAX98926_DAI_DLY_MASK); | |
373 | regmap_update_bits(max98926->regmap, MAX98926_FORMAT, | |
374 | MAX98926_DAI_BCI_MASK, invert); | |
375 | return 0; | |
376 | } | |
377 | ||
378 | static int max98926_dai_hw_params(struct snd_pcm_substream *substream, | |
379 | struct snd_pcm_hw_params *params, | |
380 | struct snd_soc_dai *dai) | |
381 | { | |
382 | int dai_sr = -EINVAL; | |
383 | int rate = params_rate(params), i; | |
384 | struct snd_soc_codec *codec = dai->codec; | |
385 | struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec); | |
cffee535 | 386 | int blr_clk_ratio; |
a2e2876a | 387 | |
388 | switch (params_format(params)) { | |
389 | case SNDRV_PCM_FORMAT_S16_LE: | |
390 | regmap_update_bits(max98926->regmap, | |
391 | MAX98926_FORMAT, | |
392 | MAX98926_DAI_CHANSZ_MASK, | |
393 | MAX98926_DAI_CHANSZ_16); | |
394 | max98926->ch_size = 16; | |
395 | break; | |
396 | case SNDRV_PCM_FORMAT_S24_LE: | |
397 | regmap_update_bits(max98926->regmap, | |
398 | MAX98926_FORMAT, | |
399 | MAX98926_DAI_CHANSZ_MASK, | |
400 | MAX98926_DAI_CHANSZ_24); | |
401 | max98926->ch_size = 24; | |
402 | break; | |
403 | case SNDRV_PCM_FORMAT_S32_LE: | |
404 | regmap_update_bits(max98926->regmap, | |
405 | MAX98926_FORMAT, | |
406 | MAX98926_DAI_CHANSZ_MASK, | |
407 | MAX98926_DAI_CHANSZ_32); | |
408 | max98926->ch_size = 32; | |
409 | break; | |
410 | default: | |
411 | dev_dbg(codec->dev, "format unsupported %d", | |
412 | params_format(params)); | |
413 | return -EINVAL; | |
414 | } | |
415 | ||
cffee535 AL |
416 | /* BCLK/LRCLK ratio calculation */ |
417 | blr_clk_ratio = params_channels(params) * max98926->ch_size; | |
418 | ||
a2e2876a | 419 | switch (blr_clk_ratio) { |
420 | case 32: | |
421 | regmap_update_bits(max98926->regmap, | |
422 | MAX98926_DAI_CLK_MODE2, | |
423 | MAX98926_DAI_BSEL_MASK, | |
424 | MAX98926_DAI_BSEL_32); | |
425 | break; | |
426 | case 48: | |
427 | regmap_update_bits(max98926->regmap, | |
428 | MAX98926_DAI_CLK_MODE2, | |
429 | MAX98926_DAI_BSEL_MASK, | |
430 | MAX98926_DAI_BSEL_48); | |
431 | break; | |
432 | case 64: | |
433 | regmap_update_bits(max98926->regmap, | |
434 | MAX98926_DAI_CLK_MODE2, | |
435 | MAX98926_DAI_BSEL_MASK, | |
436 | MAX98926_DAI_BSEL_64); | |
437 | break; | |
438 | default: | |
439 | return -EINVAL; | |
440 | } | |
441 | ||
442 | /* find the closest rate */ | |
443 | for (i = 0; i < ARRAY_SIZE(rate_table); i++) { | |
444 | if (rate_table[i].rate >= rate) { | |
445 | dai_sr = rate_table[i].sr; | |
446 | break; | |
447 | } | |
448 | } | |
449 | if (dai_sr < 0) | |
450 | return -EINVAL; | |
451 | ||
452 | /* set DAI_SR to correct LRCLK frequency */ | |
453 | regmap_update_bits(max98926->regmap, | |
454 | MAX98926_DAI_CLK_MODE2, | |
455 | MAX98926_DAI_SR_MASK, dai_sr << MAX98926_DAI_SR_SHIFT); | |
456 | return 0; | |
457 | } | |
458 | ||
459 | #define MAX98926_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | |
460 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | |
461 | ||
462 | static struct snd_soc_dai_ops max98926_dai_ops = { | |
463 | .set_fmt = max98926_dai_set_fmt, | |
464 | .hw_params = max98926_dai_hw_params, | |
465 | }; | |
466 | ||
467 | static struct snd_soc_dai_driver max98926_dai[] = { | |
468 | { | |
469 | .name = "max98926-aif1", | |
470 | .playback = { | |
471 | .stream_name = "HiFi Playback", | |
472 | .channels_min = 1, | |
473 | .channels_max = 2, | |
474 | .rates = SNDRV_PCM_RATE_8000_48000, | |
475 | .formats = MAX98926_FORMATS, | |
476 | }, | |
477 | .capture = { | |
478 | .stream_name = "HiFi Capture", | |
479 | .channels_min = 1, | |
480 | .channels_max = 2, | |
481 | .rates = SNDRV_PCM_RATE_8000_48000, | |
482 | .formats = MAX98926_FORMATS, | |
483 | }, | |
484 | .ops = &max98926_dai_ops, | |
485 | } | |
486 | }; | |
487 | ||
488 | static int max98926_probe(struct snd_soc_codec *codec) | |
489 | { | |
490 | struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec); | |
491 | ||
492 | max98926->codec = codec; | |
493 | codec->control_data = max98926->regmap; | |
494 | /* Hi-Z all the slots */ | |
495 | regmap_write(max98926->regmap, MAX98926_DOUT_HIZ_CFG4, 0xF0); | |
496 | return 0; | |
497 | } | |
498 | ||
499 | static struct snd_soc_codec_driver soc_codec_dev_max98926 = { | |
500 | .probe = max98926_probe, | |
501 | .controls = max98926_snd_controls, | |
502 | .num_controls = ARRAY_SIZE(max98926_snd_controls), | |
503 | .dapm_routes = max98926_audio_map, | |
504 | .num_dapm_routes = ARRAY_SIZE(max98926_audio_map), | |
505 | .dapm_widgets = max98926_dapm_widgets, | |
506 | .num_dapm_widgets = ARRAY_SIZE(max98926_dapm_widgets), | |
507 | }; | |
508 | ||
e354d86e | 509 | static const struct regmap_config max98926_regmap = { |
a2e2876a | 510 | .reg_bits = 8, |
511 | .val_bits = 8, | |
512 | .max_register = MAX98926_VERSION, | |
513 | .reg_defaults = max98926_reg, | |
514 | .num_reg_defaults = ARRAY_SIZE(max98926_reg), | |
515 | .volatile_reg = max98926_volatile_register, | |
516 | .readable_reg = max98926_readable_register, | |
517 | .cache_type = REGCACHE_RBTREE, | |
518 | }; | |
519 | ||
520 | static int max98926_i2c_probe(struct i2c_client *i2c, | |
521 | const struct i2c_device_id *id) | |
522 | { | |
523 | int ret, reg; | |
524 | u32 value; | |
525 | struct max98926_priv *max98926; | |
526 | ||
527 | max98926 = devm_kzalloc(&i2c->dev, | |
528 | sizeof(*max98926), GFP_KERNEL); | |
529 | if (!max98926) | |
530 | return -ENOMEM; | |
531 | ||
532 | i2c_set_clientdata(i2c, max98926); | |
533 | max98926->regmap = devm_regmap_init_i2c(i2c, &max98926_regmap); | |
534 | if (IS_ERR(max98926->regmap)) { | |
535 | ret = PTR_ERR(max98926->regmap); | |
536 | dev_err(&i2c->dev, | |
537 | "Failed to allocate regmap: %d\n", ret); | |
538 | goto err_out; | |
539 | } | |
540 | if (of_property_read_bool(i2c->dev.of_node, "interleave-mode")) | |
541 | max98926->interleave_mode = true; | |
542 | ||
543 | if (!of_property_read_u32(i2c->dev.of_node, "vmon-slot-no", &value)) { | |
544 | if (value > MAX98926_DAI_VMON_SLOT_1E_1F) { | |
545 | dev_err(&i2c->dev, "vmon slot number is wrong:\n"); | |
546 | return -EINVAL; | |
547 | } | |
548 | max98926->v_slot = value; | |
549 | } | |
550 | if (!of_property_read_u32(i2c->dev.of_node, "imon-slot-no", &value)) { | |
551 | if (value > MAX98926_DAI_IMON_SLOT_1E_1F) { | |
552 | dev_err(&i2c->dev, "imon slot number is wrong:\n"); | |
553 | return -EINVAL; | |
554 | } | |
555 | max98926->i_slot = value; | |
556 | } | |
557 | ret = regmap_read(max98926->regmap, | |
558 | MAX98926_VERSION, ®); | |
559 | if (ret < 0) { | |
560 | dev_err(&i2c->dev, "Failed to read: %x\n", reg); | |
561 | return ret; | |
562 | } | |
563 | ||
564 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98926, | |
565 | max98926_dai, ARRAY_SIZE(max98926_dai)); | |
566 | if (ret < 0) | |
567 | dev_err(&i2c->dev, | |
568 | "Failed to register codec: %d\n", ret); | |
569 | dev_info(&i2c->dev, "device version: %x\n", reg); | |
570 | err_out: | |
571 | return ret; | |
572 | } | |
573 | ||
574 | static int max98926_i2c_remove(struct i2c_client *client) | |
575 | { | |
576 | snd_soc_unregister_codec(&client->dev); | |
577 | return 0; | |
578 | } | |
579 | ||
580 | static const struct i2c_device_id max98926_i2c_id[] = { | |
581 | { "max98926", 0 }, | |
582 | { } | |
583 | }; | |
584 | MODULE_DEVICE_TABLE(i2c, max98926_i2c_id); | |
585 | ||
586 | static const struct of_device_id max98926_of_match[] = { | |
587 | { .compatible = "maxim,max98926", }, | |
588 | { } | |
589 | }; | |
590 | MODULE_DEVICE_TABLE(of, max98926_of_match); | |
591 | ||
592 | static struct i2c_driver max98926_i2c_driver = { | |
593 | .driver = { | |
594 | .name = "max98926", | |
595 | .of_match_table = of_match_ptr(max98926_of_match), | |
596 | .pm = NULL, | |
597 | }, | |
598 | .probe = max98926_i2c_probe, | |
599 | .remove = max98926_i2c_remove, | |
600 | .id_table = max98926_i2c_id, | |
601 | }; | |
602 | ||
603 | module_i2c_driver(max98926_i2c_driver) | |
604 | MODULE_DESCRIPTION("ALSA SoC MAX98926 driver"); | |
605 | MODULE_AUTHOR("Anish kumar <anish.kumar@maximintegrated.com>"); | |
606 | MODULE_LICENSE("GPL"); |