| .. | .. |
|---|
| 1 | | -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. |
|---|
| 2 | | - * |
|---|
| 3 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 4 | | - * it under the terms of the GNU General Public License version 2 and |
|---|
| 5 | | - * only version 2 as published by the Free Software Foundation. |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 8 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 9 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 10 | | - * GNU General Public License for more details. |
|---|
| 11 | | - */ |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 2 | +// Copyright (c) 2016, The Linux Foundation. All rights reserved. |
|---|
| 12 | 3 | |
|---|
| 13 | 4 | #include <linux/module.h> |
|---|
| 14 | 5 | #include <linux/err.h> |
|---|
| .. | .. |
|---|
| 196 | 187 | #define MSM8916_WCD_DIGITAL_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ |
|---|
| 197 | 188 | SNDRV_PCM_FMTBIT_S32_LE) |
|---|
| 198 | 189 | |
|---|
| 190 | +/* Codec supports 2 IIR filters */ |
|---|
| 191 | +enum { |
|---|
| 192 | + IIR1 = 0, |
|---|
| 193 | + IIR2, |
|---|
| 194 | + IIR_MAX, |
|---|
| 195 | +}; |
|---|
| 196 | + |
|---|
| 197 | +/* Codec supports 5 bands */ |
|---|
| 198 | +enum { |
|---|
| 199 | + BAND1 = 0, |
|---|
| 200 | + BAND2, |
|---|
| 201 | + BAND3, |
|---|
| 202 | + BAND4, |
|---|
| 203 | + BAND5, |
|---|
| 204 | + BAND_MAX, |
|---|
| 205 | +}; |
|---|
| 206 | + |
|---|
| 207 | +#define WCD_IIR_FILTER_SIZE (sizeof(u32)*BAND_MAX) |
|---|
| 208 | + |
|---|
| 209 | +#define WCD_IIR_FILTER_CTL(xname, iidx, bidx) \ |
|---|
| 210 | +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
|---|
| 211 | + .info = wcd_iir_filter_info, \ |
|---|
| 212 | + .get = msm8x16_wcd_get_iir_band_audio_mixer, \ |
|---|
| 213 | + .put = msm8x16_wcd_put_iir_band_audio_mixer, \ |
|---|
| 214 | + .private_value = (unsigned long)&(struct wcd_iir_filter_ctl) { \ |
|---|
| 215 | + .iir_idx = iidx, \ |
|---|
| 216 | + .band_idx = bidx, \ |
|---|
| 217 | + .bytes_ext = {.max = WCD_IIR_FILTER_SIZE, }, \ |
|---|
| 218 | + } \ |
|---|
| 219 | +} |
|---|
| 220 | + |
|---|
| 221 | +struct wcd_iir_filter_ctl { |
|---|
| 222 | + unsigned int iir_idx; |
|---|
| 223 | + unsigned int band_idx; |
|---|
| 224 | + struct soc_bytes_ext bytes_ext; |
|---|
| 225 | +}; |
|---|
| 226 | + |
|---|
| 199 | 227 | struct msm8916_wcd_digital_priv { |
|---|
| 200 | 228 | struct clk *ahbclk, *mclk; |
|---|
| 201 | 229 | }; |
|---|
| .. | .. |
|---|
| 215 | 243 | "ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3" |
|---|
| 216 | 244 | }; |
|---|
| 217 | 245 | |
|---|
| 246 | +static const char * const rx_mix2_text[] = { |
|---|
| 247 | + "ZERO", "IIR1", "IIR2" |
|---|
| 248 | +}; |
|---|
| 249 | + |
|---|
| 218 | 250 | static const char *const dec_mux_text[] = { |
|---|
| 219 | 251 | "ZERO", "ADC1", "ADC2", "ADC3", "DMIC1", "DMIC2" |
|---|
| 220 | 252 | }; |
|---|
| 221 | 253 | |
|---|
| 222 | 254 | static const char *const cic_mux_text[] = { "AMIC", "DMIC" }; |
|---|
| 223 | | -static const char *const rx_mix2_text[] = { "ZERO", "IIR1", "IIR2" }; |
|---|
| 224 | | -static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" }; |
|---|
| 225 | 255 | |
|---|
| 226 | 256 | /* RX1 MIX1 */ |
|---|
| 227 | 257 | static const struct soc_enum rx_mix1_inp_enum[] = { |
|---|
| .. | .. |
|---|
| 230 | 260 | SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B2_CTL, 0, 6, rx_mix1_text), |
|---|
| 231 | 261 | }; |
|---|
| 232 | 262 | |
|---|
| 233 | | -/* RX1 MIX2 */ |
|---|
| 234 | | -static const struct soc_enum rx_mix2_inp1_chain_enum = SOC_ENUM_SINGLE( |
|---|
| 235 | | - LPASS_CDC_CONN_RX1_B3_CTL, 0, 3, rx_mix2_text); |
|---|
| 236 | | - |
|---|
| 237 | 263 | /* RX2 MIX1 */ |
|---|
| 238 | 264 | static const struct soc_enum rx2_mix1_inp_enum[] = { |
|---|
| 239 | 265 | SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B1_CTL, 0, 6, rx_mix1_text), |
|---|
| .. | .. |
|---|
| 241 | 267 | SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B2_CTL, 0, 6, rx_mix1_text), |
|---|
| 242 | 268 | }; |
|---|
| 243 | 269 | |
|---|
| 244 | | -/* RX2 MIX2 */ |
|---|
| 245 | | -static const struct soc_enum rx2_mix2_inp1_chain_enum = SOC_ENUM_SINGLE( |
|---|
| 246 | | - LPASS_CDC_CONN_RX2_B3_CTL, 0, 3, rx_mix2_text); |
|---|
| 247 | | - |
|---|
| 248 | 270 | /* RX3 MIX1 */ |
|---|
| 249 | 271 | static const struct soc_enum rx3_mix1_inp_enum[] = { |
|---|
| 250 | 272 | SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 0, 6, rx_mix1_text), |
|---|
| 251 | 273 | SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 3, 6, rx_mix1_text), |
|---|
| 252 | 274 | SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B2_CTL, 0, 6, rx_mix1_text), |
|---|
| 253 | 275 | }; |
|---|
| 276 | + |
|---|
| 277 | +/* RX1 MIX2 */ |
|---|
| 278 | +static const struct soc_enum rx_mix2_inp1_chain_enum = |
|---|
| 279 | + SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B3_CTL, |
|---|
| 280 | + 0, 3, rx_mix2_text); |
|---|
| 281 | + |
|---|
| 282 | +/* RX2 MIX2 */ |
|---|
| 283 | +static const struct soc_enum rx2_mix2_inp1_chain_enum = |
|---|
| 284 | + SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B3_CTL, |
|---|
| 285 | + 0, 3, rx_mix2_text); |
|---|
| 254 | 286 | |
|---|
| 255 | 287 | /* DEC */ |
|---|
| 256 | 288 | static const struct soc_enum dec1_mux_enum = SOC_ENUM_SINGLE( |
|---|
| .. | .. |
|---|
| 291 | 323 | "RX3 MIX1 INP2 Mux", rx3_mix1_inp_enum[1]); |
|---|
| 292 | 324 | static const struct snd_kcontrol_new rx3_mix1_inp3_mux = SOC_DAPM_ENUM( |
|---|
| 293 | 325 | "RX3 MIX1 INP3 Mux", rx3_mix1_inp_enum[2]); |
|---|
| 326 | +static const struct snd_kcontrol_new rx1_mix2_inp1_mux = SOC_DAPM_ENUM( |
|---|
| 327 | + "RX1 MIX2 INP1 Mux", rx_mix2_inp1_chain_enum); |
|---|
| 328 | +static const struct snd_kcontrol_new rx2_mix2_inp1_mux = SOC_DAPM_ENUM( |
|---|
| 329 | + "RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum); |
|---|
| 294 | 330 | |
|---|
| 295 | | -/* Digital Gain control -38.4 dB to +38.4 dB in 0.3 dB steps */ |
|---|
| 296 | | -static const DECLARE_TLV_DB_SCALE(digital_gain, -3840, 30, 0); |
|---|
| 331 | +/* Digital Gain control -84 dB to +40 dB in 1 dB steps */ |
|---|
| 332 | +static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); |
|---|
| 297 | 333 | |
|---|
| 298 | 334 | /* Cutoff Freq for High Pass Filter at -3dB */ |
|---|
| 299 | 335 | static const char * const hpf_cutoff_text[] = { |
|---|
| .. | .. |
|---|
| 317 | 353 | static SOC_ENUM_SINGLE_DECL(rx3_dcb_cutoff_enum, LPASS_CDC_RX3_B4_CTL, 0, |
|---|
| 318 | 354 | dc_blocker_cutoff_text); |
|---|
| 319 | 355 | |
|---|
| 356 | +static int msm8x16_wcd_codec_set_iir_gain(struct snd_soc_dapm_widget *w, |
|---|
| 357 | + struct snd_kcontrol *kcontrol, int event) |
|---|
| 358 | +{ |
|---|
| 359 | + struct snd_soc_component *component = |
|---|
| 360 | + snd_soc_dapm_to_component(w->dapm); |
|---|
| 361 | + int value = 0, reg = 0; |
|---|
| 362 | + |
|---|
| 363 | + switch (event) { |
|---|
| 364 | + case SND_SOC_DAPM_POST_PMU: |
|---|
| 365 | + if (w->shift == 0) |
|---|
| 366 | + reg = LPASS_CDC_IIR1_GAIN_B1_CTL; |
|---|
| 367 | + else if (w->shift == 1) |
|---|
| 368 | + reg = LPASS_CDC_IIR2_GAIN_B1_CTL; |
|---|
| 369 | + value = snd_soc_component_read(component, reg); |
|---|
| 370 | + snd_soc_component_write(component, reg, value); |
|---|
| 371 | + break; |
|---|
| 372 | + default: |
|---|
| 373 | + break; |
|---|
| 374 | + } |
|---|
| 375 | + return 0; |
|---|
| 376 | +} |
|---|
| 377 | + |
|---|
| 378 | +static uint32_t get_iir_band_coeff(struct snd_soc_component *component, |
|---|
| 379 | + int iir_idx, int band_idx, |
|---|
| 380 | + int coeff_idx) |
|---|
| 381 | +{ |
|---|
| 382 | + uint32_t value = 0; |
|---|
| 383 | + |
|---|
| 384 | + /* Address does not automatically update if reading */ |
|---|
| 385 | + snd_soc_component_write(component, |
|---|
| 386 | + (LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx), |
|---|
| 387 | + ((band_idx * BAND_MAX + coeff_idx) |
|---|
| 388 | + * sizeof(uint32_t)) & 0x7F); |
|---|
| 389 | + |
|---|
| 390 | + value |= snd_soc_component_read(component, |
|---|
| 391 | + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)); |
|---|
| 392 | + |
|---|
| 393 | + snd_soc_component_write(component, |
|---|
| 394 | + (LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx), |
|---|
| 395 | + ((band_idx * BAND_MAX + coeff_idx) |
|---|
| 396 | + * sizeof(uint32_t) + 1) & 0x7F); |
|---|
| 397 | + |
|---|
| 398 | + value |= (snd_soc_component_read(component, |
|---|
| 399 | + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 8); |
|---|
| 400 | + |
|---|
| 401 | + snd_soc_component_write(component, |
|---|
| 402 | + (LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx), |
|---|
| 403 | + ((band_idx * BAND_MAX + coeff_idx) |
|---|
| 404 | + * sizeof(uint32_t) + 2) & 0x7F); |
|---|
| 405 | + |
|---|
| 406 | + value |= (snd_soc_component_read(component, |
|---|
| 407 | + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 16); |
|---|
| 408 | + |
|---|
| 409 | + snd_soc_component_write(component, |
|---|
| 410 | + (LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx), |
|---|
| 411 | + ((band_idx * BAND_MAX + coeff_idx) |
|---|
| 412 | + * sizeof(uint32_t) + 3) & 0x7F); |
|---|
| 413 | + |
|---|
| 414 | + /* Mask bits top 2 bits since they are reserved */ |
|---|
| 415 | + value |= ((snd_soc_component_read(component, |
|---|
| 416 | + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) & 0x3f) << 24); |
|---|
| 417 | + return value; |
|---|
| 418 | + |
|---|
| 419 | +} |
|---|
| 420 | + |
|---|
| 421 | +static int msm8x16_wcd_get_iir_band_audio_mixer( |
|---|
| 422 | + struct snd_kcontrol *kcontrol, |
|---|
| 423 | + struct snd_ctl_elem_value *ucontrol) |
|---|
| 424 | +{ |
|---|
| 425 | + |
|---|
| 426 | + struct snd_soc_component *component = |
|---|
| 427 | + snd_soc_kcontrol_component(kcontrol); |
|---|
| 428 | + struct wcd_iir_filter_ctl *ctl = |
|---|
| 429 | + (struct wcd_iir_filter_ctl *)kcontrol->private_value; |
|---|
| 430 | + struct soc_bytes_ext *params = &ctl->bytes_ext; |
|---|
| 431 | + int iir_idx = ctl->iir_idx; |
|---|
| 432 | + int band_idx = ctl->band_idx; |
|---|
| 433 | + u32 coeff[BAND_MAX]; |
|---|
| 434 | + |
|---|
| 435 | + coeff[0] = get_iir_band_coeff(component, iir_idx, band_idx, 0); |
|---|
| 436 | + coeff[1] = get_iir_band_coeff(component, iir_idx, band_idx, 1); |
|---|
| 437 | + coeff[2] = get_iir_band_coeff(component, iir_idx, band_idx, 2); |
|---|
| 438 | + coeff[3] = get_iir_band_coeff(component, iir_idx, band_idx, 3); |
|---|
| 439 | + coeff[4] = get_iir_band_coeff(component, iir_idx, band_idx, 4); |
|---|
| 440 | + |
|---|
| 441 | + memcpy(ucontrol->value.bytes.data, &coeff[0], params->max); |
|---|
| 442 | + |
|---|
| 443 | + return 0; |
|---|
| 444 | +} |
|---|
| 445 | + |
|---|
| 446 | +static void set_iir_band_coeff(struct snd_soc_component *component, |
|---|
| 447 | + int iir_idx, int band_idx, |
|---|
| 448 | + uint32_t value) |
|---|
| 449 | +{ |
|---|
| 450 | + snd_soc_component_write(component, |
|---|
| 451 | + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx), |
|---|
| 452 | + (value & 0xFF)); |
|---|
| 453 | + |
|---|
| 454 | + snd_soc_component_write(component, |
|---|
| 455 | + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx), |
|---|
| 456 | + (value >> 8) & 0xFF); |
|---|
| 457 | + |
|---|
| 458 | + snd_soc_component_write(component, |
|---|
| 459 | + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx), |
|---|
| 460 | + (value >> 16) & 0xFF); |
|---|
| 461 | + |
|---|
| 462 | + /* Mask top 2 bits, 7-8 are reserved */ |
|---|
| 463 | + snd_soc_component_write(component, |
|---|
| 464 | + (LPASS_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx), |
|---|
| 465 | + (value >> 24) & 0x3F); |
|---|
| 466 | +} |
|---|
| 467 | + |
|---|
| 468 | +static int msm8x16_wcd_put_iir_band_audio_mixer( |
|---|
| 469 | + struct snd_kcontrol *kcontrol, |
|---|
| 470 | + struct snd_ctl_elem_value *ucontrol) |
|---|
| 471 | +{ |
|---|
| 472 | + struct snd_soc_component *component = |
|---|
| 473 | + snd_soc_kcontrol_component(kcontrol); |
|---|
| 474 | + struct wcd_iir_filter_ctl *ctl = |
|---|
| 475 | + (struct wcd_iir_filter_ctl *)kcontrol->private_value; |
|---|
| 476 | + struct soc_bytes_ext *params = &ctl->bytes_ext; |
|---|
| 477 | + int iir_idx = ctl->iir_idx; |
|---|
| 478 | + int band_idx = ctl->band_idx; |
|---|
| 479 | + u32 coeff[BAND_MAX]; |
|---|
| 480 | + |
|---|
| 481 | + memcpy(&coeff[0], ucontrol->value.bytes.data, params->max); |
|---|
| 482 | + |
|---|
| 483 | + /* Mask top bit it is reserved */ |
|---|
| 484 | + /* Updates addr automatically for each B2 write */ |
|---|
| 485 | + snd_soc_component_write(component, |
|---|
| 486 | + (LPASS_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx), |
|---|
| 487 | + (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F); |
|---|
| 488 | + |
|---|
| 489 | + set_iir_band_coeff(component, iir_idx, band_idx, coeff[0]); |
|---|
| 490 | + set_iir_band_coeff(component, iir_idx, band_idx, coeff[1]); |
|---|
| 491 | + set_iir_band_coeff(component, iir_idx, band_idx, coeff[2]); |
|---|
| 492 | + set_iir_band_coeff(component, iir_idx, band_idx, coeff[3]); |
|---|
| 493 | + set_iir_band_coeff(component, iir_idx, band_idx, coeff[4]); |
|---|
| 494 | + |
|---|
| 495 | + return 0; |
|---|
| 496 | +} |
|---|
| 497 | + |
|---|
| 498 | +static int wcd_iir_filter_info(struct snd_kcontrol *kcontrol, |
|---|
| 499 | + struct snd_ctl_elem_info *ucontrol) |
|---|
| 500 | +{ |
|---|
| 501 | + struct wcd_iir_filter_ctl *ctl = |
|---|
| 502 | + (struct wcd_iir_filter_ctl *)kcontrol->private_value; |
|---|
| 503 | + struct soc_bytes_ext *params = &ctl->bytes_ext; |
|---|
| 504 | + |
|---|
| 505 | + ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES; |
|---|
| 506 | + ucontrol->count = params->max; |
|---|
| 507 | + |
|---|
| 508 | + return 0; |
|---|
| 509 | +} |
|---|
| 510 | + |
|---|
| 320 | 511 | static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = { |
|---|
| 321 | 512 | SOC_SINGLE_S8_TLV("RX1 Digital Volume", LPASS_CDC_RX1_VOL_CTL_B2_CTL, |
|---|
| 322 | | - -128, 127, digital_gain), |
|---|
| 513 | + -84, 40, digital_gain), |
|---|
| 323 | 514 | SOC_SINGLE_S8_TLV("RX2 Digital Volume", LPASS_CDC_RX2_VOL_CTL_B2_CTL, |
|---|
| 324 | | - -128, 127, digital_gain), |
|---|
| 515 | + -84, 40, digital_gain), |
|---|
| 325 | 516 | SOC_SINGLE_S8_TLV("RX3 Digital Volume", LPASS_CDC_RX3_VOL_CTL_B2_CTL, |
|---|
| 326 | | - -128, 127, digital_gain), |
|---|
| 517 | + -84, 40, digital_gain), |
|---|
| 327 | 518 | SOC_SINGLE_S8_TLV("TX1 Digital Volume", LPASS_CDC_TX1_VOL_CTL_GAIN, |
|---|
| 328 | | - -128, 127, digital_gain), |
|---|
| 519 | + -84, 40, digital_gain), |
|---|
| 329 | 520 | SOC_SINGLE_S8_TLV("TX2 Digital Volume", LPASS_CDC_TX2_VOL_CTL_GAIN, |
|---|
| 330 | | - -128, 127, digital_gain), |
|---|
| 521 | + -84, 40, digital_gain), |
|---|
| 331 | 522 | SOC_ENUM("TX1 HPF Cutoff", tx1_hpf_cutoff_enum), |
|---|
| 332 | 523 | SOC_ENUM("TX2 HPF Cutoff", tx2_hpf_cutoff_enum), |
|---|
| 333 | 524 | SOC_SINGLE("TX1 HPF Switch", LPASS_CDC_TX1_MUX_CTL, 3, 1, 0), |
|---|
| .. | .. |
|---|
| 341 | 532 | SOC_SINGLE("RX1 Mute Switch", LPASS_CDC_RX1_B6_CTL, 0, 1, 0), |
|---|
| 342 | 533 | SOC_SINGLE("RX2 Mute Switch", LPASS_CDC_RX2_B6_CTL, 0, 1, 0), |
|---|
| 343 | 534 | SOC_SINGLE("RX3 Mute Switch", LPASS_CDC_RX3_B6_CTL, 0, 1, 0), |
|---|
| 535 | + |
|---|
| 536 | + SOC_SINGLE("IIR1 Band1 Switch", LPASS_CDC_IIR1_CTL, 0, 1, 0), |
|---|
| 537 | + SOC_SINGLE("IIR1 Band2 Switch", LPASS_CDC_IIR1_CTL, 1, 1, 0), |
|---|
| 538 | + SOC_SINGLE("IIR1 Band3 Switch", LPASS_CDC_IIR1_CTL, 2, 1, 0), |
|---|
| 539 | + SOC_SINGLE("IIR1 Band4 Switch", LPASS_CDC_IIR1_CTL, 3, 1, 0), |
|---|
| 540 | + SOC_SINGLE("IIR1 Band5 Switch", LPASS_CDC_IIR1_CTL, 4, 1, 0), |
|---|
| 541 | + SOC_SINGLE("IIR2 Band1 Switch", LPASS_CDC_IIR2_CTL, 0, 1, 0), |
|---|
| 542 | + SOC_SINGLE("IIR2 Band2 Switch", LPASS_CDC_IIR2_CTL, 1, 1, 0), |
|---|
| 543 | + SOC_SINGLE("IIR2 Band3 Switch", LPASS_CDC_IIR2_CTL, 2, 1, 0), |
|---|
| 544 | + SOC_SINGLE("IIR2 Band4 Switch", LPASS_CDC_IIR2_CTL, 3, 1, 0), |
|---|
| 545 | + SOC_SINGLE("IIR2 Band5 Switch", LPASS_CDC_IIR2_CTL, 4, 1, 0), |
|---|
| 546 | + WCD_IIR_FILTER_CTL("IIR1 Band1", IIR1, BAND1), |
|---|
| 547 | + WCD_IIR_FILTER_CTL("IIR1 Band2", IIR1, BAND2), |
|---|
| 548 | + WCD_IIR_FILTER_CTL("IIR1 Band3", IIR1, BAND3), |
|---|
| 549 | + WCD_IIR_FILTER_CTL("IIR1 Band4", IIR1, BAND4), |
|---|
| 550 | + WCD_IIR_FILTER_CTL("IIR1 Band5", IIR1, BAND5), |
|---|
| 551 | + WCD_IIR_FILTER_CTL("IIR2 Band1", IIR2, BAND1), |
|---|
| 552 | + WCD_IIR_FILTER_CTL("IIR2 Band2", IIR2, BAND2), |
|---|
| 553 | + WCD_IIR_FILTER_CTL("IIR2 Band3", IIR2, BAND3), |
|---|
| 554 | + WCD_IIR_FILTER_CTL("IIR2 Band4", IIR2, BAND4), |
|---|
| 555 | + WCD_IIR_FILTER_CTL("IIR2 Band5", IIR2, BAND5), |
|---|
| 556 | + SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", LPASS_CDC_IIR1_GAIN_B1_CTL, |
|---|
| 557 | + -84, 40, digital_gain), |
|---|
| 558 | + SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", LPASS_CDC_IIR1_GAIN_B2_CTL, |
|---|
| 559 | + -84, 40, digital_gain), |
|---|
| 560 | + SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", LPASS_CDC_IIR1_GAIN_B3_CTL, |
|---|
| 561 | + -84, 40, digital_gain), |
|---|
| 562 | + SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", LPASS_CDC_IIR1_GAIN_B4_CTL, |
|---|
| 563 | + -84, 40, digital_gain), |
|---|
| 564 | + SOC_SINGLE_S8_TLV("IIR2 INP1 Volume", LPASS_CDC_IIR2_GAIN_B1_CTL, |
|---|
| 565 | + -84, 40, digital_gain), |
|---|
| 566 | + SOC_SINGLE_S8_TLV("IIR2 INP2 Volume", LPASS_CDC_IIR2_GAIN_B2_CTL, |
|---|
| 567 | + -84, 40, digital_gain), |
|---|
| 568 | + SOC_SINGLE_S8_TLV("IIR2 INP3 Volume", LPASS_CDC_IIR2_GAIN_B3_CTL, |
|---|
| 569 | + -84, 40, digital_gain), |
|---|
| 570 | + SOC_SINGLE_S8_TLV("IIR2 INP4 Volume", LPASS_CDC_IIR2_GAIN_B4_CTL, |
|---|
| 571 | + -84, 40, digital_gain), |
|---|
| 572 | + |
|---|
| 344 | 573 | }; |
|---|
| 345 | 574 | |
|---|
| 346 | 575 | static int msm8916_wcd_digital_enable_interpolator( |
|---|
| .. | .. |
|---|
| 355 | 584 | /* apply the digital gain after the interpolator is enabled */ |
|---|
| 356 | 585 | usleep_range(10000, 10100); |
|---|
| 357 | 586 | snd_soc_component_write(component, rx_gain_reg[w->shift], |
|---|
| 358 | | - snd_soc_component_read32(component, rx_gain_reg[w->shift])); |
|---|
| 587 | + snd_soc_component_read(component, rx_gain_reg[w->shift])); |
|---|
| 359 | 588 | break; |
|---|
| 360 | 589 | case SND_SOC_DAPM_POST_PMD: |
|---|
| 361 | 590 | snd_soc_component_update_bits(component, LPASS_CDC_CLK_RX_RESET_CTL, |
|---|
| .. | .. |
|---|
| 386 | 615 | snd_soc_component_update_bits(component, tx_vol_ctl_reg, |
|---|
| 387 | 616 | TX_VOL_CTL_CFG_MUTE_EN_MASK, |
|---|
| 388 | 617 | TX_VOL_CTL_CFG_MUTE_EN_ENABLE); |
|---|
| 389 | | - dec_hpf_cut_of_freq = snd_soc_component_read32(component, tx_mux_ctl_reg) & |
|---|
| 618 | + dec_hpf_cut_of_freq = snd_soc_component_read(component, tx_mux_ctl_reg) & |
|---|
| 390 | 619 | TX_MUX_CTL_CUT_OFF_FREQ_MASK; |
|---|
| 391 | 620 | dec_hpf_cut_of_freq >>= TX_MUX_CTL_CUT_OFF_FREQ_SHIFT; |
|---|
| 392 | 621 | if (dec_hpf_cut_of_freq != TX_MUX_CTL_CF_NEG_3DB_150HZ) { |
|---|
| .. | .. |
|---|
| 403 | 632 | TX_MUX_CTL_HPF_BP_SEL_NO_BYPASS); |
|---|
| 404 | 633 | /* apply the digital gain after the decimator is enabled */ |
|---|
| 405 | 634 | snd_soc_component_write(component, tx_gain_reg[w->shift], |
|---|
| 406 | | - snd_soc_component_read32(component, tx_gain_reg[w->shift])); |
|---|
| 635 | + snd_soc_component_read(component, tx_gain_reg[w->shift])); |
|---|
| 407 | 636 | snd_soc_component_update_bits(component, tx_vol_ctl_reg, |
|---|
| 408 | 637 | TX_VOL_CTL_CFG_MUTE_EN_MASK, 0); |
|---|
| 409 | 638 | break; |
|---|
| .. | .. |
|---|
| 473 | 702 | return 0; |
|---|
| 474 | 703 | } |
|---|
| 475 | 704 | |
|---|
| 705 | +static const char * const iir_inp1_text[] = { |
|---|
| 706 | + "ZERO", "DEC1", "DEC2", "RX1", "RX2", "RX3" |
|---|
| 707 | +}; |
|---|
| 708 | + |
|---|
| 709 | +static const struct soc_enum iir1_inp1_mux_enum = |
|---|
| 710 | + SOC_ENUM_SINGLE(LPASS_CDC_CONN_EQ1_B1_CTL, |
|---|
| 711 | + 0, 6, iir_inp1_text); |
|---|
| 712 | + |
|---|
| 713 | +static const struct soc_enum iir2_inp1_mux_enum = |
|---|
| 714 | + SOC_ENUM_SINGLE(LPASS_CDC_CONN_EQ2_B1_CTL, |
|---|
| 715 | + 0, 6, iir_inp1_text); |
|---|
| 716 | + |
|---|
| 717 | +static const struct snd_kcontrol_new iir1_inp1_mux = |
|---|
| 718 | + SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum); |
|---|
| 719 | + |
|---|
| 720 | +static const struct snd_kcontrol_new iir2_inp1_mux = |
|---|
| 721 | + SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum); |
|---|
| 722 | + |
|---|
| 476 | 723 | static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = { |
|---|
| 477 | 724 | /*RX stuff */ |
|---|
| 478 | 725 | SND_SOC_DAPM_AIF_IN("I2S RX1", NULL, 0, SND_SOC_NOPM, 0, 0), |
|---|
| .. | .. |
|---|
| 517 | 764 | &rx3_mix1_inp2_mux), |
|---|
| 518 | 765 | SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0, |
|---|
| 519 | 766 | &rx3_mix1_inp3_mux), |
|---|
| 767 | + SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0, |
|---|
| 768 | + &rx1_mix2_inp1_mux), |
|---|
| 769 | + SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0, |
|---|
| 770 | + &rx2_mix2_inp1_mux), |
|---|
| 520 | 771 | |
|---|
| 521 | 772 | SND_SOC_DAPM_MUX("CIC1 MUX", SND_SOC_NOPM, 0, 0, &cic1_mux), |
|---|
| 522 | 773 | SND_SOC_DAPM_MUX("CIC2 MUX", SND_SOC_NOPM, 0, 0, &cic2_mux), |
|---|
| .. | .. |
|---|
| 558 | 809 | NULL, 0), |
|---|
| 559 | 810 | SND_SOC_DAPM_MIC("Digital Mic1", NULL), |
|---|
| 560 | 811 | SND_SOC_DAPM_MIC("Digital Mic2", NULL), |
|---|
| 812 | + |
|---|
| 813 | + /* Sidetone */ |
|---|
| 814 | + SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux), |
|---|
| 815 | + SND_SOC_DAPM_PGA_E("IIR1", LPASS_CDC_CLK_SD_CTL, 0, 0, NULL, 0, |
|---|
| 816 | + msm8x16_wcd_codec_set_iir_gain, SND_SOC_DAPM_POST_PMU), |
|---|
| 817 | + |
|---|
| 818 | + SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux), |
|---|
| 819 | + SND_SOC_DAPM_PGA_E("IIR2", LPASS_CDC_CLK_SD_CTL, 1, 0, NULL, 0, |
|---|
| 820 | + msm8x16_wcd_codec_set_iir_gain, SND_SOC_DAPM_POST_PMU), |
|---|
| 561 | 821 | |
|---|
| 562 | 822 | }; |
|---|
| 563 | 823 | |
|---|
| .. | .. |
|---|
| 733 | 993 | {"RX1 MIX1 INP1", "RX1", "I2S RX1"}, |
|---|
| 734 | 994 | {"RX1 MIX1 INP1", "RX2", "I2S RX2"}, |
|---|
| 735 | 995 | {"RX1 MIX1 INP1", "RX3", "I2S RX3"}, |
|---|
| 996 | + {"RX1 MIX1 INP1", "IIR1", "IIR1"}, |
|---|
| 997 | + {"RX1 MIX1 INP1", "IIR2", "IIR2"}, |
|---|
| 736 | 998 | |
|---|
| 737 | 999 | {"RX1 MIX1 INP2", "RX1", "I2S RX1"}, |
|---|
| 738 | 1000 | {"RX1 MIX1 INP2", "RX2", "I2S RX2"}, |
|---|
| 739 | 1001 | {"RX1 MIX1 INP2", "RX3", "I2S RX3"}, |
|---|
| 1002 | + {"RX1 MIX1 INP2", "IIR1", "IIR1"}, |
|---|
| 1003 | + {"RX1 MIX1 INP2", "IIR2", "IIR2"}, |
|---|
| 740 | 1004 | |
|---|
| 741 | 1005 | {"RX1 MIX1 INP3", "RX1", "I2S RX1"}, |
|---|
| 742 | 1006 | {"RX1 MIX1 INP3", "RX2", "I2S RX2"}, |
|---|
| .. | .. |
|---|
| 753 | 1017 | {"RX2 MIX1 INP1", "RX1", "I2S RX1"}, |
|---|
| 754 | 1018 | {"RX2 MIX1 INP1", "RX2", "I2S RX2"}, |
|---|
| 755 | 1019 | {"RX2 MIX1 INP1", "RX3", "I2S RX3"}, |
|---|
| 1020 | + {"RX2 MIX1 INP1", "IIR1", "IIR1"}, |
|---|
| 1021 | + {"RX2 MIX1 INP1", "IIR2", "IIR2"}, |
|---|
| 756 | 1022 | |
|---|
| 757 | 1023 | {"RX2 MIX1 INP2", "RX1", "I2S RX1"}, |
|---|
| 758 | 1024 | {"RX2 MIX1 INP2", "RX2", "I2S RX2"}, |
|---|
| 759 | 1025 | {"RX2 MIX1 INP2", "RX3", "I2S RX3"}, |
|---|
| 1026 | + {"RX2 MIX1 INP1", "IIR1", "IIR1"}, |
|---|
| 1027 | + {"RX2 MIX1 INP1", "IIR2", "IIR2"}, |
|---|
| 760 | 1028 | |
|---|
| 761 | 1029 | {"RX2 MIX1 INP3", "RX1", "I2S RX1"}, |
|---|
| 762 | 1030 | {"RX2 MIX1 INP3", "RX2", "I2S RX2"}, |
|---|
| .. | .. |
|---|
| 773 | 1041 | {"RX3 MIX1 INP1", "RX1", "I2S RX1"}, |
|---|
| 774 | 1042 | {"RX3 MIX1 INP1", "RX2", "I2S RX2"}, |
|---|
| 775 | 1043 | {"RX3 MIX1 INP1", "RX3", "I2S RX3"}, |
|---|
| 1044 | + {"RX3 MIX1 INP1", "IIR1", "IIR1"}, |
|---|
| 1045 | + {"RX3 MIX1 INP1", "IIR2", "IIR2"}, |
|---|
| 776 | 1046 | |
|---|
| 777 | 1047 | {"RX3 MIX1 INP2", "RX1", "I2S RX1"}, |
|---|
| 778 | 1048 | {"RX3 MIX1 INP2", "RX2", "I2S RX2"}, |
|---|
| 779 | 1049 | {"RX3 MIX1 INP2", "RX3", "I2S RX3"}, |
|---|
| 1050 | + {"RX3 MIX1 INP2", "IIR1", "IIR1"}, |
|---|
| 1051 | + {"RX3 MIX1 INP2", "IIR2", "IIR2"}, |
|---|
| 1052 | + |
|---|
| 1053 | + {"RX1 MIX2 INP1", "IIR1", "IIR1"}, |
|---|
| 1054 | + {"RX2 MIX2 INP1", "IIR1", "IIR1"}, |
|---|
| 1055 | + {"RX1 MIX2 INP1", "IIR2", "IIR2"}, |
|---|
| 1056 | + {"RX2 MIX2 INP1", "IIR2", "IIR2"}, |
|---|
| 1057 | + |
|---|
| 1058 | + {"IIR1", NULL, "IIR1 INP1 MUX"}, |
|---|
| 1059 | + {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"}, |
|---|
| 1060 | + {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"}, |
|---|
| 1061 | + |
|---|
| 1062 | + {"IIR2", NULL, "IIR2 INP1 MUX"}, |
|---|
| 1063 | + {"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"}, |
|---|
| 1064 | + {"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"}, |
|---|
| 780 | 1065 | |
|---|
| 781 | 1066 | {"RX3 MIX1 INP3", "RX1", "I2S RX1"}, |
|---|
| 782 | 1067 | {"RX3 MIX1 INP3", "RX2", "I2S RX2"}, |
|---|
| .. | .. |
|---|
| 886 | 1171 | struct msm8916_wcd_digital_priv *priv; |
|---|
| 887 | 1172 | struct device *dev = &pdev->dev; |
|---|
| 888 | 1173 | void __iomem *base; |
|---|
| 889 | | - struct resource *mem_res; |
|---|
| 890 | 1174 | struct regmap *digital_map; |
|---|
| 891 | 1175 | int ret; |
|---|
| 892 | 1176 | |
|---|
| .. | .. |
|---|
| 894 | 1178 | if (!priv) |
|---|
| 895 | 1179 | return -ENOMEM; |
|---|
| 896 | 1180 | |
|---|
| 897 | | - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 898 | | - base = devm_ioremap_resource(&pdev->dev, mem_res); |
|---|
| 1181 | + base = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 899 | 1182 | if (IS_ERR(base)) |
|---|
| 900 | 1183 | return PTR_ERR(base); |
|---|
| 901 | 1184 | |
|---|
| .. | .. |
|---|
| 918 | 1201 | ret = clk_prepare_enable(priv->mclk); |
|---|
| 919 | 1202 | if (ret < 0) { |
|---|
| 920 | 1203 | dev_err(dev, "failed to enable mclk %d\n", ret); |
|---|
| 921 | | - return ret; |
|---|
| 1204 | + goto err_clk; |
|---|
| 922 | 1205 | } |
|---|
| 923 | 1206 | |
|---|
| 924 | 1207 | dev_set_drvdata(dev, priv); |
|---|
| 925 | 1208 | |
|---|
| 926 | | - return devm_snd_soc_register_component(dev, &msm8916_wcd_digital, |
|---|
| 1209 | + ret = devm_snd_soc_register_component(dev, &msm8916_wcd_digital, |
|---|
| 927 | 1210 | msm8916_wcd_digital_dai, |
|---|
| 928 | 1211 | ARRAY_SIZE(msm8916_wcd_digital_dai)); |
|---|
| 1212 | + if (ret) |
|---|
| 1213 | + goto err_mclk; |
|---|
| 1214 | + |
|---|
| 1215 | + return 0; |
|---|
| 1216 | + |
|---|
| 1217 | +err_mclk: |
|---|
| 1218 | + clk_disable_unprepare(priv->mclk); |
|---|
| 1219 | +err_clk: |
|---|
| 1220 | + clk_disable_unprepare(priv->ahbclk); |
|---|
| 1221 | + return ret; |
|---|
| 929 | 1222 | } |
|---|
| 930 | 1223 | |
|---|
| 931 | 1224 | static int msm8916_wcd_digital_remove(struct platform_device *pdev) |
|---|