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
156static const int madera_dsp_bus_error_irqs[MADERA_MAX_ADSP] = {
157	MADERA_IRQ_DSP1_BUS_ERR,
158	MADERA_IRQ_DSP2_BUS_ERR,
159	MADERA_IRQ_DSP3_BUS_ERR,
160	MADERA_IRQ_DSP4_BUS_ERR,
161	MADERA_IRQ_DSP5_BUS_ERR,
162	MADERA_IRQ_DSP6_BUS_ERR,
163	MADERA_IRQ_DSP7_BUS_ERR,
164};
165
166int 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}
206EXPORT_SYMBOL_GPL(madera_clk_ev);
207
208static 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
232int 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}
249EXPORT_SYMBOL_GPL(madera_sysclk_ev);
250
251static 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
270int 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}
304EXPORT_SYMBOL_GPL(madera_spk_ev);
305
306static 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
333int 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}
353EXPORT_SYMBOL_GPL(madera_init_overheat);
354
355int 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}
364EXPORT_SYMBOL_GPL(madera_free_overheat);
365
366static 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
398static 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
426static 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
460int 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}
478EXPORT_SYMBOL_GPL(madera_core_init);
479
480int madera_core_free(struct madera_priv *priv)
481{
482	mutex_destroy(&priv->rate_lock);
483
484	return 0;
485}
486EXPORT_SYMBOL_GPL(madera_core_free);
487
488static 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
498int 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}
538EXPORT_SYMBOL_GPL(madera_domain_clk_ev);
539
540int 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
618end:
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}
629EXPORT_SYMBOL_GPL(madera_out1_demux_put);
630
631int 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}
645EXPORT_SYMBOL_GPL(madera_out1_demux_get);
646
647static 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
704static const char * const madera_inmux_texts[] = {
705	"A",
706	"B",
707};
708
709static SOC_ENUM_SINGLE_DECL(madera_in1muxl_enum,
710			    MADERA_ADC_DIGITAL_VOLUME_1L,
711			    MADERA_IN1L_SRC_SHIFT,
712			    madera_inmux_texts);
713
714static SOC_ENUM_SINGLE_DECL(madera_in1muxr_enum,
715			    MADERA_ADC_DIGITAL_VOLUME_1R,
716			    MADERA_IN1R_SRC_SHIFT,
717			    madera_inmux_texts);
718
719static SOC_ENUM_SINGLE_DECL(madera_in2muxl_enum,
720			    MADERA_ADC_DIGITAL_VOLUME_2L,
721			    MADERA_IN2L_SRC_SHIFT,
722			    madera_inmux_texts);
723
724static SOC_ENUM_SINGLE_DECL(madera_in2muxr_enum,
725			    MADERA_ADC_DIGITAL_VOLUME_2R,
726			    MADERA_IN2R_SRC_SHIFT,
727			    madera_inmux_texts);
728
729const 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};
739EXPORT_SYMBOL_GPL(madera_inmux);
740
741static const char * const madera_dmode_texts[] = {
742	"Analog",
743	"Digital",
744};
745
746static SOC_ENUM_SINGLE_DECL(madera_in1dmode_enum,
747			    MADERA_IN1L_CONTROL,
748			    MADERA_IN1_MODE_SHIFT,
749			    madera_dmode_texts);
750
751static SOC_ENUM_SINGLE_DECL(madera_in2dmode_enum,
752			    MADERA_IN2L_CONTROL,
753			    MADERA_IN2_MODE_SHIFT,
754			    madera_dmode_texts);
755
756static SOC_ENUM_SINGLE_DECL(madera_in3dmode_enum,
757			    MADERA_IN3L_CONTROL,
758			    MADERA_IN3_MODE_SHIFT,
759			    madera_dmode_texts);
760
761const 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};
766EXPORT_SYMBOL_GPL(madera_inmode);
767
768static 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
872static 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
893static 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
930static 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
947const 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};
963EXPORT_SYMBOL_GPL(madera_adsp_rate_controls);
964
965static 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
1004err:
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
1010int 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}
1051EXPORT_SYMBOL_GPL(madera_set_adsp_clk);
1052
1053int 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	}
1092out:
1093	mutex_unlock(&priv->rate_lock);
1094
1095	return ret;
1096}
1097EXPORT_SYMBOL_GPL(madera_rate_put);
1098
1099static 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
1192int 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}
1201EXPORT_SYMBOL_GPL(madera_init_inputs);
1202
1203static 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
1212int 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}
1273EXPORT_SYMBOL_GPL(madera_init_outputs);
1274
1275int 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}
1292EXPORT_SYMBOL_GPL(madera_init_bus_error_irq);
1293
1294void 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}
1302EXPORT_SYMBOL_GPL(madera_free_bus_error_irq);
1303
1304const 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};
1454EXPORT_SYMBOL_GPL(madera_mixer_texts);
1455
1456const 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};
1606EXPORT_SYMBOL_GPL(madera_mixer_values);
1607
1608const DECLARE_TLV_DB_SCALE(madera_ana_tlv, 0, 100, 0);
1609EXPORT_SYMBOL_GPL(madera_ana_tlv);
1610
1611const DECLARE_TLV_DB_SCALE(madera_eq_tlv, -1200, 100, 0);
1612EXPORT_SYMBOL_GPL(madera_eq_tlv);
1613
1614const DECLARE_TLV_DB_SCALE(madera_digital_tlv, -6400, 50, 0);
1615EXPORT_SYMBOL_GPL(madera_digital_tlv);
1616
1617const DECLARE_TLV_DB_SCALE(madera_noise_tlv, -13200, 600, 0);
1618EXPORT_SYMBOL_GPL(madera_noise_tlv);
1619
1620const DECLARE_TLV_DB_SCALE(madera_ng_tlv, -12000, 600, 0);
1621EXPORT_SYMBOL_GPL(madera_ng_tlv);
1622
1623const DECLARE_TLV_DB_SCALE(madera_mixer_tlv, -3200, 100, 0);
1624EXPORT_SYMBOL_GPL(madera_mixer_tlv);
1625
1626const 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};
1630EXPORT_SYMBOL_GPL(madera_rate_text);
1631
1632const unsigned int madera_rate_val[MADERA_RATE_ENUM_SIZE] = {
1633	0x0, 0x1, 0x2, 0x8, 0x9,
1634};
1635EXPORT_SYMBOL_GPL(madera_rate_val);
1636
1637static 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
1641static const unsigned int madera_dfc_width_val[MADERA_DFC_WIDTH_ENUM_SIZE] = {
1642	7, 15, 19, 23, 31,
1643};
1644
1645static 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
1650static const unsigned int madera_dfc_type_val[MADERA_DFC_TYPE_ENUM_SIZE] = {
1651	0, 1, 2, 4, 5,
1652};
1653
1654const 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};
1768EXPORT_SYMBOL_GPL(madera_dfc_width);
1769
1770const 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};
1884EXPORT_SYMBOL_GPL(madera_dfc_type);
1885
1886const 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};
1904EXPORT_SYMBOL_GPL(madera_isrc_fsh);
1905
1906const 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};
1924EXPORT_SYMBOL_GPL(madera_isrc_fsl);
1925
1926const 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};
1937EXPORT_SYMBOL_GPL(madera_asrc1_rate);
1938
1939const 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};
1949EXPORT_SYMBOL_GPL(madera_asrc1_bidir_rate);
1950
1951const 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};
1962EXPORT_SYMBOL_GPL(madera_asrc2_rate);
1963
1964static 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
1969SOC_ENUM_SINGLE_DECL(madera_in_vd_ramp,
1970		     MADERA_INPUT_VOLUME_RAMP,
1971		     MADERA_IN_VD_RAMP_SHIFT,
1972		     madera_vol_ramp_text);
1973EXPORT_SYMBOL_GPL(madera_in_vd_ramp);
1974
1975SOC_ENUM_SINGLE_DECL(madera_in_vi_ramp,
1976		     MADERA_INPUT_VOLUME_RAMP,
1977		     MADERA_IN_VI_RAMP_SHIFT,
1978		     madera_vol_ramp_text);
1979EXPORT_SYMBOL_GPL(madera_in_vi_ramp);
1980
1981SOC_ENUM_SINGLE_DECL(madera_out_vd_ramp,
1982		     MADERA_OUTPUT_VOLUME_RAMP,
1983		     MADERA_OUT_VD_RAMP_SHIFT,
1984		     madera_vol_ramp_text);
1985EXPORT_SYMBOL_GPL(madera_out_vd_ramp);
1986
1987SOC_ENUM_SINGLE_DECL(madera_out_vi_ramp,
1988		     MADERA_OUTPUT_VOLUME_RAMP,
1989		     MADERA_OUT_VI_RAMP_SHIFT,
1990		     madera_vol_ramp_text);
1991EXPORT_SYMBOL_GPL(madera_out_vi_ramp);
1992
1993static const char * const madera_lhpf_mode_text[] = {
1994	"Low-pass", "High-pass"
1995};
1996
1997SOC_ENUM_SINGLE_DECL(madera_lhpf1_mode,
1998		     MADERA_HPLPF1_1,
1999		     MADERA_LHPF1_MODE_SHIFT,
2000		     madera_lhpf_mode_text);
2001EXPORT_SYMBOL_GPL(madera_lhpf1_mode);
2002
2003SOC_ENUM_SINGLE_DECL(madera_lhpf2_mode,
2004		     MADERA_HPLPF2_1,
2005		     MADERA_LHPF2_MODE_SHIFT,
2006		     madera_lhpf_mode_text);
2007EXPORT_SYMBOL_GPL(madera_lhpf2_mode);
2008
2009SOC_ENUM_SINGLE_DECL(madera_lhpf3_mode,
2010		     MADERA_HPLPF3_1,
2011		     MADERA_LHPF3_MODE_SHIFT,
2012		     madera_lhpf_mode_text);
2013EXPORT_SYMBOL_GPL(madera_lhpf3_mode);
2014
2015SOC_ENUM_SINGLE_DECL(madera_lhpf4_mode,
2016		     MADERA_HPLPF4_1,
2017		     MADERA_LHPF4_MODE_SHIFT,
2018		     madera_lhpf_mode_text);
2019EXPORT_SYMBOL_GPL(madera_lhpf4_mode);
2020
2021static const char * const madera_ng_hold_text[] = {
2022	"30ms", "120ms", "250ms", "500ms",
2023};
2024
2025SOC_ENUM_SINGLE_DECL(madera_ng_hold,
2026		     MADERA_NOISE_GATE_CONTROL,
2027		     MADERA_NGATE_HOLD_SHIFT,
2028		     madera_ng_hold_text);
2029EXPORT_SYMBOL_GPL(madera_ng_hold);
2030
2031static const char * const madera_in_hpf_cut_text[] = {
2032	"2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
2033};
2034
2035SOC_ENUM_SINGLE_DECL(madera_in_hpf_cut_enum,
2036		     MADERA_HPF_CONTROL,
2037		     MADERA_IN_HPF_CUT_SHIFT,
2038		     madera_in_hpf_cut_text);
2039EXPORT_SYMBOL_GPL(madera_in_hpf_cut_enum);
2040
2041static const char * const madera_in_dmic_osr_text[MADERA_OSR_ENUM_SIZE] = {
2042	"384kHz", "768kHz", "1.536MHz", "3.072MHz", "6.144MHz",
2043};
2044
2045static const unsigned int madera_in_dmic_osr_val[MADERA_OSR_ENUM_SIZE] = {
2046	2, 3, 4, 5, 6,
2047};
2048
2049const 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};
2069EXPORT_SYMBOL_GPL(madera_in_dmic_osr);
2070
2071static const char * const madera_anc_input_src_text[] = {
2072	"None", "IN1", "IN2", "IN3", "IN4", "IN5", "IN6",
2073};
2074
2075static const char * const madera_anc_channel_src_text[] = {
2076	"None", "Left", "Right", "Combine",
2077};
2078
2079const 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};
2097EXPORT_SYMBOL_GPL(madera_anc_input_src);
2098
2099static const char * const madera_anc_ng_texts[] = {
2100	"None", "Internal", "External",
2101};
2102
2103SOC_ENUM_SINGLE_DECL(madera_anc_ng_enum, SND_SOC_NOPM, 0, madera_anc_ng_texts);
2104EXPORT_SYMBOL_GPL(madera_anc_ng_enum);
2105
2106static const char * const madera_out_anc_src_text[] = {
2107	"None", "RXANCL", "RXANCR",
2108};
2109
2110const 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};
2160EXPORT_SYMBOL_GPL(madera_output_anc_src);
2161
2162int 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);
2186exit:
2187	snd_soc_dapm_mutex_unlock(dapm);
2188
2189	return ret;
2190}
2191EXPORT_SYMBOL_GPL(madera_dfc_put);
2192
2193int 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
2221exit:
2222	snd_soc_dapm_mutex_unlock(dapm);
2223
2224	return ret;
2225}
2226EXPORT_SYMBOL_GPL(madera_lp_mode_put);
2227
2228const 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};
2237EXPORT_SYMBOL_GPL(madera_dsp_trigger_output_mux);
2238
2239const 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};
2243EXPORT_SYMBOL_GPL(madera_drc_activity_output_mux);
2244
2245static 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
2265int 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}
2309EXPORT_SYMBOL_GPL(madera_in_ev);
2310
2311int 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}
2409EXPORT_SYMBOL_GPL(madera_out_ev);
2410
2411int 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}
2461EXPORT_SYMBOL_GPL(madera_hp_ev);
2462
2463int 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}
2484EXPORT_SYMBOL_GPL(madera_anc_ev);
2485
2486static const unsigned int madera_opclk_ref_48k_rates[] = {
2487	6144000,
2488	12288000,
2489	24576000,
2490	49152000,
2491};
2492
2493static const unsigned int madera_opclk_ref_44k1_rates[] = {
2494	5644800,
2495	11289600,
2496	22579200,
2497	45158400,
2498};
2499
2500static 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
2555static 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
2579static 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
2606static 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
2626static 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
2678int 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}
2758EXPORT_SYMBOL_GPL(madera_set_sysclk);
2759
2760static 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
2854static 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
2876static 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
2898static 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
2934static const struct snd_pcm_hw_constraint_list madera_constraint = {
2935	.count	= ARRAY_SIZE(madera_sr_vals),
2936	.list	= madera_sr_vals,
2937};
2938
2939static 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
2991static 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
3070out:
3071	mutex_unlock(&priv->rate_lock);
3072
3073	return ret;
3074}
3075
3076static 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
3097static 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
3210restore_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
3224static 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
3239static 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
3288static 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
3309static 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
3332static 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
3361const 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};
3369EXPORT_SYMBOL_GPL(madera_dai_ops);
3370
3371const 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};
3376EXPORT_SYMBOL_GPL(madera_simple_dai_ops);
3377
3378int 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}
3387EXPORT_SYMBOL_GPL(madera_init_dai);
3388
3389static 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
3402static 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
3421struct 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
3428static 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
3434static 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
3443static 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
3460static 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
3474static 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
3504static 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
3600static 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
3621static 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
3714static 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
3771static 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
3787static 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
3820static 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
3842static 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
3882static 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_SRC_SHIFT);
3888}
3889
3890static 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
3898static 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
3906static 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
3947static 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
4105err:
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
4112static 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
4122int 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}
4139EXPORT_SYMBOL_GPL(madera_set_fll_syncclk);
4140
4141int 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}
4171EXPORT_SYMBOL_GPL(madera_set_fll_refclk);
4172
4173int 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}
4188EXPORT_SYMBOL_GPL(madera_init_fll);
4189
4190static 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
4203static 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
4216struct madera_fllao_patch {
4217	unsigned int fin;
4218	unsigned int fout;
4219	const struct reg_sequence *patch;
4220	unsigned int patch_size;
4221};
4222
4223static 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
4239static 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
4295static 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
4331int 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}
4374EXPORT_SYMBOL_GPL(madera_set_fll_ao_refclk);
4375
4376static 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
4420static 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
4566static 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
4608out:
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
4631static 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
4653int 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}
4683EXPORT_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 */
4701int 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}
4724EXPORT_SYMBOL_GPL(madera_set_output_mode);
4725
4726static 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
4741int 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
4781out:
4782	kfree(data);
4783
4784	return ret;
4785}
4786EXPORT_SYMBOL_GPL(madera_eq_coeff_put);
4787
4788int 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}
4805EXPORT_SYMBOL_GPL(madera_lhpf_coeff_put);
4806
4807MODULE_SOFTDEP("pre: madera");
4808MODULE_DESCRIPTION("ASoC Cirrus Logic Madera codec support");
4809MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
4810MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
4811MODULE_LICENSE("GPL v2");
4812