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