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