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