.. | .. |
---|
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) |
---|