ASoC: wcd934x: Add support to restore IIR coefficients after power collapse
Reduce the latency of device switch during voice call by caching
IIR Band registers at bootup and restore them in
tavil_dig_core_remove_power_collapse instead of updating
through mixer controls from userspace.
Change-Id: I87b41801d5f174f5fb11917a359635e91c04d05d
Signed-off-by: Aditya Bavanari <abavanar@codeaurora.org>
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index 6df014f..ff08ccb 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -123,6 +123,7 @@
#define WCD934X_DEC_PWR_LVL_DF 0x00
#define WCD934X_STRING_LEN 100
+#define WCD934X_CDC_SIDETONE_IIR_COEFF_MAX 5
#define WCD934X_DIG_CORE_REG_MIN WCD934X_CDC_ANC0_CLK_RESET_CTL
#define WCD934X_DIG_CORE_REG_MAX 0xFFF
@@ -651,6 +652,8 @@
struct tavil_idle_detect_config idle_det_cfg;
int power_active_ref;
+ int sidetone_coeff_array[IIR_MAX][BAND_MAX]
+ [WCD934X_CDC_SIDETONE_IIR_COEFF_MAX];
};
static const struct tavil_reg_mask_val tavil_spkr_default[] = {
@@ -5159,10 +5162,12 @@
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
int iir_idx = ((struct soc_multi_mixer_control *)
kcontrol->private_value)->reg;
int band_idx = ((struct soc_multi_mixer_control *)
kcontrol->private_value)->shift;
+ int coeff_idx;
/*
* Mask top bit it is reserved
@@ -5172,16 +5177,15 @@
(WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
(band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
- set_iir_band_coeff(codec, iir_idx, band_idx,
- ucontrol->value.integer.value[0]);
- set_iir_band_coeff(codec, iir_idx, band_idx,
- ucontrol->value.integer.value[1]);
- set_iir_band_coeff(codec, iir_idx, band_idx,
- ucontrol->value.integer.value[2]);
- set_iir_band_coeff(codec, iir_idx, band_idx,
- ucontrol->value.integer.value[3]);
- set_iir_band_coeff(codec, iir_idx, band_idx,
- ucontrol->value.integer.value[4]);
+ /* Store the coefficients in sidetone coeff array */
+ for (coeff_idx = 0; coeff_idx < WCD934X_CDC_SIDETONE_IIR_COEFF_MAX;
+ coeff_idx++) {
+ tavil->sidetone_coeff_array[iir_idx][band_idx][coeff_idx] =
+ ucontrol->value.integer.value[coeff_idx];
+ set_iir_band_coeff(codec, iir_idx, band_idx,
+ tavil->sidetone_coeff_array[iir_idx][band_idx]
+ [coeff_idx]);
+ }
pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
"%s: IIR #%d band #%d b1 = 0x%x\n"
@@ -5201,6 +5205,26 @@
return 0;
}
+static void tavil_restore_iir_coeff(struct tavil_priv *tavil, int iir_idx)
+{
+ int band_idx = 0, coeff_idx = 0;
+ struct snd_soc_codec *codec = tavil->codec;
+
+ for (band_idx = 0; band_idx < BAND_MAX; band_idx++) {
+ snd_soc_write(codec,
+ (WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
+ (band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
+
+ for (coeff_idx = 0;
+ coeff_idx < WCD934X_CDC_SIDETONE_IIR_COEFF_MAX;
+ coeff_idx++) {
+ set_iir_band_coeff(codec, iir_idx, band_idx,
+ tavil->sidetone_coeff_array[iir_idx][band_idx]
+ [coeff_idx]);
+ }
+ }
+}
+
static int tavil_compander_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -8153,6 +8177,8 @@
WCD934X_DIG_CORE_REG_MIN,
WCD934X_DIG_CORE_REG_MAX);
+ tavil_restore_iir_coeff(tavil, IIR0);
+ tavil_restore_iir_coeff(tavil, IIR1);
return 0;
}