Browse Source

Merge "asoc: codecs: update IIR cofficient values before IIR band enable"

Linux Build Service Account 7 years ago
parent
commit
43667ec287
1 changed files with 50 additions and 37 deletions
  1. 50 37
      asoc/codecs/wcd934x/wcd934x.c

+ 50 - 37
asoc/codecs/wcd934x/wcd934x.c

@@ -127,6 +127,7 @@ static const struct snd_kcontrol_new name##_mux = \
 #define WCD934X_STRING_LEN 100
 
 #define WCD934X_CDC_SIDETONE_IIR_COEFF_MAX 5
+#define WCD934X_CDC_REPEAT_WRITES_MAX 16
 #define WCD934X_DIG_CORE_REG_MIN  WCD934X_CDC_ANC0_CLK_RESET_CTL
 #define WCD934X_DIG_CORE_REG_MAX  0xFFF
 
@@ -628,8 +629,8 @@ struct tavil_priv {
 	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];
+	u8 sidetone_coeff_array[IIR_MAX][BAND_MAX]
+		[WCD934X_CDC_SIDETONE_IIR_COEFF_MAX * 4];
 
 	struct spi_device *spi;
 	struct platform_device *pdev_child_devices
@@ -5323,6 +5324,36 @@ static int tavil_codec_reset_hph_registers(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static void tavil_restore_iir_coeff(struct tavil_priv *tavil, int iir_idx,
+				int band_idx)
+{
+	u16 reg_add;
+	int no_of_reg = 0;
+
+	regmap_write(tavil->wcd9xxx->regmap,
+		(WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx),
+		(band_idx * BAND_MAX * sizeof(uint32_t)) & 0x7F);
+
+	reg_add = WCD934X_CDC_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx;
+
+	if (tavil->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+		return;
+	/*
+	 * Since wcd9xxx_slim_write_repeat() supports only maximum of 16
+	 * registers at a time, split total 20 writes(5 coefficients per
+	 * band and 4 writes per coefficient) into 16 and 4.
+	 */
+	no_of_reg = WCD934X_CDC_REPEAT_WRITES_MAX;
+	wcd9xxx_slim_write_repeat(tavil->wcd9xxx, reg_add, no_of_reg,
+			&tavil->sidetone_coeff_array[iir_idx][band_idx][0]);
+
+	no_of_reg = (WCD934X_CDC_SIDETONE_IIR_COEFF_MAX * 4) -
+						WCD934X_CDC_REPEAT_WRITES_MAX;
+	wcd9xxx_slim_write_repeat(tavil->wcd9xxx, reg_add, no_of_reg,
+			&tavil->sidetone_coeff_array[iir_idx][band_idx]
+					  [WCD934X_CDC_REPEAT_WRITES_MAX]);
+}
+
 static int tavil_iir_enable_audio_mixer_get(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
@@ -5347,6 +5378,7 @@ static int tavil_iir_enable_audio_mixer_put(struct snd_kcontrol *kcontrol,
 					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 *)
@@ -5355,6 +5387,8 @@ static int tavil_iir_enable_audio_mixer_put(struct snd_kcontrol *kcontrol,
 	int value = ucontrol->value.integer.value[0];
 	u16 iir_reg = WCD934X_CDC_SIDETONE_IIR0_IIR_CTL + 16 * iir_idx;
 
+	tavil_restore_iir_coeff(tavil, iir_idx, band_idx);
+
 	/* Mask first 5 bits, 6-8 are reserved */
 	snd_soc_update_bits(codec, iir_reg, (1 << band_idx),
 			    (value << band_idx));
@@ -5481,7 +5515,7 @@ static int tavil_iir_band_audio_mixer_put(struct snd_kcontrol *kcontrol,
 					kcontrol->private_value)->reg;
 	int band_idx = ((struct soc_multi_mixer_control *)
 					kcontrol->private_value)->shift;
-	int coeff_idx;
+	int coeff_idx, idx = 0;
 
 	/*
 	 * Mask top bit it is reserved
@@ -5494,11 +5528,19 @@ static int tavil_iir_band_audio_mixer_put(struct snd_kcontrol *kcontrol,
 	/* 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]);
+		uint32_t value = ucontrol->value.integer.value[coeff_idx];
+
+		set_iir_band_coeff(codec, iir_idx, band_idx, value);
+
+		/* Four 8 bit values(one 32 bit) per coefficient */
+		tavil->sidetone_coeff_array[iir_idx][band_idx][idx++] =
+								(value & 0xFF);
+		tavil->sidetone_coeff_array[iir_idx][band_idx][idx++] =
+							 (value >> 8) & 0xFF;
+		tavil->sidetone_coeff_array[iir_idx][band_idx][idx++] =
+							 (value >> 16) & 0xFF;
+		tavil->sidetone_coeff_array[iir_idx][band_idx][idx++] =
+							 (value >> 24) & 0xFF;
 	}
 
 	pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
@@ -5519,33 +5561,6 @@ static int tavil_iir_band_audio_mixer_put(struct snd_kcontrol *kcontrol,
 	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;
-
-	/*
-	 * snd_soc_write call crashes at rmmod if there is no machine
-	 * driver and hence no codec pointer available
-	 */
-	if (!codec)
-		return;
-
-	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)
 {
@@ -8933,8 +8948,6 @@ static int tavil_dig_core_remove_power_collapse(struct tavil_priv *tavil)
 			     WCD934X_DIG_CORE_REG_MIN,
 			     WCD934X_DIG_CORE_REG_MAX);
 
-	tavil_restore_iir_coeff(tavil, IIR0);
-	tavil_restore_iir_coeff(tavil, IIR1);
 	return 0;
 }