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