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