Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 05f59b8b authored by Jay Wang's avatar Jay Wang
Browse files

ASoC: wcd9320: Add ANC loopback path and cache HPF bypass control



Add route to connect ANC FB tune signal back to decimator
DEC7 to DEC10. These paths are used to evalute the device acoustics
and provide a way to tune ANC algorithm. In addition, a logic is
implemented to cache the TX HPF bypass control to allow user
bypass the TX HPF during ANC tuning.

Change-Id: Id6b8a046480fcfb5a4d0fb1876f7c364796d4378
Signed-off-by: default avatarJay Wang <jaywang@codeaurora.org>
parent 9ff23399
Loading
Loading
Loading
Loading
+116 −25
Original line number Diff line number Diff line
@@ -342,6 +342,7 @@ struct hpf_work {
	struct taiko_priv *taiko;
	u32 decimator;
	u8 tx_hpf_cut_of_freq;
	bool tx_hpf_bypass;
	struct delayed_work dwork;
};

@@ -1267,6 +1268,52 @@ static int taiko_mad_input_put(struct snd_kcontrol *kcontrol,
	}
}

static int taiko_tx_hpf_bypass_get(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	u32	tx_index;

	tx_index = (u32)kcontrol->private_value;

	if (tx_index > NUM_DECIMATORS) {
		pr_err("%s: Invalid TX decimator %d\n", __func__,
			   tx_index);
		return -EINVAL;
	}

	ucontrol->value.integer.value[0] =
		tx_hpf_work[tx_index-1].tx_hpf_bypass;

	return 0;
}

static int taiko_tx_hpf_bypass_put(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	bool tx_hpf_bypass_cfg;
	u32	tx_index;

	tx_hpf_bypass_cfg = (bool)ucontrol->value.integer.value[0];

	pr_debug("%s: tx_hpf_bypass = %d\n", __func__,
			tx_hpf_bypass_cfg);

	tx_index = (u32)kcontrol->private_value;

	if (tx_index > NUM_DECIMATORS) {
		pr_err("%s: Invalid TX decimator %d\n", __func__,
			   tx_index);
		return -EINVAL;
	}
	if (tx_hpf_work[tx_index-1].tx_hpf_bypass != tx_hpf_bypass_cfg)
		tx_hpf_work[tx_index-1].tx_hpf_bypass = tx_hpf_bypass_cfg;

	pr_debug("%s: Set TX%d HPF bypass configuration %d",
			 __func__, tx_index,
			 tx_hpf_work[tx_index-1].tx_hpf_bypass);

	return 0;
}

static const struct snd_kcontrol_new taiko_snd_controls[] = {

@@ -1339,16 +1386,36 @@ static const struct snd_kcontrol_new taiko_snd_controls[] = {
	SOC_ENUM("TX9 HPF cut off", cf_dec9_enum),
	SOC_ENUM("TX10 HPF cut off", cf_dec10_enum),

	SOC_SINGLE("TX1 HPF Switch", TAIKO_A_CDC_TX1_MUX_CTL, 3, 1, 0),
	SOC_SINGLE("TX2 HPF Switch", TAIKO_A_CDC_TX2_MUX_CTL, 3, 1, 0),
	SOC_SINGLE("TX3 HPF Switch", TAIKO_A_CDC_TX3_MUX_CTL, 3, 1, 0),
	SOC_SINGLE("TX4 HPF Switch", TAIKO_A_CDC_TX4_MUX_CTL, 3, 1, 0),
	SOC_SINGLE("TX5 HPF Switch", TAIKO_A_CDC_TX5_MUX_CTL, 3, 1, 0),
	SOC_SINGLE("TX6 HPF Switch", TAIKO_A_CDC_TX6_MUX_CTL, 3, 1, 0),
	SOC_SINGLE("TX7 HPF Switch", TAIKO_A_CDC_TX7_MUX_CTL, 3, 1, 0),
	SOC_SINGLE("TX8 HPF Switch", TAIKO_A_CDC_TX8_MUX_CTL, 3, 1, 0),
	SOC_SINGLE("TX9 HPF Switch", TAIKO_A_CDC_TX9_MUX_CTL, 3, 1, 0),
	SOC_SINGLE("TX10 HPF Switch", TAIKO_A_CDC_TX10_MUX_CTL, 3, 1, 0),
	SOC_SINGLE_BOOL_EXT("TX1 HPF Switch", 1,
				taiko_tx_hpf_bypass_get,
				taiko_tx_hpf_bypass_put),
	SOC_SINGLE_BOOL_EXT("TX2 HPF Switch", 2,
				taiko_tx_hpf_bypass_get,
				taiko_tx_hpf_bypass_put),
	SOC_SINGLE_BOOL_EXT("TX3 HPF Switch", 3,
				taiko_tx_hpf_bypass_get,
				taiko_tx_hpf_bypass_put),
	SOC_SINGLE_BOOL_EXT("TX4 HPF Switch", 4,
				taiko_tx_hpf_bypass_get,
				taiko_tx_hpf_bypass_put),
	SOC_SINGLE_BOOL_EXT("TX5 HPF Switch", 5,
				taiko_tx_hpf_bypass_get,
				taiko_tx_hpf_bypass_put),
	SOC_SINGLE_BOOL_EXT("TX6 HPF Switch", 6,
				taiko_tx_hpf_bypass_get,
				taiko_tx_hpf_bypass_put),
	SOC_SINGLE_BOOL_EXT("TX7 HPF Switch", 7,
				taiko_tx_hpf_bypass_get,
				taiko_tx_hpf_bypass_put),
	SOC_SINGLE_BOOL_EXT("TX8 HPF Switch", 8,
				taiko_tx_hpf_bypass_get,
				taiko_tx_hpf_bypass_put),
	SOC_SINGLE_BOOL_EXT("TX9 HPF Switch", 9,
				taiko_tx_hpf_bypass_get,
				taiko_tx_hpf_bypass_put),
	SOC_SINGLE_BOOL_EXT("TX10 HPF Switch", 10,
				taiko_tx_hpf_bypass_get,
				taiko_tx_hpf_bypass_put),

	SOC_SINGLE("RX1 HPF Switch", TAIKO_A_CDC_RX1_B5_CTL, 2, 1, 0),
	SOC_SINGLE("RX2 HPF Switch", TAIKO_A_CDC_RX2_B5_CTL, 2, 1, 0),
@@ -1645,7 +1712,7 @@ static const char * const dec7_mux_text[] = {
};

static const char * const dec8_mux_text[] = {
	"ZERO", "DMIC2", "DMIC5", "ADC2", "ADC5",
	"ZERO", "DMIC2", "DMIC5", "ADC2", "ADC5", "ANC1_FB", "ANC2_FB",
};

static const char * const dec9_mux_text[] = {
@@ -3057,7 +3124,11 @@ static int taiko_codec_enable_dec(struct snd_soc_dapm_widget *w,
			1 << w->shift);
		snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);

		dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
		pr_debug("%s: decimator = %u, bypass = %d\n", __func__,
			decimator, tx_hpf_work[decimator - 1].tx_hpf_bypass);
		if (tx_hpf_work[decimator - 1].tx_hpf_bypass != true) {
			dec_hpf_cut_of_freq = snd_soc_read(codec,
							tx_mux_ctl_reg);

			dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;

@@ -3073,6 +3144,9 @@ static int taiko_codec_enable_dec(struct snd_soc_dapm_widget *w,

			/* enable HPF */
			snd_soc_update_bits(codec, tx_mux_ctl_reg , 0x08, 0x00);
		} else
			/* bypass HPF */
			snd_soc_update_bits(codec, tx_mux_ctl_reg , 0x08, 0x08);

		break;

@@ -3081,8 +3155,9 @@ static int taiko_codec_enable_dec(struct snd_soc_dapm_widget *w,
		/* Disable TX digital mute */
		snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);

		if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
				CF_MIN_3DB_150HZ) {
		if ((tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
				CF_MIN_3DB_150HZ) &&
			(tx_hpf_work[decimator - 1].tx_hpf_bypass != true)) {

			schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
					msecs_to_jiffies(300));
@@ -3763,6 +3838,12 @@ static const struct snd_soc_dapm_route audio_map[] = {
	{"ANC2 MUX", "ADC2", "ADC2"},
	{"ANC2 MUX", "ADC3", "ADC3"},
	{"ANC2 MUX", "ADC4", "ADC4"},
	{"ANC2 MUX", "DMIC1", "DMIC1"},
	{"ANC2 MUX", "DMIC2", "DMIC2"},
	{"ANC2 MUX", "DMIC3", "DMIC3"},
	{"ANC2 MUX", "DMIC4", "DMIC4"},
	{"ANC2 MUX", "DMIC5", "DMIC5"},
	{"ANC2 MUX", "DMIC6", "DMIC6"},

	{"ANC HPHR", NULL, "CDC_CONN"},

@@ -4057,21 +4138,29 @@ static const struct snd_soc_dapm_route audio_map[] = {
	{"DEC7 MUX", "DMIC6", "DMIC6"},
	{"DEC7 MUX", "ADC1", "ADC1"},
	{"DEC7 MUX", "ADC6", "ADC6"},
	{"DEC7 MUX", "ANC1_FB", "ANC1 MUX"},
	{"DEC7 MUX", "ANC2_FB", "ANC2 MUX"},
	{"DEC7 MUX", NULL, "CDC_CONN"},
	{"DEC8 MUX", "DMIC2", "DMIC2"},
	{"DEC8 MUX", "DMIC5", "DMIC5"},
	{"DEC8 MUX", "ADC2", "ADC2"},
	{"DEC8 MUX", "ADC5", "ADC5"},
	{"DEC8 MUX", "ANC1_FB", "ANC1 MUX"},
	{"DEC8 MUX", "ANC2_FB", "ANC2 MUX"},
	{"DEC8 MUX", NULL, "CDC_CONN"},
	{"DEC9 MUX", "DMIC4", "DMIC4"},
	{"DEC9 MUX", "DMIC5", "DMIC5"},
	{"DEC9 MUX", "ADC2", "ADC2"},
	{"DEC9 MUX", "ADC3", "ADC3"},
	{"DEC9 MUX", "ANC1_FB", "ANC1 MUX"},
	{"DEC9 MUX", "ANC2_FB", "ANC2 MUX"},
	{"DEC9 MUX", NULL, "CDC_CONN"},
	{"DEC10 MUX", "DMIC3", "DMIC3"},
	{"DEC10 MUX", "DMIC6", "DMIC6"},
	{"DEC10 MUX", "ADC1", "ADC1"},
	{"DEC10 MUX", "ADC4", "ADC4"},
	{"DEC10 MUX", "ANC1_FB", "ANC1 MUX"},
	{"DEC10 MUX", "ANC2_FB", "ANC2 MUX"},
	{"DEC10 MUX", NULL, "CDC_CONN"},

	/* ADC Connections */
@@ -6274,7 +6363,8 @@ static int taiko_handle_pdata(struct taiko_priv *taiko)
		0xE, dmic_b2_ctl_value);
	snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B2_CTL,
		0x1, anc_ctl_value);

	snd_soc_update_bits(codec, TAIKO_A_CDC_ANC2_B2_CTL,
		0x01, anc_ctl_value);
done:
	return rc;
}
@@ -7058,6 +7148,7 @@ static int taiko_codec_probe(struct snd_soc_codec *codec)
	for (i = 0 ; i < NUM_DECIMATORS; i++) {
		tx_hpf_work[i].taiko = taiko;
		tx_hpf_work[i].decimator = i + 1;
		tx_hpf_work[i].tx_hpf_bypass = false;
		INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
			tx_hpf_corner_freq_callback);
	}