1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * ADAV80X Audio Codec driver supporting ADAV801, ADAV803 |
4 | * |
5 | * Copyright 2011 Analog Devices Inc. |
6 | * Author: Yi Li <yi.li@analog.com> |
7 | * Author: Lars-Peter Clausen <lars@metafoo.de> |
8 | */ |
9 | |
10 | #include <linux/module.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/regmap.h> |
13 | #include <linux/slab.h> |
14 | |
15 | #include <sound/pcm.h> |
16 | #include <sound/pcm_params.h> |
17 | #include <sound/soc.h> |
18 | #include <sound/tlv.h> |
19 | |
20 | #include "adav80x.h" |
21 | |
22 | #define ADAV80X_PLAYBACK_CTRL 0x04 |
23 | #define ADAV80X_AUX_IN_CTRL 0x05 |
24 | #define ADAV80X_REC_CTRL 0x06 |
25 | #define ADAV80X_AUX_OUT_CTRL 0x07 |
26 | #define ADAV80X_DPATH_CTRL1 0x62 |
27 | #define ADAV80X_DPATH_CTRL2 0x63 |
28 | #define ADAV80X_DAC_CTRL1 0x64 |
29 | #define ADAV80X_DAC_CTRL2 0x65 |
30 | #define ADAV80X_DAC_CTRL3 0x66 |
31 | #define ADAV80X_DAC_L_VOL 0x68 |
32 | #define ADAV80X_DAC_R_VOL 0x69 |
33 | #define ADAV80X_PGA_L_VOL 0x6c |
34 | #define ADAV80X_PGA_R_VOL 0x6d |
35 | #define ADAV80X_ADC_CTRL1 0x6e |
36 | #define ADAV80X_ADC_CTRL2 0x6f |
37 | #define ADAV80X_ADC_L_VOL 0x70 |
38 | #define ADAV80X_ADC_R_VOL 0x71 |
39 | #define ADAV80X_PLL_CTRL1 0x74 |
40 | #define ADAV80X_PLL_CTRL2 0x75 |
41 | #define ADAV80X_ICLK_CTRL1 0x76 |
42 | #define ADAV80X_ICLK_CTRL2 0x77 |
43 | #define ADAV80X_PLL_CLK_SRC 0x78 |
44 | #define ADAV80X_PLL_OUTE 0x7a |
45 | |
46 | #define ADAV80X_PLL_CLK_SRC_PLL_XIN(pll) 0x00 |
47 | #define ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll) (0x40 << (pll)) |
48 | #define ADAV80X_PLL_CLK_SRC_PLL_MASK(pll) (0x40 << (pll)) |
49 | |
50 | #define ADAV80X_ICLK_CTRL1_DAC_SRC(src) ((src) << 5) |
51 | #define ADAV80X_ICLK_CTRL1_ADC_SRC(src) ((src) << 2) |
52 | #define ADAV80X_ICLK_CTRL1_ICLK2_SRC(src) (src) |
53 | #define ADAV80X_ICLK_CTRL2_ICLK1_SRC(src) ((src) << 3) |
54 | |
55 | #define ADAV80X_PLL_CTRL1_PLLDIV 0x10 |
56 | #define ADAV80X_PLL_CTRL1_PLLPD(pll) (0x04 << (pll)) |
57 | #define ADAV80X_PLL_CTRL1_XTLPD 0x02 |
58 | |
59 | #define ADAV80X_PLL_CTRL2_FIELD(pll, x) ((x) << ((pll) * 4)) |
60 | |
61 | #define ADAV80X_PLL_CTRL2_FS_48(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x00) |
62 | #define ADAV80X_PLL_CTRL2_FS_32(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x08) |
63 | #define ADAV80X_PLL_CTRL2_FS_44(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0c) |
64 | |
65 | #define ADAV80X_PLL_CTRL2_SEL(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x02) |
66 | #define ADAV80X_PLL_CTRL2_DOUB(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x01) |
67 | #define ADAV80X_PLL_CTRL2_PLL_MASK(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0f) |
68 | |
69 | #define ADAV80X_ADC_CTRL1_MODULATOR_MASK 0x80 |
70 | #define ADAV80X_ADC_CTRL1_MODULATOR_128FS 0x00 |
71 | #define ADAV80X_ADC_CTRL1_MODULATOR_64FS 0x80 |
72 | |
73 | #define ADAV80X_DAC_CTRL1_PD 0x80 |
74 | |
75 | #define ADAV80X_DAC_CTRL2_DIV1 0x00 |
76 | #define ADAV80X_DAC_CTRL2_DIV1_5 0x10 |
77 | #define ADAV80X_DAC_CTRL2_DIV2 0x20 |
78 | #define ADAV80X_DAC_CTRL2_DIV3 0x30 |
79 | #define ADAV80X_DAC_CTRL2_DIV_MASK 0x30 |
80 | |
81 | #define ADAV80X_DAC_CTRL2_INTERPOL_256FS 0x00 |
82 | #define ADAV80X_DAC_CTRL2_INTERPOL_128FS 0x40 |
83 | #define ADAV80X_DAC_CTRL2_INTERPOL_64FS 0x80 |
84 | #define ADAV80X_DAC_CTRL2_INTERPOL_MASK 0xc0 |
85 | |
86 | #define ADAV80X_DAC_CTRL2_DEEMPH_NONE 0x00 |
87 | #define ADAV80X_DAC_CTRL2_DEEMPH_44 0x01 |
88 | #define ADAV80X_DAC_CTRL2_DEEMPH_32 0x02 |
89 | #define ADAV80X_DAC_CTRL2_DEEMPH_48 0x03 |
90 | #define ADAV80X_DAC_CTRL2_DEEMPH_MASK 0x01 |
91 | |
92 | #define ADAV80X_CAPTURE_MODE_MASTER 0x20 |
93 | #define ADAV80X_CAPTURE_WORD_LEN24 0x00 |
94 | #define ADAV80X_CAPTURE_WORD_LEN20 0x04 |
95 | #define ADAV80X_CAPTRUE_WORD_LEN18 0x08 |
96 | #define ADAV80X_CAPTURE_WORD_LEN16 0x0c |
97 | #define ADAV80X_CAPTURE_WORD_LEN_MASK 0x0c |
98 | |
99 | #define ADAV80X_CAPTURE_MODE_LEFT_J 0x00 |
100 | #define ADAV80X_CAPTURE_MODE_I2S 0x01 |
101 | #define ADAV80X_CAPTURE_MODE_RIGHT_J 0x03 |
102 | #define ADAV80X_CAPTURE_MODE_MASK 0x03 |
103 | |
104 | #define ADAV80X_PLAYBACK_MODE_MASTER 0x10 |
105 | #define ADAV80X_PLAYBACK_MODE_LEFT_J 0x00 |
106 | #define ADAV80X_PLAYBACK_MODE_I2S 0x01 |
107 | #define ADAV80X_PLAYBACK_MODE_RIGHT_J_24 0x04 |
108 | #define ADAV80X_PLAYBACK_MODE_RIGHT_J_20 0x05 |
109 | #define ADAV80X_PLAYBACK_MODE_RIGHT_J_18 0x06 |
110 | #define ADAV80X_PLAYBACK_MODE_RIGHT_J_16 0x07 |
111 | #define ADAV80X_PLAYBACK_MODE_MASK 0x07 |
112 | |
113 | #define ADAV80X_PLL_OUTE_SYSCLKPD(x) BIT(2 - (x)) |
114 | |
115 | static const struct reg_default adav80x_reg_defaults[] = { |
116 | { ADAV80X_PLAYBACK_CTRL, 0x01 }, |
117 | { ADAV80X_AUX_IN_CTRL, 0x01 }, |
118 | { ADAV80X_REC_CTRL, 0x02 }, |
119 | { ADAV80X_AUX_OUT_CTRL, 0x01 }, |
120 | { ADAV80X_DPATH_CTRL1, 0xc0 }, |
121 | { ADAV80X_DPATH_CTRL2, 0x11 }, |
122 | { ADAV80X_DAC_CTRL1, 0x00 }, |
123 | { ADAV80X_DAC_CTRL2, 0x00 }, |
124 | { ADAV80X_DAC_CTRL3, 0x00 }, |
125 | { ADAV80X_DAC_L_VOL, 0xff }, |
126 | { ADAV80X_DAC_R_VOL, 0xff }, |
127 | { ADAV80X_PGA_L_VOL, 0x00 }, |
128 | { ADAV80X_PGA_R_VOL, 0x00 }, |
129 | { ADAV80X_ADC_CTRL1, 0x00 }, |
130 | { ADAV80X_ADC_CTRL2, 0x00 }, |
131 | { ADAV80X_ADC_L_VOL, 0xff }, |
132 | { ADAV80X_ADC_R_VOL, 0xff }, |
133 | { ADAV80X_PLL_CTRL1, 0x00 }, |
134 | { ADAV80X_PLL_CTRL2, 0x00 }, |
135 | { ADAV80X_ICLK_CTRL1, 0x00 }, |
136 | { ADAV80X_ICLK_CTRL2, 0x00 }, |
137 | { ADAV80X_PLL_CLK_SRC, 0x00 }, |
138 | { ADAV80X_PLL_OUTE, 0x00 }, |
139 | }; |
140 | |
141 | struct adav80x { |
142 | struct regmap *regmap; |
143 | |
144 | enum adav80x_clk_src clk_src; |
145 | unsigned int sysclk; |
146 | enum adav80x_pll_src pll_src; |
147 | |
148 | unsigned int dai_fmt[2]; |
149 | unsigned int rate; |
150 | bool deemph; |
151 | bool sysclk_pd[3]; |
152 | }; |
153 | |
154 | static const char *adav80x_mux_text[] = { |
155 | "ADC" , |
156 | "Playback" , |
157 | "Aux Playback" , |
158 | }; |
159 | |
160 | static const unsigned int adav80x_mux_values[] = { |
161 | 0, 2, 3, |
162 | }; |
163 | |
164 | #define ADAV80X_MUX_ENUM_DECL(name, reg, shift) \ |
165 | SOC_VALUE_ENUM_DOUBLE_DECL(name, reg, shift, 7, \ |
166 | ARRAY_SIZE(adav80x_mux_text), adav80x_mux_text, \ |
167 | adav80x_mux_values) |
168 | |
169 | static ADAV80X_MUX_ENUM_DECL(adav80x_aux_capture_enum, ADAV80X_DPATH_CTRL1, 0); |
170 | static ADAV80X_MUX_ENUM_DECL(adav80x_capture_enum, ADAV80X_DPATH_CTRL1, 3); |
171 | static ADAV80X_MUX_ENUM_DECL(adav80x_dac_enum, ADAV80X_DPATH_CTRL2, 3); |
172 | |
173 | static const struct snd_kcontrol_new adav80x_aux_capture_mux_ctrl = |
174 | SOC_DAPM_ENUM("Route" , adav80x_aux_capture_enum); |
175 | static const struct snd_kcontrol_new adav80x_capture_mux_ctrl = |
176 | SOC_DAPM_ENUM("Route" , adav80x_capture_enum); |
177 | static const struct snd_kcontrol_new adav80x_dac_mux_ctrl = |
178 | SOC_DAPM_ENUM("Route" , adav80x_dac_enum); |
179 | |
180 | #define ADAV80X_MUX(name, ctrl) \ |
181 | SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) |
182 | |
183 | static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = { |
184 | SND_SOC_DAPM_DAC("DAC" , NULL, ADAV80X_DAC_CTRL1, 7, 1), |
185 | SND_SOC_DAPM_ADC("ADC" , NULL, ADAV80X_ADC_CTRL1, 5, 1), |
186 | |
187 | SND_SOC_DAPM_PGA("Right PGA" , ADAV80X_ADC_CTRL1, 0, 1, NULL, 0), |
188 | SND_SOC_DAPM_PGA("Left PGA" , ADAV80X_ADC_CTRL1, 1, 1, NULL, 0), |
189 | |
190 | SND_SOC_DAPM_AIF_OUT("AIFOUT" , "HiFi Capture" , 0, SND_SOC_NOPM, 0, 0), |
191 | SND_SOC_DAPM_AIF_IN("AIFIN" , "HiFi Playback" , 0, SND_SOC_NOPM, 0, 0), |
192 | |
193 | SND_SOC_DAPM_AIF_OUT("AIFAUXOUT" , "Aux Capture" , 0, SND_SOC_NOPM, 0, 0), |
194 | SND_SOC_DAPM_AIF_IN("AIFAUXIN" , "Aux Playback" , 0, SND_SOC_NOPM, 0, 0), |
195 | |
196 | ADAV80X_MUX("Aux Capture Select" , &adav80x_aux_capture_mux_ctrl), |
197 | ADAV80X_MUX("Capture Select" , &adav80x_capture_mux_ctrl), |
198 | ADAV80X_MUX("DAC Select" , &adav80x_dac_mux_ctrl), |
199 | |
200 | SND_SOC_DAPM_INPUT("VINR" ), |
201 | SND_SOC_DAPM_INPUT("VINL" ), |
202 | SND_SOC_DAPM_OUTPUT("VOUTR" ), |
203 | SND_SOC_DAPM_OUTPUT("VOUTL" ), |
204 | |
205 | SND_SOC_DAPM_SUPPLY("SYSCLK" , SND_SOC_NOPM, 0, 0, NULL, 0), |
206 | SND_SOC_DAPM_SUPPLY("PLL1" , ADAV80X_PLL_CTRL1, 2, 1, NULL, 0), |
207 | SND_SOC_DAPM_SUPPLY("PLL2" , ADAV80X_PLL_CTRL1, 3, 1, NULL, 0), |
208 | SND_SOC_DAPM_SUPPLY("OSC" , ADAV80X_PLL_CTRL1, 1, 1, NULL, 0), |
209 | }; |
210 | |
211 | static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, |
212 | struct snd_soc_dapm_widget *sink) |
213 | { |
214 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: source->dapm); |
215 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
216 | const char *clk; |
217 | |
218 | switch (adav80x->clk_src) { |
219 | case ADAV80X_CLK_PLL1: |
220 | clk = "PLL1" ; |
221 | break; |
222 | case ADAV80X_CLK_PLL2: |
223 | clk = "PLL2" ; |
224 | break; |
225 | case ADAV80X_CLK_XTAL: |
226 | clk = "OSC" ; |
227 | break; |
228 | default: |
229 | return 0; |
230 | } |
231 | |
232 | return snd_soc_dapm_widget_name_cmp(widget: source, s: clk) == 0; |
233 | } |
234 | |
235 | static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source, |
236 | struct snd_soc_dapm_widget *sink) |
237 | { |
238 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: source->dapm); |
239 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
240 | |
241 | return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL; |
242 | } |
243 | |
244 | |
245 | static const struct snd_soc_dapm_route adav80x_dapm_routes[] = { |
246 | { "DAC Select" , "ADC" , "ADC" }, |
247 | { "DAC Select" , "Playback" , "AIFIN" }, |
248 | { "DAC Select" , "Aux Playback" , "AIFAUXIN" }, |
249 | { "DAC" , NULL, "DAC Select" }, |
250 | |
251 | { "Capture Select" , "ADC" , "ADC" }, |
252 | { "Capture Select" , "Playback" , "AIFIN" }, |
253 | { "Capture Select" , "Aux Playback" , "AIFAUXIN" }, |
254 | { "AIFOUT" , NULL, "Capture Select" }, |
255 | |
256 | { "Aux Capture Select" , "ADC" , "ADC" }, |
257 | { "Aux Capture Select" , "Playback" , "AIFIN" }, |
258 | { "Aux Capture Select" , "Aux Playback" , "AIFAUXIN" }, |
259 | { "AIFAUXOUT" , NULL, "Aux Capture Select" }, |
260 | |
261 | { "VOUTR" , NULL, "DAC" }, |
262 | { "VOUTL" , NULL, "DAC" }, |
263 | |
264 | { "Left PGA" , NULL, "VINL" }, |
265 | { "Right PGA" , NULL, "VINR" }, |
266 | { "ADC" , NULL, "Left PGA" }, |
267 | { "ADC" , NULL, "Right PGA" }, |
268 | |
269 | { "SYSCLK" , NULL, "PLL1" , adav80x_dapm_sysclk_check }, |
270 | { "SYSCLK" , NULL, "PLL2" , adav80x_dapm_sysclk_check }, |
271 | { "SYSCLK" , NULL, "OSC" , adav80x_dapm_sysclk_check }, |
272 | { "PLL1" , NULL, "OSC" , adav80x_dapm_pll_check }, |
273 | { "PLL2" , NULL, "OSC" , adav80x_dapm_pll_check }, |
274 | |
275 | { "ADC" , NULL, "SYSCLK" }, |
276 | { "DAC" , NULL, "SYSCLK" }, |
277 | { "AIFOUT" , NULL, "SYSCLK" }, |
278 | { "AIFAUXOUT" , NULL, "SYSCLK" }, |
279 | { "AIFIN" , NULL, "SYSCLK" }, |
280 | { "AIFAUXIN" , NULL, "SYSCLK" }, |
281 | }; |
282 | |
283 | static int adav80x_set_deemph(struct snd_soc_component *component) |
284 | { |
285 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
286 | unsigned int val; |
287 | |
288 | if (adav80x->deemph) { |
289 | switch (adav80x->rate) { |
290 | case 32000: |
291 | val = ADAV80X_DAC_CTRL2_DEEMPH_32; |
292 | break; |
293 | case 44100: |
294 | val = ADAV80X_DAC_CTRL2_DEEMPH_44; |
295 | break; |
296 | case 48000: |
297 | case 64000: |
298 | case 88200: |
299 | case 96000: |
300 | val = ADAV80X_DAC_CTRL2_DEEMPH_48; |
301 | break; |
302 | default: |
303 | val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; |
304 | break; |
305 | } |
306 | } else { |
307 | val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; |
308 | } |
309 | |
310 | return regmap_update_bits(map: adav80x->regmap, ADAV80X_DAC_CTRL2, |
311 | ADAV80X_DAC_CTRL2_DEEMPH_MASK, val); |
312 | } |
313 | |
314 | static int adav80x_put_deemph(struct snd_kcontrol *kcontrol, |
315 | struct snd_ctl_elem_value *ucontrol) |
316 | { |
317 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
318 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
319 | unsigned int deemph = ucontrol->value.integer.value[0]; |
320 | |
321 | if (deemph > 1) |
322 | return -EINVAL; |
323 | |
324 | adav80x->deemph = deemph; |
325 | |
326 | return adav80x_set_deemph(component); |
327 | } |
328 | |
329 | static int adav80x_get_deemph(struct snd_kcontrol *kcontrol, |
330 | struct snd_ctl_elem_value *ucontrol) |
331 | { |
332 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
333 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
334 | |
335 | ucontrol->value.integer.value[0] = adav80x->deemph; |
336 | return 0; |
337 | }; |
338 | |
339 | static const DECLARE_TLV_DB_SCALE(adav80x_inpga_tlv, 0, 50, 0); |
340 | static const DECLARE_TLV_DB_MINMAX(adav80x_digital_tlv, -9563, 0); |
341 | |
342 | static const struct snd_kcontrol_new adav80x_controls[] = { |
343 | SOC_DOUBLE_R_TLV("Master Playback Volume" , ADAV80X_DAC_L_VOL, |
344 | ADAV80X_DAC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), |
345 | SOC_DOUBLE_R_TLV("Master Capture Volume" , ADAV80X_ADC_L_VOL, |
346 | ADAV80X_ADC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), |
347 | |
348 | SOC_DOUBLE_R_TLV("PGA Capture Volume" , ADAV80X_PGA_L_VOL, |
349 | ADAV80X_PGA_R_VOL, 0, 0x30, 0, adav80x_inpga_tlv), |
350 | |
351 | SOC_DOUBLE("Master Playback Switch" , ADAV80X_DAC_CTRL1, 0, 1, 1, 0), |
352 | SOC_DOUBLE("Master Capture Switch" , ADAV80X_ADC_CTRL1, 2, 3, 1, 1), |
353 | |
354 | SOC_SINGLE("ADC High Pass Filter Switch" , ADAV80X_ADC_CTRL1, 6, 1, 0), |
355 | |
356 | SOC_SINGLE_BOOL_EXT("Playback De-emphasis Switch" , 0, |
357 | adav80x_get_deemph, adav80x_put_deemph), |
358 | }; |
359 | |
360 | static unsigned int adav80x_port_ctrl_regs[2][2] = { |
361 | { ADAV80X_REC_CTRL, ADAV80X_PLAYBACK_CTRL, }, |
362 | { ADAV80X_AUX_OUT_CTRL, ADAV80X_AUX_IN_CTRL }, |
363 | }; |
364 | |
365 | static int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
366 | { |
367 | struct snd_soc_component *component = dai->component; |
368 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
369 | unsigned int capture = 0x00; |
370 | unsigned int playback = 0x00; |
371 | |
372 | switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { |
373 | case SND_SOC_DAIFMT_CBP_CFP: |
374 | capture |= ADAV80X_CAPTURE_MODE_MASTER; |
375 | playback |= ADAV80X_PLAYBACK_MODE_MASTER; |
376 | break; |
377 | case SND_SOC_DAIFMT_CBC_CFC: |
378 | break; |
379 | default: |
380 | return -EINVAL; |
381 | } |
382 | |
383 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
384 | case SND_SOC_DAIFMT_I2S: |
385 | capture |= ADAV80X_CAPTURE_MODE_I2S; |
386 | playback |= ADAV80X_PLAYBACK_MODE_I2S; |
387 | break; |
388 | case SND_SOC_DAIFMT_LEFT_J: |
389 | capture |= ADAV80X_CAPTURE_MODE_LEFT_J; |
390 | playback |= ADAV80X_PLAYBACK_MODE_LEFT_J; |
391 | break; |
392 | case SND_SOC_DAIFMT_RIGHT_J: |
393 | capture |= ADAV80X_CAPTURE_MODE_RIGHT_J; |
394 | playback |= ADAV80X_PLAYBACK_MODE_RIGHT_J_24; |
395 | break; |
396 | default: |
397 | return -EINVAL; |
398 | } |
399 | |
400 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
401 | case SND_SOC_DAIFMT_NB_NF: |
402 | break; |
403 | default: |
404 | return -EINVAL; |
405 | } |
406 | |
407 | regmap_update_bits(map: adav80x->regmap, reg: adav80x_port_ctrl_regs[dai->id][0], |
408 | ADAV80X_CAPTURE_MODE_MASK | ADAV80X_CAPTURE_MODE_MASTER, |
409 | val: capture); |
410 | regmap_write(map: adav80x->regmap, reg: adav80x_port_ctrl_regs[dai->id][1], |
411 | val: playback); |
412 | |
413 | adav80x->dai_fmt[dai->id] = fmt & SND_SOC_DAIFMT_FORMAT_MASK; |
414 | |
415 | return 0; |
416 | } |
417 | |
418 | static int adav80x_set_adc_clock(struct snd_soc_component *component, |
419 | unsigned int sample_rate) |
420 | { |
421 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
422 | unsigned int val; |
423 | |
424 | if (sample_rate <= 48000) |
425 | val = ADAV80X_ADC_CTRL1_MODULATOR_128FS; |
426 | else |
427 | val = ADAV80X_ADC_CTRL1_MODULATOR_64FS; |
428 | |
429 | regmap_update_bits(map: adav80x->regmap, ADAV80X_ADC_CTRL1, |
430 | ADAV80X_ADC_CTRL1_MODULATOR_MASK, val); |
431 | |
432 | return 0; |
433 | } |
434 | |
435 | static int adav80x_set_dac_clock(struct snd_soc_component *component, |
436 | unsigned int sample_rate) |
437 | { |
438 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
439 | unsigned int val; |
440 | |
441 | if (sample_rate <= 48000) |
442 | val = ADAV80X_DAC_CTRL2_DIV1 | ADAV80X_DAC_CTRL2_INTERPOL_256FS; |
443 | else |
444 | val = ADAV80X_DAC_CTRL2_DIV2 | ADAV80X_DAC_CTRL2_INTERPOL_128FS; |
445 | |
446 | regmap_update_bits(map: adav80x->regmap, ADAV80X_DAC_CTRL2, |
447 | ADAV80X_DAC_CTRL2_DIV_MASK | ADAV80X_DAC_CTRL2_INTERPOL_MASK, |
448 | val); |
449 | |
450 | return 0; |
451 | } |
452 | |
453 | static int adav80x_set_capture_pcm_format(struct snd_soc_component *component, |
454 | struct snd_soc_dai *dai, struct snd_pcm_hw_params *params) |
455 | { |
456 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
457 | unsigned int val; |
458 | |
459 | switch (params_width(p: params)) { |
460 | case 16: |
461 | val = ADAV80X_CAPTURE_WORD_LEN16; |
462 | break; |
463 | case 18: |
464 | val = ADAV80X_CAPTRUE_WORD_LEN18; |
465 | break; |
466 | case 20: |
467 | val = ADAV80X_CAPTURE_WORD_LEN20; |
468 | break; |
469 | case 24: |
470 | val = ADAV80X_CAPTURE_WORD_LEN24; |
471 | break; |
472 | default: |
473 | return -EINVAL; |
474 | } |
475 | |
476 | regmap_update_bits(map: adav80x->regmap, reg: adav80x_port_ctrl_regs[dai->id][0], |
477 | ADAV80X_CAPTURE_WORD_LEN_MASK, val); |
478 | |
479 | return 0; |
480 | } |
481 | |
482 | static int adav80x_set_playback_pcm_format(struct snd_soc_component *component, |
483 | struct snd_soc_dai *dai, struct snd_pcm_hw_params *params) |
484 | { |
485 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
486 | unsigned int val; |
487 | |
488 | if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J) |
489 | return 0; |
490 | |
491 | switch (params_width(p: params)) { |
492 | case 16: |
493 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16; |
494 | break; |
495 | case 18: |
496 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18; |
497 | break; |
498 | case 20: |
499 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20; |
500 | break; |
501 | case 24: |
502 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24; |
503 | break; |
504 | default: |
505 | return -EINVAL; |
506 | } |
507 | |
508 | regmap_update_bits(map: adav80x->regmap, reg: adav80x_port_ctrl_regs[dai->id][1], |
509 | ADAV80X_PLAYBACK_MODE_MASK, val); |
510 | |
511 | return 0; |
512 | } |
513 | |
514 | static int adav80x_hw_params(struct snd_pcm_substream *substream, |
515 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
516 | { |
517 | struct snd_soc_component *component = dai->component; |
518 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
519 | unsigned int rate = params_rate(p: params); |
520 | |
521 | if (rate * 256 != adav80x->sysclk) |
522 | return -EINVAL; |
523 | |
524 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
525 | adav80x_set_playback_pcm_format(component, dai, params); |
526 | adav80x_set_dac_clock(component, sample_rate: rate); |
527 | } else { |
528 | adav80x_set_capture_pcm_format(component, dai, params); |
529 | adav80x_set_adc_clock(component, sample_rate: rate); |
530 | } |
531 | adav80x->rate = rate; |
532 | adav80x_set_deemph(component); |
533 | |
534 | return 0; |
535 | } |
536 | |
537 | static int adav80x_set_sysclk(struct snd_soc_component *component, |
538 | int clk_id, int source, |
539 | unsigned int freq, int dir) |
540 | { |
541 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
542 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
543 | |
544 | if (dir == SND_SOC_CLOCK_IN) { |
545 | switch (clk_id) { |
546 | case ADAV80X_CLK_XIN: |
547 | case ADAV80X_CLK_XTAL: |
548 | case ADAV80X_CLK_MCLKI: |
549 | case ADAV80X_CLK_PLL1: |
550 | case ADAV80X_CLK_PLL2: |
551 | break; |
552 | default: |
553 | return -EINVAL; |
554 | } |
555 | |
556 | adav80x->sysclk = freq; |
557 | |
558 | if (adav80x->clk_src != clk_id) { |
559 | unsigned int iclk_ctrl1, iclk_ctrl2; |
560 | |
561 | adav80x->clk_src = clk_id; |
562 | if (clk_id == ADAV80X_CLK_XTAL) |
563 | clk_id = ADAV80X_CLK_XIN; |
564 | |
565 | iclk_ctrl1 = ADAV80X_ICLK_CTRL1_DAC_SRC(clk_id) | |
566 | ADAV80X_ICLK_CTRL1_ADC_SRC(clk_id) | |
567 | ADAV80X_ICLK_CTRL1_ICLK2_SRC(clk_id); |
568 | iclk_ctrl2 = ADAV80X_ICLK_CTRL2_ICLK1_SRC(clk_id); |
569 | |
570 | regmap_write(map: adav80x->regmap, ADAV80X_ICLK_CTRL1, |
571 | val: iclk_ctrl1); |
572 | regmap_write(map: adav80x->regmap, ADAV80X_ICLK_CTRL2, |
573 | val: iclk_ctrl2); |
574 | |
575 | snd_soc_dapm_sync(dapm); |
576 | } |
577 | } else { |
578 | unsigned int mask; |
579 | |
580 | switch (clk_id) { |
581 | case ADAV80X_CLK_SYSCLK1: |
582 | case ADAV80X_CLK_SYSCLK2: |
583 | case ADAV80X_CLK_SYSCLK3: |
584 | break; |
585 | default: |
586 | return -EINVAL; |
587 | } |
588 | |
589 | clk_id -= ADAV80X_CLK_SYSCLK1; |
590 | mask = ADAV80X_PLL_OUTE_SYSCLKPD(clk_id); |
591 | |
592 | if (freq == 0) { |
593 | regmap_update_bits(map: adav80x->regmap, ADAV80X_PLL_OUTE, |
594 | mask, val: mask); |
595 | adav80x->sysclk_pd[clk_id] = true; |
596 | } else { |
597 | regmap_update_bits(map: adav80x->regmap, ADAV80X_PLL_OUTE, |
598 | mask, val: 0); |
599 | adav80x->sysclk_pd[clk_id] = false; |
600 | } |
601 | |
602 | snd_soc_dapm_mutex_lock(dapm); |
603 | |
604 | if (adav80x->sysclk_pd[0]) |
605 | snd_soc_dapm_disable_pin_unlocked(dapm, pin: "PLL1" ); |
606 | else |
607 | snd_soc_dapm_force_enable_pin_unlocked(dapm, pin: "PLL1" ); |
608 | |
609 | if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) |
610 | snd_soc_dapm_disable_pin_unlocked(dapm, pin: "PLL2" ); |
611 | else |
612 | snd_soc_dapm_force_enable_pin_unlocked(dapm, pin: "PLL2" ); |
613 | |
614 | snd_soc_dapm_sync_unlocked(dapm); |
615 | |
616 | snd_soc_dapm_mutex_unlock(dapm); |
617 | } |
618 | |
619 | return 0; |
620 | } |
621 | |
622 | static int adav80x_set_pll(struct snd_soc_component *component, int pll_id, |
623 | int source, unsigned int freq_in, unsigned int freq_out) |
624 | { |
625 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
626 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
627 | unsigned int pll_ctrl1 = 0; |
628 | unsigned int pll_ctrl2 = 0; |
629 | unsigned int pll_src; |
630 | |
631 | switch (source) { |
632 | case ADAV80X_PLL_SRC_XTAL: |
633 | case ADAV80X_PLL_SRC_XIN: |
634 | case ADAV80X_PLL_SRC_MCLKI: |
635 | break; |
636 | default: |
637 | return -EINVAL; |
638 | } |
639 | |
640 | if (!freq_out) |
641 | return 0; |
642 | |
643 | switch (freq_in) { |
644 | case 27000000: |
645 | break; |
646 | case 54000000: |
647 | if (source == ADAV80X_PLL_SRC_XIN) { |
648 | pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV; |
649 | break; |
650 | } |
651 | fallthrough; |
652 | default: |
653 | return -EINVAL; |
654 | } |
655 | |
656 | if (freq_out > 12288000) { |
657 | pll_ctrl2 |= ADAV80X_PLL_CTRL2_DOUB(pll_id); |
658 | freq_out /= 2; |
659 | } |
660 | |
661 | /* freq_out = sample_rate * 256 */ |
662 | switch (freq_out) { |
663 | case 8192000: |
664 | pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_32(pll_id); |
665 | break; |
666 | case 11289600: |
667 | pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_44(pll_id); |
668 | break; |
669 | case 12288000: |
670 | pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_48(pll_id); |
671 | break; |
672 | default: |
673 | return -EINVAL; |
674 | } |
675 | |
676 | regmap_update_bits(map: adav80x->regmap, ADAV80X_PLL_CTRL1, |
677 | ADAV80X_PLL_CTRL1_PLLDIV, val: pll_ctrl1); |
678 | regmap_update_bits(map: adav80x->regmap, ADAV80X_PLL_CTRL2, |
679 | ADAV80X_PLL_CTRL2_PLL_MASK(pll_id), val: pll_ctrl2); |
680 | |
681 | if (source != adav80x->pll_src) { |
682 | if (source == ADAV80X_PLL_SRC_MCLKI) |
683 | pll_src = ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll_id); |
684 | else |
685 | pll_src = ADAV80X_PLL_CLK_SRC_PLL_XIN(pll_id); |
686 | |
687 | regmap_update_bits(map: adav80x->regmap, ADAV80X_PLL_CLK_SRC, |
688 | ADAV80X_PLL_CLK_SRC_PLL_MASK(pll_id), val: pll_src); |
689 | |
690 | adav80x->pll_src = source; |
691 | |
692 | snd_soc_dapm_sync(dapm); |
693 | } |
694 | |
695 | return 0; |
696 | } |
697 | |
698 | static int adav80x_set_bias_level(struct snd_soc_component *component, |
699 | enum snd_soc_bias_level level) |
700 | { |
701 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
702 | unsigned int mask = ADAV80X_DAC_CTRL1_PD; |
703 | |
704 | switch (level) { |
705 | case SND_SOC_BIAS_ON: |
706 | break; |
707 | case SND_SOC_BIAS_PREPARE: |
708 | break; |
709 | case SND_SOC_BIAS_STANDBY: |
710 | regmap_update_bits(map: adav80x->regmap, ADAV80X_DAC_CTRL1, mask, |
711 | val: 0x00); |
712 | break; |
713 | case SND_SOC_BIAS_OFF: |
714 | regmap_update_bits(map: adav80x->regmap, ADAV80X_DAC_CTRL1, mask, |
715 | val: mask); |
716 | break; |
717 | } |
718 | |
719 | return 0; |
720 | } |
721 | |
722 | /* Enforce the same sample rate on all audio interfaces */ |
723 | static int adav80x_dai_startup(struct snd_pcm_substream *substream, |
724 | struct snd_soc_dai *dai) |
725 | { |
726 | struct snd_soc_component *component = dai->component; |
727 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
728 | |
729 | if (!snd_soc_component_active(component) || !adav80x->rate) |
730 | return 0; |
731 | |
732 | return snd_pcm_hw_constraint_single(runtime: substream->runtime, |
733 | SNDRV_PCM_HW_PARAM_RATE, val: adav80x->rate); |
734 | } |
735 | |
736 | static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, |
737 | struct snd_soc_dai *dai) |
738 | { |
739 | struct snd_soc_component *component = dai->component; |
740 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
741 | |
742 | if (!snd_soc_component_active(component)) |
743 | adav80x->rate = 0; |
744 | } |
745 | |
746 | static const struct snd_soc_dai_ops adav80x_dai_ops = { |
747 | .set_fmt = adav80x_set_dai_fmt, |
748 | .hw_params = adav80x_hw_params, |
749 | .startup = adav80x_dai_startup, |
750 | .shutdown = adav80x_dai_shutdown, |
751 | }; |
752 | |
753 | #define ADAV80X_PLAYBACK_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ |
754 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | \ |
755 | SNDRV_PCM_RATE_96000) |
756 | |
757 | #define ADAV80X_CAPTURE_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) |
758 | |
759 | #define ADAV80X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ |
760 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) |
761 | |
762 | static struct snd_soc_dai_driver adav80x_dais[] = { |
763 | { |
764 | .name = "adav80x-hifi" , |
765 | .id = 0, |
766 | .playback = { |
767 | .stream_name = "HiFi Playback" , |
768 | .channels_min = 2, |
769 | .channels_max = 2, |
770 | .rates = ADAV80X_PLAYBACK_RATES, |
771 | .formats = ADAV80X_FORMATS, |
772 | }, |
773 | .capture = { |
774 | .stream_name = "HiFi Capture" , |
775 | .channels_min = 2, |
776 | .channels_max = 2, |
777 | .rates = ADAV80X_CAPTURE_RATES, |
778 | .formats = ADAV80X_FORMATS, |
779 | }, |
780 | .ops = &adav80x_dai_ops, |
781 | }, |
782 | { |
783 | .name = "adav80x-aux" , |
784 | .id = 1, |
785 | .playback = { |
786 | .stream_name = "Aux Playback" , |
787 | .channels_min = 2, |
788 | .channels_max = 2, |
789 | .rates = ADAV80X_PLAYBACK_RATES, |
790 | .formats = ADAV80X_FORMATS, |
791 | }, |
792 | .capture = { |
793 | .stream_name = "Aux Capture" , |
794 | .channels_min = 2, |
795 | .channels_max = 2, |
796 | .rates = ADAV80X_CAPTURE_RATES, |
797 | .formats = ADAV80X_FORMATS, |
798 | }, |
799 | .ops = &adav80x_dai_ops, |
800 | }, |
801 | }; |
802 | |
803 | static int adav80x_probe(struct snd_soc_component *component) |
804 | { |
805 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
806 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
807 | |
808 | /* Force PLLs on for SYSCLK output */ |
809 | snd_soc_dapm_force_enable_pin(dapm, pin: "PLL1" ); |
810 | snd_soc_dapm_force_enable_pin(dapm, pin: "PLL2" ); |
811 | |
812 | /* Power down S/PDIF receiver, since it is currently not supported */ |
813 | regmap_write(map: adav80x->regmap, ADAV80X_PLL_OUTE, val: 0x20); |
814 | /* Disable DAC zero flag */ |
815 | regmap_write(map: adav80x->regmap, ADAV80X_DAC_CTRL3, val: 0x6); |
816 | |
817 | return 0; |
818 | } |
819 | |
820 | static int adav80x_resume(struct snd_soc_component *component) |
821 | { |
822 | struct adav80x *adav80x = snd_soc_component_get_drvdata(c: component); |
823 | |
824 | regcache_sync(map: adav80x->regmap); |
825 | |
826 | return 0; |
827 | } |
828 | |
829 | static const struct snd_soc_component_driver adav80x_component_driver = { |
830 | .probe = adav80x_probe, |
831 | .resume = adav80x_resume, |
832 | .set_bias_level = adav80x_set_bias_level, |
833 | .set_pll = adav80x_set_pll, |
834 | .set_sysclk = adav80x_set_sysclk, |
835 | .controls = adav80x_controls, |
836 | .num_controls = ARRAY_SIZE(adav80x_controls), |
837 | .dapm_widgets = adav80x_dapm_widgets, |
838 | .num_dapm_widgets = ARRAY_SIZE(adav80x_dapm_widgets), |
839 | .dapm_routes = adav80x_dapm_routes, |
840 | .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), |
841 | .suspend_bias_off = 1, |
842 | .idle_bias_on = 1, |
843 | .use_pmdown_time = 1, |
844 | .endianness = 1, |
845 | }; |
846 | |
847 | int adav80x_bus_probe(struct device *dev, struct regmap *regmap) |
848 | { |
849 | struct adav80x *adav80x; |
850 | |
851 | if (IS_ERR(ptr: regmap)) |
852 | return PTR_ERR(ptr: regmap); |
853 | |
854 | adav80x = devm_kzalloc(dev, size: sizeof(*adav80x), GFP_KERNEL); |
855 | if (!adav80x) |
856 | return -ENOMEM; |
857 | |
858 | dev_set_drvdata(dev, data: adav80x); |
859 | adav80x->regmap = regmap; |
860 | |
861 | return devm_snd_soc_register_component(dev, component_driver: &adav80x_component_driver, |
862 | dai_drv: adav80x_dais, ARRAY_SIZE(adav80x_dais)); |
863 | } |
864 | EXPORT_SYMBOL_GPL(adav80x_bus_probe); |
865 | |
866 | const struct regmap_config adav80x_regmap_config = { |
867 | .val_bits = 8, |
868 | .pad_bits = 1, |
869 | .reg_bits = 7, |
870 | |
871 | .max_register = ADAV80X_PLL_OUTE, |
872 | |
873 | .cache_type = REGCACHE_MAPLE, |
874 | .reg_defaults = adav80x_reg_defaults, |
875 | .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), |
876 | }; |
877 | EXPORT_SYMBOL_GPL(adav80x_regmap_config); |
878 | |
879 | MODULE_DESCRIPTION("ASoC ADAV80x driver" ); |
880 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>" ); |
881 | MODULE_AUTHOR("Yi Li <yi.li@analog.com>>" ); |
882 | MODULE_LICENSE("GPL" ); |
883 | |