~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/codecs/madera.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php