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