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