1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Cirrus Logic Madera class codecs common support
4 //
5 // Copyright (C) 2015-2019 Cirrus Logic, Inc. and
6 // Cirrus Logic International Semiconductor Ltd.
7 //
8
9 #include <linux/delay.h>
10 #include <linux/gcd.h>
11 #include <linux/module.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/slab.h>
14 #include <linux/string_choices.h>
15 #include <sound/pcm.h>
16 #include <sound/pcm_params.h>
17 #include <sound/tlv.h>
18
19 #include <linux/irqchip/irq-madera.h>
20 #include <linux/mfd/madera/core.h>
21 #include <linux/mfd/madera/registers.h>
22 #include <linux/mfd/madera/pdata.h>
23 #include <sound/madera-pdata.h>
24
25 #include <dt-bindings/sound/madera.h>
26
27 #include "madera.h"
28
29 #define MADERA_AIF_BCLK_CTRL 0x00
30 #define MADERA_AIF_TX_PIN_CTRL 0x01
31 #define MADERA_AIF_RX_PIN_CTRL 0x02
32 #define MADERA_AIF_RATE_CTRL 0x03
33 #define MADERA_AIF_FORMAT 0x04
34 #define MADERA_AIF_RX_BCLK_RATE 0x06
35 #define MADERA_AIF_FRAME_CTRL_1 0x07
36 #define MADERA_AIF_FRAME_CTRL_2 0x08
37 #define MADERA_AIF_FRAME_CTRL_3 0x09
38 #define MADERA_AIF_FRAME_CTRL_4 0x0A
39 #define MADERA_AIF_FRAME_CTRL_5 0x0B
40 #define MADERA_AIF_FRAME_CTRL_6 0x0C
41 #define MADERA_AIF_FRAME_CTRL_7 0x0D
42 #define MADERA_AIF_FRAME_CTRL_8 0x0E
43 #define MADERA_AIF_FRAME_CTRL_9 0x0F
44 #define MADERA_AIF_FRAME_CTRL_10 0x10
45 #define MADERA_AIF_FRAME_CTRL_11 0x11
46 #define MADERA_AIF_FRAME_CTRL_12 0x12
47 #define MADERA_AIF_FRAME_CTRL_13 0x13
48 #define MADERA_AIF_FRAME_CTRL_14 0x14
49 #define MADERA_AIF_FRAME_CTRL_15 0x15
50 #define MADERA_AIF_FRAME_CTRL_16 0x16
51 #define MADERA_AIF_FRAME_CTRL_17 0x17
52 #define MADERA_AIF_FRAME_CTRL_18 0x18
53 #define MADERA_AIF_TX_ENABLES 0x19
54 #define MADERA_AIF_RX_ENABLES 0x1A
55 #define MADERA_AIF_FORCE_WRITE 0x1B
56
57 #define MADERA_DSP_CONFIG_1_OFFS 0x00
58 #define MADERA_DSP_CONFIG_2_OFFS 0x02
59
60 #define MADERA_DSP_CLK_SEL_MASK 0x70000
61 #define MADERA_DSP_CLK_SEL_SHIFT 16
62
63 #define MADERA_DSP_RATE_MASK 0x7800
64 #define MADERA_DSP_RATE_SHIFT 11
65
66 #define MADERA_SYSCLK_6MHZ 0
67 #define MADERA_SYSCLK_12MHZ 1
68 #define MADERA_SYSCLK_24MHZ 2
69 #define MADERA_SYSCLK_49MHZ 3
70 #define MADERA_SYSCLK_98MHZ 4
71
72 #define MADERA_DSPCLK_9MHZ 0
73 #define MADERA_DSPCLK_18MHZ 1
74 #define MADERA_DSPCLK_36MHZ 2
75 #define MADERA_DSPCLK_73MHZ 3
76 #define MADERA_DSPCLK_147MHZ 4
77
78 #define MADERA_FLL_VCO_CORNER 141900000
79 #define MADERA_FLL_MAX_FREF 13500000
80 #define MADERA_FLL_MAX_N 1023
81 #define MADERA_FLL_MIN_FOUT 90000000
82 #define MADERA_FLL_MAX_FOUT 100000000
83 #define MADERA_FLL_MAX_FRATIO 16
84 #define MADERA_FLL_MAX_REFDIV 8
85 #define MADERA_FLL_OUTDIV 3
86 #define MADERA_FLL_VCO_MULT 3
87 #define MADERA_FLLAO_MAX_FREF 12288000
88 #define MADERA_FLLAO_MIN_N 4
89 #define MADERA_FLLAO_MAX_N 1023
90 #define MADERA_FLLAO_MAX_FBDIV 254
91 #define MADERA_FLLHJ_INT_MAX_N 1023
92 #define MADERA_FLLHJ_INT_MIN_N 1
93 #define MADERA_FLLHJ_FRAC_MAX_N 255
94 #define MADERA_FLLHJ_FRAC_MIN_N 4
95 #define MADERA_FLLHJ_LOW_THRESH 192000
96 #define MADERA_FLLHJ_MID_THRESH 1152000
97 #define MADERA_FLLHJ_MAX_THRESH 13000000
98 #define MADERA_FLLHJ_LOW_GAINS 0x23f0
99 #define MADERA_FLLHJ_MID_GAINS 0x22f2
100 #define MADERA_FLLHJ_HIGH_GAINS 0x21f0
101
102 #define MADERA_FLL_SYNCHRONISER_OFFS 0x10
103 #define CS47L35_FLL_SYNCHRONISER_OFFS 0xE
104 #define MADERA_FLL_CONTROL_1_OFFS 0x1
105 #define MADERA_FLL_CONTROL_2_OFFS 0x2
106 #define MADERA_FLL_CONTROL_3_OFFS 0x3
107 #define MADERA_FLL_CONTROL_4_OFFS 0x4
108 #define MADERA_FLL_CONTROL_5_OFFS 0x5
109 #define MADERA_FLL_CONTROL_6_OFFS 0x6
110 #define MADERA_FLL_GAIN_OFFS 0x8
111 #define MADERA_FLL_CONTROL_7_OFFS 0x9
112 #define MADERA_FLL_EFS_2_OFFS 0xA
113 #define MADERA_FLL_SYNCHRONISER_1_OFFS 0x1
114 #define MADERA_FLL_SYNCHRONISER_2_OFFS 0x2
115 #define MADERA_FLL_SYNCHRONISER_3_OFFS 0x3
116 #define MADERA_FLL_SYNCHRONISER_4_OFFS 0x4
117 #define MADERA_FLL_SYNCHRONISER_5_OFFS 0x5
118 #define MADERA_FLL_SYNCHRONISER_6_OFFS 0x6
119 #define MADERA_FLL_SYNCHRONISER_7_OFFS 0x7
120 #define MADERA_FLL_SPREAD_SPECTRUM_OFFS 0x9
121 #define MADERA_FLL_GPIO_CLOCK_OFFS 0xA
122 #define MADERA_FLL_CONTROL_10_OFFS 0xA
123 #define MADERA_FLL_CONTROL_11_OFFS 0xB
124 #define MADERA_FLL1_DIGITAL_TEST_1_OFFS 0xD
125
126 #define MADERA_FLLAO_CONTROL_1_OFFS 0x1
127 #define MADERA_FLLAO_CONTROL_2_OFFS 0x2
128 #define MADERA_FLLAO_CONTROL_3_OFFS 0x3
129 #define MADERA_FLLAO_CONTROL_4_OFFS 0x4
130 #define MADERA_FLLAO_CONTROL_5_OFFS 0x5
131 #define MADERA_FLLAO_CONTROL_6_OFFS 0x6
132 #define MADERA_FLLAO_CONTROL_7_OFFS 0x8
133 #define MADERA_FLLAO_CONTROL_8_OFFS 0xA
134 #define MADERA_FLLAO_CONTROL_9_OFFS 0xB
135 #define MADERA_FLLAO_CONTROL_10_OFFS 0xC
136 #define MADERA_FLLAO_CONTROL_11_OFFS 0xD
137
138 #define MADERA_FMT_DSP_MODE_A 0
139 #define MADERA_FMT_DSP_MODE_B 1
140 #define MADERA_FMT_I2S_MODE 2
141 #define MADERA_FMT_LEFT_JUSTIFIED_MODE 3
142
143 #define madera_fll_err(_fll, fmt, ...) \
144 dev_err(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
145 #define madera_fll_warn(_fll, fmt, ...) \
146 dev_warn(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
147 #define madera_fll_dbg(_fll, fmt, ...) \
148 dev_dbg(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
149
150 #define madera_aif_err(_dai, fmt, ...) \
151 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
152 #define madera_aif_warn(_dai, fmt, ...) \
153 dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
154 #define madera_aif_dbg(_dai, fmt, ...) \
155 dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
156
157 static const int madera_dsp_bus_error_irqs[MADERA_MAX_ADSP] = {
158 MADERA_IRQ_DSP1_BUS_ERR,
159 MADERA_IRQ_DSP2_BUS_ERR,
160 MADERA_IRQ_DSP3_BUS_ERR,
161 MADERA_IRQ_DSP4_BUS_ERR,
162 MADERA_IRQ_DSP5_BUS_ERR,
163 MADERA_IRQ_DSP6_BUS_ERR,
164 MADERA_IRQ_DSP7_BUS_ERR,
165 };
166
madera_clk_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)167 int madera_clk_ev(struct snd_soc_dapm_widget *w,
168 struct snd_kcontrol *kcontrol, int event)
169 {
170 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
171 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
172 struct madera *madera = priv->madera;
173 unsigned int val;
174 int clk_idx;
175 int ret;
176
177 ret = regmap_read(madera->regmap, w->reg, &val);
178 if (ret) {
179 dev_err(madera->dev, "Failed to check clock source: %d\n", ret);
180 return ret;
181 }
182
183 switch ((val & MADERA_SYSCLK_SRC_MASK) >> MADERA_SYSCLK_SRC_SHIFT) {
184 case MADERA_CLK_SRC_MCLK1:
185 clk_idx = MADERA_MCLK1;
186 break;
187 case MADERA_CLK_SRC_MCLK2:
188 clk_idx = MADERA_MCLK2;
189 break;
190 case MADERA_CLK_SRC_MCLK3:
191 clk_idx = MADERA_MCLK3;
192 break;
193 default:
194 return 0;
195 }
196
197 switch (event) {
198 case SND_SOC_DAPM_PRE_PMU:
199 return clk_prepare_enable(madera->mclk[clk_idx].clk);
200 case SND_SOC_DAPM_POST_PMD:
201 clk_disable_unprepare(madera->mclk[clk_idx].clk);
202 return 0;
203 default:
204 return 0;
205 }
206 }
207 EXPORT_SYMBOL_GPL(madera_clk_ev);
208
madera_spin_sysclk(struct madera_priv * priv)209 static void madera_spin_sysclk(struct madera_priv *priv)
210 {
211 struct madera *madera = priv->madera;
212 unsigned int val;
213 int ret, i;
214
215 /* Skip this if the chip is down */
216 if (pm_runtime_suspended(madera->dev))
217 return;
218
219 /*
220 * Just read a register a few times to ensure the internal
221 * oscillator sends out a few clocks.
222 */
223 for (i = 0; i < 4; i++) {
224 ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &val);
225 if (ret)
226 dev_err(madera->dev,
227 "Failed to read sysclk spin %d: %d\n", i, ret);
228 }
229
230 udelay(300);
231 }
232
madera_sysclk_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)233 int madera_sysclk_ev(struct snd_soc_dapm_widget *w,
234 struct snd_kcontrol *kcontrol, int event)
235 {
236 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
237 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
238
239 switch (event) {
240 case SND_SOC_DAPM_POST_PMU:
241 case SND_SOC_DAPM_PRE_PMD:
242 madera_spin_sysclk(priv);
243 break;
244 default:
245 break;
246 }
247
248 return madera_clk_ev(w, kcontrol, event);
249 }
250 EXPORT_SYMBOL_GPL(madera_sysclk_ev);
251
madera_check_speaker_overheat(struct madera * madera,bool * warn,bool * shutdown)252 static int madera_check_speaker_overheat(struct madera *madera,
253 bool *warn, bool *shutdown)
254 {
255 unsigned int val;
256 int ret;
257
258 ret = regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_15, &val);
259 if (ret) {
260 dev_err(madera->dev, "Failed to read thermal status: %d\n",
261 ret);
262 return ret;
263 }
264
265 *warn = val & MADERA_SPK_OVERHEAT_WARN_STS1;
266 *shutdown = val & MADERA_SPK_OVERHEAT_STS1;
267
268 return 0;
269 }
270
madera_spk_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)271 int madera_spk_ev(struct snd_soc_dapm_widget *w,
272 struct snd_kcontrol *kcontrol, int event)
273 {
274 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
275 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
276 struct madera *madera = priv->madera;
277 bool warn, shutdown;
278 int ret;
279
280 switch (event) {
281 case SND_SOC_DAPM_POST_PMU:
282 ret = madera_check_speaker_overheat(madera, &warn, &shutdown);
283 if (ret)
284 return ret;
285
286 if (shutdown) {
287 dev_crit(madera->dev,
288 "Speaker not enabled due to temperature\n");
289 return -EBUSY;
290 }
291
292 regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
293 1 << w->shift, 1 << w->shift);
294 break;
295 case SND_SOC_DAPM_PRE_PMD:
296 regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
297 1 << w->shift, 0);
298 break;
299 default:
300 break;
301 }
302
303 return 0;
304 }
305 EXPORT_SYMBOL_GPL(madera_spk_ev);
306
madera_thermal_warn(int irq,void * data)307 static irqreturn_t madera_thermal_warn(int irq, void *data)
308 {
309 struct madera *madera = data;
310 bool warn, shutdown;
311 int ret;
312
313 ret = madera_check_speaker_overheat(madera, &warn, &shutdown);
314 if (ret || shutdown) { /* for safety attempt to shutdown on error */
315 dev_crit(madera->dev, "Thermal shutdown\n");
316 ret = regmap_update_bits(madera->regmap,
317 MADERA_OUTPUT_ENABLES_1,
318 MADERA_OUT4L_ENA |
319 MADERA_OUT4R_ENA, 0);
320 if (ret != 0)
321 dev_crit(madera->dev,
322 "Failed to disable speaker outputs: %d\n",
323 ret);
324 } else if (warn) {
325 dev_alert(madera->dev, "Thermal warning\n");
326 } else {
327 dev_info(madera->dev, "Spurious thermal warning\n");
328 return IRQ_NONE;
329 }
330
331 return IRQ_HANDLED;
332 }
333
madera_init_overheat(struct madera_priv * priv)334 int madera_init_overheat(struct madera_priv *priv)
335 {
336 struct madera *madera = priv->madera;
337 struct device *dev = madera->dev;
338 int ret;
339
340 ret = madera_request_irq(madera, MADERA_IRQ_SPK_OVERHEAT_WARN,
341 "Thermal warning", madera_thermal_warn,
342 madera);
343 if (ret)
344 dev_err(dev, "Failed to get thermal warning IRQ: %d\n", ret);
345
346 ret = madera_request_irq(madera, MADERA_IRQ_SPK_OVERHEAT,
347 "Thermal shutdown", madera_thermal_warn,
348 madera);
349 if (ret)
350 dev_err(dev, "Failed to get thermal shutdown IRQ: %d\n", ret);
351
352 return 0;
353 }
354 EXPORT_SYMBOL_GPL(madera_init_overheat);
355
madera_free_overheat(struct madera_priv * priv)356 int madera_free_overheat(struct madera_priv *priv)
357 {
358 struct madera *madera = priv->madera;
359
360 madera_free_irq(madera, MADERA_IRQ_SPK_OVERHEAT_WARN, madera);
361 madera_free_irq(madera, MADERA_IRQ_SPK_OVERHEAT, madera);
362
363 return 0;
364 }
365 EXPORT_SYMBOL_GPL(madera_free_overheat);
366
madera_get_variable_u32_array(struct device * dev,const char * propname,u32 * dest,int n_max,int multiple)367 static int madera_get_variable_u32_array(struct device *dev,
368 const char *propname,
369 u32 *dest, int n_max,
370 int multiple)
371 {
372 int n, ret;
373
374 n = device_property_count_u32(dev, propname);
375 if (n < 0) {
376 if (n == -EINVAL)
377 return 0; /* missing, ignore */
378
379 dev_warn(dev, "%s malformed (%d)\n", propname, n);
380
381 return n;
382 } else if ((n % multiple) != 0) {
383 dev_warn(dev, "%s not a multiple of %d entries\n",
384 propname, multiple);
385
386 return -EINVAL;
387 }
388
389 if (n > n_max)
390 n = n_max;
391
392 ret = device_property_read_u32_array(dev, propname, dest, n);
393 if (ret < 0)
394 return ret;
395
396 return n;
397 }
398
madera_prop_get_inmode(struct madera_priv * priv)399 static void madera_prop_get_inmode(struct madera_priv *priv)
400 {
401 struct madera *madera = priv->madera;
402 struct madera_codec_pdata *pdata = &madera->pdata.codec;
403 u32 tmp[MADERA_MAX_INPUT * MADERA_MAX_MUXED_CHANNELS];
404 int n, i, in_idx, ch_idx;
405
406 BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode) != MADERA_MAX_INPUT);
407 BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode[0]) != MADERA_MAX_MUXED_CHANNELS);
408
409 n = madera_get_variable_u32_array(madera->dev, "cirrus,inmode",
410 tmp, ARRAY_SIZE(tmp),
411 MADERA_MAX_MUXED_CHANNELS);
412 if (n < 0)
413 return;
414
415 in_idx = 0;
416 ch_idx = 0;
417 for (i = 0; i < n; ++i) {
418 pdata->inmode[in_idx][ch_idx] = tmp[i];
419
420 if (++ch_idx == MADERA_MAX_MUXED_CHANNELS) {
421 ch_idx = 0;
422 ++in_idx;
423 }
424 }
425 }
426
madera_prop_get_pdata(struct madera_priv * priv)427 static void madera_prop_get_pdata(struct madera_priv *priv)
428 {
429 struct madera *madera = priv->madera;
430 struct madera_codec_pdata *pdata = &madera->pdata.codec;
431 u32 out_mono[ARRAY_SIZE(pdata->out_mono)];
432 int i, n;
433
434 madera_prop_get_inmode(priv);
435
436 n = madera_get_variable_u32_array(madera->dev, "cirrus,out-mono",
437 out_mono, ARRAY_SIZE(out_mono), 1);
438 if (n > 0)
439 for (i = 0; i < n; ++i)
440 pdata->out_mono[i] = !!out_mono[i];
441
442 madera_get_variable_u32_array(madera->dev,
443 "cirrus,max-channels-clocked",
444 pdata->max_channels_clocked,
445 ARRAY_SIZE(pdata->max_channels_clocked),
446 1);
447
448 madera_get_variable_u32_array(madera->dev, "cirrus,pdm-fmt",
449 pdata->pdm_fmt,
450 ARRAY_SIZE(pdata->pdm_fmt), 1);
451
452 madera_get_variable_u32_array(madera->dev, "cirrus,pdm-mute",
453 pdata->pdm_mute,
454 ARRAY_SIZE(pdata->pdm_mute), 1);
455
456 madera_get_variable_u32_array(madera->dev, "cirrus,dmic-ref",
457 pdata->dmic_ref,
458 ARRAY_SIZE(pdata->dmic_ref), 1);
459 }
460
madera_core_init(struct madera_priv * priv)461 int madera_core_init(struct madera_priv *priv)
462 {
463 int i;
464
465 /* trap undersized array initializers */
466 BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]);
467 BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]);
468
469 if (!dev_get_platdata(priv->madera->dev))
470 madera_prop_get_pdata(priv);
471
472 mutex_init(&priv->rate_lock);
473
474 for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++)
475 priv->madera->out_clamp[i] = true;
476
477 return 0;
478 }
479 EXPORT_SYMBOL_GPL(madera_core_init);
480
madera_core_free(struct madera_priv * priv)481 int madera_core_free(struct madera_priv *priv)
482 {
483 mutex_destroy(&priv->rate_lock);
484
485 return 0;
486 }
487 EXPORT_SYMBOL_GPL(madera_core_free);
488
madera_debug_dump_domain_groups(const struct madera_priv * priv)489 static void madera_debug_dump_domain_groups(const struct madera_priv *priv)
490 {
491 struct madera *madera = priv->madera;
492 int i;
493
494 for (i = 0; i < ARRAY_SIZE(priv->domain_group_ref); ++i)
495 dev_dbg(madera->dev, "domain_grp_ref[%d]=%d\n", i,
496 priv->domain_group_ref[i]);
497 }
498
madera_domain_clk_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)499 int madera_domain_clk_ev(struct snd_soc_dapm_widget *w,
500 struct snd_kcontrol *kcontrol,
501 int event)
502 {
503 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
504 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
505 int dom_grp = w->shift;
506
507 if (dom_grp >= ARRAY_SIZE(priv->domain_group_ref)) {
508 WARN(true, "%s dom_grp exceeds array size\n", __func__);
509 return -EINVAL;
510 }
511
512 /*
513 * We can't rely on the DAPM mutex for locking because we need a lock
514 * that can safely be called in hw_params
515 */
516 mutex_lock(&priv->rate_lock);
517
518 switch (event) {
519 case SND_SOC_DAPM_PRE_PMU:
520 dev_dbg(priv->madera->dev, "Inc ref on domain group %d\n",
521 dom_grp);
522 ++priv->domain_group_ref[dom_grp];
523 break;
524 case SND_SOC_DAPM_POST_PMD:
525 dev_dbg(priv->madera->dev, "Dec ref on domain group %d\n",
526 dom_grp);
527 --priv->domain_group_ref[dom_grp];
528 break;
529 default:
530 break;
531 }
532
533 madera_debug_dump_domain_groups(priv);
534
535 mutex_unlock(&priv->rate_lock);
536
537 return 0;
538 }
539 EXPORT_SYMBOL_GPL(madera_domain_clk_ev);
540
madera_out1_demux_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)541 int madera_out1_demux_put(struct snd_kcontrol *kcontrol,
542 struct snd_ctl_elem_value *ucontrol)
543 {
544 struct snd_soc_component *component =
545 snd_soc_dapm_kcontrol_component(kcontrol);
546 struct snd_soc_dapm_context *dapm =
547 snd_soc_dapm_kcontrol_dapm(kcontrol);
548 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
549 struct madera *madera = priv->madera;
550 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
551 unsigned int ep_sel, mux, change;
552 bool out_mono;
553 int ret;
554
555 if (ucontrol->value.enumerated.item[0] > e->items - 1)
556 return -EINVAL;
557
558 mux = ucontrol->value.enumerated.item[0];
559
560 snd_soc_dapm_mutex_lock(dapm);
561
562 ep_sel = mux << MADERA_EP_SEL_SHIFT;
563
564 change = snd_soc_component_test_bits(component, MADERA_OUTPUT_ENABLES_1,
565 MADERA_EP_SEL_MASK,
566 ep_sel);
567 if (!change)
568 goto end;
569
570 /* EP_SEL should not be modified while HP or EP driver is enabled */
571 ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
572 MADERA_OUT1L_ENA | MADERA_OUT1R_ENA, 0);
573 if (ret)
574 dev_warn(madera->dev, "Failed to disable outputs: %d\n", ret);
575
576 usleep_range(2000, 3000); /* wait for wseq to complete */
577
578 /* change demux setting */
579 ret = 0;
580 if (madera->out_clamp[0])
581 ret = regmap_update_bits(madera->regmap,
582 MADERA_OUTPUT_ENABLES_1,
583 MADERA_EP_SEL_MASK, ep_sel);
584 if (ret) {
585 dev_err(madera->dev, "Failed to set OUT1 demux: %d\n", ret);
586 } else {
587 /* apply correct setting for mono mode */
588 if (!ep_sel && !madera->pdata.codec.out_mono[0])
589 out_mono = false; /* stereo HP */
590 else
591 out_mono = true; /* EP or mono HP */
592
593 ret = madera_set_output_mode(component, 1, out_mono);
594 if (ret)
595 dev_warn(madera->dev,
596 "Failed to set output mode: %d\n", ret);
597 }
598
599 /*
600 * if HPDET has disabled the clamp while switching to HPOUT
601 * OUT1 should remain disabled
602 */
603 if (ep_sel ||
604 (madera->out_clamp[0] && !madera->out_shorted[0])) {
605 ret = regmap_update_bits(madera->regmap,
606 MADERA_OUTPUT_ENABLES_1,
607 MADERA_OUT1L_ENA | MADERA_OUT1R_ENA,
608 madera->hp_ena);
609 if (ret)
610 dev_warn(madera->dev,
611 "Failed to restore earpiece outputs: %d\n",
612 ret);
613 else if (madera->hp_ena)
614 msleep(34); /* wait for enable wseq */
615 else
616 usleep_range(2000, 3000); /* wait for disable wseq */
617 }
618
619 end:
620 snd_soc_dapm_mutex_unlock(dapm);
621
622 ret = snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
623 if (ret < 0) {
624 dev_err(madera->dev, "Failed to update demux power state: %d\n", ret);
625 return ret;
626 }
627
628 return change;
629 }
630 EXPORT_SYMBOL_GPL(madera_out1_demux_put);
631
madera_out1_demux_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)632 int madera_out1_demux_get(struct snd_kcontrol *kcontrol,
633 struct snd_ctl_elem_value *ucontrol)
634 {
635 struct snd_soc_component *component =
636 snd_soc_dapm_kcontrol_component(kcontrol);
637 unsigned int val;
638
639 val = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1);
640 val &= MADERA_EP_SEL_MASK;
641 val >>= MADERA_EP_SEL_SHIFT;
642 ucontrol->value.enumerated.item[0] = val;
643
644 return 0;
645 }
646 EXPORT_SYMBOL_GPL(madera_out1_demux_get);
647
madera_inmux_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)648 static int madera_inmux_put(struct snd_kcontrol *kcontrol,
649 struct snd_ctl_elem_value *ucontrol)
650 {
651 struct snd_soc_component *component =
652 snd_soc_dapm_kcontrol_component(kcontrol);
653 struct snd_soc_dapm_context *dapm =
654 snd_soc_dapm_kcontrol_dapm(kcontrol);
655 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
656 struct madera *madera = priv->madera;
657 struct regmap *regmap = madera->regmap;
658 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
659 unsigned int mux, val, mask;
660 unsigned int inmode;
661 bool changed;
662 int ret;
663
664 mux = ucontrol->value.enumerated.item[0];
665 if (mux > 1)
666 return -EINVAL;
667
668 val = mux << e->shift_l;
669 mask = (e->mask << e->shift_l) | MADERA_IN1L_SRC_SE_MASK;
670
671 switch (e->reg) {
672 case MADERA_ADC_DIGITAL_VOLUME_1L:
673 inmode = madera->pdata.codec.inmode[0][2 * mux];
674 break;
675 case MADERA_ADC_DIGITAL_VOLUME_1R:
676 inmode = madera->pdata.codec.inmode[0][1 + (2 * mux)];
677 break;
678 case MADERA_ADC_DIGITAL_VOLUME_2L:
679 inmode = madera->pdata.codec.inmode[1][2 * mux];
680 break;
681 case MADERA_ADC_DIGITAL_VOLUME_2R:
682 inmode = madera->pdata.codec.inmode[1][1 + (2 * mux)];
683 break;
684 default:
685 return -EINVAL;
686 }
687
688 if (inmode & MADERA_INMODE_SE)
689 val |= 1 << MADERA_IN1L_SRC_SE_SHIFT;
690
691 dev_dbg(madera->dev, "mux=%u reg=0x%x inmode=0x%x mask=0x%x val=0x%x\n",
692 mux, e->reg, inmode, mask, val);
693
694 ret = regmap_update_bits_check(regmap, e->reg, mask, val, &changed);
695 if (ret < 0)
696 return ret;
697
698 if (changed)
699 return snd_soc_dapm_mux_update_power(dapm, kcontrol,
700 mux, e, NULL);
701 else
702 return 0;
703 }
704
705 static const char * const madera_inmux_texts[] = {
706 "A",
707 "B",
708 };
709
710 static SOC_ENUM_SINGLE_DECL(madera_in1muxl_enum,
711 MADERA_ADC_DIGITAL_VOLUME_1L,
712 MADERA_IN1L_SRC_SHIFT,
713 madera_inmux_texts);
714
715 static SOC_ENUM_SINGLE_DECL(madera_in1muxr_enum,
716 MADERA_ADC_DIGITAL_VOLUME_1R,
717 MADERA_IN1R_SRC_SHIFT,
718 madera_inmux_texts);
719
720 static SOC_ENUM_SINGLE_DECL(madera_in2muxl_enum,
721 MADERA_ADC_DIGITAL_VOLUME_2L,
722 MADERA_IN2L_SRC_SHIFT,
723 madera_inmux_texts);
724
725 static SOC_ENUM_SINGLE_DECL(madera_in2muxr_enum,
726 MADERA_ADC_DIGITAL_VOLUME_2R,
727 MADERA_IN2R_SRC_SHIFT,
728 madera_inmux_texts);
729
730 const struct snd_kcontrol_new madera_inmux[] = {
731 SOC_DAPM_ENUM_EXT("IN1L Mux", madera_in1muxl_enum,
732 snd_soc_dapm_get_enum_double, madera_inmux_put),
733 SOC_DAPM_ENUM_EXT("IN1R Mux", madera_in1muxr_enum,
734 snd_soc_dapm_get_enum_double, madera_inmux_put),
735 SOC_DAPM_ENUM_EXT("IN2L Mux", madera_in2muxl_enum,
736 snd_soc_dapm_get_enum_double, madera_inmux_put),
737 SOC_DAPM_ENUM_EXT("IN2R Mux", madera_in2muxr_enum,
738 snd_soc_dapm_get_enum_double, madera_inmux_put),
739 };
740 EXPORT_SYMBOL_GPL(madera_inmux);
741
742 static const char * const madera_dmode_texts[] = {
743 "Analog",
744 "Digital",
745 };
746
747 static SOC_ENUM_SINGLE_DECL(madera_in1dmode_enum,
748 MADERA_IN1L_CONTROL,
749 MADERA_IN1_MODE_SHIFT,
750 madera_dmode_texts);
751
752 static SOC_ENUM_SINGLE_DECL(madera_in2dmode_enum,
753 MADERA_IN2L_CONTROL,
754 MADERA_IN2_MODE_SHIFT,
755 madera_dmode_texts);
756
757 static SOC_ENUM_SINGLE_DECL(madera_in3dmode_enum,
758 MADERA_IN3L_CONTROL,
759 MADERA_IN3_MODE_SHIFT,
760 madera_dmode_texts);
761
762 const struct snd_kcontrol_new madera_inmode[] = {
763 SOC_DAPM_ENUM("IN1 Mode", madera_in1dmode_enum),
764 SOC_DAPM_ENUM("IN2 Mode", madera_in2dmode_enum),
765 SOC_DAPM_ENUM("IN3 Mode", madera_in3dmode_enum),
766 };
767 EXPORT_SYMBOL_GPL(madera_inmode);
768
madera_can_change_grp_rate(const struct madera_priv * priv,unsigned int reg)769 static bool madera_can_change_grp_rate(const struct madera_priv *priv,
770 unsigned int reg)
771 {
772 int count;
773
774 switch (reg) {
775 case MADERA_FX_CTRL1:
776 count = priv->domain_group_ref[MADERA_DOM_GRP_FX];
777 break;
778 case MADERA_ASRC1_RATE1:
779 case MADERA_ASRC1_RATE2:
780 count = priv->domain_group_ref[MADERA_DOM_GRP_ASRC1];
781 break;
782 case MADERA_ASRC2_RATE1:
783 case MADERA_ASRC2_RATE2:
784 count = priv->domain_group_ref[MADERA_DOM_GRP_ASRC2];
785 break;
786 case MADERA_ISRC_1_CTRL_1:
787 case MADERA_ISRC_1_CTRL_2:
788 count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC1];
789 break;
790 case MADERA_ISRC_2_CTRL_1:
791 case MADERA_ISRC_2_CTRL_2:
792 count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC2];
793 break;
794 case MADERA_ISRC_3_CTRL_1:
795 case MADERA_ISRC_3_CTRL_2:
796 count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC3];
797 break;
798 case MADERA_ISRC_4_CTRL_1:
799 case MADERA_ISRC_4_CTRL_2:
800 count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC4];
801 break;
802 case MADERA_OUTPUT_RATE_1:
803 count = priv->domain_group_ref[MADERA_DOM_GRP_OUT];
804 break;
805 case MADERA_SPD1_TX_CONTROL:
806 count = priv->domain_group_ref[MADERA_DOM_GRP_SPD];
807 break;
808 case MADERA_DSP1_CONFIG_1:
809 case MADERA_DSP1_CONFIG_2:
810 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP1];
811 break;
812 case MADERA_DSP2_CONFIG_1:
813 case MADERA_DSP2_CONFIG_2:
814 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP2];
815 break;
816 case MADERA_DSP3_CONFIG_1:
817 case MADERA_DSP3_CONFIG_2:
818 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP3];
819 break;
820 case MADERA_DSP4_CONFIG_1:
821 case MADERA_DSP4_CONFIG_2:
822 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP4];
823 break;
824 case MADERA_DSP5_CONFIG_1:
825 case MADERA_DSP5_CONFIG_2:
826 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP5];
827 break;
828 case MADERA_DSP6_CONFIG_1:
829 case MADERA_DSP6_CONFIG_2:
830 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP6];
831 break;
832 case MADERA_DSP7_CONFIG_1:
833 case MADERA_DSP7_CONFIG_2:
834 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP7];
835 break;
836 case MADERA_AIF1_RATE_CTRL:
837 count = priv->domain_group_ref[MADERA_DOM_GRP_AIF1];
838 break;
839 case MADERA_AIF2_RATE_CTRL:
840 count = priv->domain_group_ref[MADERA_DOM_GRP_AIF2];
841 break;
842 case MADERA_AIF3_RATE_CTRL:
843 count = priv->domain_group_ref[MADERA_DOM_GRP_AIF3];
844 break;
845 case MADERA_AIF4_RATE_CTRL:
846 count = priv->domain_group_ref[MADERA_DOM_GRP_AIF4];
847 break;
848 case MADERA_SLIMBUS_RATES_1:
849 case MADERA_SLIMBUS_RATES_2:
850 case MADERA_SLIMBUS_RATES_3:
851 case MADERA_SLIMBUS_RATES_4:
852 case MADERA_SLIMBUS_RATES_5:
853 case MADERA_SLIMBUS_RATES_6:
854 case MADERA_SLIMBUS_RATES_7:
855 case MADERA_SLIMBUS_RATES_8:
856 count = priv->domain_group_ref[MADERA_DOM_GRP_SLIMBUS];
857 break;
858 case MADERA_PWM_DRIVE_1:
859 count = priv->domain_group_ref[MADERA_DOM_GRP_PWM];
860 break;
861 default:
862 return false;
863 }
864
865 dev_dbg(priv->madera->dev, "Rate reg 0x%x group ref %d\n", reg, count);
866
867 if (count)
868 return false;
869 else
870 return true;
871 }
872
madera_adsp_rate_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)873 static int madera_adsp_rate_get(struct snd_kcontrol *kcontrol,
874 struct snd_ctl_elem_value *ucontrol)
875 {
876 struct snd_soc_component *component =
877 snd_soc_kcontrol_component(kcontrol);
878 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
879 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
880 unsigned int cached_rate;
881 const int adsp_num = e->shift_l;
882 int item;
883
884 mutex_lock(&priv->rate_lock);
885 cached_rate = priv->adsp_rate_cache[adsp_num];
886 mutex_unlock(&priv->rate_lock);
887
888 item = snd_soc_enum_val_to_item(e, cached_rate);
889 ucontrol->value.enumerated.item[0] = item;
890
891 return 0;
892 }
893
madera_adsp_rate_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)894 static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol,
895 struct snd_ctl_elem_value *ucontrol)
896 {
897 struct snd_soc_component *component =
898 snd_soc_kcontrol_component(kcontrol);
899 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
900 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
901 const int adsp_num = e->shift_l;
902 const unsigned int item = ucontrol->value.enumerated.item[0];
903 int ret = 0;
904
905 if (item >= e->items)
906 return -EINVAL;
907
908 /*
909 * We don't directly write the rate register here but we want to
910 * maintain consistent behaviour that rate domains cannot be changed
911 * while in use since this is a hardware requirement
912 */
913 mutex_lock(&priv->rate_lock);
914
915 if (!madera_can_change_grp_rate(priv, priv->adsp[adsp_num].cs_dsp.base)) {
916 dev_warn(priv->madera->dev,
917 "Cannot change '%s' while in use by active audio paths\n",
918 kcontrol->id.name);
919 ret = -EBUSY;
920 } else if (priv->adsp_rate_cache[adsp_num] != e->values[item]) {
921 /* Volatile register so defer until the codec is powered up */
922 priv->adsp_rate_cache[adsp_num] = e->values[item];
923 ret = 1;
924 }
925
926 mutex_unlock(&priv->rate_lock);
927
928 return ret;
929 }
930
931 static const struct soc_enum madera_adsp_rate_enum[] = {
932 SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 0xf, MADERA_RATE_ENUM_SIZE,
933 madera_rate_text, madera_rate_val),
934 SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 1, 0xf, MADERA_RATE_ENUM_SIZE,
935 madera_rate_text, madera_rate_val),
936 SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 2, 0xf, MADERA_RATE_ENUM_SIZE,
937 madera_rate_text, madera_rate_val),
938 SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 3, 0xf, MADERA_RATE_ENUM_SIZE,
939 madera_rate_text, madera_rate_val),
940 SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 4, 0xf, MADERA_RATE_ENUM_SIZE,
941 madera_rate_text, madera_rate_val),
942 SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 5, 0xf, MADERA_RATE_ENUM_SIZE,
943 madera_rate_text, madera_rate_val),
944 SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 6, 0xf, MADERA_RATE_ENUM_SIZE,
945 madera_rate_text, madera_rate_val),
946 };
947
948 const struct snd_kcontrol_new madera_adsp_rate_controls[] = {
949 SOC_ENUM_EXT("DSP1 Rate", madera_adsp_rate_enum[0],
950 madera_adsp_rate_get, madera_adsp_rate_put),
951 SOC_ENUM_EXT("DSP2 Rate", madera_adsp_rate_enum[1],
952 madera_adsp_rate_get, madera_adsp_rate_put),
953 SOC_ENUM_EXT("DSP3 Rate", madera_adsp_rate_enum[2],
954 madera_adsp_rate_get, madera_adsp_rate_put),
955 SOC_ENUM_EXT("DSP4 Rate", madera_adsp_rate_enum[3],
956 madera_adsp_rate_get, madera_adsp_rate_put),
957 SOC_ENUM_EXT("DSP5 Rate", madera_adsp_rate_enum[4],
958 madera_adsp_rate_get, madera_adsp_rate_put),
959 SOC_ENUM_EXT("DSP6 Rate", madera_adsp_rate_enum[5],
960 madera_adsp_rate_get, madera_adsp_rate_put),
961 SOC_ENUM_EXT("DSP7 Rate", madera_adsp_rate_enum[6],
962 madera_adsp_rate_get, madera_adsp_rate_put),
963 };
964 EXPORT_SYMBOL_GPL(madera_adsp_rate_controls);
965
madera_write_adsp_clk_setting(struct madera_priv * priv,struct wm_adsp * dsp,unsigned int freq)966 static int madera_write_adsp_clk_setting(struct madera_priv *priv,
967 struct wm_adsp *dsp,
968 unsigned int freq)
969 {
970 unsigned int val;
971 unsigned int mask = MADERA_DSP_RATE_MASK;
972 int ret;
973
974 val = priv->adsp_rate_cache[dsp->cs_dsp.num - 1] << MADERA_DSP_RATE_SHIFT;
975
976 switch (priv->madera->type) {
977 case CS47L35:
978 case CS47L85:
979 case WM1840:
980 /* use legacy frequency registers */
981 mask |= MADERA_DSP_CLK_SEL_MASK;
982 val |= (freq << MADERA_DSP_CLK_SEL_SHIFT);
983 break;
984 default:
985 /* Configure exact dsp frequency */
986 dev_dbg(priv->madera->dev, "Set DSP frequency to 0x%x\n", freq);
987
988 ret = regmap_write(dsp->cs_dsp.regmap,
989 dsp->cs_dsp.base + MADERA_DSP_CONFIG_2_OFFS, freq);
990 if (ret)
991 goto err;
992 break;
993 }
994
995 ret = regmap_update_bits(dsp->cs_dsp.regmap,
996 dsp->cs_dsp.base + MADERA_DSP_CONFIG_1_OFFS,
997 mask, val);
998 if (ret)
999 goto err;
1000
1001 dev_dbg(priv->madera->dev, "Set DSP clocking to 0x%x\n", val);
1002
1003 return 0;
1004
1005 err:
1006 dev_err(dsp->cs_dsp.dev, "Failed to set DSP%d clock: %d\n", dsp->cs_dsp.num, ret);
1007
1008 return ret;
1009 }
1010
madera_set_adsp_clk(struct madera_priv * priv,int dsp_num,unsigned int freq)1011 int madera_set_adsp_clk(struct madera_priv *priv, int dsp_num,
1012 unsigned int freq)
1013 {
1014 struct wm_adsp *dsp = &priv->adsp[dsp_num];
1015 struct madera *madera = priv->madera;
1016 unsigned int cur, new;
1017 int ret;
1018
1019 /*
1020 * This is called at a higher DAPM priority than the mux widgets so
1021 * the muxes are still off at this point and it's safe to change
1022 * the rate domain control.
1023 * Also called at a lower DAPM priority than the domain group widgets
1024 * so locking the reads of adsp_rate_cache is not necessary as we know
1025 * changes are locked out by the domain_group_ref reference count.
1026 */
1027
1028 ret = regmap_read(dsp->cs_dsp.regmap, dsp->cs_dsp.base, &cur);
1029 if (ret) {
1030 dev_err(madera->dev,
1031 "Failed to read current DSP rate: %d\n", ret);
1032 return ret;
1033 }
1034
1035 cur &= MADERA_DSP_RATE_MASK;
1036
1037 new = priv->adsp_rate_cache[dsp->cs_dsp.num - 1] << MADERA_DSP_RATE_SHIFT;
1038
1039 if (new == cur) {
1040 dev_dbg(madera->dev, "DSP rate not changed\n");
1041 return madera_write_adsp_clk_setting(priv, dsp, freq);
1042 } else {
1043 dev_dbg(madera->dev, "DSP rate changed\n");
1044
1045 /* The write must be guarded by a number of SYSCLK cycles */
1046 madera_spin_sysclk(priv);
1047 ret = madera_write_adsp_clk_setting(priv, dsp, freq);
1048 madera_spin_sysclk(priv);
1049 return ret;
1050 }
1051 }
1052 EXPORT_SYMBOL_GPL(madera_set_adsp_clk);
1053
madera_rate_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1054 int madera_rate_put(struct snd_kcontrol *kcontrol,
1055 struct snd_ctl_elem_value *ucontrol)
1056 {
1057 struct snd_soc_component *component =
1058 snd_soc_kcontrol_component(kcontrol);
1059 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
1060 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1061 unsigned int item = ucontrol->value.enumerated.item[0];
1062 unsigned int val;
1063 int ret;
1064
1065 if (item >= e->items)
1066 return -EINVAL;
1067
1068 /*
1069 * Prevent the domain powering up while we're checking whether it's
1070 * safe to change rate domain
1071 */
1072 mutex_lock(&priv->rate_lock);
1073
1074 val = snd_soc_component_read(component, e->reg);
1075 val >>= e->shift_l;
1076 val &= e->mask;
1077 if (snd_soc_enum_item_to_val(e, item) == val) {
1078 ret = 0;
1079 goto out;
1080 }
1081
1082 if (!madera_can_change_grp_rate(priv, e->reg)) {
1083 dev_warn(priv->madera->dev,
1084 "Cannot change '%s' while in use by active audio paths\n",
1085 kcontrol->id.name);
1086 ret = -EBUSY;
1087 } else {
1088 /* The write must be guarded by a number of SYSCLK cycles */
1089 madera_spin_sysclk(priv);
1090 ret = snd_soc_put_enum_double(kcontrol, ucontrol);
1091 madera_spin_sysclk(priv);
1092 }
1093 out:
1094 mutex_unlock(&priv->rate_lock);
1095
1096 return ret;
1097 }
1098 EXPORT_SYMBOL_GPL(madera_rate_put);
1099
madera_configure_input_mode(struct madera * madera)1100 static void madera_configure_input_mode(struct madera *madera)
1101 {
1102 unsigned int dig_mode, ana_mode_l, ana_mode_r;
1103 int max_analogue_inputs, max_dmic_sup, i;
1104
1105 switch (madera->type) {
1106 case CS47L15:
1107 max_analogue_inputs = 1;
1108 max_dmic_sup = 2;
1109 break;
1110 case CS47L35:
1111 max_analogue_inputs = 2;
1112 max_dmic_sup = 2;
1113 break;
1114 case CS47L85:
1115 case WM1840:
1116 max_analogue_inputs = 3;
1117 max_dmic_sup = 3;
1118 break;
1119 case CS47L90:
1120 case CS47L91:
1121 max_analogue_inputs = 2;
1122 max_dmic_sup = 2;
1123 break;
1124 default:
1125 max_analogue_inputs = 2;
1126 max_dmic_sup = 4;
1127 break;
1128 }
1129
1130 /*
1131 * Initialize input modes from the A settings. For muxed inputs the
1132 * B settings will be applied if the mux is changed
1133 */
1134 for (i = 0; i < max_dmic_sup; i++) {
1135 dev_dbg(madera->dev, "IN%d mode %u:%u:%u:%u\n", i + 1,
1136 madera->pdata.codec.inmode[i][0],
1137 madera->pdata.codec.inmode[i][1],
1138 madera->pdata.codec.inmode[i][2],
1139 madera->pdata.codec.inmode[i][3]);
1140
1141 dig_mode = madera->pdata.codec.dmic_ref[i] <<
1142 MADERA_IN1_DMIC_SUP_SHIFT;
1143
1144 switch (madera->pdata.codec.inmode[i][0]) {
1145 case MADERA_INMODE_DIFF:
1146 ana_mode_l = 0;
1147 break;
1148 case MADERA_INMODE_SE:
1149 ana_mode_l = 1 << MADERA_IN1L_SRC_SE_SHIFT;
1150 break;
1151 default:
1152 dev_warn(madera->dev,
1153 "IN%dAL Illegal inmode %u ignored\n",
1154 i + 1, madera->pdata.codec.inmode[i][0]);
1155 continue;
1156 }
1157
1158 switch (madera->pdata.codec.inmode[i][1]) {
1159 case MADERA_INMODE_DIFF:
1160 ana_mode_r = 0;
1161 break;
1162 case MADERA_INMODE_SE:
1163 ana_mode_r = 1 << MADERA_IN1R_SRC_SE_SHIFT;
1164 break;
1165 default:
1166 dev_warn(madera->dev,
1167 "IN%dAR Illegal inmode %u ignored\n",
1168 i + 1, madera->pdata.codec.inmode[i][1]);
1169 continue;
1170 }
1171
1172 dev_dbg(madera->dev,
1173 "IN%dA DMIC mode=0x%x Analogue mode=0x%x,0x%x\n",
1174 i + 1, dig_mode, ana_mode_l, ana_mode_r);
1175
1176 regmap_update_bits(madera->regmap,
1177 MADERA_IN1L_CONTROL + (i * 8),
1178 MADERA_IN1_DMIC_SUP_MASK, dig_mode);
1179
1180 if (i >= max_analogue_inputs)
1181 continue;
1182
1183 regmap_update_bits(madera->regmap,
1184 MADERA_ADC_DIGITAL_VOLUME_1L + (i * 8),
1185 MADERA_IN1L_SRC_SE_MASK, ana_mode_l);
1186
1187 regmap_update_bits(madera->regmap,
1188 MADERA_ADC_DIGITAL_VOLUME_1R + (i * 8),
1189 MADERA_IN1R_SRC_SE_MASK, ana_mode_r);
1190 }
1191 }
1192
madera_init_inputs(struct snd_soc_component * component)1193 int madera_init_inputs(struct snd_soc_component *component)
1194 {
1195 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
1196 struct madera *madera = priv->madera;
1197
1198 madera_configure_input_mode(madera);
1199
1200 return 0;
1201 }
1202 EXPORT_SYMBOL_GPL(madera_init_inputs);
1203
1204 static const struct snd_soc_dapm_route madera_mono_routes[] = {
1205 { "OUT1R", NULL, "OUT1L" },
1206 { "OUT2R", NULL, "OUT2L" },
1207 { "OUT3R", NULL, "OUT3L" },
1208 { "OUT4R", NULL, "OUT4L" },
1209 { "OUT5R", NULL, "OUT5L" },
1210 { "OUT6R", NULL, "OUT6L" },
1211 };
1212
madera_init_outputs(struct snd_soc_component * component,const struct snd_soc_dapm_route * routes,int n_mono_routes,int n_real)1213 int madera_init_outputs(struct snd_soc_component *component,
1214 const struct snd_soc_dapm_route *routes,
1215 int n_mono_routes, int n_real)
1216 {
1217 struct snd_soc_dapm_context *dapm =
1218 snd_soc_component_get_dapm(component);
1219 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
1220 struct madera *madera = priv->madera;
1221 const struct madera_codec_pdata *pdata = &madera->pdata.codec;
1222 unsigned int val;
1223 int i;
1224
1225 if (n_mono_routes > MADERA_MAX_OUTPUT) {
1226 dev_warn(madera->dev,
1227 "Requested %d mono outputs, using maximum allowed %d\n",
1228 n_mono_routes, MADERA_MAX_OUTPUT);
1229 n_mono_routes = MADERA_MAX_OUTPUT;
1230 }
1231
1232 if (!routes)
1233 routes = madera_mono_routes;
1234
1235 for (i = 0; i < n_mono_routes; i++) {
1236 /* Default is 0 so noop with defaults */
1237 if (pdata->out_mono[i]) {
1238 val = MADERA_OUT1_MONO;
1239 snd_soc_dapm_add_routes(dapm, &routes[i], 1);
1240 } else {
1241 val = 0;
1242 }
1243
1244 if (i >= n_real)
1245 continue;
1246
1247 regmap_update_bits(madera->regmap,
1248 MADERA_OUTPUT_PATH_CONFIG_1L + (i * 8),
1249 MADERA_OUT1_MONO, val);
1250
1251 dev_dbg(madera->dev, "OUT%d mono=0x%x\n", i + 1, val);
1252 }
1253
1254 for (i = 0; i < MADERA_MAX_PDM_SPK; i++) {
1255 dev_dbg(madera->dev, "PDM%d fmt=0x%x mute=0x%x\n", i + 1,
1256 pdata->pdm_fmt[i], pdata->pdm_mute[i]);
1257
1258 if (pdata->pdm_mute[i])
1259 regmap_update_bits(madera->regmap,
1260 MADERA_PDM_SPK1_CTRL_1 + (i * 2),
1261 MADERA_SPK1_MUTE_ENDIAN_MASK |
1262 MADERA_SPK1_MUTE_SEQ1_MASK,
1263 pdata->pdm_mute[i]);
1264
1265 if (pdata->pdm_fmt[i])
1266 regmap_update_bits(madera->regmap,
1267 MADERA_PDM_SPK1_CTRL_2 + (i * 2),
1268 MADERA_SPK1_FMT_MASK,
1269 pdata->pdm_fmt[i]);
1270 }
1271
1272 return 0;
1273 }
1274 EXPORT_SYMBOL_GPL(madera_init_outputs);
1275
madera_init_bus_error_irq(struct madera_priv * priv,int dsp_num,irq_handler_t handler)1276 int madera_init_bus_error_irq(struct madera_priv *priv, int dsp_num,
1277 irq_handler_t handler)
1278 {
1279 struct madera *madera = priv->madera;
1280 int ret;
1281
1282 ret = madera_request_irq(madera,
1283 madera_dsp_bus_error_irqs[dsp_num],
1284 "ADSP2 bus error",
1285 handler,
1286 &priv->adsp[dsp_num]);
1287 if (ret)
1288 dev_err(madera->dev,
1289 "Failed to request DSP Lock region IRQ: %d\n", ret);
1290
1291 return ret;
1292 }
1293 EXPORT_SYMBOL_GPL(madera_init_bus_error_irq);
1294
madera_free_bus_error_irq(struct madera_priv * priv,int dsp_num)1295 void madera_free_bus_error_irq(struct madera_priv *priv, int dsp_num)
1296 {
1297 struct madera *madera = priv->madera;
1298
1299 madera_free_irq(madera,
1300 madera_dsp_bus_error_irqs[dsp_num],
1301 &priv->adsp[dsp_num]);
1302 }
1303 EXPORT_SYMBOL_GPL(madera_free_bus_error_irq);
1304
1305 const char * const madera_mixer_texts[] = {
1306 "None",
1307 "Tone Generator 1",
1308 "Tone Generator 2",
1309 "Haptics",
1310 "AEC1",
1311 "AEC2",
1312 "Mic Mute Mixer",
1313 "Noise Generator",
1314 "IN1L",
1315 "IN1R",
1316 "IN2L",
1317 "IN2R",
1318 "IN3L",
1319 "IN3R",
1320 "IN4L",
1321 "IN4R",
1322 "IN5L",
1323 "IN5R",
1324 "IN6L",
1325 "IN6R",
1326 "AIF1RX1",
1327 "AIF1RX2",
1328 "AIF1RX3",
1329 "AIF1RX4",
1330 "AIF1RX5",
1331 "AIF1RX6",
1332 "AIF1RX7",
1333 "AIF1RX8",
1334 "AIF2RX1",
1335 "AIF2RX2",
1336 "AIF2RX3",
1337 "AIF2RX4",
1338 "AIF2RX5",
1339 "AIF2RX6",
1340 "AIF2RX7",
1341 "AIF2RX8",
1342 "AIF3RX1",
1343 "AIF3RX2",
1344 "AIF3RX3",
1345 "AIF3RX4",
1346 "AIF4RX1",
1347 "AIF4RX2",
1348 "SLIMRX1",
1349 "SLIMRX2",
1350 "SLIMRX3",
1351 "SLIMRX4",
1352 "SLIMRX5",
1353 "SLIMRX6",
1354 "SLIMRX7",
1355 "SLIMRX8",
1356 "EQ1",
1357 "EQ2",
1358 "EQ3",
1359 "EQ4",
1360 "DRC1L",
1361 "DRC1R",
1362 "DRC2L",
1363 "DRC2R",
1364 "LHPF1",
1365 "LHPF2",
1366 "LHPF3",
1367 "LHPF4",
1368 "DSP1.1",
1369 "DSP1.2",
1370 "DSP1.3",
1371 "DSP1.4",
1372 "DSP1.5",
1373 "DSP1.6",
1374 "DSP2.1",
1375 "DSP2.2",
1376 "DSP2.3",
1377 "DSP2.4",
1378 "DSP2.5",
1379 "DSP2.6",
1380 "DSP3.1",
1381 "DSP3.2",
1382 "DSP3.3",
1383 "DSP3.4",
1384 "DSP3.5",
1385 "DSP3.6",
1386 "DSP4.1",
1387 "DSP4.2",
1388 "DSP4.3",
1389 "DSP4.4",
1390 "DSP4.5",
1391 "DSP4.6",
1392 "DSP5.1",
1393 "DSP5.2",
1394 "DSP5.3",
1395 "DSP5.4",
1396 "DSP5.5",
1397 "DSP5.6",
1398 "DSP6.1",
1399 "DSP6.2",
1400 "DSP6.3",
1401 "DSP6.4",
1402 "DSP6.5",
1403 "DSP6.6",
1404 "DSP7.1",
1405 "DSP7.2",
1406 "DSP7.3",
1407 "DSP7.4",
1408 "DSP7.5",
1409 "DSP7.6",
1410 "ASRC1IN1L",
1411 "ASRC1IN1R",
1412 "ASRC1IN2L",
1413 "ASRC1IN2R",
1414 "ASRC2IN1L",
1415 "ASRC2IN1R",
1416 "ASRC2IN2L",
1417 "ASRC2IN2R",
1418 "ISRC1INT1",
1419 "ISRC1INT2",
1420 "ISRC1INT3",
1421 "ISRC1INT4",
1422 "ISRC1DEC1",
1423 "ISRC1DEC2",
1424 "ISRC1DEC3",
1425 "ISRC1DEC4",
1426 "ISRC2INT1",
1427 "ISRC2INT2",
1428 "ISRC2INT3",
1429 "ISRC2INT4",
1430 "ISRC2DEC1",
1431 "ISRC2DEC2",
1432 "ISRC2DEC3",
1433 "ISRC2DEC4",
1434 "ISRC3INT1",
1435 "ISRC3INT2",
1436 "ISRC3INT3",
1437 "ISRC3INT4",
1438 "ISRC3DEC1",
1439 "ISRC3DEC2",
1440 "ISRC3DEC3",
1441 "ISRC3DEC4",
1442 "ISRC4INT1",
1443 "ISRC4INT2",
1444 "ISRC4DEC1",
1445 "ISRC4DEC2",
1446 "DFC1",
1447 "DFC2",
1448 "DFC3",
1449 "DFC4",
1450 "DFC5",
1451 "DFC6",
1452 "DFC7",
1453 "DFC8",
1454 };
1455 EXPORT_SYMBOL_GPL(madera_mixer_texts);
1456
1457 const unsigned int madera_mixer_values[] = {
1458 0x00, /* None */
1459 0x04, /* Tone Generator 1 */
1460 0x05, /* Tone Generator 2 */
1461 0x06, /* Haptics */
1462 0x08, /* AEC */
1463 0x09, /* AEC2 */
1464 0x0c, /* Noise mixer */
1465 0x0d, /* Comfort noise */
1466 0x10, /* IN1L */
1467 0x11,
1468 0x12,
1469 0x13,
1470 0x14,
1471 0x15,
1472 0x16,
1473 0x17,
1474 0x18,
1475 0x19,
1476 0x1A,
1477 0x1B,
1478 0x20, /* AIF1RX1 */
1479 0x21,
1480 0x22,
1481 0x23,
1482 0x24,
1483 0x25,
1484 0x26,
1485 0x27,
1486 0x28, /* AIF2RX1 */
1487 0x29,
1488 0x2a,
1489 0x2b,
1490 0x2c,
1491 0x2d,
1492 0x2e,
1493 0x2f,
1494 0x30, /* AIF3RX1 */
1495 0x31,
1496 0x32,
1497 0x33,
1498 0x34, /* AIF4RX1 */
1499 0x35,
1500 0x38, /* SLIMRX1 */
1501 0x39,
1502 0x3a,
1503 0x3b,
1504 0x3c,
1505 0x3d,
1506 0x3e,
1507 0x3f,
1508 0x50, /* EQ1 */
1509 0x51,
1510 0x52,
1511 0x53,
1512 0x58, /* DRC1L */
1513 0x59,
1514 0x5a,
1515 0x5b,
1516 0x60, /* LHPF1 */
1517 0x61,
1518 0x62,
1519 0x63,
1520 0x68, /* DSP1.1 */
1521 0x69,
1522 0x6a,
1523 0x6b,
1524 0x6c,
1525 0x6d,
1526 0x70, /* DSP2.1 */
1527 0x71,
1528 0x72,
1529 0x73,
1530 0x74,
1531 0x75,
1532 0x78, /* DSP3.1 */
1533 0x79,
1534 0x7a,
1535 0x7b,
1536 0x7c,
1537 0x7d,
1538 0x80, /* DSP4.1 */
1539 0x81,
1540 0x82,
1541 0x83,
1542 0x84,
1543 0x85,
1544 0x88, /* DSP5.1 */
1545 0x89,
1546 0x8a,
1547 0x8b,
1548 0x8c,
1549 0x8d,
1550 0xc0, /* DSP6.1 */
1551 0xc1,
1552 0xc2,
1553 0xc3,
1554 0xc4,
1555 0xc5,
1556 0xc8, /* DSP7.1 */
1557 0xc9,
1558 0xca,
1559 0xcb,
1560 0xcc,
1561 0xcd,
1562 0x90, /* ASRC1IN1L */
1563 0x91,
1564 0x92,
1565 0x93,
1566 0x94, /* ASRC2IN1L */
1567 0x95,
1568 0x96,
1569 0x97,
1570 0xa0, /* ISRC1INT1 */
1571 0xa1,
1572 0xa2,
1573 0xa3,
1574 0xa4, /* ISRC1DEC1 */
1575 0xa5,
1576 0xa6,
1577 0xa7,
1578 0xa8, /* ISRC2DEC1 */
1579 0xa9,
1580 0xaa,
1581 0xab,
1582 0xac, /* ISRC2INT1 */
1583 0xad,
1584 0xae,
1585 0xaf,
1586 0xb0, /* ISRC3DEC1 */
1587 0xb1,
1588 0xb2,
1589 0xb3,
1590 0xb4, /* ISRC3INT1 */
1591 0xb5,
1592 0xb6,
1593 0xb7,
1594 0xb8, /* ISRC4INT1 */
1595 0xb9,
1596 0xbc, /* ISRC4DEC1 */
1597 0xbd,
1598 0xf8, /* DFC1 */
1599 0xf9,
1600 0xfa,
1601 0xfb,
1602 0xfc,
1603 0xfd,
1604 0xfe,
1605 0xff, /* DFC8 */
1606 };
1607 EXPORT_SYMBOL_GPL(madera_mixer_values);
1608
1609 const DECLARE_TLV_DB_SCALE(madera_ana_tlv, 0, 100, 0);
1610 EXPORT_SYMBOL_GPL(madera_ana_tlv);
1611
1612 const DECLARE_TLV_DB_SCALE(madera_eq_tlv, -1200, 100, 0);
1613 EXPORT_SYMBOL_GPL(madera_eq_tlv);
1614
1615 const DECLARE_TLV_DB_SCALE(madera_digital_tlv, -6400, 50, 0);
1616 EXPORT_SYMBOL_GPL(madera_digital_tlv);
1617
1618 const DECLARE_TLV_DB_SCALE(madera_noise_tlv, -13200, 600, 0);
1619 EXPORT_SYMBOL_GPL(madera_noise_tlv);
1620
1621 const DECLARE_TLV_DB_SCALE(madera_ng_tlv, -12000, 600, 0);
1622 EXPORT_SYMBOL_GPL(madera_ng_tlv);
1623
1624 const DECLARE_TLV_DB_SCALE(madera_mixer_tlv, -3200, 100, 0);
1625 EXPORT_SYMBOL_GPL(madera_mixer_tlv);
1626
1627 const char * const madera_rate_text[MADERA_RATE_ENUM_SIZE] = {
1628 "SYNCCLK rate 1", "SYNCCLK rate 2", "SYNCCLK rate 3",
1629 "ASYNCCLK rate 1", "ASYNCCLK rate 2",
1630 };
1631 EXPORT_SYMBOL_GPL(madera_rate_text);
1632
1633 const unsigned int madera_rate_val[MADERA_RATE_ENUM_SIZE] = {
1634 0x0, 0x1, 0x2, 0x8, 0x9,
1635 };
1636 EXPORT_SYMBOL_GPL(madera_rate_val);
1637
1638 static const char * const madera_dfc_width_text[MADERA_DFC_WIDTH_ENUM_SIZE] = {
1639 "8 bit", "16 bit", "20 bit", "24 bit", "32 bit",
1640 };
1641
1642 static const unsigned int madera_dfc_width_val[MADERA_DFC_WIDTH_ENUM_SIZE] = {
1643 7, 15, 19, 23, 31,
1644 };
1645
1646 static const char * const madera_dfc_type_text[MADERA_DFC_TYPE_ENUM_SIZE] = {
1647 "Fixed", "Unsigned Fixed", "Single Precision Floating",
1648 "Half Precision Floating", "Arm Alternative Floating",
1649 };
1650
1651 static const unsigned int madera_dfc_type_val[MADERA_DFC_TYPE_ENUM_SIZE] = {
1652 0, 1, 2, 4, 5,
1653 };
1654
1655 const struct soc_enum madera_dfc_width[] = {
1656 SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_RX,
1657 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1658 MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1659 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1660 ARRAY_SIZE(madera_dfc_width_text),
1661 madera_dfc_width_text,
1662 madera_dfc_width_val),
1663 SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_TX,
1664 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1665 MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1666 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1667 ARRAY_SIZE(madera_dfc_width_text),
1668 madera_dfc_width_text,
1669 madera_dfc_width_val),
1670 SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_RX,
1671 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1672 MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1673 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1674 ARRAY_SIZE(madera_dfc_width_text),
1675 madera_dfc_width_text,
1676 madera_dfc_width_val),
1677 SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_TX,
1678 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1679 MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1680 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1681 ARRAY_SIZE(madera_dfc_width_text),
1682 madera_dfc_width_text,
1683 madera_dfc_width_val),
1684 SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_RX,
1685 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1686 MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1687 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1688 ARRAY_SIZE(madera_dfc_width_text),
1689 madera_dfc_width_text,
1690 madera_dfc_width_val),
1691 SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_TX,
1692 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1693 MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1694 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1695 ARRAY_SIZE(madera_dfc_width_text),
1696 madera_dfc_width_text,
1697 madera_dfc_width_val),
1698 SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_RX,
1699 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1700 MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1701 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1702 ARRAY_SIZE(madera_dfc_width_text),
1703 madera_dfc_width_text,
1704 madera_dfc_width_val),
1705 SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_TX,
1706 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1707 MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1708 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1709 ARRAY_SIZE(madera_dfc_width_text),
1710 madera_dfc_width_text,
1711 madera_dfc_width_val),
1712 SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_RX,
1713 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1714 MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1715 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1716 ARRAY_SIZE(madera_dfc_width_text),
1717 madera_dfc_width_text,
1718 madera_dfc_width_val),
1719 SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_TX,
1720 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1721 MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1722 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1723 ARRAY_SIZE(madera_dfc_width_text),
1724 madera_dfc_width_text,
1725 madera_dfc_width_val),
1726 SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_RX,
1727 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1728 MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1729 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1730 ARRAY_SIZE(madera_dfc_width_text),
1731 madera_dfc_width_text,
1732 madera_dfc_width_val),
1733 SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_TX,
1734 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1735 MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1736 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1737 ARRAY_SIZE(madera_dfc_width_text),
1738 madera_dfc_width_text,
1739 madera_dfc_width_val),
1740 SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_RX,
1741 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1742 MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1743 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1744 ARRAY_SIZE(madera_dfc_width_text),
1745 madera_dfc_width_text,
1746 madera_dfc_width_val),
1747 SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_TX,
1748 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1749 MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1750 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1751 ARRAY_SIZE(madera_dfc_width_text),
1752 madera_dfc_width_text,
1753 madera_dfc_width_val),
1754 SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_RX,
1755 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1756 MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1757 MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1758 ARRAY_SIZE(madera_dfc_width_text),
1759 madera_dfc_width_text,
1760 madera_dfc_width_val),
1761 SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_TX,
1762 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1763 MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1764 MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1765 ARRAY_SIZE(madera_dfc_width_text),
1766 madera_dfc_width_text,
1767 madera_dfc_width_val),
1768 };
1769 EXPORT_SYMBOL_GPL(madera_dfc_width);
1770
1771 const struct soc_enum madera_dfc_type[] = {
1772 SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_RX,
1773 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1774 MADERA_DFC1_RX_DATA_TYPE_MASK >>
1775 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1776 ARRAY_SIZE(madera_dfc_type_text),
1777 madera_dfc_type_text,
1778 madera_dfc_type_val),
1779 SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_TX,
1780 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1781 MADERA_DFC1_TX_DATA_TYPE_MASK >>
1782 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1783 ARRAY_SIZE(madera_dfc_type_text),
1784 madera_dfc_type_text,
1785 madera_dfc_type_val),
1786 SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_RX,
1787 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1788 MADERA_DFC1_RX_DATA_TYPE_MASK >>
1789 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1790 ARRAY_SIZE(madera_dfc_type_text),
1791 madera_dfc_type_text,
1792 madera_dfc_type_val),
1793 SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_TX,
1794 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1795 MADERA_DFC1_TX_DATA_TYPE_MASK >>
1796 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1797 ARRAY_SIZE(madera_dfc_type_text),
1798 madera_dfc_type_text,
1799 madera_dfc_type_val),
1800 SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_RX,
1801 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1802 MADERA_DFC1_RX_DATA_TYPE_MASK >>
1803 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1804 ARRAY_SIZE(madera_dfc_type_text),
1805 madera_dfc_type_text,
1806 madera_dfc_type_val),
1807 SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_TX,
1808 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1809 MADERA_DFC1_TX_DATA_TYPE_MASK >>
1810 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1811 ARRAY_SIZE(madera_dfc_type_text),
1812 madera_dfc_type_text,
1813 madera_dfc_type_val),
1814 SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_RX,
1815 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1816 MADERA_DFC1_RX_DATA_TYPE_MASK >>
1817 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1818 ARRAY_SIZE(madera_dfc_type_text),
1819 madera_dfc_type_text,
1820 madera_dfc_type_val),
1821 SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_TX,
1822 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1823 MADERA_DFC1_TX_DATA_TYPE_MASK >>
1824 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1825 ARRAY_SIZE(madera_dfc_type_text),
1826 madera_dfc_type_text,
1827 madera_dfc_type_val),
1828 SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_RX,
1829 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1830 MADERA_DFC1_RX_DATA_TYPE_MASK >>
1831 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1832 ARRAY_SIZE(madera_dfc_type_text),
1833 madera_dfc_type_text,
1834 madera_dfc_type_val),
1835 SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_TX,
1836 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1837 MADERA_DFC1_TX_DATA_TYPE_MASK >>
1838 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1839 ARRAY_SIZE(madera_dfc_type_text),
1840 madera_dfc_type_text,
1841 madera_dfc_type_val),
1842 SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_RX,
1843 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1844 MADERA_DFC1_RX_DATA_TYPE_MASK >>
1845 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1846 ARRAY_SIZE(madera_dfc_type_text),
1847 madera_dfc_type_text,
1848 madera_dfc_type_val),
1849 SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_TX,
1850 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1851 MADERA_DFC1_TX_DATA_TYPE_MASK >>
1852 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1853 ARRAY_SIZE(madera_dfc_type_text),
1854 madera_dfc_type_text,
1855 madera_dfc_type_val),
1856 SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_RX,
1857 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1858 MADERA_DFC1_RX_DATA_TYPE_MASK >>
1859 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1860 ARRAY_SIZE(madera_dfc_type_text),
1861 madera_dfc_type_text,
1862 madera_dfc_type_val),
1863 SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_TX,
1864 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1865 MADERA_DFC1_TX_DATA_TYPE_MASK >>
1866 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1867 ARRAY_SIZE(madera_dfc_type_text),
1868 madera_dfc_type_text,
1869 madera_dfc_type_val),
1870 SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_RX,
1871 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1872 MADERA_DFC1_RX_DATA_TYPE_MASK >>
1873 MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1874 ARRAY_SIZE(madera_dfc_type_text),
1875 madera_dfc_type_text,
1876 madera_dfc_type_val),
1877 SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_TX,
1878 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1879 MADERA_DFC1_TX_DATA_TYPE_MASK >>
1880 MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1881 ARRAY_SIZE(madera_dfc_type_text),
1882 madera_dfc_type_text,
1883 madera_dfc_type_val),
1884 };
1885 EXPORT_SYMBOL_GPL(madera_dfc_type);
1886
1887 const struct soc_enum madera_isrc_fsh[] = {
1888 SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_1_CTRL_1,
1889 MADERA_ISRC1_FSH_SHIFT, 0xf,
1890 MADERA_RATE_ENUM_SIZE,
1891 madera_rate_text, madera_rate_val),
1892 SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_2_CTRL_1,
1893 MADERA_ISRC2_FSH_SHIFT, 0xf,
1894 MADERA_RATE_ENUM_SIZE,
1895 madera_rate_text, madera_rate_val),
1896 SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_3_CTRL_1,
1897 MADERA_ISRC3_FSH_SHIFT, 0xf,
1898 MADERA_RATE_ENUM_SIZE,
1899 madera_rate_text, madera_rate_val),
1900 SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_4_CTRL_1,
1901 MADERA_ISRC4_FSH_SHIFT, 0xf,
1902 MADERA_RATE_ENUM_SIZE,
1903 madera_rate_text, madera_rate_val),
1904 };
1905 EXPORT_SYMBOL_GPL(madera_isrc_fsh);
1906
1907 const struct soc_enum madera_isrc_fsl[] = {
1908 SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_1_CTRL_2,
1909 MADERA_ISRC1_FSL_SHIFT, 0xf,
1910 MADERA_RATE_ENUM_SIZE,
1911 madera_rate_text, madera_rate_val),
1912 SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_2_CTRL_2,
1913 MADERA_ISRC2_FSL_SHIFT, 0xf,
1914 MADERA_RATE_ENUM_SIZE,
1915 madera_rate_text, madera_rate_val),
1916 SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_3_CTRL_2,
1917 MADERA_ISRC3_FSL_SHIFT, 0xf,
1918 MADERA_RATE_ENUM_SIZE,
1919 madera_rate_text, madera_rate_val),
1920 SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_4_CTRL_2,
1921 MADERA_ISRC4_FSL_SHIFT, 0xf,
1922 MADERA_RATE_ENUM_SIZE,
1923 madera_rate_text, madera_rate_val),
1924 };
1925 EXPORT_SYMBOL_GPL(madera_isrc_fsl);
1926
1927 const struct soc_enum madera_asrc1_rate[] = {
1928 SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE1,
1929 MADERA_ASRC1_RATE1_SHIFT, 0xf,
1930 MADERA_SYNC_RATE_ENUM_SIZE,
1931 madera_rate_text, madera_rate_val),
1932 SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE2,
1933 MADERA_ASRC1_RATE1_SHIFT, 0xf,
1934 MADERA_ASYNC_RATE_ENUM_SIZE,
1935 madera_rate_text + MADERA_SYNC_RATE_ENUM_SIZE,
1936 madera_rate_val + MADERA_SYNC_RATE_ENUM_SIZE),
1937 };
1938 EXPORT_SYMBOL_GPL(madera_asrc1_rate);
1939
1940 const struct soc_enum madera_asrc1_bidir_rate[] = {
1941 SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE1,
1942 MADERA_ASRC1_RATE1_SHIFT, 0xf,
1943 MADERA_RATE_ENUM_SIZE,
1944 madera_rate_text, madera_rate_val),
1945 SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE2,
1946 MADERA_ASRC1_RATE2_SHIFT, 0xf,
1947 MADERA_RATE_ENUM_SIZE,
1948 madera_rate_text, madera_rate_val),
1949 };
1950 EXPORT_SYMBOL_GPL(madera_asrc1_bidir_rate);
1951
1952 const struct soc_enum madera_asrc2_rate[] = {
1953 SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE1,
1954 MADERA_ASRC2_RATE1_SHIFT, 0xf,
1955 MADERA_SYNC_RATE_ENUM_SIZE,
1956 madera_rate_text, madera_rate_val),
1957 SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE2,
1958 MADERA_ASRC2_RATE2_SHIFT, 0xf,
1959 MADERA_ASYNC_RATE_ENUM_SIZE,
1960 madera_rate_text + MADERA_SYNC_RATE_ENUM_SIZE,
1961 madera_rate_val + MADERA_SYNC_RATE_ENUM_SIZE),
1962 };
1963 EXPORT_SYMBOL_GPL(madera_asrc2_rate);
1964
1965 static const char * const madera_vol_ramp_text[] = {
1966 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
1967 "15ms/6dB", "30ms/6dB",
1968 };
1969
1970 SOC_ENUM_SINGLE_DECL(madera_in_vd_ramp,
1971 MADERA_INPUT_VOLUME_RAMP,
1972 MADERA_IN_VD_RAMP_SHIFT,
1973 madera_vol_ramp_text);
1974 EXPORT_SYMBOL_GPL(madera_in_vd_ramp);
1975
1976 SOC_ENUM_SINGLE_DECL(madera_in_vi_ramp,
1977 MADERA_INPUT_VOLUME_RAMP,
1978 MADERA_IN_VI_RAMP_SHIFT,
1979 madera_vol_ramp_text);
1980 EXPORT_SYMBOL_GPL(madera_in_vi_ramp);
1981
1982 SOC_ENUM_SINGLE_DECL(madera_out_vd_ramp,
1983 MADERA_OUTPUT_VOLUME_RAMP,
1984 MADERA_OUT_VD_RAMP_SHIFT,
1985 madera_vol_ramp_text);
1986 EXPORT_SYMBOL_GPL(madera_out_vd_ramp);
1987
1988 SOC_ENUM_SINGLE_DECL(madera_out_vi_ramp,
1989 MADERA_OUTPUT_VOLUME_RAMP,
1990 MADERA_OUT_VI_RAMP_SHIFT,
1991 madera_vol_ramp_text);
1992 EXPORT_SYMBOL_GPL(madera_out_vi_ramp);
1993
1994 static const char * const madera_lhpf_mode_text[] = {
1995 "Low-pass", "High-pass"
1996 };
1997
1998 SOC_ENUM_SINGLE_DECL(madera_lhpf1_mode,
1999 MADERA_HPLPF1_1,
2000 MADERA_LHPF1_MODE_SHIFT,
2001 madera_lhpf_mode_text);
2002 EXPORT_SYMBOL_GPL(madera_lhpf1_mode);
2003
2004 SOC_ENUM_SINGLE_DECL(madera_lhpf2_mode,
2005 MADERA_HPLPF2_1,
2006 MADERA_LHPF2_MODE_SHIFT,
2007 madera_lhpf_mode_text);
2008 EXPORT_SYMBOL_GPL(madera_lhpf2_mode);
2009
2010 SOC_ENUM_SINGLE_DECL(madera_lhpf3_mode,
2011 MADERA_HPLPF3_1,
2012 MADERA_LHPF3_MODE_SHIFT,
2013 madera_lhpf_mode_text);
2014 EXPORT_SYMBOL_GPL(madera_lhpf3_mode);
2015
2016 SOC_ENUM_SINGLE_DECL(madera_lhpf4_mode,
2017 MADERA_HPLPF4_1,
2018 MADERA_LHPF4_MODE_SHIFT,
2019 madera_lhpf_mode_text);
2020 EXPORT_SYMBOL_GPL(madera_lhpf4_mode);
2021
2022 static const char * const madera_ng_hold_text[] = {
2023 "30ms", "120ms", "250ms", "500ms",
2024 };
2025
2026 SOC_ENUM_SINGLE_DECL(madera_ng_hold,
2027 MADERA_NOISE_GATE_CONTROL,
2028 MADERA_NGATE_HOLD_SHIFT,
2029 madera_ng_hold_text);
2030 EXPORT_SYMBOL_GPL(madera_ng_hold);
2031
2032 static const char * const madera_in_hpf_cut_text[] = {
2033 "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
2034 };
2035
2036 SOC_ENUM_SINGLE_DECL(madera_in_hpf_cut_enum,
2037 MADERA_HPF_CONTROL,
2038 MADERA_IN_HPF_CUT_SHIFT,
2039 madera_in_hpf_cut_text);
2040 EXPORT_SYMBOL_GPL(madera_in_hpf_cut_enum);
2041
2042 static const char * const madera_in_dmic_osr_text[MADERA_OSR_ENUM_SIZE] = {
2043 "384kHz", "768kHz", "1.536MHz", "3.072MHz", "6.144MHz",
2044 };
2045
2046 static const unsigned int madera_in_dmic_osr_val[MADERA_OSR_ENUM_SIZE] = {
2047 2, 3, 4, 5, 6,
2048 };
2049
2050 const struct soc_enum madera_in_dmic_osr[] = {
2051 SOC_VALUE_ENUM_SINGLE(MADERA_DMIC1L_CONTROL, MADERA_IN1_OSR_SHIFT,
2052 0x7, MADERA_OSR_ENUM_SIZE,
2053 madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2054 SOC_VALUE_ENUM_SINGLE(MADERA_DMIC2L_CONTROL, MADERA_IN2_OSR_SHIFT,
2055 0x7, MADERA_OSR_ENUM_SIZE,
2056 madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2057 SOC_VALUE_ENUM_SINGLE(MADERA_DMIC3L_CONTROL, MADERA_IN3_OSR_SHIFT,
2058 0x7, MADERA_OSR_ENUM_SIZE,
2059 madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2060 SOC_VALUE_ENUM_SINGLE(MADERA_DMIC4L_CONTROL, MADERA_IN4_OSR_SHIFT,
2061 0x7, MADERA_OSR_ENUM_SIZE,
2062 madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2063 SOC_VALUE_ENUM_SINGLE(MADERA_DMIC5L_CONTROL, MADERA_IN5_OSR_SHIFT,
2064 0x7, MADERA_OSR_ENUM_SIZE,
2065 madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2066 SOC_VALUE_ENUM_SINGLE(MADERA_DMIC6L_CONTROL, MADERA_IN6_OSR_SHIFT,
2067 0x7, MADERA_OSR_ENUM_SIZE,
2068 madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2069 };
2070 EXPORT_SYMBOL_GPL(madera_in_dmic_osr);
2071
2072 static const char * const madera_anc_input_src_text[] = {
2073 "None", "IN1", "IN2", "IN3", "IN4", "IN5", "IN6",
2074 };
2075
2076 static const char * const madera_anc_channel_src_text[] = {
2077 "None", "Left", "Right", "Combine",
2078 };
2079
2080 const struct soc_enum madera_anc_input_src[] = {
2081 SOC_ENUM_SINGLE(MADERA_ANC_SRC,
2082 MADERA_IN_RXANCL_SEL_SHIFT,
2083 ARRAY_SIZE(madera_anc_input_src_text),
2084 madera_anc_input_src_text),
2085 SOC_ENUM_SINGLE(MADERA_FCL_ADC_REFORMATTER_CONTROL,
2086 MADERA_FCL_MIC_MODE_SEL_SHIFT,
2087 ARRAY_SIZE(madera_anc_channel_src_text),
2088 madera_anc_channel_src_text),
2089 SOC_ENUM_SINGLE(MADERA_ANC_SRC,
2090 MADERA_IN_RXANCR_SEL_SHIFT,
2091 ARRAY_SIZE(madera_anc_input_src_text),
2092 madera_anc_input_src_text),
2093 SOC_ENUM_SINGLE(MADERA_FCR_ADC_REFORMATTER_CONTROL,
2094 MADERA_FCR_MIC_MODE_SEL_SHIFT,
2095 ARRAY_SIZE(madera_anc_channel_src_text),
2096 madera_anc_channel_src_text),
2097 };
2098 EXPORT_SYMBOL_GPL(madera_anc_input_src);
2099
2100 static const char * const madera_anc_ng_texts[] = {
2101 "None", "Internal", "External",
2102 };
2103
2104 SOC_ENUM_SINGLE_DECL(madera_anc_ng_enum, SND_SOC_NOPM, 0, madera_anc_ng_texts);
2105 EXPORT_SYMBOL_GPL(madera_anc_ng_enum);
2106
2107 static const char * const madera_out_anc_src_text[] = {
2108 "None", "RXANCL", "RXANCR",
2109 };
2110
2111 const struct soc_enum madera_output_anc_src[] = {
2112 SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_1L,
2113 MADERA_OUT1L_ANC_SRC_SHIFT,
2114 ARRAY_SIZE(madera_out_anc_src_text),
2115 madera_out_anc_src_text),
2116 SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_1R,
2117 MADERA_OUT1R_ANC_SRC_SHIFT,
2118 ARRAY_SIZE(madera_out_anc_src_text),
2119 madera_out_anc_src_text),
2120 SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_2L,
2121 MADERA_OUT2L_ANC_SRC_SHIFT,
2122 ARRAY_SIZE(madera_out_anc_src_text),
2123 madera_out_anc_src_text),
2124 SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_2R,
2125 MADERA_OUT2R_ANC_SRC_SHIFT,
2126 ARRAY_SIZE(madera_out_anc_src_text),
2127 madera_out_anc_src_text),
2128 SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_3L,
2129 MADERA_OUT3L_ANC_SRC_SHIFT,
2130 ARRAY_SIZE(madera_out_anc_src_text),
2131 madera_out_anc_src_text),
2132 SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_3R,
2133 MADERA_OUT3R_ANC_SRC_SHIFT,
2134 ARRAY_SIZE(madera_out_anc_src_text),
2135 madera_out_anc_src_text),
2136 SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_4L,
2137 MADERA_OUT4L_ANC_SRC_SHIFT,
2138 ARRAY_SIZE(madera_out_anc_src_text),
2139 madera_out_anc_src_text),
2140 SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_4R,
2141 MADERA_OUT4R_ANC_SRC_SHIFT,
2142 ARRAY_SIZE(madera_out_anc_src_text),
2143 madera_out_anc_src_text),
2144 SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_5L,
2145 MADERA_OUT5L_ANC_SRC_SHIFT,
2146 ARRAY_SIZE(madera_out_anc_src_text),
2147 madera_out_anc_src_text),
2148 SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_5R,
2149 MADERA_OUT5R_ANC_SRC_SHIFT,
2150 ARRAY_SIZE(madera_out_anc_src_text),
2151 madera_out_anc_src_text),
2152 SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_6L,
2153 MADERA_OUT6L_ANC_SRC_SHIFT,
2154 ARRAY_SIZE(madera_out_anc_src_text),
2155 madera_out_anc_src_text),
2156 SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_6R,
2157 MADERA_OUT6R_ANC_SRC_SHIFT,
2158 ARRAY_SIZE(madera_out_anc_src_text),
2159 madera_out_anc_src_text),
2160 };
2161 EXPORT_SYMBOL_GPL(madera_output_anc_src);
2162
madera_dfc_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2163 int madera_dfc_put(struct snd_kcontrol *kcontrol,
2164 struct snd_ctl_elem_value *ucontrol)
2165 {
2166 struct snd_soc_component *component =
2167 snd_soc_kcontrol_component(kcontrol);
2168 struct snd_soc_dapm_context *dapm =
2169 snd_soc_component_get_dapm(component);
2170 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2171 unsigned int reg = e->reg;
2172 unsigned int val;
2173 int ret = 0;
2174
2175 reg = ((reg / 6) * 6) - 2;
2176
2177 snd_soc_dapm_mutex_lock(dapm);
2178
2179 val = snd_soc_component_read(component, reg);
2180 if (val & MADERA_DFC1_ENA) {
2181 ret = -EBUSY;
2182 dev_err(component->dev, "Can't change mode on an active DFC\n");
2183 goto exit;
2184 }
2185
2186 ret = snd_soc_put_enum_double(kcontrol, ucontrol);
2187 exit:
2188 snd_soc_dapm_mutex_unlock(dapm);
2189
2190 return ret;
2191 }
2192 EXPORT_SYMBOL_GPL(madera_dfc_put);
2193
madera_lp_mode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2194 int madera_lp_mode_put(struct snd_kcontrol *kcontrol,
2195 struct snd_ctl_elem_value *ucontrol)
2196 {
2197 struct soc_mixer_control *mc =
2198 (struct soc_mixer_control *)kcontrol->private_value;
2199 struct snd_soc_component *component =
2200 snd_soc_kcontrol_component(kcontrol);
2201 struct snd_soc_dapm_context *dapm =
2202 snd_soc_component_get_dapm(component);
2203 unsigned int val, mask;
2204 int ret;
2205
2206 snd_soc_dapm_mutex_lock(dapm);
2207
2208 /* Cannot change lp mode on an active input */
2209 val = snd_soc_component_read(component, MADERA_INPUT_ENABLES);
2210 mask = (mc->reg - MADERA_ADC_DIGITAL_VOLUME_1L) / 4;
2211 mask ^= 0x1; /* Flip bottom bit for channel order */
2212
2213 if (val & (1 << mask)) {
2214 ret = -EBUSY;
2215 dev_err(component->dev,
2216 "Can't change lp mode on an active input\n");
2217 goto exit;
2218 }
2219
2220 ret = snd_soc_put_volsw(kcontrol, ucontrol);
2221
2222 exit:
2223 snd_soc_dapm_mutex_unlock(dapm);
2224
2225 return ret;
2226 }
2227 EXPORT_SYMBOL_GPL(madera_lp_mode_put);
2228
2229 const struct snd_kcontrol_new madera_dsp_trigger_output_mux[] = {
2230 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2231 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2232 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2233 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2234 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2235 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2236 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2237 };
2238 EXPORT_SYMBOL_GPL(madera_dsp_trigger_output_mux);
2239
2240 const struct snd_kcontrol_new madera_drc_activity_output_mux[] = {
2241 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2242 SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2243 };
2244 EXPORT_SYMBOL_GPL(madera_drc_activity_output_mux);
2245
madera_in_set_vu(struct madera_priv * priv,bool enable)2246 static void madera_in_set_vu(struct madera_priv *priv, bool enable)
2247 {
2248 unsigned int val;
2249 int i, ret;
2250
2251 if (enable)
2252 val = MADERA_IN_VU;
2253 else
2254 val = 0;
2255
2256 for (i = 0; i < priv->num_inputs; i++) {
2257 ret = regmap_update_bits(priv->madera->regmap,
2258 MADERA_ADC_DIGITAL_VOLUME_1L + (i * 4),
2259 MADERA_IN_VU, val);
2260 if (ret)
2261 dev_warn(priv->madera->dev,
2262 "Failed to modify VU bits: %d\n", ret);
2263 }
2264 }
2265
madera_in_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)2266 int madera_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
2267 int event)
2268 {
2269 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2270 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2271 unsigned int reg, val;
2272
2273 if (w->shift % 2)
2274 reg = MADERA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8);
2275 else
2276 reg = MADERA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
2277
2278 switch (event) {
2279 case SND_SOC_DAPM_PRE_PMU:
2280 priv->in_pending++;
2281 break;
2282 case SND_SOC_DAPM_POST_PMU:
2283 priv->in_pending--;
2284 snd_soc_component_update_bits(component, reg,
2285 MADERA_IN1L_MUTE, 0);
2286
2287 /* If this is the last input pending then allow VU */
2288 if (priv->in_pending == 0) {
2289 usleep_range(1000, 3000);
2290 madera_in_set_vu(priv, true);
2291 }
2292 break;
2293 case SND_SOC_DAPM_PRE_PMD:
2294 snd_soc_component_update_bits(component, reg,
2295 MADERA_IN1L_MUTE | MADERA_IN_VU,
2296 MADERA_IN1L_MUTE | MADERA_IN_VU);
2297 break;
2298 case SND_SOC_DAPM_POST_PMD:
2299 /* Disable volume updates if no inputs are enabled */
2300 val = snd_soc_component_read(component, MADERA_INPUT_ENABLES);
2301 if (!val)
2302 madera_in_set_vu(priv, false);
2303 break;
2304 default:
2305 break;
2306 }
2307
2308 return 0;
2309 }
2310 EXPORT_SYMBOL_GPL(madera_in_ev);
2311
madera_out_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)2312 int madera_out_ev(struct snd_soc_dapm_widget *w,
2313 struct snd_kcontrol *kcontrol, int event)
2314 {
2315 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2316 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2317 struct madera *madera = priv->madera;
2318 int out_up_delay;
2319
2320 switch (madera->type) {
2321 case CS47L90:
2322 case CS47L91:
2323 case CS42L92:
2324 case CS47L92:
2325 case CS47L93:
2326 out_up_delay = 6000;
2327 break;
2328 default:
2329 out_up_delay = 17000;
2330 break;
2331 }
2332
2333 switch (event) {
2334 case SND_SOC_DAPM_PRE_PMU:
2335 switch (w->shift) {
2336 case MADERA_OUT1L_ENA_SHIFT:
2337 case MADERA_OUT1R_ENA_SHIFT:
2338 case MADERA_OUT2L_ENA_SHIFT:
2339 case MADERA_OUT2R_ENA_SHIFT:
2340 case MADERA_OUT3L_ENA_SHIFT:
2341 case MADERA_OUT3R_ENA_SHIFT:
2342 priv->out_up_pending++;
2343 priv->out_up_delay += out_up_delay;
2344 break;
2345 default:
2346 break;
2347 }
2348 break;
2349
2350 case SND_SOC_DAPM_POST_PMU:
2351 switch (w->shift) {
2352 case MADERA_OUT1L_ENA_SHIFT:
2353 case MADERA_OUT1R_ENA_SHIFT:
2354 case MADERA_OUT2L_ENA_SHIFT:
2355 case MADERA_OUT2R_ENA_SHIFT:
2356 case MADERA_OUT3L_ENA_SHIFT:
2357 case MADERA_OUT3R_ENA_SHIFT:
2358 priv->out_up_pending--;
2359 if (!priv->out_up_pending) {
2360 fsleep(priv->out_up_delay);
2361 priv->out_up_delay = 0;
2362 }
2363 break;
2364
2365 default:
2366 break;
2367 }
2368 break;
2369
2370 case SND_SOC_DAPM_PRE_PMD:
2371 switch (w->shift) {
2372 case MADERA_OUT1L_ENA_SHIFT:
2373 case MADERA_OUT1R_ENA_SHIFT:
2374 case MADERA_OUT2L_ENA_SHIFT:
2375 case MADERA_OUT2R_ENA_SHIFT:
2376 case MADERA_OUT3L_ENA_SHIFT:
2377 case MADERA_OUT3R_ENA_SHIFT:
2378 priv->out_down_pending++;
2379 priv->out_down_delay += 1000;
2380 break;
2381 default:
2382 break;
2383 }
2384 break;
2385
2386 case SND_SOC_DAPM_POST_PMD:
2387 switch (w->shift) {
2388 case MADERA_OUT1L_ENA_SHIFT:
2389 case MADERA_OUT1R_ENA_SHIFT:
2390 case MADERA_OUT2L_ENA_SHIFT:
2391 case MADERA_OUT2R_ENA_SHIFT:
2392 case MADERA_OUT3L_ENA_SHIFT:
2393 case MADERA_OUT3R_ENA_SHIFT:
2394 priv->out_down_pending--;
2395 if (!priv->out_down_pending) {
2396 fsleep(priv->out_down_delay);
2397 priv->out_down_delay = 0;
2398 }
2399 break;
2400 default:
2401 break;
2402 }
2403 break;
2404 default:
2405 break;
2406 }
2407
2408 return 0;
2409 }
2410 EXPORT_SYMBOL_GPL(madera_out_ev);
2411
madera_hp_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)2412 int madera_hp_ev(struct snd_soc_dapm_widget *w,
2413 struct snd_kcontrol *kcontrol, int event)
2414 {
2415 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2416 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2417 struct madera *madera = priv->madera;
2418 unsigned int mask = 1 << w->shift;
2419 unsigned int out_num = w->shift / 2;
2420 unsigned int val;
2421 unsigned int ep_sel = 0;
2422
2423 switch (event) {
2424 case SND_SOC_DAPM_POST_PMU:
2425 val = mask;
2426 break;
2427 case SND_SOC_DAPM_PRE_PMD:
2428 val = 0;
2429 break;
2430 case SND_SOC_DAPM_PRE_PMU:
2431 case SND_SOC_DAPM_POST_PMD:
2432 return madera_out_ev(w, kcontrol, event);
2433 default:
2434 return 0;
2435 }
2436
2437 /* Store the desired state for the HP outputs */
2438 madera->hp_ena &= ~mask;
2439 madera->hp_ena |= val;
2440
2441 switch (madera->type) {
2442 case CS42L92:
2443 case CS47L92:
2444 case CS47L93:
2445 break;
2446 default:
2447 /* if OUT1 is routed to EPOUT, ignore HP clamp and impedance */
2448 regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel);
2449 ep_sel &= MADERA_EP_SEL_MASK;
2450 break;
2451 }
2452
2453 /* Force off if HPDET has disabled the clamp for this output */
2454 if (!ep_sel &&
2455 (!madera->out_clamp[out_num] || madera->out_shorted[out_num]))
2456 val = 0;
2457
2458 regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, mask, val);
2459
2460 return madera_out_ev(w, kcontrol, event);
2461 }
2462 EXPORT_SYMBOL_GPL(madera_hp_ev);
2463
madera_anc_ev(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)2464 int madera_anc_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
2465 int event)
2466 {
2467 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2468 unsigned int val;
2469
2470 switch (event) {
2471 case SND_SOC_DAPM_POST_PMU:
2472 val = 1 << w->shift;
2473 break;
2474 case SND_SOC_DAPM_PRE_PMD:
2475 val = 1 << (w->shift + 1);
2476 break;
2477 default:
2478 return 0;
2479 }
2480
2481 snd_soc_component_write(component, MADERA_CLOCK_CONTROL, val);
2482
2483 return 0;
2484 }
2485 EXPORT_SYMBOL_GPL(madera_anc_ev);
2486
2487 static const unsigned int madera_opclk_ref_48k_rates[] = {
2488 6144000,
2489 12288000,
2490 24576000,
2491 49152000,
2492 };
2493
2494 static const unsigned int madera_opclk_ref_44k1_rates[] = {
2495 5644800,
2496 11289600,
2497 22579200,
2498 45158400,
2499 };
2500
madera_set_opclk(struct snd_soc_component * component,unsigned int clk,unsigned int freq)2501 static int madera_set_opclk(struct snd_soc_component *component,
2502 unsigned int clk, unsigned int freq)
2503 {
2504 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2505 unsigned int mask = MADERA_OPCLK_DIV_MASK | MADERA_OPCLK_SEL_MASK;
2506 unsigned int reg, val;
2507 const unsigned int *rates;
2508 int ref, div, refclk;
2509
2510 BUILD_BUG_ON(ARRAY_SIZE(madera_opclk_ref_48k_rates) !=
2511 ARRAY_SIZE(madera_opclk_ref_44k1_rates));
2512
2513 switch (clk) {
2514 case MADERA_CLK_OPCLK:
2515 reg = MADERA_OUTPUT_SYSTEM_CLOCK;
2516 refclk = priv->sysclk;
2517 break;
2518 case MADERA_CLK_ASYNC_OPCLK:
2519 reg = MADERA_OUTPUT_ASYNC_CLOCK;
2520 refclk = priv->asyncclk;
2521 break;
2522 default:
2523 return -EINVAL;
2524 }
2525
2526 if (refclk % 4000)
2527 rates = madera_opclk_ref_44k1_rates;
2528 else
2529 rates = madera_opclk_ref_48k_rates;
2530
2531 for (ref = 0; ref < ARRAY_SIZE(madera_opclk_ref_48k_rates); ++ref) {
2532 if (rates[ref] > refclk)
2533 continue;
2534
2535 div = 2;
2536 while ((rates[ref] / div >= freq) && (div <= 30)) {
2537 if (rates[ref] / div == freq) {
2538 dev_dbg(component->dev, "Configured %dHz OPCLK\n",
2539 freq);
2540
2541 val = (div << MADERA_OPCLK_DIV_SHIFT) | ref;
2542
2543 snd_soc_component_update_bits(component, reg,
2544 mask, val);
2545 return 0;
2546 }
2547 div += 2;
2548 }
2549 }
2550
2551 dev_err(component->dev, "Unable to generate %dHz OPCLK\n", freq);
2552
2553 return -EINVAL;
2554 }
2555
madera_get_sysclk_setting(unsigned int freq)2556 static int madera_get_sysclk_setting(unsigned int freq)
2557 {
2558 switch (freq) {
2559 case 0:
2560 case 5644800:
2561 case 6144000:
2562 return 0;
2563 case 11289600:
2564 case 12288000:
2565 return MADERA_SYSCLK_12MHZ << MADERA_SYSCLK_FREQ_SHIFT;
2566 case 22579200:
2567 case 24576000:
2568 return MADERA_SYSCLK_24MHZ << MADERA_SYSCLK_FREQ_SHIFT;
2569 case 45158400:
2570 case 49152000:
2571 return MADERA_SYSCLK_49MHZ << MADERA_SYSCLK_FREQ_SHIFT;
2572 case 90316800:
2573 case 98304000:
2574 return MADERA_SYSCLK_98MHZ << MADERA_SYSCLK_FREQ_SHIFT;
2575 default:
2576 return -EINVAL;
2577 }
2578 }
2579
madera_get_legacy_dspclk_setting(struct madera * madera,unsigned int freq)2580 static int madera_get_legacy_dspclk_setting(struct madera *madera,
2581 unsigned int freq)
2582 {
2583 switch (freq) {
2584 case 0:
2585 return 0;
2586 case 45158400:
2587 case 49152000:
2588 switch (madera->type) {
2589 case CS47L85:
2590 case WM1840:
2591 if (madera->rev < 3)
2592 return -EINVAL;
2593 else
2594 return MADERA_SYSCLK_49MHZ <<
2595 MADERA_SYSCLK_FREQ_SHIFT;
2596 default:
2597 return -EINVAL;
2598 }
2599 case 135475200:
2600 case 147456000:
2601 return MADERA_DSPCLK_147MHZ << MADERA_DSP_CLK_FREQ_LEGACY_SHIFT;
2602 default:
2603 return -EINVAL;
2604 }
2605 }
2606
madera_get_dspclk_setting(struct madera * madera,unsigned int freq,unsigned int * clock_2_val)2607 static int madera_get_dspclk_setting(struct madera *madera,
2608 unsigned int freq,
2609 unsigned int *clock_2_val)
2610 {
2611 switch (madera->type) {
2612 case CS47L35:
2613 case CS47L85:
2614 case WM1840:
2615 *clock_2_val = 0; /* don't use MADERA_DSP_CLOCK_2 */
2616 return madera_get_legacy_dspclk_setting(madera, freq);
2617 default:
2618 if (freq > 150000000)
2619 return -EINVAL;
2620
2621 /* Use new exact frequency control */
2622 *clock_2_val = freq / 15625; /* freq * (2^6) / (10^6) */
2623 return 0;
2624 }
2625 }
2626
madera_set_outclk(struct snd_soc_component * component,unsigned int source,unsigned int freq)2627 static int madera_set_outclk(struct snd_soc_component *component,
2628 unsigned int source, unsigned int freq)
2629 {
2630 int div, div_inc, rate;
2631
2632 switch (source) {
2633 case MADERA_OUTCLK_SYSCLK:
2634 dev_dbg(component->dev, "Configured OUTCLK to SYSCLK\n");
2635 snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1,
2636 MADERA_OUT_CLK_SRC_MASK, source);
2637 return 0;
2638 case MADERA_OUTCLK_ASYNCCLK:
2639 dev_dbg(component->dev, "Configured OUTCLK to ASYNCCLK\n");
2640 snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1,
2641 MADERA_OUT_CLK_SRC_MASK, source);
2642 return 0;
2643 case MADERA_OUTCLK_MCLK1:
2644 case MADERA_OUTCLK_MCLK2:
2645 case MADERA_OUTCLK_MCLK3:
2646 break;
2647 default:
2648 return -EINVAL;
2649 }
2650
2651 if (freq % 4000)
2652 rate = 5644800;
2653 else
2654 rate = 6144000;
2655
2656 div = 1;
2657 div_inc = 0;
2658 while (div <= 8) {
2659 if (freq / div == rate && !(freq % div)) {
2660 dev_dbg(component->dev, "Configured %dHz OUTCLK\n", rate);
2661 snd_soc_component_update_bits(component,
2662 MADERA_OUTPUT_RATE_1,
2663 MADERA_OUT_EXT_CLK_DIV_MASK |
2664 MADERA_OUT_CLK_SRC_MASK,
2665 (div_inc << MADERA_OUT_EXT_CLK_DIV_SHIFT) |
2666 source);
2667 return 0;
2668 }
2669 div_inc++;
2670 div *= 2;
2671 }
2672
2673 dev_err(component->dev,
2674 "Unable to generate %dHz OUTCLK from %dHz MCLK\n",
2675 rate, freq);
2676 return -EINVAL;
2677 }
2678
madera_set_sysclk(struct snd_soc_component * component,int clk_id,int source,unsigned int freq,int dir)2679 int madera_set_sysclk(struct snd_soc_component *component, int clk_id,
2680 int source, unsigned int freq, int dir)
2681 {
2682 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2683 struct madera *madera = priv->madera;
2684 char *name;
2685 unsigned int reg, clock_2_val = 0;
2686 unsigned int mask = MADERA_SYSCLK_FREQ_MASK | MADERA_SYSCLK_SRC_MASK;
2687 unsigned int val = source << MADERA_SYSCLK_SRC_SHIFT;
2688 int clk_freq_sel, *clk;
2689 int ret = 0;
2690
2691 switch (clk_id) {
2692 case MADERA_CLK_SYSCLK_1:
2693 name = "SYSCLK";
2694 reg = MADERA_SYSTEM_CLOCK_1;
2695 clk = &priv->sysclk;
2696 clk_freq_sel = madera_get_sysclk_setting(freq);
2697 mask |= MADERA_SYSCLK_FRAC;
2698 break;
2699 case MADERA_CLK_ASYNCCLK_1:
2700 name = "ASYNCCLK";
2701 reg = MADERA_ASYNC_CLOCK_1;
2702 clk = &priv->asyncclk;
2703 clk_freq_sel = madera_get_sysclk_setting(freq);
2704 break;
2705 case MADERA_CLK_DSPCLK:
2706 name = "DSPCLK";
2707 reg = MADERA_DSP_CLOCK_1;
2708 clk = &priv->dspclk;
2709 clk_freq_sel = madera_get_dspclk_setting(madera, freq,
2710 &clock_2_val);
2711 break;
2712 case MADERA_CLK_OPCLK:
2713 case MADERA_CLK_ASYNC_OPCLK:
2714 return madera_set_opclk(component, clk_id, freq);
2715 case MADERA_CLK_OUTCLK:
2716 return madera_set_outclk(component, source, freq);
2717 default:
2718 return -EINVAL;
2719 }
2720
2721 if (clk_freq_sel < 0) {
2722 dev_err(madera->dev,
2723 "Failed to get clk setting for %dHZ\n", freq);
2724 return clk_freq_sel;
2725 }
2726
2727 *clk = freq;
2728
2729 if (freq == 0) {
2730 dev_dbg(madera->dev, "%s cleared\n", name);
2731 return 0;
2732 }
2733
2734 val |= clk_freq_sel;
2735
2736 if (clock_2_val) {
2737 ret = regmap_write(madera->regmap, MADERA_DSP_CLOCK_2,
2738 clock_2_val);
2739 if (ret) {
2740 dev_err(madera->dev,
2741 "Failed to write DSP_CONFIG2: %d\n", ret);
2742 return ret;
2743 }
2744
2745 /*
2746 * We're using the frequency setting in MADERA_DSP_CLOCK_2 so
2747 * don't change the frequency select bits in MADERA_DSP_CLOCK_1
2748 */
2749 mask = MADERA_SYSCLK_SRC_MASK;
2750 }
2751
2752 if (freq % 6144000)
2753 val |= MADERA_SYSCLK_FRAC;
2754
2755 dev_dbg(madera->dev, "%s set to %uHz\n", name, freq);
2756
2757 return regmap_update_bits(madera->regmap, reg, mask, val);
2758 }
2759 EXPORT_SYMBOL_GPL(madera_set_sysclk);
2760
madera_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)2761 static int madera_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2762 {
2763 struct snd_soc_component *component = dai->component;
2764 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2765 struct madera *madera = priv->madera;
2766 int lrclk, bclk, mode, base;
2767
2768 base = dai->driver->base;
2769
2770 lrclk = 0;
2771 bclk = 0;
2772
2773 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
2774 case SND_SOC_DAIFMT_DSP_A:
2775 mode = MADERA_FMT_DSP_MODE_A;
2776 break;
2777 case SND_SOC_DAIFMT_DSP_B:
2778 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) !=
2779 SND_SOC_DAIFMT_CBM_CFM) {
2780 madera_aif_err(dai, "DSP_B not valid in slave mode\n");
2781 return -EINVAL;
2782 }
2783 mode = MADERA_FMT_DSP_MODE_B;
2784 break;
2785 case SND_SOC_DAIFMT_I2S:
2786 mode = MADERA_FMT_I2S_MODE;
2787 break;
2788 case SND_SOC_DAIFMT_LEFT_J:
2789 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) !=
2790 SND_SOC_DAIFMT_CBM_CFM) {
2791 madera_aif_err(dai, "LEFT_J not valid in slave mode\n");
2792 return -EINVAL;
2793 }
2794 mode = MADERA_FMT_LEFT_JUSTIFIED_MODE;
2795 break;
2796 default:
2797 madera_aif_err(dai, "Unsupported DAI format %d\n",
2798 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
2799 return -EINVAL;
2800 }
2801
2802 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
2803 case SND_SOC_DAIFMT_CBS_CFS:
2804 break;
2805 case SND_SOC_DAIFMT_CBS_CFM:
2806 lrclk |= MADERA_AIF1TX_LRCLK_MSTR;
2807 break;
2808 case SND_SOC_DAIFMT_CBM_CFS:
2809 bclk |= MADERA_AIF1_BCLK_MSTR;
2810 break;
2811 case SND_SOC_DAIFMT_CBM_CFM:
2812 bclk |= MADERA_AIF1_BCLK_MSTR;
2813 lrclk |= MADERA_AIF1TX_LRCLK_MSTR;
2814 break;
2815 default:
2816 madera_aif_err(dai, "Unsupported master mode %d\n",
2817 fmt & SND_SOC_DAIFMT_MASTER_MASK);
2818 return -EINVAL;
2819 }
2820
2821 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
2822 case SND_SOC_DAIFMT_NB_NF:
2823 break;
2824 case SND_SOC_DAIFMT_IB_IF:
2825 bclk |= MADERA_AIF1_BCLK_INV;
2826 lrclk |= MADERA_AIF1TX_LRCLK_INV;
2827 break;
2828 case SND_SOC_DAIFMT_IB_NF:
2829 bclk |= MADERA_AIF1_BCLK_INV;
2830 break;
2831 case SND_SOC_DAIFMT_NB_IF:
2832 lrclk |= MADERA_AIF1TX_LRCLK_INV;
2833 break;
2834 default:
2835 madera_aif_err(dai, "Unsupported invert mode %d\n",
2836 fmt & SND_SOC_DAIFMT_INV_MASK);
2837 return -EINVAL;
2838 }
2839
2840 regmap_update_bits(madera->regmap, base + MADERA_AIF_BCLK_CTRL,
2841 MADERA_AIF1_BCLK_INV | MADERA_AIF1_BCLK_MSTR,
2842 bclk);
2843 regmap_update_bits(madera->regmap, base + MADERA_AIF_TX_PIN_CTRL,
2844 MADERA_AIF1TX_LRCLK_INV | MADERA_AIF1TX_LRCLK_MSTR,
2845 lrclk);
2846 regmap_update_bits(madera->regmap, base + MADERA_AIF_RX_PIN_CTRL,
2847 MADERA_AIF1RX_LRCLK_INV | MADERA_AIF1RX_LRCLK_MSTR,
2848 lrclk);
2849 regmap_update_bits(madera->regmap, base + MADERA_AIF_FORMAT,
2850 MADERA_AIF1_FMT_MASK, mode);
2851
2852 return 0;
2853 }
2854
2855 static const int madera_48k_bclk_rates[] = {
2856 -1,
2857 48000,
2858 64000,
2859 96000,
2860 128000,
2861 192000,
2862 256000,
2863 384000,
2864 512000,
2865 768000,
2866 1024000,
2867 1536000,
2868 2048000,
2869 3072000,
2870 4096000,
2871 6144000,
2872 8192000,
2873 12288000,
2874 24576000,
2875 };
2876
2877 static const int madera_44k1_bclk_rates[] = {
2878 -1,
2879 44100,
2880 58800,
2881 88200,
2882 117600,
2883 177640,
2884 235200,
2885 352800,
2886 470400,
2887 705600,
2888 940800,
2889 1411200,
2890 1881600,
2891 2822400,
2892 3763200,
2893 5644800,
2894 7526400,
2895 11289600,
2896 22579200,
2897 };
2898
2899 static const unsigned int madera_sr_vals[] = {
2900 0,
2901 12000,
2902 24000,
2903 48000,
2904 96000,
2905 192000,
2906 384000,
2907 768000,
2908 0,
2909 11025,
2910 22050,
2911 44100,
2912 88200,
2913 176400,
2914 352800,
2915 705600,
2916 4000,
2917 8000,
2918 16000,
2919 32000,
2920 64000,
2921 128000,
2922 256000,
2923 512000,
2924 };
2925
2926 #define MADERA_192K_48K_RATE_MASK 0x0F003E
2927 #define MADERA_192K_44K1_RATE_MASK 0x003E00
2928 #define MADERA_192K_RATE_MASK (MADERA_192K_48K_RATE_MASK | \
2929 MADERA_192K_44K1_RATE_MASK)
2930 #define MADERA_384K_48K_RATE_MASK 0x0F007E
2931 #define MADERA_384K_44K1_RATE_MASK 0x007E00
2932 #define MADERA_384K_RATE_MASK (MADERA_384K_48K_RATE_MASK | \
2933 MADERA_384K_44K1_RATE_MASK)
2934
2935 static const struct snd_pcm_hw_constraint_list madera_constraint = {
2936 .count = ARRAY_SIZE(madera_sr_vals),
2937 .list = madera_sr_vals,
2938 };
2939
madera_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)2940 static int madera_startup(struct snd_pcm_substream *substream,
2941 struct snd_soc_dai *dai)
2942 {
2943 struct snd_soc_component *component = dai->component;
2944 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2945 struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1];
2946 struct madera *madera = priv->madera;
2947 unsigned int base_rate;
2948
2949 if (!substream->runtime)
2950 return 0;
2951
2952 switch (dai_priv->clk) {
2953 case MADERA_CLK_SYSCLK_1:
2954 case MADERA_CLK_SYSCLK_2:
2955 case MADERA_CLK_SYSCLK_3:
2956 base_rate = priv->sysclk;
2957 break;
2958 case MADERA_CLK_ASYNCCLK_1:
2959 case MADERA_CLK_ASYNCCLK_2:
2960 base_rate = priv->asyncclk;
2961 break;
2962 default:
2963 return 0;
2964 }
2965
2966 switch (madera->type) {
2967 case CS42L92:
2968 case CS47L92:
2969 case CS47L93:
2970 if (base_rate == 0)
2971 dai_priv->constraint.mask = MADERA_384K_RATE_MASK;
2972 else if (base_rate % 4000)
2973 dai_priv->constraint.mask = MADERA_384K_44K1_RATE_MASK;
2974 else
2975 dai_priv->constraint.mask = MADERA_384K_48K_RATE_MASK;
2976 break;
2977 default:
2978 if (base_rate == 0)
2979 dai_priv->constraint.mask = MADERA_192K_RATE_MASK;
2980 else if (base_rate % 4000)
2981 dai_priv->constraint.mask = MADERA_192K_44K1_RATE_MASK;
2982 else
2983 dai_priv->constraint.mask = MADERA_192K_48K_RATE_MASK;
2984 break;
2985 }
2986
2987 return snd_pcm_hw_constraint_list(substream->runtime, 0,
2988 SNDRV_PCM_HW_PARAM_RATE,
2989 &dai_priv->constraint);
2990 }
2991
madera_hw_params_rate(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)2992 static int madera_hw_params_rate(struct snd_pcm_substream *substream,
2993 struct snd_pcm_hw_params *params,
2994 struct snd_soc_dai *dai)
2995 {
2996 struct snd_soc_component *component = dai->component;
2997 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2998 struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1];
2999 int base = dai->driver->base;
3000 int i, sr_val;
3001 unsigned int reg, cur, tar;
3002 int ret;
3003
3004 for (i = 0; i < ARRAY_SIZE(madera_sr_vals); i++)
3005 if (madera_sr_vals[i] == params_rate(params))
3006 break;
3007
3008 if (i == ARRAY_SIZE(madera_sr_vals)) {
3009 madera_aif_err(dai, "Unsupported sample rate %dHz\n",
3010 params_rate(params));
3011 return -EINVAL;
3012 }
3013 sr_val = i;
3014
3015 switch (dai_priv->clk) {
3016 case MADERA_CLK_SYSCLK_1:
3017 reg = MADERA_SAMPLE_RATE_1;
3018 tar = 0 << MADERA_AIF1_RATE_SHIFT;
3019 break;
3020 case MADERA_CLK_SYSCLK_2:
3021 reg = MADERA_SAMPLE_RATE_2;
3022 tar = 1 << MADERA_AIF1_RATE_SHIFT;
3023 break;
3024 case MADERA_CLK_SYSCLK_3:
3025 reg = MADERA_SAMPLE_RATE_3;
3026 tar = 2 << MADERA_AIF1_RATE_SHIFT;
3027 break;
3028 case MADERA_CLK_ASYNCCLK_1:
3029 reg = MADERA_ASYNC_SAMPLE_RATE_1;
3030 tar = 8 << MADERA_AIF1_RATE_SHIFT;
3031 break;
3032 case MADERA_CLK_ASYNCCLK_2:
3033 reg = MADERA_ASYNC_SAMPLE_RATE_2;
3034 tar = 9 << MADERA_AIF1_RATE_SHIFT;
3035 break;
3036 default:
3037 madera_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
3038 return -EINVAL;
3039 }
3040
3041 snd_soc_component_update_bits(component, reg, MADERA_SAMPLE_RATE_1_MASK,
3042 sr_val);
3043
3044 if (!base)
3045 return 0;
3046
3047 ret = regmap_read(priv->madera->regmap,
3048 base + MADERA_AIF_RATE_CTRL, &cur);
3049 if (ret != 0) {
3050 madera_aif_err(dai, "Failed to check rate: %d\n", ret);
3051 return ret;
3052 }
3053
3054 if ((cur & MADERA_AIF1_RATE_MASK) == (tar & MADERA_AIF1_RATE_MASK))
3055 return 0;
3056
3057 mutex_lock(&priv->rate_lock);
3058
3059 if (!madera_can_change_grp_rate(priv, base + MADERA_AIF_RATE_CTRL)) {
3060 madera_aif_warn(dai, "Cannot change rate while active\n");
3061 ret = -EBUSY;
3062 goto out;
3063 }
3064
3065 /* Guard the rate change with SYSCLK cycles */
3066 madera_spin_sysclk(priv);
3067 snd_soc_component_update_bits(component, base + MADERA_AIF_RATE_CTRL,
3068 MADERA_AIF1_RATE_MASK, tar);
3069 madera_spin_sysclk(priv);
3070
3071 out:
3072 mutex_unlock(&priv->rate_lock);
3073
3074 return ret;
3075 }
3076
madera_aif_cfg_changed(struct snd_soc_component * component,int base,int bclk,int lrclk,int frame)3077 static int madera_aif_cfg_changed(struct snd_soc_component *component,
3078 int base, int bclk, int lrclk, int frame)
3079 {
3080 unsigned int val;
3081
3082 val = snd_soc_component_read(component, base + MADERA_AIF_BCLK_CTRL);
3083 if (bclk != (val & MADERA_AIF1_BCLK_FREQ_MASK))
3084 return 1;
3085
3086 val = snd_soc_component_read(component, base + MADERA_AIF_RX_BCLK_RATE);
3087 if (lrclk != (val & MADERA_AIF1RX_BCPF_MASK))
3088 return 1;
3089
3090 val = snd_soc_component_read(component, base + MADERA_AIF_FRAME_CTRL_1);
3091 if (frame != (val & (MADERA_AIF1TX_WL_MASK |
3092 MADERA_AIF1TX_SLOT_LEN_MASK)))
3093 return 1;
3094
3095 return 0;
3096 }
3097
madera_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)3098 static int madera_hw_params(struct snd_pcm_substream *substream,
3099 struct snd_pcm_hw_params *params,
3100 struct snd_soc_dai *dai)
3101 {
3102 struct snd_soc_component *component = dai->component;
3103 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
3104 struct madera *madera = priv->madera;
3105 int base = dai->driver->base;
3106 const int *rates;
3107 int i, ret;
3108 unsigned int val;
3109 unsigned int channels = params_channels(params);
3110 unsigned int rate = params_rate(params);
3111 unsigned int chan_limit =
3112 madera->pdata.codec.max_channels_clocked[dai->id - 1];
3113 int tdm_width = priv->tdm_width[dai->id - 1];
3114 int tdm_slots = priv->tdm_slots[dai->id - 1];
3115 int bclk, lrclk, wl, frame, bclk_target, num_rates;
3116 int reconfig;
3117 unsigned int aif_tx_state = 0, aif_rx_state = 0;
3118
3119 if (rate % 4000) {
3120 rates = &madera_44k1_bclk_rates[0];
3121 num_rates = ARRAY_SIZE(madera_44k1_bclk_rates);
3122 } else {
3123 rates = &madera_48k_bclk_rates[0];
3124 num_rates = ARRAY_SIZE(madera_48k_bclk_rates);
3125 }
3126
3127 wl = snd_pcm_format_width(params_format(params));
3128
3129 if (tdm_slots) {
3130 madera_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
3131 tdm_slots, tdm_width);
3132 bclk_target = tdm_slots * tdm_width * rate;
3133 channels = tdm_slots;
3134 } else {
3135 bclk_target = snd_soc_params_to_bclk(params);
3136 tdm_width = wl;
3137 }
3138
3139 if (chan_limit && chan_limit < channels) {
3140 madera_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
3141 bclk_target /= channels;
3142 bclk_target *= chan_limit;
3143 }
3144
3145 /* Force multiple of 2 channels for I2S mode */
3146 val = snd_soc_component_read(component, base + MADERA_AIF_FORMAT);
3147 val &= MADERA_AIF1_FMT_MASK;
3148 if ((channels & 1) && val == MADERA_FMT_I2S_MODE) {
3149 madera_aif_dbg(dai, "Forcing stereo mode\n");
3150 bclk_target /= channels;
3151 bclk_target *= channels + 1;
3152 }
3153
3154 for (i = 0; i < num_rates; i++) {
3155 if (rates[i] >= bclk_target && rates[i] % rate == 0) {
3156 bclk = i;
3157 break;
3158 }
3159 }
3160
3161 if (i == num_rates) {
3162 madera_aif_err(dai, "Unsupported sample rate %dHz\n", rate);
3163 return -EINVAL;
3164 }
3165
3166 lrclk = rates[bclk] / rate;
3167
3168 madera_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
3169 rates[bclk], rates[bclk] / lrclk);
3170
3171 frame = wl << MADERA_AIF1TX_WL_SHIFT | tdm_width;
3172
3173 reconfig = madera_aif_cfg_changed(component, base, bclk, lrclk, frame);
3174 if (reconfig < 0)
3175 return reconfig;
3176
3177 if (reconfig) {
3178 /* Save AIF TX/RX state */
3179 regmap_read(madera->regmap, base + MADERA_AIF_TX_ENABLES,
3180 &aif_tx_state);
3181 regmap_read(madera->regmap, base + MADERA_AIF_RX_ENABLES,
3182 &aif_rx_state);
3183 /* Disable AIF TX/RX before reconfiguring it */
3184 regmap_update_bits(madera->regmap,
3185 base + MADERA_AIF_TX_ENABLES, 0xff, 0x0);
3186 regmap_update_bits(madera->regmap,
3187 base + MADERA_AIF_RX_ENABLES, 0xff, 0x0);
3188 }
3189
3190 ret = madera_hw_params_rate(substream, params, dai);
3191 if (ret != 0)
3192 goto restore_aif;
3193
3194 if (reconfig) {
3195 regmap_update_bits(madera->regmap,
3196 base + MADERA_AIF_BCLK_CTRL,
3197 MADERA_AIF1_BCLK_FREQ_MASK, bclk);
3198 regmap_update_bits(madera->regmap,
3199 base + MADERA_AIF_RX_BCLK_RATE,
3200 MADERA_AIF1RX_BCPF_MASK, lrclk);
3201 regmap_update_bits(madera->regmap,
3202 base + MADERA_AIF_FRAME_CTRL_1,
3203 MADERA_AIF1TX_WL_MASK |
3204 MADERA_AIF1TX_SLOT_LEN_MASK, frame);
3205 regmap_update_bits(madera->regmap,
3206 base + MADERA_AIF_FRAME_CTRL_2,
3207 MADERA_AIF1RX_WL_MASK |
3208 MADERA_AIF1RX_SLOT_LEN_MASK, frame);
3209 }
3210
3211 restore_aif:
3212 if (reconfig) {
3213 /* Restore AIF TX/RX state */
3214 regmap_update_bits(madera->regmap,
3215 base + MADERA_AIF_TX_ENABLES,
3216 0xff, aif_tx_state);
3217 regmap_update_bits(madera->regmap,
3218 base + MADERA_AIF_RX_ENABLES,
3219 0xff, aif_rx_state);
3220 }
3221
3222 return ret;
3223 }
3224
madera_is_syncclk(int clk_id)3225 static int madera_is_syncclk(int clk_id)
3226 {
3227 switch (clk_id) {
3228 case MADERA_CLK_SYSCLK_1:
3229 case MADERA_CLK_SYSCLK_2:
3230 case MADERA_CLK_SYSCLK_3:
3231 return 1;
3232 case MADERA_CLK_ASYNCCLK_1:
3233 case MADERA_CLK_ASYNCCLK_2:
3234 return 0;
3235 default:
3236 return -EINVAL;
3237 }
3238 }
3239
madera_dai_set_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)3240 static int madera_dai_set_sysclk(struct snd_soc_dai *dai,
3241 int clk_id, unsigned int freq, int dir)
3242 {
3243 struct snd_soc_component *component = dai->component;
3244 struct snd_soc_dapm_context *dapm =
3245 snd_soc_component_get_dapm(component);
3246 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
3247 struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1];
3248 struct snd_soc_dapm_route routes[2];
3249 int is_sync;
3250
3251 is_sync = madera_is_syncclk(clk_id);
3252 if (is_sync < 0) {
3253 dev_err(component->dev, "Illegal DAI clock id %d\n", clk_id);
3254 return is_sync;
3255 }
3256
3257 if (is_sync == madera_is_syncclk(dai_priv->clk))
3258 return 0;
3259
3260 if (snd_soc_dai_active(dai)) {
3261 dev_err(component->dev, "Can't change clock on active DAI %d\n",
3262 dai->id);
3263 return -EBUSY;
3264 }
3265
3266 dev_dbg(component->dev, "Setting AIF%d to %s\n", dai->id,
3267 is_sync ? "SYSCLK" : "ASYNCCLK");
3268
3269 /*
3270 * A connection to SYSCLK is always required, we only add and remove
3271 * a connection to ASYNCCLK
3272 */
3273 memset(&routes, 0, sizeof(routes));
3274 routes[0].sink = dai->driver->capture.stream_name;
3275 routes[1].sink = dai->driver->playback.stream_name;
3276 routes[0].source = "ASYNCCLK";
3277 routes[1].source = "ASYNCCLK";
3278
3279 if (is_sync)
3280 snd_soc_dapm_del_routes(dapm, routes, ARRAY_SIZE(routes));
3281 else
3282 snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
3283
3284 dai_priv->clk = clk_id;
3285
3286 return snd_soc_dapm_sync(dapm);
3287 }
3288
madera_set_tristate(struct snd_soc_dai * dai,int tristate)3289 static int madera_set_tristate(struct snd_soc_dai *dai, int tristate)
3290 {
3291 struct snd_soc_component *component = dai->component;
3292 int base = dai->driver->base;
3293 unsigned int reg;
3294 int ret;
3295
3296 if (tristate)
3297 reg = MADERA_AIF1_TRI;
3298 else
3299 reg = 0;
3300
3301 ret = snd_soc_component_update_bits(component,
3302 base + MADERA_AIF_RATE_CTRL,
3303 MADERA_AIF1_TRI, reg);
3304 if (ret < 0)
3305 return ret;
3306 else
3307 return 0;
3308 }
3309
madera_set_channels_to_mask(struct snd_soc_dai * dai,unsigned int base,int channels,unsigned int mask)3310 static void madera_set_channels_to_mask(struct snd_soc_dai *dai,
3311 unsigned int base,
3312 int channels, unsigned int mask)
3313 {
3314 struct snd_soc_component *component = dai->component;
3315 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
3316 struct madera *madera = priv->madera;
3317 int slot, i;
3318
3319 for (i = 0; i < channels; ++i) {
3320 slot = ffs(mask) - 1;
3321 if (slot < 0)
3322 return;
3323
3324 regmap_write(madera->regmap, base + i, slot);
3325
3326 mask &= ~(1 << slot);
3327 }
3328
3329 if (mask)
3330 madera_aif_warn(dai, "Too many channels in TDM mask\n");
3331 }
3332
madera_set_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)3333 static int madera_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
3334 unsigned int rx_mask, int slots, int slot_width)
3335 {
3336 struct snd_soc_component *component = dai->component;
3337 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
3338 int base = dai->driver->base;
3339 int rx_max_chan = dai->driver->playback.channels_max;
3340 int tx_max_chan = dai->driver->capture.channels_max;
3341
3342 /* Only support TDM for the physical AIFs */
3343 if (dai->id > MADERA_MAX_AIF)
3344 return -ENOTSUPP;
3345
3346 if (slots == 0) {
3347 tx_mask = (1 << tx_max_chan) - 1;
3348 rx_mask = (1 << rx_max_chan) - 1;
3349 }
3350
3351 madera_set_channels_to_mask(dai, base + MADERA_AIF_FRAME_CTRL_3,
3352 tx_max_chan, tx_mask);
3353 madera_set_channels_to_mask(dai, base + MADERA_AIF_FRAME_CTRL_11,
3354 rx_max_chan, rx_mask);
3355
3356 priv->tdm_width[dai->id - 1] = slot_width;
3357 priv->tdm_slots[dai->id - 1] = slots;
3358
3359 return 0;
3360 }
3361
3362 const struct snd_soc_dai_ops madera_dai_ops = {
3363 .startup = &madera_startup,
3364 .set_fmt = &madera_set_fmt,
3365 .set_tdm_slot = &madera_set_tdm_slot,
3366 .hw_params = &madera_hw_params,
3367 .set_sysclk = &madera_dai_set_sysclk,
3368 .set_tristate = &madera_set_tristate,
3369 };
3370 EXPORT_SYMBOL_GPL(madera_dai_ops);
3371
3372 const struct snd_soc_dai_ops madera_simple_dai_ops = {
3373 .startup = &madera_startup,
3374 .hw_params = &madera_hw_params_rate,
3375 .set_sysclk = &madera_dai_set_sysclk,
3376 };
3377 EXPORT_SYMBOL_GPL(madera_simple_dai_ops);
3378
madera_init_dai(struct madera_priv * priv,int id)3379 int madera_init_dai(struct madera_priv *priv, int id)
3380 {
3381 struct madera_dai_priv *dai_priv = &priv->dai[id];
3382
3383 dai_priv->clk = MADERA_CLK_SYSCLK_1;
3384 dai_priv->constraint = madera_constraint;
3385
3386 return 0;
3387 }
3388 EXPORT_SYMBOL_GPL(madera_init_dai);
3389
3390 static const struct {
3391 unsigned int min;
3392 unsigned int max;
3393 u16 fratio;
3394 int ratio;
3395 } fll_sync_fratios[] = {
3396 { 0, 64000, 4, 16 },
3397 { 64000, 128000, 3, 8 },
3398 { 128000, 256000, 2, 4 },
3399 { 256000, 1000000, 1, 2 },
3400 { 1000000, 13500000, 0, 1 },
3401 };
3402
3403 static const unsigned int pseudo_fref_max[MADERA_FLL_MAX_FRATIO] = {
3404 13500000,
3405 6144000,
3406 6144000,
3407 3072000,
3408 3072000,
3409 2822400,
3410 2822400,
3411 1536000,
3412 1536000,
3413 1536000,
3414 1536000,
3415 1536000,
3416 1536000,
3417 1536000,
3418 1536000,
3419 768000,
3420 };
3421
3422 struct madera_fll_gains {
3423 unsigned int min;
3424 unsigned int max;
3425 int gain; /* main gain */
3426 int alt_gain; /* alternate integer gain */
3427 };
3428
3429 static const struct madera_fll_gains madera_fll_sync_gains[] = {
3430 { 0, 256000, 0, -1 },
3431 { 256000, 1000000, 2, -1 },
3432 { 1000000, 13500000, 4, -1 },
3433 };
3434
3435 static const struct madera_fll_gains madera_fll_main_gains[] = {
3436 { 0, 100000, 0, 2 },
3437 { 100000, 375000, 2, 2 },
3438 { 375000, 768000, 3, 2 },
3439 { 768001, 1500000, 3, 3 },
3440 { 1500000, 6000000, 4, 3 },
3441 { 6000000, 13500000, 5, 3 },
3442 };
3443
madera_find_sync_fratio(unsigned int fref,int * fratio)3444 static int madera_find_sync_fratio(unsigned int fref, int *fratio)
3445 {
3446 int i;
3447
3448 for (i = 0; i < ARRAY_SIZE(fll_sync_fratios); i++) {
3449 if (fll_sync_fratios[i].min <= fref &&
3450 fref <= fll_sync_fratios[i].max) {
3451 if (fratio)
3452 *fratio = fll_sync_fratios[i].fratio;
3453
3454 return fll_sync_fratios[i].ratio;
3455 }
3456 }
3457
3458 return -EINVAL;
3459 }
3460
madera_find_main_fratio(unsigned int fref,unsigned int fout,int * fratio)3461 static int madera_find_main_fratio(unsigned int fref, unsigned int fout,
3462 int *fratio)
3463 {
3464 int ratio = 1;
3465
3466 while ((fout / (ratio * fref)) > MADERA_FLL_MAX_N)
3467 ratio++;
3468
3469 if (fratio)
3470 *fratio = ratio - 1;
3471
3472 return ratio;
3473 }
3474
madera_find_fratio(struct madera_fll * fll,unsigned int fref,bool sync,int * fratio)3475 static int madera_find_fratio(struct madera_fll *fll, unsigned int fref,
3476 bool sync, int *fratio)
3477 {
3478 switch (fll->madera->type) {
3479 case CS47L35:
3480 switch (fll->madera->rev) {
3481 case 0:
3482 /* rev A0 uses sync calculation for both loops */
3483 return madera_find_sync_fratio(fref, fratio);
3484 default:
3485 if (sync)
3486 return madera_find_sync_fratio(fref, fratio);
3487 else
3488 return madera_find_main_fratio(fref,
3489 fll->fout,
3490 fratio);
3491 }
3492 break;
3493 case CS47L85:
3494 case WM1840:
3495 /* these use the same calculation for main and sync loops */
3496 return madera_find_sync_fratio(fref, fratio);
3497 default:
3498 if (sync)
3499 return madera_find_sync_fratio(fref, fratio);
3500 else
3501 return madera_find_main_fratio(fref, fll->fout, fratio);
3502 }
3503 }
3504
madera_calc_fratio(struct madera_fll * fll,struct madera_fll_cfg * cfg,unsigned int fref,bool sync)3505 static int madera_calc_fratio(struct madera_fll *fll,
3506 struct madera_fll_cfg *cfg,
3507 unsigned int fref, bool sync)
3508 {
3509 int init_ratio, ratio;
3510 int refdiv, div;
3511
3512 /* fref must be <=13.5MHz, find initial refdiv */
3513 div = 1;
3514 cfg->refdiv = 0;
3515 while (fref > MADERA_FLL_MAX_FREF) {
3516 div *= 2;
3517 fref /= 2;
3518 cfg->refdiv++;
3519
3520 if (div > MADERA_FLL_MAX_REFDIV)
3521 return -EINVAL;
3522 }
3523
3524 /* Find an appropriate FLL_FRATIO */
3525 init_ratio = madera_find_fratio(fll, fref, sync, &cfg->fratio);
3526 if (init_ratio < 0) {
3527 madera_fll_err(fll, "Unable to find FRATIO for fref=%uHz\n",
3528 fref);
3529 return init_ratio;
3530 }
3531
3532 if (!sync)
3533 cfg->fratio = init_ratio - 1;
3534
3535 switch (fll->madera->type) {
3536 case CS47L35:
3537 switch (fll->madera->rev) {
3538 case 0:
3539 if (sync)
3540 return init_ratio;
3541 break;
3542 default:
3543 return init_ratio;
3544 }
3545 break;
3546 case CS47L85:
3547 case WM1840:
3548 if (sync)
3549 return init_ratio;
3550 break;
3551 default:
3552 return init_ratio;
3553 }
3554
3555 /*
3556 * For CS47L35 rev A0, CS47L85 and WM1840 adjust FRATIO/refdiv to avoid
3557 * integer mode if possible
3558 */
3559 refdiv = cfg->refdiv;
3560
3561 while (div <= MADERA_FLL_MAX_REFDIV) {
3562 /*
3563 * start from init_ratio because this may already give a
3564 * fractional N.K
3565 */
3566 for (ratio = init_ratio; ratio > 0; ratio--) {
3567 if (fll->fout % (ratio * fref)) {
3568 cfg->refdiv = refdiv;
3569 cfg->fratio = ratio - 1;
3570 return ratio;
3571 }
3572 }
3573
3574 for (ratio = init_ratio + 1; ratio <= MADERA_FLL_MAX_FRATIO;
3575 ratio++) {
3576 if ((MADERA_FLL_VCO_CORNER / 2) /
3577 (MADERA_FLL_VCO_MULT * ratio) < fref)
3578 break;
3579
3580 if (fref > pseudo_fref_max[ratio - 1])
3581 break;
3582
3583 if (fll->fout % (ratio * fref)) {
3584 cfg->refdiv = refdiv;
3585 cfg->fratio = ratio - 1;
3586 return ratio;
3587 }
3588 }
3589
3590 div *= 2;
3591 fref /= 2;
3592 refdiv++;
3593 init_ratio = madera_find_fratio(fll, fref, sync, NULL);
3594 }
3595
3596 madera_fll_warn(fll, "Falling back to integer mode operation\n");
3597
3598 return cfg->fratio + 1;
3599 }
3600
madera_find_fll_gain(struct madera_fll * fll,struct madera_fll_cfg * cfg,unsigned int fref,const struct madera_fll_gains * gains,int n_gains)3601 static int madera_find_fll_gain(struct madera_fll *fll,
3602 struct madera_fll_cfg *cfg,
3603 unsigned int fref,
3604 const struct madera_fll_gains *gains,
3605 int n_gains)
3606 {
3607 int i;
3608
3609 for (i = 0; i < n_gains; i++) {
3610 if (gains[i].min <= fref && fref <= gains[i].max) {
3611 cfg->gain = gains[i].gain;
3612 cfg->alt_gain = gains[i].alt_gain;
3613 return 0;
3614 }
3615 }
3616
3617 madera_fll_err(fll, "Unable to find gain for fref=%uHz\n", fref);
3618
3619 return -EINVAL;
3620 }
3621
madera_calc_fll(struct madera_fll * fll,struct madera_fll_cfg * cfg,unsigned int fref,bool sync)3622 static int madera_calc_fll(struct madera_fll *fll,
3623 struct madera_fll_cfg *cfg,
3624 unsigned int fref, bool sync)
3625 {
3626 unsigned int gcd_fll;
3627 const struct madera_fll_gains *gains;
3628 int n_gains;
3629 int ratio, ret;
3630
3631 madera_fll_dbg(fll, "fref=%u Fout=%u fvco=%u\n",
3632 fref, fll->fout, fll->fout * MADERA_FLL_VCO_MULT);
3633
3634 /* Find an appropriate FLL_FRATIO and refdiv */
3635 ratio = madera_calc_fratio(fll, cfg, fref, sync);
3636 if (ratio < 0)
3637 return ratio;
3638
3639 /* Apply the division for our remaining calculations */
3640 fref = fref / (1 << cfg->refdiv);
3641
3642 cfg->n = fll->fout / (ratio * fref);
3643
3644 if (fll->fout % (ratio * fref)) {
3645 gcd_fll = gcd(fll->fout, ratio * fref);
3646 madera_fll_dbg(fll, "GCD=%u\n", gcd_fll);
3647
3648 cfg->theta = (fll->fout - (cfg->n * ratio * fref))
3649 / gcd_fll;
3650 cfg->lambda = (ratio * fref) / gcd_fll;
3651 } else {
3652 cfg->theta = 0;
3653 cfg->lambda = 0;
3654 }
3655
3656 /*
3657 * Round down to 16bit range with cost of accuracy lost.
3658 * Denominator must be bigger than numerator so we only
3659 * take care of it.
3660 */
3661 while (cfg->lambda >= (1 << 16)) {
3662 cfg->theta >>= 1;
3663 cfg->lambda >>= 1;
3664 }
3665
3666 switch (fll->madera->type) {
3667 case CS47L35:
3668 switch (fll->madera->rev) {
3669 case 0:
3670 /* Rev A0 uses the sync gains for both loops */
3671 gains = madera_fll_sync_gains;
3672 n_gains = ARRAY_SIZE(madera_fll_sync_gains);
3673 break;
3674 default:
3675 if (sync) {
3676 gains = madera_fll_sync_gains;
3677 n_gains = ARRAY_SIZE(madera_fll_sync_gains);
3678 } else {
3679 gains = madera_fll_main_gains;
3680 n_gains = ARRAY_SIZE(madera_fll_main_gains);
3681 }
3682 break;
3683 }
3684 break;
3685 case CS47L85:
3686 case WM1840:
3687 /* These use the sync gains for both loops */
3688 gains = madera_fll_sync_gains;
3689 n_gains = ARRAY_SIZE(madera_fll_sync_gains);
3690 break;
3691 default:
3692 if (sync) {
3693 gains = madera_fll_sync_gains;
3694 n_gains = ARRAY_SIZE(madera_fll_sync_gains);
3695 } else {
3696 gains = madera_fll_main_gains;
3697 n_gains = ARRAY_SIZE(madera_fll_main_gains);
3698 }
3699 break;
3700 }
3701
3702 ret = madera_find_fll_gain(fll, cfg, fref, gains, n_gains);
3703 if (ret)
3704 return ret;
3705
3706 madera_fll_dbg(fll, "N=%d THETA=%d LAMBDA=%d\n",
3707 cfg->n, cfg->theta, cfg->lambda);
3708 madera_fll_dbg(fll, "FRATIO=0x%x(%d) REFCLK_DIV=0x%x(%d)\n",
3709 cfg->fratio, ratio, cfg->refdiv, 1 << cfg->refdiv);
3710 madera_fll_dbg(fll, "GAIN=0x%x(%d)\n", cfg->gain, 1 << cfg->gain);
3711
3712 return 0;
3713 }
3714
madera_write_fll(struct madera * madera,unsigned int base,struct madera_fll_cfg * cfg,int source,bool sync,int gain)3715 static bool madera_write_fll(struct madera *madera, unsigned int base,
3716 struct madera_fll_cfg *cfg, int source,
3717 bool sync, int gain)
3718 {
3719 bool change, fll_change;
3720
3721 fll_change = false;
3722 regmap_update_bits_check(madera->regmap,
3723 base + MADERA_FLL_CONTROL_3_OFFS,
3724 MADERA_FLL1_THETA_MASK,
3725 cfg->theta, &change);
3726 fll_change |= change;
3727 regmap_update_bits_check(madera->regmap,
3728 base + MADERA_FLL_CONTROL_4_OFFS,
3729 MADERA_FLL1_LAMBDA_MASK,
3730 cfg->lambda, &change);
3731 fll_change |= change;
3732 regmap_update_bits_check(madera->regmap,
3733 base + MADERA_FLL_CONTROL_5_OFFS,
3734 MADERA_FLL1_FRATIO_MASK,
3735 cfg->fratio << MADERA_FLL1_FRATIO_SHIFT,
3736 &change);
3737 fll_change |= change;
3738 regmap_update_bits_check(madera->regmap,
3739 base + MADERA_FLL_CONTROL_6_OFFS,
3740 MADERA_FLL1_REFCLK_DIV_MASK |
3741 MADERA_FLL1_REFCLK_SRC_MASK,
3742 cfg->refdiv << MADERA_FLL1_REFCLK_DIV_SHIFT |
3743 source << MADERA_FLL1_REFCLK_SRC_SHIFT,
3744 &change);
3745 fll_change |= change;
3746
3747 if (sync) {
3748 regmap_update_bits_check(madera->regmap,
3749 base + MADERA_FLL_SYNCHRONISER_7_OFFS,
3750 MADERA_FLL1_GAIN_MASK,
3751 gain << MADERA_FLL1_GAIN_SHIFT,
3752 &change);
3753 fll_change |= change;
3754 } else {
3755 regmap_update_bits_check(madera->regmap,
3756 base + MADERA_FLL_CONTROL_7_OFFS,
3757 MADERA_FLL1_GAIN_MASK,
3758 gain << MADERA_FLL1_GAIN_SHIFT,
3759 &change);
3760 fll_change |= change;
3761 }
3762
3763 regmap_update_bits_check(madera->regmap,
3764 base + MADERA_FLL_CONTROL_2_OFFS,
3765 MADERA_FLL1_CTRL_UPD | MADERA_FLL1_N_MASK,
3766 MADERA_FLL1_CTRL_UPD | cfg->n, &change);
3767 fll_change |= change;
3768
3769 return fll_change;
3770 }
3771
madera_is_enabled_fll(struct madera_fll * fll,int base)3772 static int madera_is_enabled_fll(struct madera_fll *fll, int base)
3773 {
3774 struct madera *madera = fll->madera;
3775 unsigned int reg;
3776 int ret;
3777
3778 ret = regmap_read(madera->regmap,
3779 base + MADERA_FLL_CONTROL_1_OFFS, ®);
3780 if (ret != 0) {
3781 madera_fll_err(fll, "Failed to read current state: %d\n", ret);
3782 return ret;
3783 }
3784
3785 return reg & MADERA_FLL1_ENA;
3786 }
3787
madera_wait_for_fll(struct madera_fll * fll,bool requested)3788 static int madera_wait_for_fll(struct madera_fll *fll, bool requested)
3789 {
3790 struct madera *madera = fll->madera;
3791 unsigned int val = 0;
3792 bool status;
3793 int i;
3794
3795 madera_fll_dbg(fll, "Waiting for FLL...\n");
3796
3797 for (i = 0; i < 30; i++) {
3798 regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_2, &val);
3799 status = val & (MADERA_FLL1_LOCK_STS1 << (fll->id - 1));
3800 if (status == requested)
3801 return 0;
3802
3803 switch (i) {
3804 case 0 ... 5:
3805 usleep_range(75, 125);
3806 break;
3807 case 11 ... 20:
3808 usleep_range(750, 1250);
3809 break;
3810 default:
3811 msleep(20);
3812 break;
3813 }
3814 }
3815
3816 madera_fll_warn(fll, "Timed out waiting for lock\n");
3817
3818 return -ETIMEDOUT;
3819 }
3820
madera_set_fll_phase_integrator(struct madera_fll * fll,struct madera_fll_cfg * ref_cfg,bool sync)3821 static bool madera_set_fll_phase_integrator(struct madera_fll *fll,
3822 struct madera_fll_cfg *ref_cfg,
3823 bool sync)
3824 {
3825 unsigned int val;
3826 bool reg_change;
3827
3828 if (!sync && ref_cfg->theta == 0)
3829 val = (1 << MADERA_FLL1_PHASE_ENA_SHIFT) |
3830 (2 << MADERA_FLL1_PHASE_GAIN_SHIFT);
3831 else
3832 val = 2 << MADERA_FLL1_PHASE_GAIN_SHIFT;
3833
3834 regmap_update_bits_check(fll->madera->regmap,
3835 fll->base + MADERA_FLL_EFS_2_OFFS,
3836 MADERA_FLL1_PHASE_ENA_MASK |
3837 MADERA_FLL1_PHASE_GAIN_MASK,
3838 val, ®_change);
3839
3840 return reg_change;
3841 }
3842
madera_set_fll_clks_reg(struct madera_fll * fll,bool ena,unsigned int reg,unsigned int mask,unsigned int shift)3843 static int madera_set_fll_clks_reg(struct madera_fll *fll, bool ena,
3844 unsigned int reg, unsigned int mask,
3845 unsigned int shift)
3846 {
3847 struct madera *madera = fll->madera;
3848 unsigned int src;
3849 struct clk *clk;
3850 int ret;
3851
3852 ret = regmap_read(madera->regmap, reg, &src);
3853 if (ret != 0) {
3854 madera_fll_err(fll, "Failed to read current source: %d\n",
3855 ret);
3856 return ret;
3857 }
3858
3859 src = (src & mask) >> shift;
3860
3861 switch (src) {
3862 case MADERA_FLL_SRC_MCLK1:
3863 clk = madera->mclk[MADERA_MCLK1].clk;
3864 break;
3865 case MADERA_FLL_SRC_MCLK2:
3866 clk = madera->mclk[MADERA_MCLK2].clk;
3867 break;
3868 case MADERA_FLL_SRC_MCLK3:
3869 clk = madera->mclk[MADERA_MCLK3].clk;
3870 break;
3871 default:
3872 return 0;
3873 }
3874
3875 if (ena) {
3876 return clk_prepare_enable(clk);
3877 } else {
3878 clk_disable_unprepare(clk);
3879 return 0;
3880 }
3881 }
3882
madera_set_fll_clks(struct madera_fll * fll,int base,bool ena)3883 static inline int madera_set_fll_clks(struct madera_fll *fll, int base, bool ena)
3884 {
3885 return madera_set_fll_clks_reg(fll, ena,
3886 base + MADERA_FLL_CONTROL_6_OFFS,
3887 MADERA_FLL1_REFCLK_SRC_MASK,
3888 MADERA_FLL1_REFCLK_SRC_SHIFT);
3889 }
3890
madera_set_fllao_clks(struct madera_fll * fll,int base,bool ena)3891 static inline int madera_set_fllao_clks(struct madera_fll *fll, int base, bool ena)
3892 {
3893 return madera_set_fll_clks_reg(fll, ena,
3894 base + MADERA_FLLAO_CONTROL_6_OFFS,
3895 MADERA_FLL_AO_REFCLK_SRC_MASK,
3896 MADERA_FLL_AO_REFCLK_SRC_SHIFT);
3897 }
3898
madera_set_fllhj_clks(struct madera_fll * fll,int base,bool ena)3899 static inline int madera_set_fllhj_clks(struct madera_fll *fll, int base, bool ena)
3900 {
3901 return madera_set_fll_clks_reg(fll, ena,
3902 base + MADERA_FLL_CONTROL_1_OFFS,
3903 CS47L92_FLL1_REFCLK_SRC_MASK,
3904 CS47L92_FLL1_REFCLK_SRC_SHIFT);
3905 }
3906
madera_disable_fll(struct madera_fll * fll)3907 static void madera_disable_fll(struct madera_fll *fll)
3908 {
3909 struct madera *madera = fll->madera;
3910 unsigned int sync_base;
3911 bool ref_change, sync_change;
3912
3913 switch (madera->type) {
3914 case CS47L35:
3915 sync_base = fll->base + CS47L35_FLL_SYNCHRONISER_OFFS;
3916 break;
3917 default:
3918 sync_base = fll->base + MADERA_FLL_SYNCHRONISER_OFFS;
3919 break;
3920 }
3921
3922 madera_fll_dbg(fll, "Disabling FLL\n");
3923
3924 regmap_update_bits(madera->regmap,
3925 fll->base + MADERA_FLL_CONTROL_1_OFFS,
3926 MADERA_FLL1_FREERUN, MADERA_FLL1_FREERUN);
3927 regmap_update_bits_check(madera->regmap,
3928 fll->base + MADERA_FLL_CONTROL_1_OFFS,
3929 MADERA_FLL1_ENA, 0, &ref_change);
3930 regmap_update_bits_check(madera->regmap,
3931 sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS,
3932 MADERA_FLL1_SYNC_ENA, 0, &sync_change);
3933 regmap_update_bits(madera->regmap,
3934 fll->base + MADERA_FLL_CONTROL_1_OFFS,
3935 MADERA_FLL1_FREERUN, 0);
3936
3937 madera_wait_for_fll(fll, false);
3938
3939 if (sync_change)
3940 madera_set_fll_clks(fll, sync_base, false);
3941
3942 if (ref_change) {
3943 madera_set_fll_clks(fll, fll->base, false);
3944 pm_runtime_put_autosuspend(madera->dev);
3945 }
3946 }
3947
madera_enable_fll(struct madera_fll * fll)3948 static int madera_enable_fll(struct madera_fll *fll)
3949 {
3950 struct madera *madera = fll->madera;
3951 bool have_sync = false;
3952 int already_enabled = madera_is_enabled_fll(fll, fll->base);
3953 int sync_enabled;
3954 struct madera_fll_cfg cfg;
3955 unsigned int sync_base;
3956 int gain, ret;
3957 bool fll_change = false;
3958
3959 if (already_enabled < 0)
3960 return already_enabled; /* error getting current state */
3961
3962 if (fll->ref_src < 0 || fll->ref_freq == 0) {
3963 madera_fll_err(fll, "No REFCLK\n");
3964 ret = -EINVAL;
3965 goto err;
3966 }
3967
3968 madera_fll_dbg(fll, "Enabling FLL, initially %s\n",
3969 str_enabled_disabled(already_enabled));
3970
3971 if (fll->fout < MADERA_FLL_MIN_FOUT ||
3972 fll->fout > MADERA_FLL_MAX_FOUT) {
3973 madera_fll_err(fll, "invalid fout %uHz\n", fll->fout);
3974 ret = -EINVAL;
3975 goto err;
3976 }
3977
3978 switch (madera->type) {
3979 case CS47L35:
3980 sync_base = fll->base + CS47L35_FLL_SYNCHRONISER_OFFS;
3981 break;
3982 default:
3983 sync_base = fll->base + MADERA_FLL_SYNCHRONISER_OFFS;
3984 break;
3985 }
3986
3987 sync_enabled = madera_is_enabled_fll(fll, sync_base);
3988 if (sync_enabled < 0)
3989 return sync_enabled;
3990
3991 if (already_enabled) {
3992 /* Facilitate smooth refclk across the transition */
3993 regmap_update_bits(fll->madera->regmap,
3994 fll->base + MADERA_FLL_CONTROL_1_OFFS,
3995 MADERA_FLL1_FREERUN,
3996 MADERA_FLL1_FREERUN);
3997 udelay(32);
3998 regmap_update_bits(fll->madera->regmap,
3999 fll->base + MADERA_FLL_CONTROL_7_OFFS,
4000 MADERA_FLL1_GAIN_MASK, 0);
4001
4002 if (sync_enabled > 0)
4003 madera_set_fll_clks(fll, sync_base, false);
4004 madera_set_fll_clks(fll, fll->base, false);
4005 }
4006
4007 /* Apply SYNCCLK setting */
4008 if (fll->sync_src >= 0) {
4009 ret = madera_calc_fll(fll, &cfg, fll->sync_freq, true);
4010 if (ret < 0)
4011 goto err;
4012
4013 fll_change |= madera_write_fll(madera, sync_base,
4014 &cfg, fll->sync_src,
4015 true, cfg.gain);
4016 have_sync = true;
4017 }
4018
4019 if (already_enabled && !!sync_enabled != have_sync)
4020 madera_fll_warn(fll, "Synchroniser changed on active FLL\n");
4021
4022 /* Apply REFCLK setting */
4023 ret = madera_calc_fll(fll, &cfg, fll->ref_freq, false);
4024 if (ret < 0)
4025 goto err;
4026
4027 /* Ref path hardcodes lambda to 65536 when sync is on */
4028 if (have_sync && cfg.lambda)
4029 cfg.theta = (cfg.theta * (1 << 16)) / cfg.lambda;
4030
4031 switch (fll->madera->type) {
4032 case CS47L35:
4033 switch (fll->madera->rev) {
4034 case 0:
4035 gain = cfg.gain;
4036 break;
4037 default:
4038 fll_change |=
4039 madera_set_fll_phase_integrator(fll, &cfg,
4040 have_sync);
4041 if (!have_sync && cfg.theta == 0)
4042 gain = cfg.alt_gain;
4043 else
4044 gain = cfg.gain;
4045 break;
4046 }
4047 break;
4048 case CS47L85:
4049 case WM1840:
4050 gain = cfg.gain;
4051 break;
4052 default:
4053 fll_change |= madera_set_fll_phase_integrator(fll, &cfg,
4054 have_sync);
4055 if (!have_sync && cfg.theta == 0)
4056 gain = cfg.alt_gain;
4057 else
4058 gain = cfg.gain;
4059 break;
4060 }
4061
4062 fll_change |= madera_write_fll(madera, fll->base,
4063 &cfg, fll->ref_src,
4064 false, gain);
4065
4066 /*
4067 * Increase the bandwidth if we're not using a low frequency
4068 * sync source.
4069 */
4070 if (have_sync && fll->sync_freq > 100000)
4071 regmap_update_bits(madera->regmap,
4072 sync_base + MADERA_FLL_SYNCHRONISER_7_OFFS,
4073 MADERA_FLL1_SYNC_DFSAT_MASK, 0);
4074 else
4075 regmap_update_bits(madera->regmap,
4076 sync_base + MADERA_FLL_SYNCHRONISER_7_OFFS,
4077 MADERA_FLL1_SYNC_DFSAT_MASK,
4078 MADERA_FLL1_SYNC_DFSAT);
4079
4080 if (!already_enabled)
4081 pm_runtime_get_sync(madera->dev);
4082
4083 if (have_sync) {
4084 madera_set_fll_clks(fll, sync_base, true);
4085 regmap_update_bits(madera->regmap,
4086 sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS,
4087 MADERA_FLL1_SYNC_ENA,
4088 MADERA_FLL1_SYNC_ENA);
4089 }
4090
4091 madera_set_fll_clks(fll, fll->base, true);
4092 regmap_update_bits(madera->regmap,
4093 fll->base + MADERA_FLL_CONTROL_1_OFFS,
4094 MADERA_FLL1_ENA, MADERA_FLL1_ENA);
4095
4096 if (already_enabled)
4097 regmap_update_bits(madera->regmap,
4098 fll->base + MADERA_FLL_CONTROL_1_OFFS,
4099 MADERA_FLL1_FREERUN, 0);
4100
4101 if (fll_change || !already_enabled)
4102 madera_wait_for_fll(fll, true);
4103
4104 return 0;
4105
4106 err:
4107 /* In case of error don't leave the FLL running with an old config */
4108 madera_disable_fll(fll);
4109
4110 return ret;
4111 }
4112
madera_apply_fll(struct madera_fll * fll)4113 static int madera_apply_fll(struct madera_fll *fll)
4114 {
4115 if (fll->fout) {
4116 return madera_enable_fll(fll);
4117 } else {
4118 madera_disable_fll(fll);
4119 return 0;
4120 }
4121 }
4122
madera_set_fll_syncclk(struct madera_fll * fll,int source,unsigned int fref,unsigned int fout)4123 int madera_set_fll_syncclk(struct madera_fll *fll, int source,
4124 unsigned int fref, unsigned int fout)
4125 {
4126 /*
4127 * fout is ignored, since the synchronizer is an optional extra
4128 * constraint on the Fout generated from REFCLK, so the Fout is
4129 * set when configuring REFCLK
4130 */
4131
4132 if (fll->sync_src == source && fll->sync_freq == fref)
4133 return 0;
4134
4135 fll->sync_src = source;
4136 fll->sync_freq = fref;
4137
4138 return madera_apply_fll(fll);
4139 }
4140 EXPORT_SYMBOL_GPL(madera_set_fll_syncclk);
4141
madera_set_fll_refclk(struct madera_fll * fll,int source,unsigned int fref,unsigned int fout)4142 int madera_set_fll_refclk(struct madera_fll *fll, int source,
4143 unsigned int fref, unsigned int fout)
4144 {
4145 int ret;
4146
4147 if (fll->ref_src == source &&
4148 fll->ref_freq == fref && fll->fout == fout)
4149 return 0;
4150
4151 /*
4152 * Changes of fout on an enabled FLL aren't allowed except when
4153 * setting fout==0 to disable the FLL
4154 */
4155 if (fout && fout != fll->fout) {
4156 ret = madera_is_enabled_fll(fll, fll->base);
4157 if (ret < 0)
4158 return ret;
4159
4160 if (ret) {
4161 madera_fll_err(fll, "Can't change Fout on active FLL\n");
4162 return -EBUSY;
4163 }
4164 }
4165
4166 fll->ref_src = source;
4167 fll->ref_freq = fref;
4168 fll->fout = fout;
4169
4170 return madera_apply_fll(fll);
4171 }
4172 EXPORT_SYMBOL_GPL(madera_set_fll_refclk);
4173
madera_init_fll(struct madera * madera,int id,int base,struct madera_fll * fll)4174 int madera_init_fll(struct madera *madera, int id, int base,
4175 struct madera_fll *fll)
4176 {
4177 fll->id = id;
4178 fll->base = base;
4179 fll->madera = madera;
4180 fll->ref_src = MADERA_FLL_SRC_NONE;
4181 fll->sync_src = MADERA_FLL_SRC_NONE;
4182
4183 regmap_update_bits(madera->regmap,
4184 fll->base + MADERA_FLL_CONTROL_1_OFFS,
4185 MADERA_FLL1_FREERUN, 0);
4186
4187 return 0;
4188 }
4189 EXPORT_SYMBOL_GPL(madera_init_fll);
4190
4191 static const struct reg_sequence madera_fll_ao_32K_49M_patch[] = {
4192 { MADERA_FLLAO_CONTROL_2, 0x02EE },
4193 { MADERA_FLLAO_CONTROL_3, 0x0000 },
4194 { MADERA_FLLAO_CONTROL_4, 0x0001 },
4195 { MADERA_FLLAO_CONTROL_5, 0x0002 },
4196 { MADERA_FLLAO_CONTROL_6, 0x8001 },
4197 { MADERA_FLLAO_CONTROL_7, 0x0004 },
4198 { MADERA_FLLAO_CONTROL_8, 0x0077 },
4199 { MADERA_FLLAO_CONTROL_10, 0x06D8 },
4200 { MADERA_FLLAO_CONTROL_11, 0x0085 },
4201 { MADERA_FLLAO_CONTROL_2, 0x82EE },
4202 };
4203
4204 static const struct reg_sequence madera_fll_ao_32K_45M_patch[] = {
4205 { MADERA_FLLAO_CONTROL_2, 0x02B1 },
4206 { MADERA_FLLAO_CONTROL_3, 0x0001 },
4207 { MADERA_FLLAO_CONTROL_4, 0x0010 },
4208 { MADERA_FLLAO_CONTROL_5, 0x0002 },
4209 { MADERA_FLLAO_CONTROL_6, 0x8001 },
4210 { MADERA_FLLAO_CONTROL_7, 0x0004 },
4211 { MADERA_FLLAO_CONTROL_8, 0x0077 },
4212 { MADERA_FLLAO_CONTROL_10, 0x06D8 },
4213 { MADERA_FLLAO_CONTROL_11, 0x0005 },
4214 { MADERA_FLLAO_CONTROL_2, 0x82B1 },
4215 };
4216
4217 struct madera_fllao_patch {
4218 unsigned int fin;
4219 unsigned int fout;
4220 const struct reg_sequence *patch;
4221 unsigned int patch_size;
4222 };
4223
4224 static const struct madera_fllao_patch madera_fllao_settings[] = {
4225 {
4226 .fin = 32768,
4227 .fout = 49152000,
4228 .patch = madera_fll_ao_32K_49M_patch,
4229 .patch_size = ARRAY_SIZE(madera_fll_ao_32K_49M_patch),
4230
4231 },
4232 {
4233 .fin = 32768,
4234 .fout = 45158400,
4235 .patch = madera_fll_ao_32K_45M_patch,
4236 .patch_size = ARRAY_SIZE(madera_fll_ao_32K_45M_patch),
4237 },
4238 };
4239
madera_enable_fll_ao(struct madera_fll * fll,const struct reg_sequence * patch,unsigned int patch_size)4240 static int madera_enable_fll_ao(struct madera_fll *fll,
4241 const struct reg_sequence *patch,
4242 unsigned int patch_size)
4243 {
4244 struct madera *madera = fll->madera;
4245 int already_enabled = madera_is_enabled_fll(fll, fll->base);
4246 unsigned int val;
4247 int i;
4248
4249 if (already_enabled < 0)
4250 return already_enabled;
4251
4252 if (!already_enabled)
4253 pm_runtime_get_sync(madera->dev);
4254
4255 madera_fll_dbg(fll, "Enabling FLL_AO, initially %s\n",
4256 str_enabled_disabled(already_enabled));
4257
4258 /* FLL_AO_HOLD must be set before configuring any registers */
4259 regmap_update_bits(fll->madera->regmap,
4260 fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4261 MADERA_FLL_AO_HOLD, MADERA_FLL_AO_HOLD);
4262
4263 if (already_enabled)
4264 madera_set_fllao_clks(fll, fll->base, false);
4265
4266 for (i = 0; i < patch_size; i++) {
4267 val = patch[i].def;
4268
4269 /* modify the patch to apply fll->ref_src as input clock */
4270 if (patch[i].reg == MADERA_FLLAO_CONTROL_6) {
4271 val &= ~MADERA_FLL_AO_REFCLK_SRC_MASK;
4272 val |= (fll->ref_src << MADERA_FLL_AO_REFCLK_SRC_SHIFT)
4273 & MADERA_FLL_AO_REFCLK_SRC_MASK;
4274 }
4275
4276 regmap_write(madera->regmap, patch[i].reg, val);
4277 }
4278
4279 madera_set_fllao_clks(fll, fll->base, true);
4280
4281 regmap_update_bits(madera->regmap,
4282 fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4283 MADERA_FLL_AO_ENA, MADERA_FLL_AO_ENA);
4284
4285 /* Release the hold so that fll_ao locks to external frequency */
4286 regmap_update_bits(madera->regmap,
4287 fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4288 MADERA_FLL_AO_HOLD, 0);
4289
4290 if (!already_enabled)
4291 madera_wait_for_fll(fll, true);
4292
4293 return 0;
4294 }
4295
madera_disable_fll_ao(struct madera_fll * fll)4296 static int madera_disable_fll_ao(struct madera_fll *fll)
4297 {
4298 struct madera *madera = fll->madera;
4299 bool change;
4300
4301 madera_fll_dbg(fll, "Disabling FLL_AO\n");
4302
4303 regmap_update_bits(madera->regmap,
4304 fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4305 MADERA_FLL_AO_HOLD, MADERA_FLL_AO_HOLD);
4306 regmap_update_bits_check(madera->regmap,
4307 fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4308 MADERA_FLL_AO_ENA, 0, &change);
4309
4310 madera_wait_for_fll(fll, false);
4311
4312 /*
4313 * ctrl_up gates the writes to all fll_ao register, setting it to 0
4314 * here ensures that after a runtime suspend/resume cycle when one
4315 * enables the fllao then ctrl_up is the last bit that is configured
4316 * by the fllao enable code rather than the cache sync operation which
4317 * would have updated it much earlier before writing out all fllao
4318 * registers
4319 */
4320 regmap_update_bits(madera->regmap,
4321 fll->base + MADERA_FLLAO_CONTROL_2_OFFS,
4322 MADERA_FLL_AO_CTRL_UPD_MASK, 0);
4323
4324 if (change) {
4325 madera_set_fllao_clks(fll, fll->base, false);
4326 pm_runtime_put_autosuspend(madera->dev);
4327 }
4328
4329 return 0;
4330 }
4331
madera_set_fll_ao_refclk(struct madera_fll * fll,int source,unsigned int fin,unsigned int fout)4332 int madera_set_fll_ao_refclk(struct madera_fll *fll, int source,
4333 unsigned int fin, unsigned int fout)
4334 {
4335 int ret = 0;
4336 const struct reg_sequence *patch = NULL;
4337 int patch_size = 0;
4338 unsigned int i;
4339
4340 if (fll->ref_src == source &&
4341 fll->ref_freq == fin && fll->fout == fout)
4342 return 0;
4343
4344 madera_fll_dbg(fll, "Change FLL_AO refclk to fin=%u fout=%u source=%d\n",
4345 fin, fout, source);
4346
4347 if (fout && (fll->ref_freq != fin || fll->fout != fout)) {
4348 for (i = 0; i < ARRAY_SIZE(madera_fllao_settings); i++) {
4349 if (madera_fllao_settings[i].fin == fin &&
4350 madera_fllao_settings[i].fout == fout)
4351 break;
4352 }
4353
4354 if (i == ARRAY_SIZE(madera_fllao_settings)) {
4355 madera_fll_err(fll,
4356 "No matching configuration for FLL_AO\n");
4357 return -EINVAL;
4358 }
4359
4360 patch = madera_fllao_settings[i].patch;
4361 patch_size = madera_fllao_settings[i].patch_size;
4362 }
4363
4364 fll->ref_src = source;
4365 fll->ref_freq = fin;
4366 fll->fout = fout;
4367
4368 if (fout)
4369 ret = madera_enable_fll_ao(fll, patch, patch_size);
4370 else
4371 madera_disable_fll_ao(fll);
4372
4373 return ret;
4374 }
4375 EXPORT_SYMBOL_GPL(madera_set_fll_ao_refclk);
4376
madera_fllhj_disable(struct madera_fll * fll)4377 static int madera_fllhj_disable(struct madera_fll *fll)
4378 {
4379 struct madera *madera = fll->madera;
4380 bool change;
4381
4382 madera_fll_dbg(fll, "Disabling FLL\n");
4383
4384 /* Disable lockdet, but don't set ctrl_upd update but. This allows the
4385 * lock status bit to clear as normal, but should the FLL be enabled
4386 * again due to a control clock being required, the lock won't re-assert
4387 * as the FLL config registers are automatically applied when the FLL
4388 * enables.
4389 */
4390 regmap_update_bits(madera->regmap,
4391 fll->base + MADERA_FLL_CONTROL_11_OFFS,
4392 MADERA_FLL1_LOCKDET_MASK, 0);
4393 regmap_update_bits(madera->regmap,
4394 fll->base + MADERA_FLL_CONTROL_1_OFFS,
4395 MADERA_FLL1_HOLD_MASK, MADERA_FLL1_HOLD_MASK);
4396 regmap_update_bits_check(madera->regmap,
4397 fll->base + MADERA_FLL_CONTROL_1_OFFS,
4398 MADERA_FLL1_ENA_MASK, 0, &change);
4399
4400 madera_wait_for_fll(fll, false);
4401
4402 /* ctrl_up gates the writes to all the fll's registers, setting it to 0
4403 * here ensures that after a runtime suspend/resume cycle when one
4404 * enables the fll then ctrl_up is the last bit that is configured
4405 * by the fll enable code rather than the cache sync operation which
4406 * would have updated it much earlier before writing out all fll
4407 * registers
4408 */
4409 regmap_update_bits(madera->regmap,
4410 fll->base + MADERA_FLL_CONTROL_2_OFFS,
4411 MADERA_FLL1_CTRL_UPD_MASK, 0);
4412
4413 if (change) {
4414 madera_set_fllhj_clks(fll, fll->base, false);
4415 pm_runtime_put_autosuspend(madera->dev);
4416 }
4417
4418 return 0;
4419 }
4420
madera_fllhj_apply(struct madera_fll * fll,int fin)4421 static int madera_fllhj_apply(struct madera_fll *fll, int fin)
4422 {
4423 struct madera *madera = fll->madera;
4424 int refdiv, fref, fout, lockdet_thr, fbdiv, hp, fast_clk, fllgcd;
4425 bool frac = false;
4426 unsigned int fll_n, min_n, max_n, ratio, theta, lambda;
4427 unsigned int gains, val, num;
4428
4429 madera_fll_dbg(fll, "fin=%d, fout=%d\n", fin, fll->fout);
4430
4431 for (refdiv = 0; refdiv < 4; refdiv++)
4432 if ((fin / (1 << refdiv)) <= MADERA_FLLHJ_MAX_THRESH)
4433 break;
4434
4435 fref = fin / (1 << refdiv);
4436
4437 /* Use simple heuristic approach to find a configuration that
4438 * should work for most input clocks.
4439 */
4440 fast_clk = 0;
4441 fout = fll->fout;
4442 frac = fout % fref;
4443
4444 if (fref < MADERA_FLLHJ_LOW_THRESH) {
4445 lockdet_thr = 2;
4446 gains = MADERA_FLLHJ_LOW_GAINS;
4447 if (frac)
4448 fbdiv = 256;
4449 else
4450 fbdiv = 4;
4451 } else if (fref < MADERA_FLLHJ_MID_THRESH) {
4452 lockdet_thr = 8;
4453 gains = MADERA_FLLHJ_MID_GAINS;
4454 fbdiv = 1;
4455 } else {
4456 lockdet_thr = 8;
4457 gains = MADERA_FLLHJ_HIGH_GAINS;
4458 fbdiv = 1;
4459 /* For high speed input clocks, enable 300MHz fast oscillator
4460 * when we're in fractional divider mode.
4461 */
4462 if (frac) {
4463 fast_clk = 0x3;
4464 fout = fll->fout * 6;
4465 }
4466 }
4467 /* Use high performance mode for fractional configurations. */
4468 if (frac) {
4469 hp = 0x3;
4470 min_n = MADERA_FLLHJ_FRAC_MIN_N;
4471 max_n = MADERA_FLLHJ_FRAC_MAX_N;
4472 } else {
4473 hp = 0x0;
4474 min_n = MADERA_FLLHJ_INT_MIN_N;
4475 max_n = MADERA_FLLHJ_INT_MAX_N;
4476 }
4477
4478 ratio = fout / fref;
4479
4480 madera_fll_dbg(fll, "refdiv=%d, fref=%d, frac:%d\n",
4481 refdiv, fref, frac);
4482
4483 while (ratio / fbdiv < min_n) {
4484 fbdiv /= 2;
4485 if (fbdiv < 1) {
4486 madera_fll_err(fll, "FBDIV (%d) must be >= 1\n", fbdiv);
4487 return -EINVAL;
4488 }
4489 }
4490 while (frac && (ratio / fbdiv > max_n)) {
4491 fbdiv *= 2;
4492 if (fbdiv >= 1024) {
4493 madera_fll_err(fll, "FBDIV (%u) >= 1024\n", fbdiv);
4494 return -EINVAL;
4495 }
4496 }
4497
4498 madera_fll_dbg(fll, "lockdet=%d, hp=0x%x, fbdiv:%d\n",
4499 lockdet_thr, hp, fbdiv);
4500
4501 /* Calculate N.K values */
4502 fllgcd = gcd(fout, fbdiv * fref);
4503 num = fout / fllgcd;
4504 lambda = (fref * fbdiv) / fllgcd;
4505 fll_n = num / lambda;
4506 theta = num % lambda;
4507
4508 madera_fll_dbg(fll, "fll_n=%d, gcd=%d, theta=%d, lambda=%d\n",
4509 fll_n, fllgcd, theta, lambda);
4510
4511 /* Some sanity checks before any registers are written. */
4512 if (fll_n < min_n || fll_n > max_n) {
4513 madera_fll_err(fll, "N not in valid %s mode range %d-%d: %d\n",
4514 frac ? "fractional" : "integer", min_n, max_n,
4515 fll_n);
4516 return -EINVAL;
4517 }
4518 if (fbdiv < 1 || (frac && fbdiv >= 1024) || (!frac && fbdiv >= 256)) {
4519 madera_fll_err(fll, "Invalid fbdiv for %s mode (%u)\n",
4520 frac ? "fractional" : "integer", fbdiv);
4521 return -EINVAL;
4522 }
4523
4524 /* clear the ctrl_upd bit to guarantee we write to it later. */
4525 regmap_write(madera->regmap,
4526 fll->base + MADERA_FLL_CONTROL_2_OFFS,
4527 fll_n << MADERA_FLL1_N_SHIFT);
4528 regmap_update_bits(madera->regmap,
4529 fll->base + MADERA_FLL_CONTROL_3_OFFS,
4530 MADERA_FLL1_THETA_MASK,
4531 theta << MADERA_FLL1_THETA_SHIFT);
4532 regmap_update_bits(madera->regmap,
4533 fll->base + MADERA_FLL_CONTROL_4_OFFS,
4534 MADERA_FLL1_LAMBDA_MASK,
4535 lambda << MADERA_FLL1_LAMBDA_SHIFT);
4536 regmap_update_bits(madera->regmap,
4537 fll->base + MADERA_FLL_CONTROL_5_OFFS,
4538 MADERA_FLL1_FB_DIV_MASK,
4539 fbdiv << MADERA_FLL1_FB_DIV_SHIFT);
4540 regmap_update_bits(madera->regmap,
4541 fll->base + MADERA_FLL_CONTROL_6_OFFS,
4542 MADERA_FLL1_REFCLK_DIV_MASK,
4543 refdiv << MADERA_FLL1_REFCLK_DIV_SHIFT);
4544 regmap_update_bits(madera->regmap,
4545 fll->base + MADERA_FLL_GAIN_OFFS,
4546 0xffff,
4547 gains);
4548 val = hp << MADERA_FLL1_HP_SHIFT;
4549 val |= 1 << MADERA_FLL1_PHASEDET_ENA_SHIFT;
4550 regmap_update_bits(madera->regmap,
4551 fll->base + MADERA_FLL_CONTROL_10_OFFS,
4552 MADERA_FLL1_HP_MASK | MADERA_FLL1_PHASEDET_ENA_MASK,
4553 val);
4554 regmap_update_bits(madera->regmap,
4555 fll->base + MADERA_FLL_CONTROL_11_OFFS,
4556 MADERA_FLL1_LOCKDET_THR_MASK,
4557 lockdet_thr << MADERA_FLL1_LOCKDET_THR_SHIFT);
4558 regmap_update_bits(madera->regmap,
4559 fll->base + MADERA_FLL1_DIGITAL_TEST_1_OFFS,
4560 MADERA_FLL1_SYNC_EFS_ENA_MASK |
4561 MADERA_FLL1_CLK_VCO_FAST_SRC_MASK,
4562 fast_clk);
4563
4564 return 0;
4565 }
4566
madera_fllhj_enable(struct madera_fll * fll)4567 static int madera_fllhj_enable(struct madera_fll *fll)
4568 {
4569 struct madera *madera = fll->madera;
4570 int already_enabled = madera_is_enabled_fll(fll, fll->base);
4571 int ret;
4572
4573 if (already_enabled < 0)
4574 return already_enabled;
4575
4576 if (!already_enabled)
4577 pm_runtime_get_sync(madera->dev);
4578
4579 madera_fll_dbg(fll, "Enabling FLL, initially %s\n",
4580 str_enabled_disabled(already_enabled));
4581
4582 /* FLLn_HOLD must be set before configuring any registers */
4583 regmap_update_bits(fll->madera->regmap,
4584 fll->base + MADERA_FLL_CONTROL_1_OFFS,
4585 MADERA_FLL1_HOLD_MASK,
4586 MADERA_FLL1_HOLD_MASK);
4587
4588 if (already_enabled)
4589 madera_set_fllhj_clks(fll, fll->base, false);
4590
4591 /* Apply refclk */
4592 ret = madera_fllhj_apply(fll, fll->ref_freq);
4593 if (ret) {
4594 madera_fll_err(fll, "Failed to set FLL: %d\n", ret);
4595 goto out;
4596 }
4597 regmap_update_bits(madera->regmap,
4598 fll->base + MADERA_FLL_CONTROL_1_OFFS,
4599 CS47L92_FLL1_REFCLK_SRC_MASK,
4600 fll->ref_src << CS47L92_FLL1_REFCLK_SRC_SHIFT);
4601
4602 madera_set_fllhj_clks(fll, fll->base, true);
4603
4604 regmap_update_bits(madera->regmap,
4605 fll->base + MADERA_FLL_CONTROL_1_OFFS,
4606 MADERA_FLL1_ENA_MASK,
4607 MADERA_FLL1_ENA_MASK);
4608
4609 out:
4610 regmap_update_bits(madera->regmap,
4611 fll->base + MADERA_FLL_CONTROL_11_OFFS,
4612 MADERA_FLL1_LOCKDET_MASK,
4613 MADERA_FLL1_LOCKDET_MASK);
4614
4615 regmap_update_bits(madera->regmap,
4616 fll->base + MADERA_FLL_CONTROL_2_OFFS,
4617 MADERA_FLL1_CTRL_UPD_MASK,
4618 MADERA_FLL1_CTRL_UPD_MASK);
4619
4620 /* Release the hold so that flln locks to external frequency */
4621 regmap_update_bits(madera->regmap,
4622 fll->base + MADERA_FLL_CONTROL_1_OFFS,
4623 MADERA_FLL1_HOLD_MASK,
4624 0);
4625
4626 if (!already_enabled)
4627 madera_wait_for_fll(fll, true);
4628
4629 return 0;
4630 }
4631
madera_fllhj_validate(struct madera_fll * fll,unsigned int ref_in,unsigned int fout)4632 static int madera_fllhj_validate(struct madera_fll *fll,
4633 unsigned int ref_in,
4634 unsigned int fout)
4635 {
4636 if (fout && !ref_in) {
4637 madera_fll_err(fll, "fllout set without valid input clk\n");
4638 return -EINVAL;
4639 }
4640
4641 if (fll->fout && fout != fll->fout) {
4642 madera_fll_err(fll, "Can't change output on active FLL\n");
4643 return -EINVAL;
4644 }
4645
4646 if (ref_in / MADERA_FLL_MAX_REFDIV > MADERA_FLLHJ_MAX_THRESH) {
4647 madera_fll_err(fll, "Can't scale %dMHz to <=13MHz\n", ref_in);
4648 return -EINVAL;
4649 }
4650
4651 return 0;
4652 }
4653
madera_fllhj_set_refclk(struct madera_fll * fll,int source,unsigned int fin,unsigned int fout)4654 int madera_fllhj_set_refclk(struct madera_fll *fll, int source,
4655 unsigned int fin, unsigned int fout)
4656 {
4657 int ret = 0;
4658
4659 /* To remain consistent with previous FLLs, we expect fout to be
4660 * provided in the form of the required sysclk rate, which is
4661 * 2x the calculated fll out.
4662 */
4663 if (fout)
4664 fout /= 2;
4665
4666 if (fll->ref_src == source && fll->ref_freq == fin &&
4667 fll->fout == fout)
4668 return 0;
4669
4670 if (fin && fout && madera_fllhj_validate(fll, fin, fout))
4671 return -EINVAL;
4672
4673 fll->ref_src = source;
4674 fll->ref_freq = fin;
4675 fll->fout = fout;
4676
4677 if (fout)
4678 ret = madera_fllhj_enable(fll);
4679 else
4680 madera_fllhj_disable(fll);
4681
4682 return ret;
4683 }
4684 EXPORT_SYMBOL_GPL(madera_fllhj_set_refclk);
4685
4686 /**
4687 * madera_set_output_mode - Set the mode of the specified output
4688 *
4689 * @component: Device to configure
4690 * @output: Output number
4691 * @differential: True to set the output to differential mode
4692 *
4693 * Some systems use external analogue switches to connect more
4694 * analogue devices to the CODEC than are supported by the device. In
4695 * some systems this requires changing the switched output from single
4696 * ended to differential mode dynamically at runtime, an operation
4697 * supported using this function.
4698 *
4699 * Most systems have a single static configuration and should use
4700 * platform data instead.
4701 */
madera_set_output_mode(struct snd_soc_component * component,int output,bool differential)4702 int madera_set_output_mode(struct snd_soc_component *component, int output,
4703 bool differential)
4704 {
4705 unsigned int reg, val;
4706 int ret;
4707
4708 if (output < 1 || output > MADERA_MAX_OUTPUT)
4709 return -EINVAL;
4710
4711 reg = MADERA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
4712
4713 if (differential)
4714 val = MADERA_OUT1_MONO;
4715 else
4716 val = 0;
4717
4718 ret = snd_soc_component_update_bits(component, reg, MADERA_OUT1_MONO,
4719 val);
4720 if (ret < 0)
4721 return ret;
4722 else
4723 return 0;
4724 }
4725 EXPORT_SYMBOL_GPL(madera_set_output_mode);
4726
madera_eq_filter_unstable(bool mode,__be16 _a,__be16 _b)4727 static bool madera_eq_filter_unstable(bool mode, __be16 _a, __be16 _b)
4728 {
4729 s16 a = be16_to_cpu(_a);
4730 s16 b = be16_to_cpu(_b);
4731
4732 if (!mode) {
4733 return abs(a) >= 4096;
4734 } else {
4735 if (abs(b) >= 4096)
4736 return true;
4737
4738 return (abs((a << 16) / (4096 - b)) >= 4096 << 4);
4739 }
4740 }
4741
madera_eq_coeff_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)4742 int madera_eq_coeff_put(struct snd_kcontrol *kcontrol,
4743 struct snd_ctl_elem_value *ucontrol)
4744 {
4745 struct snd_soc_component *component =
4746 snd_soc_kcontrol_component(kcontrol);
4747 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
4748 struct madera *madera = priv->madera;
4749 struct soc_bytes *params = (void *)kcontrol->private_value;
4750 unsigned int val;
4751 __be16 *data;
4752 int len;
4753 int ret;
4754
4755 len = params->num_regs * regmap_get_val_bytes(madera->regmap);
4756
4757 data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
4758 if (!data)
4759 return -ENOMEM;
4760
4761 data[0] &= cpu_to_be16(MADERA_EQ1_B1_MODE);
4762
4763 if (madera_eq_filter_unstable(!!data[0], data[1], data[2]) ||
4764 madera_eq_filter_unstable(true, data[4], data[5]) ||
4765 madera_eq_filter_unstable(true, data[8], data[9]) ||
4766 madera_eq_filter_unstable(true, data[12], data[13]) ||
4767 madera_eq_filter_unstable(false, data[16], data[17])) {
4768 dev_err(madera->dev, "Rejecting unstable EQ coefficients\n");
4769 ret = -EINVAL;
4770 goto out;
4771 }
4772
4773 ret = regmap_read(madera->regmap, params->base, &val);
4774 if (ret != 0)
4775 goto out;
4776
4777 val &= ~MADERA_EQ1_B1_MODE;
4778 data[0] |= cpu_to_be16(val);
4779
4780 ret = regmap_raw_write(madera->regmap, params->base, data, len);
4781
4782 out:
4783 kfree(data);
4784
4785 return ret;
4786 }
4787 EXPORT_SYMBOL_GPL(madera_eq_coeff_put);
4788
madera_lhpf_coeff_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)4789 int madera_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
4790 struct snd_ctl_elem_value *ucontrol)
4791 {
4792 struct snd_soc_component *component =
4793 snd_soc_kcontrol_component(kcontrol);
4794 struct madera_priv *priv = snd_soc_component_get_drvdata(component);
4795 struct madera *madera = priv->madera;
4796 __be16 *data = (__be16 *)ucontrol->value.bytes.data;
4797 s16 val = be16_to_cpu(*data);
4798
4799 if (abs(val) >= 4096) {
4800 dev_err(madera->dev, "Rejecting unstable LHPF coefficients\n");
4801 return -EINVAL;
4802 }
4803
4804 return snd_soc_bytes_put(kcontrol, ucontrol);
4805 }
4806 EXPORT_SYMBOL_GPL(madera_lhpf_coeff_put);
4807
4808 MODULE_SOFTDEP("pre: madera");
4809 MODULE_DESCRIPTION("ASoC Cirrus Logic Madera codec support");
4810 MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
4811 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
4812 MODULE_LICENSE("GPL v2");
4813