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