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