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