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