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