1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * es8328.c -- ES8328 ALSA SoC Audio driver |
4 | * |
5 | * Copyright 2014 Sutajio Ko-Usagi PTE LTD |
6 | * |
7 | * Author: Sean Cross <xobs@kosagi.com> |
8 | */ |
9 | |
10 | #include <linux/clk.h> |
11 | #include <linux/delay.h> |
12 | #include <linux/module.h> |
13 | #include <linux/pm.h> |
14 | #include <linux/regmap.h> |
15 | #include <linux/slab.h> |
16 | #include <linux/regulator/consumer.h> |
17 | #include <sound/core.h> |
18 | #include <sound/initval.h> |
19 | #include <sound/pcm.h> |
20 | #include <sound/pcm_params.h> |
21 | #include <sound/soc.h> |
22 | #include <sound/tlv.h> |
23 | #include "es8328.h" |
24 | |
25 | static const unsigned int rates_12288[] = { |
26 | 8000, 12000, 16000, 24000, 32000, 48000, 96000, |
27 | }; |
28 | |
29 | static const int ratios_12288[] = { |
30 | 10, 7, 6, 4, 3, 2, 0, |
31 | }; |
32 | |
33 | static const struct snd_pcm_hw_constraint_list constraints_12288 = { |
34 | .count = ARRAY_SIZE(rates_12288), |
35 | .list = rates_12288, |
36 | }; |
37 | |
38 | static const unsigned int rates_11289[] = { |
39 | 8018, 11025, 22050, 44100, 88200, |
40 | }; |
41 | |
42 | static const int ratios_11289[] = { |
43 | 9, 7, 4, 2, 0, |
44 | }; |
45 | |
46 | static const struct snd_pcm_hw_constraint_list constraints_11289 = { |
47 | .count = ARRAY_SIZE(rates_11289), |
48 | .list = rates_11289, |
49 | }; |
50 | |
51 | /* regulator supplies for sgtl5000, VDDD is an optional external supply */ |
52 | enum sgtl5000_regulator_supplies { |
53 | DVDD, |
54 | AVDD, |
55 | PVDD, |
56 | HPVDD, |
57 | ES8328_SUPPLY_NUM |
58 | }; |
59 | |
60 | /* vddd is optional supply */ |
61 | static const char * const supply_names[ES8328_SUPPLY_NUM] = { |
62 | "DVDD" , |
63 | "AVDD" , |
64 | "PVDD" , |
65 | "HPVDD" , |
66 | }; |
67 | |
68 | #define ES8328_RATES (SNDRV_PCM_RATE_192000 | \ |
69 | SNDRV_PCM_RATE_96000 | \ |
70 | SNDRV_PCM_RATE_88200 | \ |
71 | SNDRV_PCM_RATE_8000_48000) |
72 | #define ES8328_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
73 | SNDRV_PCM_FMTBIT_S18_3LE | \ |
74 | SNDRV_PCM_FMTBIT_S20_3LE | \ |
75 | SNDRV_PCM_FMTBIT_S24_LE | \ |
76 | SNDRV_PCM_FMTBIT_S32_LE) |
77 | |
78 | struct es8328_priv { |
79 | struct regmap *regmap; |
80 | struct clk *clk; |
81 | int playback_fs; |
82 | bool deemph; |
83 | int mclkdiv2; |
84 | const struct snd_pcm_hw_constraint_list *sysclk_constraints; |
85 | const int *mclk_ratios; |
86 | bool provider; |
87 | struct regulator_bulk_data supplies[ES8328_SUPPLY_NUM]; |
88 | }; |
89 | |
90 | /* |
91 | * ES8328 Controls |
92 | */ |
93 | |
94 | static const char * const adcpol_txt[] = {"Normal" , "L Invert" , "R Invert" , |
95 | "L + R Invert" }; |
96 | static SOC_ENUM_SINGLE_DECL(adcpol, |
97 | ES8328_ADCCONTROL6, 6, adcpol_txt); |
98 | |
99 | static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0); |
100 | static const DECLARE_TLV_DB_SCALE(dac_adc_tlv, -9600, 50, 0); |
101 | static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); |
102 | static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 300, 0); |
103 | |
104 | static const struct { |
105 | int rate; |
106 | unsigned int val; |
107 | } deemph_settings[] = { |
108 | { 0, ES8328_DACCONTROL6_DEEMPH_OFF }, |
109 | { 32000, ES8328_DACCONTROL6_DEEMPH_32k }, |
110 | { 44100, ES8328_DACCONTROL6_DEEMPH_44_1k }, |
111 | { 48000, ES8328_DACCONTROL6_DEEMPH_48k }, |
112 | }; |
113 | |
114 | static int es8328_set_deemph(struct snd_soc_component *component) |
115 | { |
116 | struct es8328_priv *es8328 = snd_soc_component_get_drvdata(c: component); |
117 | int val, i, best; |
118 | |
119 | /* |
120 | * If we're using deemphasis select the nearest available sample |
121 | * rate. |
122 | */ |
123 | if (es8328->deemph) { |
124 | best = 0; |
125 | for (i = 1; i < ARRAY_SIZE(deemph_settings); i++) { |
126 | if (abs(deemph_settings[i].rate - es8328->playback_fs) < |
127 | abs(deemph_settings[best].rate - es8328->playback_fs)) |
128 | best = i; |
129 | } |
130 | |
131 | val = deemph_settings[best].val; |
132 | } else { |
133 | val = ES8328_DACCONTROL6_DEEMPH_OFF; |
134 | } |
135 | |
136 | dev_dbg(component->dev, "Set deemphasis %d\n" , val); |
137 | |
138 | return snd_soc_component_update_bits(component, ES8328_DACCONTROL6, |
139 | ES8328_DACCONTROL6_DEEMPH_MASK, val); |
140 | } |
141 | |
142 | static int es8328_get_deemph(struct snd_kcontrol *kcontrol, |
143 | struct snd_ctl_elem_value *ucontrol) |
144 | { |
145 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
146 | struct es8328_priv *es8328 = snd_soc_component_get_drvdata(c: component); |
147 | |
148 | ucontrol->value.integer.value[0] = es8328->deemph; |
149 | return 0; |
150 | } |
151 | |
152 | static int es8328_put_deemph(struct snd_kcontrol *kcontrol, |
153 | struct snd_ctl_elem_value *ucontrol) |
154 | { |
155 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
156 | struct es8328_priv *es8328 = snd_soc_component_get_drvdata(c: component); |
157 | unsigned int deemph = ucontrol->value.integer.value[0]; |
158 | int ret; |
159 | |
160 | if (deemph > 1) |
161 | return -EINVAL; |
162 | |
163 | if (es8328->deemph == deemph) |
164 | return 0; |
165 | |
166 | ret = es8328_set_deemph(component); |
167 | if (ret < 0) |
168 | return ret; |
169 | |
170 | es8328->deemph = deemph; |
171 | |
172 | return 1; |
173 | } |
174 | |
175 | |
176 | |
177 | static const struct snd_kcontrol_new es8328_snd_controls[] = { |
178 | SOC_DOUBLE_R_TLV("Capture Digital Volume" , |
179 | ES8328_ADCCONTROL8, ES8328_ADCCONTROL9, |
180 | 0, 0xc0, 1, dac_adc_tlv), |
181 | SOC_SINGLE("Capture ZC Switch" , ES8328_ADCCONTROL7, 6, 1, 0), |
182 | |
183 | SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch" , 0, |
184 | es8328_get_deemph, es8328_put_deemph), |
185 | |
186 | SOC_ENUM("Capture Polarity" , adcpol), |
187 | |
188 | SOC_SINGLE_TLV("Left Mixer Left Bypass Volume" , |
189 | ES8328_DACCONTROL17, 3, 7, 1, bypass_tlv), |
190 | SOC_SINGLE_TLV("Left Mixer Right Bypass Volume" , |
191 | ES8328_DACCONTROL19, 3, 7, 1, bypass_tlv), |
192 | SOC_SINGLE_TLV("Right Mixer Left Bypass Volume" , |
193 | ES8328_DACCONTROL18, 3, 7, 1, bypass_tlv), |
194 | SOC_SINGLE_TLV("Right Mixer Right Bypass Volume" , |
195 | ES8328_DACCONTROL20, 3, 7, 1, bypass_tlv), |
196 | |
197 | SOC_DOUBLE_R_TLV("PCM Volume" , |
198 | ES8328_LDACVOL, ES8328_RDACVOL, |
199 | 0, ES8328_DACVOL_MAX, 1, dac_adc_tlv), |
200 | |
201 | SOC_DOUBLE_R_TLV("Output 1 Playback Volume" , |
202 | ES8328_LOUT1VOL, ES8328_ROUT1VOL, |
203 | 0, ES8328_OUT1VOL_MAX, 0, play_tlv), |
204 | |
205 | SOC_DOUBLE_R_TLV("Output 2 Playback Volume" , |
206 | ES8328_LOUT2VOL, ES8328_ROUT2VOL, |
207 | 0, ES8328_OUT2VOL_MAX, 0, play_tlv), |
208 | |
209 | SOC_DOUBLE_TLV("Mic PGA Volume" , ES8328_ADCCONTROL1, |
210 | 4, 0, 8, 0, mic_tlv), |
211 | }; |
212 | |
213 | /* |
214 | * DAPM Controls |
215 | */ |
216 | |
217 | static const char * const es8328_line_texts[] = { |
218 | "Line 1" , "Line 2" , "PGA" , "Differential" }; |
219 | |
220 | static const struct soc_enum es8328_lline_enum = |
221 | SOC_ENUM_SINGLE(ES8328_DACCONTROL16, 3, |
222 | ARRAY_SIZE(es8328_line_texts), |
223 | es8328_line_texts); |
224 | static const struct snd_kcontrol_new es8328_left_line_controls = |
225 | SOC_DAPM_ENUM("Route" , es8328_lline_enum); |
226 | |
227 | static const struct soc_enum es8328_rline_enum = |
228 | SOC_ENUM_SINGLE(ES8328_DACCONTROL16, 0, |
229 | ARRAY_SIZE(es8328_line_texts), |
230 | es8328_line_texts); |
231 | static const struct snd_kcontrol_new es8328_right_line_controls = |
232 | SOC_DAPM_ENUM("Route" , es8328_rline_enum); |
233 | |
234 | /* Left Mixer */ |
235 | static const struct snd_kcontrol_new es8328_left_mixer_controls[] = { |
236 | SOC_DAPM_SINGLE("Playback Switch" , ES8328_DACCONTROL17, 7, 1, 0), |
237 | SOC_DAPM_SINGLE("Left Bypass Switch" , ES8328_DACCONTROL17, 6, 1, 0), |
238 | SOC_DAPM_SINGLE("Right Playback Switch" , ES8328_DACCONTROL18, 7, 1, 0), |
239 | SOC_DAPM_SINGLE("Right Bypass Switch" , ES8328_DACCONTROL18, 6, 1, 0), |
240 | }; |
241 | |
242 | /* Right Mixer */ |
243 | static const struct snd_kcontrol_new es8328_right_mixer_controls[] = { |
244 | SOC_DAPM_SINGLE("Left Playback Switch" , ES8328_DACCONTROL19, 7, 1, 0), |
245 | SOC_DAPM_SINGLE("Left Bypass Switch" , ES8328_DACCONTROL19, 6, 1, 0), |
246 | SOC_DAPM_SINGLE("Playback Switch" , ES8328_DACCONTROL20, 7, 1, 0), |
247 | SOC_DAPM_SINGLE("Right Bypass Switch" , ES8328_DACCONTROL20, 6, 1, 0), |
248 | }; |
249 | |
250 | static const char * const es8328_pga_sel[] = { |
251 | "Line 1" , "Line 2" , "Line 3" , "Differential" }; |
252 | |
253 | /* Left PGA Mux */ |
254 | static const struct soc_enum es8328_lpga_enum = |
255 | SOC_ENUM_SINGLE(ES8328_ADCCONTROL2, 6, |
256 | ARRAY_SIZE(es8328_pga_sel), |
257 | es8328_pga_sel); |
258 | static const struct snd_kcontrol_new es8328_left_pga_controls = |
259 | SOC_DAPM_ENUM("Route" , es8328_lpga_enum); |
260 | |
261 | /* Right PGA Mux */ |
262 | static const struct soc_enum es8328_rpga_enum = |
263 | SOC_ENUM_SINGLE(ES8328_ADCCONTROL2, 4, |
264 | ARRAY_SIZE(es8328_pga_sel), |
265 | es8328_pga_sel); |
266 | static const struct snd_kcontrol_new es8328_right_pga_controls = |
267 | SOC_DAPM_ENUM("Route" , es8328_rpga_enum); |
268 | |
269 | /* Differential Mux */ |
270 | static const char * const es8328_diff_sel[] = {"Line 1" , "Line 2" }; |
271 | static SOC_ENUM_SINGLE_DECL(diffmux, |
272 | ES8328_ADCCONTROL3, 7, es8328_diff_sel); |
273 | static const struct snd_kcontrol_new es8328_diffmux_controls = |
274 | SOC_DAPM_ENUM("Route" , diffmux); |
275 | |
276 | /* Mono ADC Mux */ |
277 | static const char * const es8328_mono_mux[] = {"Stereo" , "Mono (Left)" , |
278 | "Mono (Right)" , "Digital Mono" }; |
279 | static SOC_ENUM_SINGLE_DECL(monomux, |
280 | ES8328_ADCCONTROL3, 3, es8328_mono_mux); |
281 | static const struct snd_kcontrol_new es8328_monomux_controls = |
282 | SOC_DAPM_ENUM("Route" , monomux); |
283 | |
284 | static const struct snd_soc_dapm_widget es8328_dapm_widgets[] = { |
285 | SND_SOC_DAPM_MUX("Differential Mux" , SND_SOC_NOPM, 0, 0, |
286 | &es8328_diffmux_controls), |
287 | SND_SOC_DAPM_MUX("Left ADC Mux" , SND_SOC_NOPM, 0, 0, |
288 | &es8328_monomux_controls), |
289 | SND_SOC_DAPM_MUX("Right ADC Mux" , SND_SOC_NOPM, 0, 0, |
290 | &es8328_monomux_controls), |
291 | |
292 | SND_SOC_DAPM_MUX("Left PGA Mux" , ES8328_ADCPOWER, |
293 | ES8328_ADCPOWER_AINL_OFF, 1, |
294 | &es8328_left_pga_controls), |
295 | SND_SOC_DAPM_MUX("Right PGA Mux" , ES8328_ADCPOWER, |
296 | ES8328_ADCPOWER_AINR_OFF, 1, |
297 | &es8328_right_pga_controls), |
298 | |
299 | SND_SOC_DAPM_MUX("Left Line Mux" , SND_SOC_NOPM, 0, 0, |
300 | &es8328_left_line_controls), |
301 | SND_SOC_DAPM_MUX("Right Line Mux" , SND_SOC_NOPM, 0, 0, |
302 | &es8328_right_line_controls), |
303 | |
304 | SND_SOC_DAPM_ADC("Right ADC" , "Right Capture" , ES8328_ADCPOWER, |
305 | ES8328_ADCPOWER_ADCR_OFF, 1), |
306 | SND_SOC_DAPM_ADC("Left ADC" , "Left Capture" , ES8328_ADCPOWER, |
307 | ES8328_ADCPOWER_ADCL_OFF, 1), |
308 | |
309 | SND_SOC_DAPM_SUPPLY("Mic Bias" , ES8328_ADCPOWER, |
310 | ES8328_ADCPOWER_MIC_BIAS_OFF, 1, NULL, 0), |
311 | SND_SOC_DAPM_SUPPLY("Mic Bias Gen" , ES8328_ADCPOWER, |
312 | ES8328_ADCPOWER_ADC_BIAS_GEN_OFF, 1, NULL, 0), |
313 | |
314 | SND_SOC_DAPM_SUPPLY("DAC STM" , ES8328_CHIPPOWER, |
315 | ES8328_CHIPPOWER_DACSTM_RESET, 1, NULL, 0), |
316 | SND_SOC_DAPM_SUPPLY("ADC STM" , ES8328_CHIPPOWER, |
317 | ES8328_CHIPPOWER_ADCSTM_RESET, 1, NULL, 0), |
318 | |
319 | SND_SOC_DAPM_SUPPLY("DAC DIG" , ES8328_CHIPPOWER, |
320 | ES8328_CHIPPOWER_DACDIG_OFF, 1, NULL, 0), |
321 | SND_SOC_DAPM_SUPPLY("ADC DIG" , ES8328_CHIPPOWER, |
322 | ES8328_CHIPPOWER_ADCDIG_OFF, 1, NULL, 0), |
323 | |
324 | SND_SOC_DAPM_SUPPLY("DAC DLL" , ES8328_CHIPPOWER, |
325 | ES8328_CHIPPOWER_DACDLL_OFF, 1, NULL, 0), |
326 | SND_SOC_DAPM_SUPPLY("ADC DLL" , ES8328_CHIPPOWER, |
327 | ES8328_CHIPPOWER_ADCDLL_OFF, 1, NULL, 0), |
328 | |
329 | SND_SOC_DAPM_SUPPLY("ADC Vref" , ES8328_CHIPPOWER, |
330 | ES8328_CHIPPOWER_ADCVREF_OFF, 1, NULL, 0), |
331 | SND_SOC_DAPM_SUPPLY("DAC Vref" , ES8328_CHIPPOWER, |
332 | ES8328_CHIPPOWER_DACVREF_OFF, 1, NULL, 0), |
333 | |
334 | SND_SOC_DAPM_DAC("Right DAC" , "Right Playback" , ES8328_DACPOWER, |
335 | ES8328_DACPOWER_RDAC_OFF, 1), |
336 | SND_SOC_DAPM_DAC("Left DAC" , "Left Playback" , ES8328_DACPOWER, |
337 | ES8328_DACPOWER_LDAC_OFF, 1), |
338 | |
339 | SND_SOC_DAPM_MIXER("Left Mixer" , SND_SOC_NOPM, 0, 0, |
340 | &es8328_left_mixer_controls[0], |
341 | ARRAY_SIZE(es8328_left_mixer_controls)), |
342 | SND_SOC_DAPM_MIXER("Right Mixer" , SND_SOC_NOPM, 0, 0, |
343 | &es8328_right_mixer_controls[0], |
344 | ARRAY_SIZE(es8328_right_mixer_controls)), |
345 | |
346 | SND_SOC_DAPM_PGA("Right Out 2" , ES8328_DACPOWER, |
347 | ES8328_DACPOWER_ROUT2_ON, 0, NULL, 0), |
348 | SND_SOC_DAPM_PGA("Left Out 2" , ES8328_DACPOWER, |
349 | ES8328_DACPOWER_LOUT2_ON, 0, NULL, 0), |
350 | SND_SOC_DAPM_PGA("Right Out 1" , ES8328_DACPOWER, |
351 | ES8328_DACPOWER_ROUT1_ON, 0, NULL, 0), |
352 | SND_SOC_DAPM_PGA("Left Out 1" , ES8328_DACPOWER, |
353 | ES8328_DACPOWER_LOUT1_ON, 0, NULL, 0), |
354 | |
355 | SND_SOC_DAPM_OUTPUT("LOUT1" ), |
356 | SND_SOC_DAPM_OUTPUT("ROUT1" ), |
357 | SND_SOC_DAPM_OUTPUT("LOUT2" ), |
358 | SND_SOC_DAPM_OUTPUT("ROUT2" ), |
359 | |
360 | SND_SOC_DAPM_INPUT("LINPUT1" ), |
361 | SND_SOC_DAPM_INPUT("LINPUT2" ), |
362 | SND_SOC_DAPM_INPUT("RINPUT1" ), |
363 | SND_SOC_DAPM_INPUT("RINPUT2" ), |
364 | }; |
365 | |
366 | static const struct snd_soc_dapm_route es8328_dapm_routes[] = { |
367 | |
368 | { "Left Line Mux" , "Line 1" , "LINPUT1" }, |
369 | { "Left Line Mux" , "Line 2" , "LINPUT2" }, |
370 | { "Left Line Mux" , "PGA" , "Left PGA Mux" }, |
371 | { "Left Line Mux" , "Differential" , "Differential Mux" }, |
372 | |
373 | { "Right Line Mux" , "Line 1" , "RINPUT1" }, |
374 | { "Right Line Mux" , "Line 2" , "RINPUT2" }, |
375 | { "Right Line Mux" , "PGA" , "Right PGA Mux" }, |
376 | { "Right Line Mux" , "Differential" , "Differential Mux" }, |
377 | |
378 | { "Left PGA Mux" , "Line 1" , "LINPUT1" }, |
379 | { "Left PGA Mux" , "Line 2" , "LINPUT2" }, |
380 | { "Left PGA Mux" , "Differential" , "Differential Mux" }, |
381 | |
382 | { "Right PGA Mux" , "Line 1" , "RINPUT1" }, |
383 | { "Right PGA Mux" , "Line 2" , "RINPUT2" }, |
384 | { "Right PGA Mux" , "Differential" , "Differential Mux" }, |
385 | |
386 | { "Differential Mux" , "Line 1" , "LINPUT1" }, |
387 | { "Differential Mux" , "Line 1" , "RINPUT1" }, |
388 | { "Differential Mux" , "Line 2" , "LINPUT2" }, |
389 | { "Differential Mux" , "Line 2" , "RINPUT2" }, |
390 | |
391 | { "Left ADC Mux" , "Stereo" , "Left PGA Mux" }, |
392 | { "Left ADC Mux" , "Mono (Left)" , "Left PGA Mux" }, |
393 | { "Left ADC Mux" , "Digital Mono" , "Left PGA Mux" }, |
394 | |
395 | { "Right ADC Mux" , "Stereo" , "Right PGA Mux" }, |
396 | { "Right ADC Mux" , "Mono (Right)" , "Right PGA Mux" }, |
397 | { "Right ADC Mux" , "Digital Mono" , "Right PGA Mux" }, |
398 | |
399 | { "Left ADC" , NULL, "Left ADC Mux" }, |
400 | { "Right ADC" , NULL, "Right ADC Mux" }, |
401 | |
402 | { "ADC DIG" , NULL, "ADC STM" }, |
403 | { "ADC DIG" , NULL, "ADC Vref" }, |
404 | { "ADC DIG" , NULL, "ADC DLL" }, |
405 | |
406 | { "Left ADC" , NULL, "ADC DIG" }, |
407 | { "Right ADC" , NULL, "ADC DIG" }, |
408 | |
409 | { "Mic Bias" , NULL, "Mic Bias Gen" }, |
410 | |
411 | { "Left Line Mux" , "Line 1" , "LINPUT1" }, |
412 | { "Left Line Mux" , "Line 2" , "LINPUT2" }, |
413 | { "Left Line Mux" , "PGA" , "Left PGA Mux" }, |
414 | { "Left Line Mux" , "Differential" , "Differential Mux" }, |
415 | |
416 | { "Right Line Mux" , "Line 1" , "RINPUT1" }, |
417 | { "Right Line Mux" , "Line 2" , "RINPUT2" }, |
418 | { "Right Line Mux" , "PGA" , "Right PGA Mux" }, |
419 | { "Right Line Mux" , "Differential" , "Differential Mux" }, |
420 | |
421 | { "Left Out 1" , NULL, "Left DAC" }, |
422 | { "Right Out 1" , NULL, "Right DAC" }, |
423 | { "Left Out 2" , NULL, "Left DAC" }, |
424 | { "Right Out 2" , NULL, "Right DAC" }, |
425 | |
426 | { "Left Mixer" , "Playback Switch" , "Left DAC" }, |
427 | { "Left Mixer" , "Left Bypass Switch" , "Left Line Mux" }, |
428 | { "Left Mixer" , "Right Playback Switch" , "Right DAC" }, |
429 | { "Left Mixer" , "Right Bypass Switch" , "Right Line Mux" }, |
430 | |
431 | { "Right Mixer" , "Left Playback Switch" , "Left DAC" }, |
432 | { "Right Mixer" , "Left Bypass Switch" , "Left Line Mux" }, |
433 | { "Right Mixer" , "Playback Switch" , "Right DAC" }, |
434 | { "Right Mixer" , "Right Bypass Switch" , "Right Line Mux" }, |
435 | |
436 | { "DAC DIG" , NULL, "DAC STM" }, |
437 | { "DAC DIG" , NULL, "DAC Vref" }, |
438 | { "DAC DIG" , NULL, "DAC DLL" }, |
439 | |
440 | { "Left DAC" , NULL, "DAC DIG" }, |
441 | { "Right DAC" , NULL, "DAC DIG" }, |
442 | |
443 | { "Left Out 1" , NULL, "Left Mixer" }, |
444 | { "LOUT1" , NULL, "Left Out 1" }, |
445 | { "Right Out 1" , NULL, "Right Mixer" }, |
446 | { "ROUT1" , NULL, "Right Out 1" }, |
447 | |
448 | { "Left Out 2" , NULL, "Left Mixer" }, |
449 | { "LOUT2" , NULL, "Left Out 2" }, |
450 | { "Right Out 2" , NULL, "Right Mixer" }, |
451 | { "ROUT2" , NULL, "Right Out 2" }, |
452 | }; |
453 | |
454 | static int es8328_mute(struct snd_soc_dai *dai, int mute, int direction) |
455 | { |
456 | return snd_soc_component_update_bits(component: dai->component, ES8328_DACCONTROL3, |
457 | ES8328_DACCONTROL3_DACMUTE, |
458 | val: mute ? ES8328_DACCONTROL3_DACMUTE : 0); |
459 | } |
460 | |
461 | static int es8328_startup(struct snd_pcm_substream *substream, |
462 | struct snd_soc_dai *dai) |
463 | { |
464 | struct snd_soc_component *component = dai->component; |
465 | struct es8328_priv *es8328 = snd_soc_component_get_drvdata(c: component); |
466 | |
467 | if (es8328->provider && es8328->sysclk_constraints) |
468 | snd_pcm_hw_constraint_list(runtime: substream->runtime, cond: 0, |
469 | SNDRV_PCM_HW_PARAM_RATE, |
470 | l: es8328->sysclk_constraints); |
471 | |
472 | return 0; |
473 | } |
474 | |
475 | static int es8328_hw_params(struct snd_pcm_substream *substream, |
476 | struct snd_pcm_hw_params *params, |
477 | struct snd_soc_dai *dai) |
478 | { |
479 | struct snd_soc_component *component = dai->component; |
480 | struct es8328_priv *es8328 = snd_soc_component_get_drvdata(c: component); |
481 | int i; |
482 | int reg; |
483 | int wl; |
484 | int ratio; |
485 | |
486 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
487 | reg = ES8328_DACCONTROL2; |
488 | else |
489 | reg = ES8328_ADCCONTROL5; |
490 | |
491 | if (es8328->provider) { |
492 | if (!es8328->sysclk_constraints) { |
493 | dev_err(component->dev, "No MCLK configured\n" ); |
494 | return -EINVAL; |
495 | } |
496 | |
497 | for (i = 0; i < es8328->sysclk_constraints->count; i++) |
498 | if (es8328->sysclk_constraints->list[i] == |
499 | params_rate(p: params)) |
500 | break; |
501 | |
502 | if (i == es8328->sysclk_constraints->count) { |
503 | dev_err(component->dev, |
504 | "LRCLK %d unsupported with current clock\n" , |
505 | params_rate(params)); |
506 | return -EINVAL; |
507 | } |
508 | ratio = es8328->mclk_ratios[i]; |
509 | } else { |
510 | ratio = 0; |
511 | es8328->mclkdiv2 = 0; |
512 | } |
513 | |
514 | snd_soc_component_update_bits(component, ES8328_MASTERMODE, |
515 | ES8328_MASTERMODE_MCLKDIV2, |
516 | val: es8328->mclkdiv2 ? ES8328_MASTERMODE_MCLKDIV2 : 0); |
517 | |
518 | switch (params_width(p: params)) { |
519 | case 16: |
520 | wl = 3; |
521 | break; |
522 | case 18: |
523 | wl = 2; |
524 | break; |
525 | case 20: |
526 | wl = 1; |
527 | break; |
528 | case 24: |
529 | wl = 0; |
530 | break; |
531 | case 32: |
532 | wl = 4; |
533 | break; |
534 | default: |
535 | return -EINVAL; |
536 | } |
537 | |
538 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
539 | snd_soc_component_update_bits(component, ES8328_DACCONTROL1, |
540 | ES8328_DACCONTROL1_DACWL_MASK, |
541 | val: wl << ES8328_DACCONTROL1_DACWL_SHIFT); |
542 | |
543 | es8328->playback_fs = params_rate(p: params); |
544 | es8328_set_deemph(component); |
545 | } else |
546 | snd_soc_component_update_bits(component, ES8328_ADCCONTROL4, |
547 | ES8328_ADCCONTROL4_ADCWL_MASK, |
548 | val: wl << ES8328_ADCCONTROL4_ADCWL_SHIFT); |
549 | |
550 | return snd_soc_component_update_bits(component, reg, ES8328_RATEMASK, val: ratio); |
551 | } |
552 | |
553 | static int es8328_set_sysclk(struct snd_soc_dai *codec_dai, |
554 | int clk_id, unsigned int freq, int dir) |
555 | { |
556 | struct snd_soc_component *component = codec_dai->component; |
557 | struct es8328_priv *es8328 = snd_soc_component_get_drvdata(c: component); |
558 | int mclkdiv2 = 0; |
559 | unsigned int round_freq; |
560 | |
561 | /* |
562 | * Allow a small tolerance for frequencies within 100hz. Note |
563 | * this value is chosen arbitrarily. |
564 | */ |
565 | round_freq = DIV_ROUND_CLOSEST(freq, 100) * 100; |
566 | |
567 | switch (round_freq) { |
568 | case 0: |
569 | es8328->sysclk_constraints = NULL; |
570 | es8328->mclk_ratios = NULL; |
571 | break; |
572 | case 22579200: |
573 | mclkdiv2 = 1; |
574 | fallthrough; |
575 | case 11289600: |
576 | es8328->sysclk_constraints = &constraints_11289; |
577 | es8328->mclk_ratios = ratios_11289; |
578 | break; |
579 | case 24576000: |
580 | mclkdiv2 = 1; |
581 | fallthrough; |
582 | case 12288000: |
583 | es8328->sysclk_constraints = &constraints_12288; |
584 | es8328->mclk_ratios = ratios_12288; |
585 | break; |
586 | default: |
587 | return -EINVAL; |
588 | } |
589 | |
590 | es8328->mclkdiv2 = mclkdiv2; |
591 | return 0; |
592 | } |
593 | |
594 | static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai, |
595 | unsigned int fmt) |
596 | { |
597 | struct snd_soc_component *component = codec_dai->component; |
598 | struct es8328_priv *es8328 = snd_soc_component_get_drvdata(c: component); |
599 | u8 dac_mode = 0; |
600 | u8 adc_mode = 0; |
601 | |
602 | switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { |
603 | case SND_SOC_DAIFMT_CBP_CFP: |
604 | /* Master serial port mode, with BCLK generated automatically */ |
605 | snd_soc_component_update_bits(component, ES8328_MASTERMODE, |
606 | ES8328_MASTERMODE_MSC, |
607 | ES8328_MASTERMODE_MSC); |
608 | es8328->provider = true; |
609 | break; |
610 | case SND_SOC_DAIFMT_CBC_CFC: |
611 | /* Slave serial port mode */ |
612 | snd_soc_component_update_bits(component, ES8328_MASTERMODE, |
613 | ES8328_MASTERMODE_MSC, val: 0); |
614 | es8328->provider = false; |
615 | break; |
616 | default: |
617 | return -EINVAL; |
618 | } |
619 | |
620 | /* interface format */ |
621 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
622 | case SND_SOC_DAIFMT_I2S: |
623 | dac_mode |= ES8328_DACCONTROL1_DACFORMAT_I2S; |
624 | adc_mode |= ES8328_ADCCONTROL4_ADCFORMAT_I2S; |
625 | break; |
626 | case SND_SOC_DAIFMT_RIGHT_J: |
627 | dac_mode |= ES8328_DACCONTROL1_DACFORMAT_RJUST; |
628 | adc_mode |= ES8328_ADCCONTROL4_ADCFORMAT_RJUST; |
629 | break; |
630 | case SND_SOC_DAIFMT_LEFT_J: |
631 | dac_mode |= ES8328_DACCONTROL1_DACFORMAT_LJUST; |
632 | adc_mode |= ES8328_ADCCONTROL4_ADCFORMAT_LJUST; |
633 | break; |
634 | default: |
635 | return -EINVAL; |
636 | } |
637 | |
638 | /* clock inversion */ |
639 | if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) |
640 | return -EINVAL; |
641 | |
642 | snd_soc_component_update_bits(component, ES8328_DACCONTROL1, |
643 | ES8328_DACCONTROL1_DACFORMAT_MASK, val: dac_mode); |
644 | snd_soc_component_update_bits(component, ES8328_ADCCONTROL4, |
645 | ES8328_ADCCONTROL4_ADCFORMAT_MASK, val: adc_mode); |
646 | |
647 | return 0; |
648 | } |
649 | |
650 | static int es8328_set_bias_level(struct snd_soc_component *component, |
651 | enum snd_soc_bias_level level) |
652 | { |
653 | switch (level) { |
654 | case SND_SOC_BIAS_ON: |
655 | break; |
656 | |
657 | case SND_SOC_BIAS_PREPARE: |
658 | /* VREF, VMID=2x50k, digital enabled */ |
659 | snd_soc_component_write(component, ES8328_CHIPPOWER, val: 0); |
660 | snd_soc_component_update_bits(component, ES8328_CONTROL1, |
661 | ES8328_CONTROL1_VMIDSEL_MASK | |
662 | ES8328_CONTROL1_ENREF, |
663 | ES8328_CONTROL1_VMIDSEL_50k | |
664 | ES8328_CONTROL1_ENREF); |
665 | break; |
666 | |
667 | case SND_SOC_BIAS_STANDBY: |
668 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { |
669 | snd_soc_component_update_bits(component, ES8328_CONTROL1, |
670 | ES8328_CONTROL1_VMIDSEL_MASK | |
671 | ES8328_CONTROL1_ENREF, |
672 | ES8328_CONTROL1_VMIDSEL_5k | |
673 | ES8328_CONTROL1_ENREF); |
674 | |
675 | /* Charge caps */ |
676 | msleep(msecs: 100); |
677 | } |
678 | |
679 | snd_soc_component_write(component, ES8328_CONTROL2, |
680 | ES8328_CONTROL2_OVERCURRENT_ON | |
681 | ES8328_CONTROL2_THERMAL_SHUTDOWN_ON); |
682 | |
683 | /* VREF, VMID=2*500k, digital stopped */ |
684 | snd_soc_component_update_bits(component, ES8328_CONTROL1, |
685 | ES8328_CONTROL1_VMIDSEL_MASK | |
686 | ES8328_CONTROL1_ENREF, |
687 | ES8328_CONTROL1_VMIDSEL_500k | |
688 | ES8328_CONTROL1_ENREF); |
689 | break; |
690 | |
691 | case SND_SOC_BIAS_OFF: |
692 | snd_soc_component_update_bits(component, ES8328_CONTROL1, |
693 | ES8328_CONTROL1_VMIDSEL_MASK | |
694 | ES8328_CONTROL1_ENREF, |
695 | val: 0); |
696 | break; |
697 | } |
698 | return 0; |
699 | } |
700 | |
701 | static const struct snd_soc_dai_ops es8328_dai_ops = { |
702 | .startup = es8328_startup, |
703 | .hw_params = es8328_hw_params, |
704 | .mute_stream = es8328_mute, |
705 | .set_sysclk = es8328_set_sysclk, |
706 | .set_fmt = es8328_set_dai_fmt, |
707 | .no_capture_mute = 1, |
708 | }; |
709 | |
710 | static struct snd_soc_dai_driver es8328_dai = { |
711 | .name = "es8328-hifi-analog" , |
712 | .playback = { |
713 | .stream_name = "Playback" , |
714 | .channels_min = 2, |
715 | .channels_max = 2, |
716 | .rates = ES8328_RATES, |
717 | .formats = ES8328_FORMATS, |
718 | }, |
719 | .capture = { |
720 | .stream_name = "Capture" , |
721 | .channels_min = 2, |
722 | .channels_max = 2, |
723 | .rates = ES8328_RATES, |
724 | .formats = ES8328_FORMATS, |
725 | }, |
726 | .ops = &es8328_dai_ops, |
727 | .symmetric_rate = 1, |
728 | }; |
729 | |
730 | static int es8328_suspend(struct snd_soc_component *component) |
731 | { |
732 | struct es8328_priv *es8328; |
733 | int ret; |
734 | |
735 | es8328 = snd_soc_component_get_drvdata(c: component); |
736 | |
737 | clk_disable_unprepare(clk: es8328->clk); |
738 | |
739 | ret = regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), |
740 | consumers: es8328->supplies); |
741 | if (ret) { |
742 | dev_err(component->dev, "unable to disable regulators\n" ); |
743 | return ret; |
744 | } |
745 | return 0; |
746 | } |
747 | |
748 | static int es8328_resume(struct snd_soc_component *component) |
749 | { |
750 | struct regmap *regmap = dev_get_regmap(dev: component->dev, NULL); |
751 | struct es8328_priv *es8328; |
752 | int ret; |
753 | |
754 | es8328 = snd_soc_component_get_drvdata(c: component); |
755 | |
756 | ret = clk_prepare_enable(clk: es8328->clk); |
757 | if (ret) { |
758 | dev_err(component->dev, "unable to enable clock\n" ); |
759 | return ret; |
760 | } |
761 | |
762 | ret = regulator_bulk_enable(ARRAY_SIZE(es8328->supplies), |
763 | consumers: es8328->supplies); |
764 | if (ret) { |
765 | dev_err(component->dev, "unable to enable regulators\n" ); |
766 | return ret; |
767 | } |
768 | |
769 | regcache_mark_dirty(map: regmap); |
770 | ret = regcache_sync(map: regmap); |
771 | if (ret) { |
772 | dev_err(component->dev, "unable to sync regcache\n" ); |
773 | return ret; |
774 | } |
775 | |
776 | return 0; |
777 | } |
778 | |
779 | static int es8328_component_probe(struct snd_soc_component *component) |
780 | { |
781 | struct es8328_priv *es8328; |
782 | int ret; |
783 | |
784 | es8328 = snd_soc_component_get_drvdata(c: component); |
785 | |
786 | ret = regulator_bulk_enable(ARRAY_SIZE(es8328->supplies), |
787 | consumers: es8328->supplies); |
788 | if (ret) { |
789 | dev_err(component->dev, "unable to enable regulators\n" ); |
790 | return ret; |
791 | } |
792 | |
793 | /* Setup clocks */ |
794 | es8328->clk = devm_clk_get(dev: component->dev, NULL); |
795 | if (IS_ERR(ptr: es8328->clk)) { |
796 | dev_err(component->dev, "codec clock missing or invalid\n" ); |
797 | ret = PTR_ERR(ptr: es8328->clk); |
798 | goto clk_fail; |
799 | } |
800 | |
801 | ret = clk_prepare_enable(clk: es8328->clk); |
802 | if (ret) { |
803 | dev_err(component->dev, "unable to prepare codec clk\n" ); |
804 | goto clk_fail; |
805 | } |
806 | |
807 | return 0; |
808 | |
809 | clk_fail: |
810 | regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), |
811 | consumers: es8328->supplies); |
812 | return ret; |
813 | } |
814 | |
815 | static void es8328_remove(struct snd_soc_component *component) |
816 | { |
817 | struct es8328_priv *es8328; |
818 | |
819 | es8328 = snd_soc_component_get_drvdata(c: component); |
820 | |
821 | clk_disable_unprepare(clk: es8328->clk); |
822 | |
823 | regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), |
824 | consumers: es8328->supplies); |
825 | } |
826 | |
827 | const struct regmap_config es8328_regmap_config = { |
828 | .reg_bits = 8, |
829 | .val_bits = 8, |
830 | .max_register = ES8328_REG_MAX, |
831 | .cache_type = REGCACHE_MAPLE, |
832 | .use_single_read = true, |
833 | .use_single_write = true, |
834 | }; |
835 | EXPORT_SYMBOL_GPL(es8328_regmap_config); |
836 | |
837 | static const struct snd_soc_component_driver es8328_component_driver = { |
838 | .probe = es8328_component_probe, |
839 | .remove = es8328_remove, |
840 | .suspend = es8328_suspend, |
841 | .resume = es8328_resume, |
842 | .set_bias_level = es8328_set_bias_level, |
843 | .controls = es8328_snd_controls, |
844 | .num_controls = ARRAY_SIZE(es8328_snd_controls), |
845 | .dapm_widgets = es8328_dapm_widgets, |
846 | .num_dapm_widgets = ARRAY_SIZE(es8328_dapm_widgets), |
847 | .dapm_routes = es8328_dapm_routes, |
848 | .num_dapm_routes = ARRAY_SIZE(es8328_dapm_routes), |
849 | .suspend_bias_off = 1, |
850 | .idle_bias_on = 1, |
851 | .use_pmdown_time = 1, |
852 | .endianness = 1, |
853 | }; |
854 | |
855 | int es8328_probe(struct device *dev, struct regmap *regmap) |
856 | { |
857 | struct es8328_priv *es8328; |
858 | int ret; |
859 | int i; |
860 | |
861 | if (IS_ERR(ptr: regmap)) |
862 | return PTR_ERR(ptr: regmap); |
863 | |
864 | es8328 = devm_kzalloc(dev, size: sizeof(*es8328), GFP_KERNEL); |
865 | if (es8328 == NULL) |
866 | return -ENOMEM; |
867 | |
868 | es8328->regmap = regmap; |
869 | |
870 | for (i = 0; i < ARRAY_SIZE(es8328->supplies); i++) |
871 | es8328->supplies[i].supply = supply_names[i]; |
872 | |
873 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(es8328->supplies), |
874 | consumers: es8328->supplies); |
875 | if (ret) { |
876 | dev_err(dev, "unable to get regulators\n" ); |
877 | return ret; |
878 | } |
879 | |
880 | dev_set_drvdata(dev, data: es8328); |
881 | |
882 | return devm_snd_soc_register_component(dev, |
883 | component_driver: &es8328_component_driver, dai_drv: &es8328_dai, num_dai: 1); |
884 | } |
885 | EXPORT_SYMBOL_GPL(es8328_probe); |
886 | |
887 | MODULE_DESCRIPTION("ASoC ES8328 driver" ); |
888 | MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>" ); |
889 | MODULE_LICENSE("GPL" ); |
890 | |