Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 //
0003 // Cirrus Logic Madera class codecs common support
0004 //
0005 // Copyright (C) 2015-2019 Cirrus Logic, Inc. and
0006 //                         Cirrus Logic International Semiconductor Ltd.
0007 //
0008 
0009 #include <linux/delay.h>
0010 #include <linux/gcd.h>
0011 #include <linux/module.h>
0012 #include <linux/pm_runtime.h>
0013 #include <linux/slab.h>
0014 #include <sound/pcm.h>
0015 #include <sound/pcm_params.h>
0016 #include <sound/tlv.h>
0017 
0018 #include <linux/irqchip/irq-madera.h>
0019 #include <linux/mfd/madera/core.h>
0020 #include <linux/mfd/madera/registers.h>
0021 #include <linux/mfd/madera/pdata.h>
0022 #include <sound/madera-pdata.h>
0023 
0024 #include <dt-bindings/sound/madera.h>
0025 
0026 #include "madera.h"
0027 
0028 #define MADERA_AIF_BCLK_CTRL            0x00
0029 #define MADERA_AIF_TX_PIN_CTRL          0x01
0030 #define MADERA_AIF_RX_PIN_CTRL          0x02
0031 #define MADERA_AIF_RATE_CTRL            0x03
0032 #define MADERA_AIF_FORMAT           0x04
0033 #define MADERA_AIF_RX_BCLK_RATE         0x06
0034 #define MADERA_AIF_FRAME_CTRL_1         0x07
0035 #define MADERA_AIF_FRAME_CTRL_2         0x08
0036 #define MADERA_AIF_FRAME_CTRL_3         0x09
0037 #define MADERA_AIF_FRAME_CTRL_4         0x0A
0038 #define MADERA_AIF_FRAME_CTRL_5         0x0B
0039 #define MADERA_AIF_FRAME_CTRL_6         0x0C
0040 #define MADERA_AIF_FRAME_CTRL_7         0x0D
0041 #define MADERA_AIF_FRAME_CTRL_8         0x0E
0042 #define MADERA_AIF_FRAME_CTRL_9         0x0F
0043 #define MADERA_AIF_FRAME_CTRL_10        0x10
0044 #define MADERA_AIF_FRAME_CTRL_11        0x11
0045 #define MADERA_AIF_FRAME_CTRL_12        0x12
0046 #define MADERA_AIF_FRAME_CTRL_13        0x13
0047 #define MADERA_AIF_FRAME_CTRL_14        0x14
0048 #define MADERA_AIF_FRAME_CTRL_15        0x15
0049 #define MADERA_AIF_FRAME_CTRL_16        0x16
0050 #define MADERA_AIF_FRAME_CTRL_17        0x17
0051 #define MADERA_AIF_FRAME_CTRL_18        0x18
0052 #define MADERA_AIF_TX_ENABLES           0x19
0053 #define MADERA_AIF_RX_ENABLES           0x1A
0054 #define MADERA_AIF_FORCE_WRITE          0x1B
0055 
0056 #define MADERA_DSP_CONFIG_1_OFFS        0x00
0057 #define MADERA_DSP_CONFIG_2_OFFS        0x02
0058 
0059 #define MADERA_DSP_CLK_SEL_MASK         0x70000
0060 #define MADERA_DSP_CLK_SEL_SHIFT        16
0061 
0062 #define MADERA_DSP_RATE_MASK            0x7800
0063 #define MADERA_DSP_RATE_SHIFT           11
0064 
0065 #define MADERA_SYSCLK_6MHZ          0
0066 #define MADERA_SYSCLK_12MHZ         1
0067 #define MADERA_SYSCLK_24MHZ         2
0068 #define MADERA_SYSCLK_49MHZ         3
0069 #define MADERA_SYSCLK_98MHZ         4
0070 
0071 #define MADERA_DSPCLK_9MHZ          0
0072 #define MADERA_DSPCLK_18MHZ         1
0073 #define MADERA_DSPCLK_36MHZ         2
0074 #define MADERA_DSPCLK_73MHZ         3
0075 #define MADERA_DSPCLK_147MHZ            4
0076 
0077 #define MADERA_FLL_VCO_CORNER           141900000
0078 #define MADERA_FLL_MAX_FREF         13500000
0079 #define MADERA_FLL_MAX_N            1023
0080 #define MADERA_FLL_MIN_FOUT         90000000
0081 #define MADERA_FLL_MAX_FOUT         100000000
0082 #define MADERA_FLL_MAX_FRATIO           16
0083 #define MADERA_FLL_MAX_REFDIV           8
0084 #define MADERA_FLL_OUTDIV           3
0085 #define MADERA_FLL_VCO_MULT         3
0086 #define MADERA_FLLAO_MAX_FREF           12288000
0087 #define MADERA_FLLAO_MIN_N          4
0088 #define MADERA_FLLAO_MAX_N          1023
0089 #define MADERA_FLLAO_MAX_FBDIV          254
0090 #define MADERA_FLLHJ_INT_MAX_N          1023
0091 #define MADERA_FLLHJ_INT_MIN_N          1
0092 #define MADERA_FLLHJ_FRAC_MAX_N         255
0093 #define MADERA_FLLHJ_FRAC_MIN_N         4
0094 #define MADERA_FLLHJ_LOW_THRESH         192000
0095 #define MADERA_FLLHJ_MID_THRESH         1152000
0096 #define MADERA_FLLHJ_MAX_THRESH         13000000
0097 #define MADERA_FLLHJ_LOW_GAINS          0x23f0
0098 #define MADERA_FLLHJ_MID_GAINS          0x22f2
0099 #define MADERA_FLLHJ_HIGH_GAINS         0x21f0
0100 
0101 #define MADERA_FLL_SYNCHRONISER_OFFS        0x10
0102 #define CS47L35_FLL_SYNCHRONISER_OFFS       0xE
0103 #define MADERA_FLL_CONTROL_1_OFFS       0x1
0104 #define MADERA_FLL_CONTROL_2_OFFS       0x2
0105 #define MADERA_FLL_CONTROL_3_OFFS       0x3
0106 #define MADERA_FLL_CONTROL_4_OFFS       0x4
0107 #define MADERA_FLL_CONTROL_5_OFFS       0x5
0108 #define MADERA_FLL_CONTROL_6_OFFS       0x6
0109 #define MADERA_FLL_GAIN_OFFS            0x8
0110 #define MADERA_FLL_CONTROL_7_OFFS       0x9
0111 #define MADERA_FLL_EFS_2_OFFS           0xA
0112 #define MADERA_FLL_SYNCHRONISER_1_OFFS      0x1
0113 #define MADERA_FLL_SYNCHRONISER_2_OFFS      0x2
0114 #define MADERA_FLL_SYNCHRONISER_3_OFFS      0x3
0115 #define MADERA_FLL_SYNCHRONISER_4_OFFS      0x4
0116 #define MADERA_FLL_SYNCHRONISER_5_OFFS      0x5
0117 #define MADERA_FLL_SYNCHRONISER_6_OFFS      0x6
0118 #define MADERA_FLL_SYNCHRONISER_7_OFFS      0x7
0119 #define MADERA_FLL_SPREAD_SPECTRUM_OFFS     0x9
0120 #define MADERA_FLL_GPIO_CLOCK_OFFS      0xA
0121 #define MADERA_FLL_CONTROL_10_OFFS      0xA
0122 #define MADERA_FLL_CONTROL_11_OFFS      0xB
0123 #define MADERA_FLL1_DIGITAL_TEST_1_OFFS     0xD
0124 
0125 #define MADERA_FLLAO_CONTROL_1_OFFS     0x1
0126 #define MADERA_FLLAO_CONTROL_2_OFFS     0x2
0127 #define MADERA_FLLAO_CONTROL_3_OFFS     0x3
0128 #define MADERA_FLLAO_CONTROL_4_OFFS     0x4
0129 #define MADERA_FLLAO_CONTROL_5_OFFS     0x5
0130 #define MADERA_FLLAO_CONTROL_6_OFFS     0x6
0131 #define MADERA_FLLAO_CONTROL_7_OFFS     0x8
0132 #define MADERA_FLLAO_CONTROL_8_OFFS     0xA
0133 #define MADERA_FLLAO_CONTROL_9_OFFS     0xB
0134 #define MADERA_FLLAO_CONTROL_10_OFFS        0xC
0135 #define MADERA_FLLAO_CONTROL_11_OFFS        0xD
0136 
0137 #define MADERA_FMT_DSP_MODE_A           0
0138 #define MADERA_FMT_DSP_MODE_B           1
0139 #define MADERA_FMT_I2S_MODE         2
0140 #define MADERA_FMT_LEFT_JUSTIFIED_MODE      3
0141 
0142 #define madera_fll_err(_fll, fmt, ...) \
0143     dev_err(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
0144 #define madera_fll_warn(_fll, fmt, ...) \
0145     dev_warn(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
0146 #define madera_fll_dbg(_fll, fmt, ...) \
0147     dev_dbg(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
0148 
0149 #define madera_aif_err(_dai, fmt, ...) \
0150     dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
0151 #define madera_aif_warn(_dai, fmt, ...) \
0152     dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
0153 #define madera_aif_dbg(_dai, fmt, ...) \
0154     dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
0155 
0156 static const int madera_dsp_bus_error_irqs[MADERA_MAX_ADSP] = {
0157     MADERA_IRQ_DSP1_BUS_ERR,
0158     MADERA_IRQ_DSP2_BUS_ERR,
0159     MADERA_IRQ_DSP3_BUS_ERR,
0160     MADERA_IRQ_DSP4_BUS_ERR,
0161     MADERA_IRQ_DSP5_BUS_ERR,
0162     MADERA_IRQ_DSP6_BUS_ERR,
0163     MADERA_IRQ_DSP7_BUS_ERR,
0164 };
0165 
0166 int madera_clk_ev(struct snd_soc_dapm_widget *w,
0167           struct snd_kcontrol *kcontrol, int event)
0168 {
0169     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0170     struct madera_priv *priv = snd_soc_component_get_drvdata(component);
0171     struct madera *madera = priv->madera;
0172     unsigned int val;
0173     int clk_idx;
0174     int ret;
0175 
0176     ret = regmap_read(madera->regmap, w->reg, &val);
0177     if (ret) {
0178         dev_err(madera->dev, "Failed to check clock source: %d\n", ret);
0179         return ret;
0180     }
0181 
0182     switch ((val & MADERA_SYSCLK_SRC_MASK) >> MADERA_SYSCLK_SRC_SHIFT) {
0183     case MADERA_CLK_SRC_MCLK1:
0184         clk_idx = MADERA_MCLK1;
0185         break;
0186     case MADERA_CLK_SRC_MCLK2:
0187         clk_idx = MADERA_MCLK2;
0188         break;
0189     case MADERA_CLK_SRC_MCLK3:
0190         clk_idx = MADERA_MCLK3;
0191         break;
0192     default:
0193         return 0;
0194     }
0195 
0196     switch (event) {
0197     case SND_SOC_DAPM_PRE_PMU:
0198         return clk_prepare_enable(madera->mclk[clk_idx].clk);
0199     case SND_SOC_DAPM_POST_PMD:
0200         clk_disable_unprepare(madera->mclk[clk_idx].clk);
0201         return 0;
0202     default:
0203         return 0;
0204     }
0205 }
0206 EXPORT_SYMBOL_GPL(madera_clk_ev);
0207 
0208 static void madera_spin_sysclk(struct madera_priv *priv)
0209 {
0210     struct madera *madera = priv->madera;
0211     unsigned int val;
0212     int ret, i;
0213 
0214     /* Skip this if the chip is down */
0215     if (pm_runtime_suspended(madera->dev))
0216         return;
0217 
0218     /*
0219      * Just read a register a few times to ensure the internal
0220      * oscillator sends out a few clocks.
0221      */
0222     for (i = 0; i < 4; i++) {
0223         ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &val);
0224         if (ret)
0225             dev_err(madera->dev,
0226                 "Failed to read sysclk spin %d: %d\n", i, ret);
0227     }
0228 
0229     udelay(300);
0230 }
0231 
0232 int madera_sysclk_ev(struct snd_soc_dapm_widget *w,
0233              struct snd_kcontrol *kcontrol, int event)
0234 {
0235     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0236     struct madera_priv *priv = snd_soc_component_get_drvdata(component);
0237 
0238     switch (event) {
0239     case SND_SOC_DAPM_POST_PMU:
0240     case SND_SOC_DAPM_PRE_PMD:
0241         madera_spin_sysclk(priv);
0242         break;
0243     default:
0244         break;
0245     }
0246 
0247     return madera_clk_ev(w, kcontrol, event);
0248 }
0249 EXPORT_SYMBOL_GPL(madera_sysclk_ev);
0250 
0251 static int madera_check_speaker_overheat(struct madera *madera,
0252                      bool *warn, bool *shutdown)
0253 {
0254     unsigned int val;
0255     int ret;
0256 
0257     ret = regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_15, &val);
0258     if (ret) {
0259         dev_err(madera->dev, "Failed to read thermal status: %d\n",
0260             ret);
0261         return ret;
0262     }
0263 
0264     *warn = val & MADERA_SPK_OVERHEAT_WARN_STS1;
0265     *shutdown = val & MADERA_SPK_OVERHEAT_STS1;
0266 
0267     return 0;
0268 }
0269 
0270 int madera_spk_ev(struct snd_soc_dapm_widget *w,
0271           struct snd_kcontrol *kcontrol, int event)
0272 {
0273     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0274     struct madera_priv *priv = snd_soc_component_get_drvdata(component);
0275     struct madera *madera = priv->madera;
0276     bool warn, shutdown;
0277     int ret;
0278 
0279     switch (event) {
0280     case SND_SOC_DAPM_POST_PMU:
0281         ret = madera_check_speaker_overheat(madera, &warn, &shutdown);
0282         if (ret)
0283             return ret;
0284 
0285         if (shutdown) {
0286             dev_crit(madera->dev,
0287                  "Speaker not enabled due to temperature\n");
0288             return -EBUSY;
0289         }
0290 
0291         regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
0292                    1 << w->shift, 1 << w->shift);
0293         break;
0294     case SND_SOC_DAPM_PRE_PMD:
0295         regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
0296                    1 << w->shift, 0);
0297         break;
0298     default:
0299         break;
0300     }
0301 
0302     return 0;
0303 }
0304 EXPORT_SYMBOL_GPL(madera_spk_ev);
0305 
0306 static irqreturn_t madera_thermal_warn(int irq, void *data)
0307 {
0308     struct madera *madera = data;
0309     bool warn, shutdown;
0310     int ret;
0311 
0312     ret = madera_check_speaker_overheat(madera, &warn, &shutdown);
0313     if (ret || shutdown) { /* for safety attempt to shutdown on error */
0314         dev_crit(madera->dev, "Thermal shutdown\n");
0315         ret = regmap_update_bits(madera->regmap,
0316                      MADERA_OUTPUT_ENABLES_1,
0317                      MADERA_OUT4L_ENA |
0318                      MADERA_OUT4R_ENA, 0);
0319         if (ret != 0)
0320             dev_crit(madera->dev,
0321                  "Failed to disable speaker outputs: %d\n",
0322                  ret);
0323     } else if (warn) {
0324         dev_alert(madera->dev, "Thermal warning\n");
0325     } else {
0326         dev_info(madera->dev, "Spurious thermal warning\n");
0327         return IRQ_NONE;
0328     }
0329 
0330     return IRQ_HANDLED;
0331 }
0332 
0333 int madera_init_overheat(struct madera_priv *priv)
0334 {
0335     struct madera *madera = priv->madera;
0336     struct device *dev = madera->dev;
0337     int ret;
0338 
0339     ret = madera_request_irq(madera, MADERA_IRQ_SPK_OVERHEAT_WARN,
0340                  "Thermal warning", madera_thermal_warn,
0341                  madera);
0342     if (ret)
0343         dev_err(dev, "Failed to get thermal warning IRQ: %d\n", ret);
0344 
0345     ret = madera_request_irq(madera, MADERA_IRQ_SPK_OVERHEAT,
0346                  "Thermal shutdown", madera_thermal_warn,
0347                  madera);
0348     if (ret)
0349         dev_err(dev, "Failed to get thermal shutdown IRQ: %d\n", ret);
0350 
0351     return 0;
0352 }
0353 EXPORT_SYMBOL_GPL(madera_init_overheat);
0354 
0355 int madera_free_overheat(struct madera_priv *priv)
0356 {
0357     struct madera *madera = priv->madera;
0358 
0359     madera_free_irq(madera, MADERA_IRQ_SPK_OVERHEAT_WARN, madera);
0360     madera_free_irq(madera, MADERA_IRQ_SPK_OVERHEAT, madera);
0361 
0362     return 0;
0363 }
0364 EXPORT_SYMBOL_GPL(madera_free_overheat);
0365 
0366 static int madera_get_variable_u32_array(struct device *dev,
0367                      const char *propname,
0368                      u32 *dest, int n_max,
0369                      int multiple)
0370 {
0371     int n, ret;
0372 
0373     n = device_property_count_u32(dev, propname);
0374     if (n < 0) {
0375         if (n == -EINVAL)
0376             return 0;   /* missing, ignore */
0377 
0378         dev_warn(dev, "%s malformed (%d)\n", propname, n);
0379 
0380         return n;
0381     } else if ((n % multiple) != 0) {
0382         dev_warn(dev, "%s not a multiple of %d entries\n",
0383              propname, multiple);
0384 
0385         return -EINVAL;
0386     }
0387 
0388     if (n > n_max)
0389         n = n_max;
0390 
0391     ret = device_property_read_u32_array(dev, propname, dest, n);
0392     if (ret < 0)
0393         return ret;
0394 
0395     return n;
0396 }
0397 
0398 static void madera_prop_get_inmode(struct madera_priv *priv)
0399 {
0400     struct madera *madera = priv->madera;
0401     struct madera_codec_pdata *pdata = &madera->pdata.codec;
0402     u32 tmp[MADERA_MAX_INPUT * MADERA_MAX_MUXED_CHANNELS];
0403     int n, i, in_idx, ch_idx;
0404 
0405     BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode) != MADERA_MAX_INPUT);
0406     BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode[0]) != MADERA_MAX_MUXED_CHANNELS);
0407 
0408     n = madera_get_variable_u32_array(madera->dev, "cirrus,inmode",
0409                       tmp, ARRAY_SIZE(tmp),
0410                       MADERA_MAX_MUXED_CHANNELS);
0411     if (n < 0)
0412         return;
0413 
0414     in_idx = 0;
0415     ch_idx = 0;
0416     for (i = 0; i < n; ++i) {
0417         pdata->inmode[in_idx][ch_idx] = tmp[i];
0418 
0419         if (++ch_idx == MADERA_MAX_MUXED_CHANNELS) {
0420             ch_idx = 0;
0421             ++in_idx;
0422         }
0423     }
0424 }
0425 
0426 static void madera_prop_get_pdata(struct madera_priv *priv)
0427 {
0428     struct madera *madera = priv->madera;
0429     struct madera_codec_pdata *pdata = &madera->pdata.codec;
0430     u32 out_mono[ARRAY_SIZE(pdata->out_mono)];
0431     int i, n;
0432 
0433     madera_prop_get_inmode(priv);
0434 
0435     n = madera_get_variable_u32_array(madera->dev, "cirrus,out-mono",
0436                       out_mono, ARRAY_SIZE(out_mono), 1);
0437     if (n > 0)
0438         for (i = 0; i < n; ++i)
0439             pdata->out_mono[i] = !!out_mono[i];
0440 
0441     madera_get_variable_u32_array(madera->dev,
0442                       "cirrus,max-channels-clocked",
0443                       pdata->max_channels_clocked,
0444                       ARRAY_SIZE(pdata->max_channels_clocked),
0445                       1);
0446 
0447     madera_get_variable_u32_array(madera->dev, "cirrus,pdm-fmt",
0448                       pdata->pdm_fmt,
0449                       ARRAY_SIZE(pdata->pdm_fmt), 1);
0450 
0451     madera_get_variable_u32_array(madera->dev, "cirrus,pdm-mute",
0452                       pdata->pdm_mute,
0453                       ARRAY_SIZE(pdata->pdm_mute), 1);
0454 
0455     madera_get_variable_u32_array(madera->dev, "cirrus,dmic-ref",
0456                       pdata->dmic_ref,
0457                       ARRAY_SIZE(pdata->dmic_ref), 1);
0458 }
0459 
0460 int madera_core_init(struct madera_priv *priv)
0461 {
0462     int i;
0463 
0464     /* trap undersized array initializers */
0465     BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]);
0466     BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]);
0467 
0468     if (!dev_get_platdata(priv->madera->dev))
0469         madera_prop_get_pdata(priv);
0470 
0471     mutex_init(&priv->rate_lock);
0472 
0473     for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++)
0474         priv->madera->out_clamp[i] = true;
0475 
0476     return 0;
0477 }
0478 EXPORT_SYMBOL_GPL(madera_core_init);
0479 
0480 int madera_core_free(struct madera_priv *priv)
0481 {
0482     mutex_destroy(&priv->rate_lock);
0483 
0484     return 0;
0485 }
0486 EXPORT_SYMBOL_GPL(madera_core_free);
0487 
0488 static void madera_debug_dump_domain_groups(const struct madera_priv *priv)
0489 {
0490     struct madera *madera = priv->madera;
0491     int i;
0492 
0493     for (i = 0; i < ARRAY_SIZE(priv->domain_group_ref); ++i)
0494         dev_dbg(madera->dev, "domain_grp_ref[%d]=%d\n", i,
0495             priv->domain_group_ref[i]);
0496 }
0497 
0498 int madera_domain_clk_ev(struct snd_soc_dapm_widget *w,
0499              struct snd_kcontrol *kcontrol,
0500              int event)
0501 {
0502     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0503     struct madera_priv *priv = snd_soc_component_get_drvdata(component);
0504     int dom_grp = w->shift;
0505 
0506     if (dom_grp >= ARRAY_SIZE(priv->domain_group_ref)) {
0507         WARN(true, "%s dom_grp exceeds array size\n", __func__);
0508         return -EINVAL;
0509     }
0510 
0511     /*
0512      * We can't rely on the DAPM mutex for locking because we need a lock
0513      * that can safely be called in hw_params
0514      */
0515     mutex_lock(&priv->rate_lock);
0516 
0517     switch (event) {
0518     case SND_SOC_DAPM_PRE_PMU:
0519         dev_dbg(priv->madera->dev, "Inc ref on domain group %d\n",
0520             dom_grp);
0521         ++priv->domain_group_ref[dom_grp];
0522         break;
0523     case SND_SOC_DAPM_POST_PMD:
0524         dev_dbg(priv->madera->dev, "Dec ref on domain group %d\n",
0525             dom_grp);
0526         --priv->domain_group_ref[dom_grp];
0527         break;
0528     default:
0529         break;
0530     }
0531 
0532     madera_debug_dump_domain_groups(priv);
0533 
0534     mutex_unlock(&priv->rate_lock);
0535 
0536     return 0;
0537 }
0538 EXPORT_SYMBOL_GPL(madera_domain_clk_ev);
0539 
0540 int madera_out1_demux_put(struct snd_kcontrol *kcontrol,
0541               struct snd_ctl_elem_value *ucontrol)
0542 {
0543     struct snd_soc_component *component =
0544         snd_soc_dapm_kcontrol_component(kcontrol);
0545     struct snd_soc_dapm_context *dapm =
0546         snd_soc_dapm_kcontrol_dapm(kcontrol);
0547     struct madera_priv *priv = snd_soc_component_get_drvdata(component);
0548     struct madera *madera = priv->madera;
0549     struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
0550     unsigned int ep_sel, mux, change;
0551     bool out_mono;
0552     int ret;
0553 
0554     if (ucontrol->value.enumerated.item[0] > e->items - 1)
0555         return -EINVAL;
0556 
0557     mux = ucontrol->value.enumerated.item[0];
0558 
0559     snd_soc_dapm_mutex_lock(dapm);
0560 
0561     ep_sel = mux << MADERA_EP_SEL_SHIFT;
0562 
0563     change = snd_soc_component_test_bits(component, MADERA_OUTPUT_ENABLES_1,
0564                          MADERA_EP_SEL_MASK,
0565                          ep_sel);
0566     if (!change)
0567         goto end;
0568 
0569     /* EP_SEL should not be modified while HP or EP driver is enabled */
0570     ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
0571                  MADERA_OUT1L_ENA | MADERA_OUT1R_ENA, 0);
0572     if (ret)
0573         dev_warn(madera->dev, "Failed to disable outputs: %d\n", ret);
0574 
0575     usleep_range(2000, 3000); /* wait for wseq to complete */
0576 
0577     /* change demux setting */
0578     ret = 0;
0579     if (madera->out_clamp[0])
0580         ret = regmap_update_bits(madera->regmap,
0581                      MADERA_OUTPUT_ENABLES_1,
0582                      MADERA_EP_SEL_MASK, ep_sel);
0583     if (ret) {
0584         dev_err(madera->dev, "Failed to set OUT1 demux: %d\n", ret);
0585     } else {
0586         /* apply correct setting for mono mode */
0587         if (!ep_sel && !madera->pdata.codec.out_mono[0])
0588             out_mono = false; /* stereo HP */
0589         else
0590             out_mono = true; /* EP or mono HP */
0591 
0592         ret = madera_set_output_mode(component, 1, out_mono);
0593         if (ret)
0594             dev_warn(madera->dev,
0595                  "Failed to set output mode: %d\n", ret);
0596     }
0597 
0598     /*
0599      * if HPDET has disabled the clamp while switching to HPOUT
0600      * OUT1 should remain disabled
0601      */
0602     if (ep_sel ||
0603         (madera->out_clamp[0] && !madera->out_shorted[0])) {
0604         ret = regmap_update_bits(madera->regmap,
0605                      MADERA_OUTPUT_ENABLES_1,
0606                      MADERA_OUT1L_ENA | MADERA_OUT1R_ENA,
0607                      madera->hp_ena);
0608         if (ret)
0609             dev_warn(madera->dev,
0610                  "Failed to restore earpiece outputs: %d\n",
0611                  ret);
0612         else if (madera->hp_ena)
0613             msleep(34); /* wait for enable wseq */
0614         else
0615             usleep_range(2000, 3000); /* wait for disable wseq */
0616     }
0617 
0618 end:
0619     snd_soc_dapm_mutex_unlock(dapm);
0620 
0621     ret = snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
0622     if (ret < 0) {
0623         dev_err(madera->dev, "Failed to update demux power state: %d\n", ret);
0624         return ret;
0625     }
0626 
0627     return change;
0628 }
0629 EXPORT_SYMBOL_GPL(madera_out1_demux_put);
0630 
0631 int madera_out1_demux_get(struct snd_kcontrol *kcontrol,
0632               struct snd_ctl_elem_value *ucontrol)
0633 {
0634     struct snd_soc_component *component =
0635         snd_soc_dapm_kcontrol_component(kcontrol);
0636     unsigned int val;
0637 
0638     val = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1);
0639     val &= MADERA_EP_SEL_MASK;
0640     val >>= MADERA_EP_SEL_SHIFT;
0641     ucontrol->value.enumerated.item[0] = val;
0642 
0643     return 0;
0644 }
0645 EXPORT_SYMBOL_GPL(madera_out1_demux_get);
0646 
0647 static int madera_inmux_put(struct snd_kcontrol *kcontrol,
0648                 struct snd_ctl_elem_value *ucontrol)
0649 {
0650     struct snd_soc_component *component =
0651         snd_soc_dapm_kcontrol_component(kcontrol);
0652     struct snd_soc_dapm_context *dapm =
0653         snd_soc_dapm_kcontrol_dapm(kcontrol);
0654     struct madera_priv *priv = snd_soc_component_get_drvdata(component);
0655     struct madera *madera = priv->madera;
0656     struct regmap *regmap = madera->regmap;
0657     struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
0658     unsigned int mux, val, mask;
0659     unsigned int inmode;
0660     bool changed;
0661     int ret;
0662 
0663     mux = ucontrol->value.enumerated.item[0];
0664     if (mux > 1)
0665         return -EINVAL;
0666 
0667     val = mux << e->shift_l;
0668     mask = (e->mask << e->shift_l) | MADERA_IN1L_SRC_SE_MASK;
0669 
0670     switch (e->reg) {
0671     case MADERA_ADC_DIGITAL_VOLUME_1L:
0672         inmode = madera->pdata.codec.inmode[0][2 * mux];
0673         break;
0674     case MADERA_ADC_DIGITAL_VOLUME_1R:
0675         inmode = madera->pdata.codec.inmode[0][1 + (2 * mux)];
0676         break;
0677     case MADERA_ADC_DIGITAL_VOLUME_2L:
0678         inmode = madera->pdata.codec.inmode[1][2 * mux];
0679         break;
0680     case MADERA_ADC_DIGITAL_VOLUME_2R:
0681         inmode = madera->pdata.codec.inmode[1][1 + (2 * mux)];
0682         break;
0683     default:
0684         return -EINVAL;
0685     }
0686 
0687     if (inmode & MADERA_INMODE_SE)
0688         val |= 1 << MADERA_IN1L_SRC_SE_SHIFT;
0689 
0690     dev_dbg(madera->dev, "mux=%u reg=0x%x inmode=0x%x mask=0x%x val=0x%x\n",
0691         mux, e->reg, inmode, mask, val);
0692 
0693     ret = regmap_update_bits_check(regmap, e->reg, mask, val, &changed);
0694     if (ret < 0)
0695         return ret;
0696 
0697     if (changed)
0698         return snd_soc_dapm_mux_update_power(dapm, kcontrol,
0699                              mux, e, NULL);
0700     else
0701         return 0;
0702 }
0703 
0704 static const char * const madera_inmux_texts[] = {
0705     "A",
0706     "B",
0707 };
0708 
0709 static SOC_ENUM_SINGLE_DECL(madera_in1muxl_enum,
0710                 MADERA_ADC_DIGITAL_VOLUME_1L,
0711                 MADERA_IN1L_SRC_SHIFT,
0712                 madera_inmux_texts);
0713 
0714 static SOC_ENUM_SINGLE_DECL(madera_in1muxr_enum,
0715                 MADERA_ADC_DIGITAL_VOLUME_1R,
0716                 MADERA_IN1R_SRC_SHIFT,
0717                 madera_inmux_texts);
0718 
0719 static SOC_ENUM_SINGLE_DECL(madera_in2muxl_enum,
0720                 MADERA_ADC_DIGITAL_VOLUME_2L,
0721                 MADERA_IN2L_SRC_SHIFT,
0722                 madera_inmux_texts);
0723 
0724 static SOC_ENUM_SINGLE_DECL(madera_in2muxr_enum,
0725                 MADERA_ADC_DIGITAL_VOLUME_2R,
0726                 MADERA_IN2R_SRC_SHIFT,
0727                 madera_inmux_texts);
0728 
0729 const struct snd_kcontrol_new madera_inmux[] = {
0730     SOC_DAPM_ENUM_EXT("IN1L Mux", madera_in1muxl_enum,
0731               snd_soc_dapm_get_enum_double, madera_inmux_put),
0732     SOC_DAPM_ENUM_EXT("IN1R Mux", madera_in1muxr_enum,
0733               snd_soc_dapm_get_enum_double, madera_inmux_put),
0734     SOC_DAPM_ENUM_EXT("IN2L Mux", madera_in2muxl_enum,
0735               snd_soc_dapm_get_enum_double, madera_inmux_put),
0736     SOC_DAPM_ENUM_EXT("IN2R Mux", madera_in2muxr_enum,
0737               snd_soc_dapm_get_enum_double, madera_inmux_put),
0738 };
0739 EXPORT_SYMBOL_GPL(madera_inmux);
0740 
0741 static const char * const madera_dmode_texts[] = {
0742     "Analog",
0743     "Digital",
0744 };
0745 
0746 static SOC_ENUM_SINGLE_DECL(madera_in1dmode_enum,
0747                 MADERA_IN1L_CONTROL,
0748                 MADERA_IN1_MODE_SHIFT,
0749                 madera_dmode_texts);
0750 
0751 static SOC_ENUM_SINGLE_DECL(madera_in2dmode_enum,
0752                 MADERA_IN2L_CONTROL,
0753                 MADERA_IN2_MODE_SHIFT,
0754                 madera_dmode_texts);
0755 
0756 static SOC_ENUM_SINGLE_DECL(madera_in3dmode_enum,
0757                 MADERA_IN3L_CONTROL,
0758                 MADERA_IN3_MODE_SHIFT,
0759                 madera_dmode_texts);
0760 
0761 const struct snd_kcontrol_new madera_inmode[] = {
0762     SOC_DAPM_ENUM("IN1 Mode", madera_in1dmode_enum),
0763     SOC_DAPM_ENUM("IN2 Mode", madera_in2dmode_enum),
0764     SOC_DAPM_ENUM("IN3 Mode", madera_in3dmode_enum),
0765 };
0766 EXPORT_SYMBOL_GPL(madera_inmode);
0767 
0768 static bool madera_can_change_grp_rate(const struct madera_priv *priv,
0769                        unsigned int reg)
0770 {
0771     int count;
0772 
0773     switch (reg) {
0774     case MADERA_FX_CTRL1:
0775         count = priv->domain_group_ref[MADERA_DOM_GRP_FX];
0776         break;
0777     case MADERA_ASRC1_RATE1:
0778     case MADERA_ASRC1_RATE2:
0779         count = priv->domain_group_ref[MADERA_DOM_GRP_ASRC1];
0780         break;
0781     case MADERA_ASRC2_RATE1:
0782     case MADERA_ASRC2_RATE2:
0783         count = priv->domain_group_ref[MADERA_DOM_GRP_ASRC2];
0784         break;
0785     case MADERA_ISRC_1_CTRL_1:
0786     case MADERA_ISRC_1_CTRL_2:
0787         count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC1];
0788         break;
0789     case MADERA_ISRC_2_CTRL_1:
0790     case MADERA_ISRC_2_CTRL_2:
0791         count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC2];
0792         break;
0793     case MADERA_ISRC_3_CTRL_1:
0794     case MADERA_ISRC_3_CTRL_2:
0795         count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC3];
0796         break;
0797     case MADERA_ISRC_4_CTRL_1:
0798     case MADERA_ISRC_4_CTRL_2:
0799         count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC4];
0800         break;
0801     case MADERA_OUTPUT_RATE_1:
0802         count = priv->domain_group_ref[MADERA_DOM_GRP_OUT];
0803         break;
0804     case MADERA_SPD1_TX_CONTROL:
0805         count = priv->domain_group_ref[MADERA_DOM_GRP_SPD];
0806         break;
0807     case MADERA_DSP1_CONFIG_1:
0808     case MADERA_DSP1_CONFIG_2:
0809         count = priv->domain_group_ref[MADERA_DOM_GRP_DSP1];
0810         break;
0811     case MADERA_DSP2_CONFIG_1:
0812     case MADERA_DSP2_CONFIG_2:
0813         count = priv->domain_group_ref[MADERA_DOM_GRP_DSP2];
0814         break;
0815     case MADERA_DSP3_CONFIG_1:
0816     case MADERA_DSP3_CONFIG_2:
0817         count = priv->domain_group_ref[MADERA_DOM_GRP_DSP3];
0818         break;
0819     case MADERA_DSP4_CONFIG_1:
0820     case MADERA_DSP4_CONFIG_2:
0821         count = priv->domain_group_ref[MADERA_DOM_GRP_DSP4];
0822         break;
0823     case MADERA_DSP5_CONFIG_1:
0824     case MADERA_DSP5_CONFIG_2:
0825         count = priv->domain_group_ref[MADERA_DOM_GRP_DSP5];
0826         break;
0827     case MADERA_DSP6_CONFIG_1:
0828     case MADERA_DSP6_CONFIG_2:
0829         count = priv->domain_group_ref[MADERA_DOM_GRP_DSP6];
0830         break;
0831     case MADERA_DSP7_CONFIG_1:
0832     case MADERA_DSP7_CONFIG_2:
0833         count = priv->domain_group_ref[MADERA_DOM_GRP_DSP7];
0834         break;
0835     case MADERA_AIF1_RATE_CTRL:
0836         count = priv->domain_group_ref[MADERA_DOM_GRP_AIF1];
0837         break;
0838     case MADERA_AIF2_RATE_CTRL:
0839         count = priv->domain_group_ref[MADERA_DOM_GRP_AIF2];
0840         break;
0841     case MADERA_AIF3_RATE_CTRL:
0842         count = priv->domain_group_ref[MADERA_DOM_GRP_AIF3];
0843         break;
0844     case MADERA_AIF4_RATE_CTRL:
0845         count = priv->domain_group_ref[MADERA_DOM_GRP_AIF4];
0846         break;
0847     case MADERA_SLIMBUS_RATES_1:
0848     case MADERA_SLIMBUS_RATES_2:
0849     case MADERA_SLIMBUS_RATES_3:
0850     case MADERA_SLIMBUS_RATES_4:
0851     case MADERA_SLIMBUS_RATES_5:
0852     case MADERA_SLIMBUS_RATES_6:
0853     case MADERA_SLIMBUS_RATES_7:
0854     case MADERA_SLIMBUS_RATES_8:
0855         count = priv->domain_group_ref[MADERA_DOM_GRP_SLIMBUS];
0856         break;
0857     case MADERA_PWM_DRIVE_1:
0858         count = priv->domain_group_ref[MADERA_DOM_GRP_PWM];
0859         break;
0860     default:
0861         return false;
0862     }
0863 
0864     dev_dbg(priv->madera->dev, "Rate reg 0x%x group ref %d\n", reg, count);
0865 
0866     if (count)
0867         return false;
0868     else
0869         return true;
0870 }
0871 
0872 static int madera_adsp_rate_get(struct snd_kcontrol *kcontrol,
0873                 struct snd_ctl_elem_value *ucontrol)
0874 {
0875     struct snd_soc_component *component =
0876         snd_soc_kcontrol_component(kcontrol);
0877     struct madera_priv *priv = snd_soc_component_get_drvdata(component);
0878     struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
0879     unsigned int cached_rate;
0880     const int adsp_num = e->shift_l;
0881     int item;
0882 
0883     mutex_lock(&priv->rate_lock);
0884     cached_rate = priv->adsp_rate_cache[adsp_num];
0885     mutex_unlock(&priv->rate_lock);
0886 
0887     item = snd_soc_enum_val_to_item(e, cached_rate);
0888     ucontrol->value.enumerated.item[0] = item;
0889 
0890     return 0;
0891 }
0892 
0893 static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol,
0894                 struct snd_ctl_elem_value *ucontrol)
0895 {
0896     struct snd_soc_component *component =
0897         snd_soc_kcontrol_component(kcontrol);
0898     struct madera_priv *priv = snd_soc_component_get_drvdata(component);
0899     struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
0900     const int adsp_num = e->shift_l;
0901     const unsigned int item = ucontrol->value.enumerated.item[0];
0902     int ret = 0;
0903 
0904     if (item >= e->items)
0905         return -EINVAL;
0906 
0907     /*
0908      * We don't directly write the rate register here but we want to
0909      * maintain consistent behaviour that rate domains cannot be changed
0910      * while in use since this is a hardware requirement
0911      */
0912     mutex_lock(&priv->rate_lock);
0913 
0914     if (!madera_can_change_grp_rate(priv, priv->adsp[adsp_num].cs_dsp.base)) {
0915         dev_warn(priv->madera->dev,
0916              "Cannot change '%s' while in use by active audio paths\n",
0917              kcontrol->id.name);
0918         ret = -EBUSY;
0919     } else if (priv->adsp_rate_cache[adsp_num] != e->values[item]) {
0920         /* Volatile register so defer until the codec is powered up */
0921         priv->adsp_rate_cache[adsp_num] = e->values[item];
0922         ret = 1;
0923     }
0924 
0925     mutex_unlock(&priv->rate_lock);
0926 
0927     return ret;
0928 }
0929 
0930 static const struct soc_enum madera_adsp_rate_enum[] = {
0931     SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 0xf, MADERA_RATE_ENUM_SIZE,
0932                   madera_rate_text, madera_rate_val),
0933     SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 1, 0xf, MADERA_RATE_ENUM_SIZE,
0934                   madera_rate_text, madera_rate_val),
0935     SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 2, 0xf, MADERA_RATE_ENUM_SIZE,
0936                   madera_rate_text, madera_rate_val),
0937     SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 3, 0xf, MADERA_RATE_ENUM_SIZE,
0938                   madera_rate_text, madera_rate_val),
0939     SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 4, 0xf, MADERA_RATE_ENUM_SIZE,
0940                   madera_rate_text, madera_rate_val),
0941     SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 5, 0xf, MADERA_RATE_ENUM_SIZE,
0942                   madera_rate_text, madera_rate_val),
0943     SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 6, 0xf, MADERA_RATE_ENUM_SIZE,
0944                   madera_rate_text, madera_rate_val),
0945 };
0946 
0947 const struct snd_kcontrol_new madera_adsp_rate_controls[] = {
0948     SOC_ENUM_EXT("DSP1 Rate", madera_adsp_rate_enum[0],
0949              madera_adsp_rate_get, madera_adsp_rate_put),
0950     SOC_ENUM_EXT("DSP2 Rate", madera_adsp_rate_enum[1],
0951              madera_adsp_rate_get, madera_adsp_rate_put),
0952     SOC_ENUM_EXT("DSP3 Rate", madera_adsp_rate_enum[2],
0953              madera_adsp_rate_get, madera_adsp_rate_put),
0954     SOC_ENUM_EXT("DSP4 Rate", madera_adsp_rate_enum[3],
0955              madera_adsp_rate_get, madera_adsp_rate_put),
0956     SOC_ENUM_EXT("DSP5 Rate", madera_adsp_rate_enum[4],
0957              madera_adsp_rate_get, madera_adsp_rate_put),
0958     SOC_ENUM_EXT("DSP6 Rate", madera_adsp_rate_enum[5],
0959              madera_adsp_rate_get, madera_adsp_rate_put),
0960     SOC_ENUM_EXT("DSP7 Rate", madera_adsp_rate_enum[6],
0961              madera_adsp_rate_get, madera_adsp_rate_put),
0962 };
0963 EXPORT_SYMBOL_GPL(madera_adsp_rate_controls);
0964 
0965 static int madera_write_adsp_clk_setting(struct madera_priv *priv,
0966                      struct wm_adsp *dsp,
0967                      unsigned int freq)
0968 {
0969     unsigned int val;
0970     unsigned int mask = MADERA_DSP_RATE_MASK;
0971     int ret;
0972 
0973     val = priv->adsp_rate_cache[dsp->cs_dsp.num - 1] << MADERA_DSP_RATE_SHIFT;
0974 
0975     switch (priv->madera->type) {
0976     case CS47L35:
0977     case CS47L85:
0978     case WM1840:
0979         /* use legacy frequency registers */
0980         mask |= MADERA_DSP_CLK_SEL_MASK;
0981         val |= (freq << MADERA_DSP_CLK_SEL_SHIFT);
0982         break;
0983     default:
0984         /* Configure exact dsp frequency */
0985         dev_dbg(priv->madera->dev, "Set DSP frequency to 0x%x\n", freq);
0986 
0987         ret = regmap_write(dsp->cs_dsp.regmap,
0988                    dsp->cs_dsp.base + MADERA_DSP_CONFIG_2_OFFS, freq);
0989         if (ret)
0990             goto err;
0991         break;
0992     }
0993 
0994     ret = regmap_update_bits(dsp->cs_dsp.regmap,
0995                  dsp->cs_dsp.base + MADERA_DSP_CONFIG_1_OFFS,
0996                  mask, val);
0997     if (ret)
0998         goto err;
0999 
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_DIV_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");