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