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