0001
0002
0003
0004
0005
0006
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
0215 if (pm_runtime_suspended(madera->dev))
0216 return;
0217
0218
0219
0220
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) {
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;
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
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
0513
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
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);
0576
0577
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
0587 if (!ep_sel && !madera->pdata.codec.out_mono[0])
0588 out_mono = false;
0589 else
0590 out_mono = true;
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
0600
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);
0614 else
0615 usleep_range(2000, 3000);
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
0909
0910
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
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
0980 mask |= MADERA_DSP_CLK_SEL_MASK;
0981 val |= (freq << MADERA_DSP_CLK_SEL_SHIFT);
0982 break;
0983 default:
0984
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
1020
1021
1022
1023
1024
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
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
1069
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
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
1131
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
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,
1458 0x04,
1459 0x05,
1460 0x06,
1461 0x08,
1462 0x09,
1463 0x0c,
1464 0x0d,
1465 0x10,
1466 0x11,
1467 0x12,
1468 0x13,
1469 0x14,
1470 0x15,
1471 0x16,
1472 0x17,
1473 0x18,
1474 0x19,
1475 0x1A,
1476 0x1B,
1477 0x20,
1478 0x21,
1479 0x22,
1480 0x23,
1481 0x24,
1482 0x25,
1483 0x26,
1484 0x27,
1485 0x28,
1486 0x29,
1487 0x2a,
1488 0x2b,
1489 0x2c,
1490 0x2d,
1491 0x2e,
1492 0x2f,
1493 0x30,
1494 0x31,
1495 0x32,
1496 0x33,
1497 0x34,
1498 0x35,
1499 0x38,
1500 0x39,
1501 0x3a,
1502 0x3b,
1503 0x3c,
1504 0x3d,
1505 0x3e,
1506 0x3f,
1507 0x50,
1508 0x51,
1509 0x52,
1510 0x53,
1511 0x58,
1512 0x59,
1513 0x5a,
1514 0x5b,
1515 0x60,
1516 0x61,
1517 0x62,
1518 0x63,
1519 0x68,
1520 0x69,
1521 0x6a,
1522 0x6b,
1523 0x6c,
1524 0x6d,
1525 0x70,
1526 0x71,
1527 0x72,
1528 0x73,
1529 0x74,
1530 0x75,
1531 0x78,
1532 0x79,
1533 0x7a,
1534 0x7b,
1535 0x7c,
1536 0x7d,
1537 0x80,
1538 0x81,
1539 0x82,
1540 0x83,
1541 0x84,
1542 0x85,
1543 0x88,
1544 0x89,
1545 0x8a,
1546 0x8b,
1547 0x8c,
1548 0x8d,
1549 0xc0,
1550 0xc1,
1551 0xc2,
1552 0xc3,
1553 0xc4,
1554 0xc5,
1555 0xc8,
1556 0xc9,
1557 0xca,
1558 0xcb,
1559 0xcc,
1560 0xcd,
1561 0x90,
1562 0x91,
1563 0x92,
1564 0x93,
1565 0x94,
1566 0x95,
1567 0x96,
1568 0x97,
1569 0xa0,
1570 0xa1,
1571 0xa2,
1572 0xa3,
1573 0xa4,
1574 0xa5,
1575 0xa6,
1576 0xa7,
1577 0xa8,
1578 0xa9,
1579 0xaa,
1580 0xab,
1581 0xac,
1582 0xad,
1583 0xae,
1584 0xaf,
1585 0xb0,
1586 0xb1,
1587 0xb2,
1588 0xb3,
1589 0xb4,
1590 0xb5,
1591 0xb6,
1592 0xb7,
1593 0xb8,
1594 0xb9,
1595 0xbc,
1596 0xbd,
1597 0xf8,
1598 0xf9,
1599 0xfa,
1600 0xfb,
1601 0xfc,
1602 0xfd,
1603 0xfe,
1604 0xff,
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
2208 val = snd_soc_component_read(component, MADERA_INPUT_ENABLES);
2209 mask = (mc->reg - MADERA_ADC_DIGITAL_VOLUME_1L) / 4;
2210 mask ^= 0x1;
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
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
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
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
2447 regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel);
2448 ep_sel &= MADERA_EP_SEL_MASK;
2449 break;
2450 }
2451
2452
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;
2615 return madera_get_legacy_dspclk_setting(madera, freq);
2616 default:
2617 if (freq > 150000000)
2618 return -EINVAL;
2619
2620
2621 *clock_2_val = freq / 15625;
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
2746
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
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
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
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
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
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
3270
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
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;
3425 int alt_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
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
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
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
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
3556
3557
3558 refdiv = cfg->refdiv;
3559
3560 while (div <= MADERA_FLL_MAX_REFDIV) {
3561
3562
3563
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
3634 ratio = madera_calc_fratio(fll, cfg, fref, sync);
3635 if (ratio < 0)
3636 return ratio;
3637
3638
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
3657
3658
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
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
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, ®);
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, ®_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;
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
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
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
4022 ret = madera_calc_fll(fll, &cfg, fll->ref_freq, false);
4023 if (ret < 0)
4024 goto err;
4025
4026
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
4067
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
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
4127
4128
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
4152
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
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
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
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
4313
4314
4315
4316
4317
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
4384
4385
4386
4387
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
4402
4403
4404
4405
4406
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
4437
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
4459
4460
4461 if (frac) {
4462 fast_clk = 0x3;
4463 fout = fll->fout * 6;
4464 }
4465 }
4466
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
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
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
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
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
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
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
4659
4660
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
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
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");