ASoC: wcd9310: Update the sequence to apply the digital gain
The digital gain implementation requires that the specific decimator or
interpolation path be enabled for the digital gain to be physically
applied in the signal path. If the gain is set prior to enabling
the decimator/interpolator path, the register will show the programmed
gain value correctly, but it will not be applied in the signal
chain. Setting a digital gain value and then enabling the
decimator/interpolator path will not cause the gain to be applied.
The only way for the programmed gain value to be implemented
correctly is to first enable the decimator/interpolator path and then
set the digital gain of the path.
Change the codec driver to apply the digital gain again for a given
digital RX or TX path right after digital path is turned on.
CRS-fixed: 340236
Change-Id: Ie737a3875ad3a4e55a76ea17f155d02f6be4a85e
Signed-off-by: Kuirong Wang <kuirongw@codeaurora.org>
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 6788322..830b98f 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -354,6 +354,30 @@
},
};
+static unsigned short rx_digital_gain_reg[] = {
+ TABLA_A_CDC_RX1_VOL_CTL_B2_CTL,
+ TABLA_A_CDC_RX2_VOL_CTL_B2_CTL,
+ TABLA_A_CDC_RX3_VOL_CTL_B2_CTL,
+ TABLA_A_CDC_RX4_VOL_CTL_B2_CTL,
+ TABLA_A_CDC_RX5_VOL_CTL_B2_CTL,
+ TABLA_A_CDC_RX6_VOL_CTL_B2_CTL,
+ TABLA_A_CDC_RX7_VOL_CTL_B2_CTL,
+};
+
+
+static unsigned short tx_digital_gain_reg[] = {
+ TABLA_A_CDC_TX1_VOL_CTL_GAIN,
+ TABLA_A_CDC_TX2_VOL_CTL_GAIN,
+ TABLA_A_CDC_TX3_VOL_CTL_GAIN,
+ TABLA_A_CDC_TX4_VOL_CTL_GAIN,
+ TABLA_A_CDC_TX5_VOL_CTL_GAIN,
+ TABLA_A_CDC_TX6_VOL_CTL_GAIN,
+ TABLA_A_CDC_TX7_VOL_CTL_GAIN,
+ TABLA_A_CDC_TX8_VOL_CTL_GAIN,
+ TABLA_A_CDC_TX9_VOL_CTL_GAIN,
+ TABLA_A_CDC_TX10_VOL_CTL_GAIN,
+};
+
static int tabla_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -2432,6 +2456,8 @@
int ret = 0;
u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
u8 dec_hpf_cut_of_freq;
+ int offset;
+
pr_debug("%s %d\n", __func__, event);
@@ -2458,11 +2484,13 @@
pr_debug("%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
w->name, dec_name, decimator);
- if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL)
+ if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL) {
dec_reset_reg = TABLA_A_CDC_CLK_TX_RESET_B1_CTL;
- else if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL)
+ offset = 0;
+ } else if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL) {
dec_reset_reg = TABLA_A_CDC_CLK_TX_RESET_B2_CTL;
- else {
+ offset = 8;
+ } else {
pr_err("%s: Error, incorrect dec\n", __func__);
return -EINVAL;
}
@@ -2510,6 +2538,14 @@
schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
msecs_to_jiffies(300));
}
+ /* apply the digital gain after the decimator is enabled*/
+ if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
+ snd_soc_write(codec,
+ tx_digital_gain_reg[w->shift + offset],
+ snd_soc_read(codec,
+ tx_digital_gain_reg[w->shift + offset])
+ );
+
break;
case SND_SOC_DAPM_PRE_PMD:
@@ -2545,6 +2581,15 @@
snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL,
1 << w->shift, 0x0);
break;
+ case SND_SOC_DAPM_POST_PMU:
+ /* apply the digital gain after the interpolator is enabled*/
+ if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
+ snd_soc_write(codec,
+ rx_digital_gain_reg[w->shift],
+ snd_soc_read(codec,
+ rx_digital_gain_reg[w->shift])
+ );
+ break;
}
return 0;
}
@@ -3213,7 +3258,34 @@
return tabla_reg_readable[reg];
}
-
+static bool tabla_is_digital_gain_register(unsigned int reg)
+{
+ bool rtn = false;
+ switch (reg) {
+ case TABLA_A_CDC_RX1_VOL_CTL_B2_CTL:
+ case TABLA_A_CDC_RX2_VOL_CTL_B2_CTL:
+ case TABLA_A_CDC_RX3_VOL_CTL_B2_CTL:
+ case TABLA_A_CDC_RX4_VOL_CTL_B2_CTL:
+ case TABLA_A_CDC_RX5_VOL_CTL_B2_CTL:
+ case TABLA_A_CDC_RX6_VOL_CTL_B2_CTL:
+ case TABLA_A_CDC_RX7_VOL_CTL_B2_CTL:
+ case TABLA_A_CDC_TX1_VOL_CTL_GAIN:
+ case TABLA_A_CDC_TX2_VOL_CTL_GAIN:
+ case TABLA_A_CDC_TX3_VOL_CTL_GAIN:
+ case TABLA_A_CDC_TX4_VOL_CTL_GAIN:
+ case TABLA_A_CDC_TX5_VOL_CTL_GAIN:
+ case TABLA_A_CDC_TX6_VOL_CTL_GAIN:
+ case TABLA_A_CDC_TX7_VOL_CTL_GAIN:
+ case TABLA_A_CDC_TX8_VOL_CTL_GAIN:
+ case TABLA_A_CDC_TX9_VOL_CTL_GAIN:
+ case TABLA_A_CDC_TX10_VOL_CTL_GAIN:
+ rtn = true;
+ break;
+ default:
+ break;
+ }
+ return rtn;
+}
static int tabla_volatile(struct snd_soc_codec *ssc, unsigned int reg)
{
/* Registers lower than 0x100 are top level registers which can be
@@ -3228,6 +3300,12 @@
(reg <= TABLA_A_CDC_IIR2_COEF_B5_CTL))
return 1;
+ /* Digital gain register is not cacheable so we have to write
+ * the setting even it is the same
+ */
+ if (tabla_is_digital_gain_register(reg))
+ return 1;
+
return 0;
}
@@ -3971,19 +4049,26 @@
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MIXER_E("RX1 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MIXER_E("RX2 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MIXER_E("RX3 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MIXER_E("RX4 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MIXER_E("RX5 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MIXER_E("RX6 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MIXER_E("RX7 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0,
&rx4_dsm_mux, tabla_codec_reset_interpolator,