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