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