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