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

Commit 9a11d5dd authored by Sudheer Papothi's avatar Sudheer Papothi
Browse files

ASoC: wcd9xxx: Enable headset in high performance



Invoke class AB mode for headset path when sample rate
is set to 192KHz and bit width is set to 24. Change enables
headset path in Ultra High Quality Audio(UHQA)mode.

Change-Id: I6cd05952114b88602fc9dcc883d83a39214311b9
Signed-off-by: default avatarSudheer Papothi <spapothi@codeaurora.org>
parent 32a565cb
Loading
Loading
Loading
Loading
+81 −5
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@
#define TOMTOM_CPE_MAJOR_VER 1
#define TOMTOM_CPE_MINOR_VER 0
#define TOMTOM_CPE_CDC_ID 1
#define RX8_PATH 8

static int cpe_debug_mode;
module_param(cpe_debug_mode, int,
@@ -64,6 +65,11 @@ MODULE_PARM_DESC(cpe_debug_mode, "boot cpe in debug mode");

static atomic_t kp_tomtom_priv;

static int high_perf_mode;
module_param(high_perf_mode, int,
			S_IRUGO | S_IWUSR | S_IWGRP);
MODULE_PARM_DESC(high_perf_mode, "enable/disable class AB config for hph");

static struct afe_param_slimbus_slave_port_cfg tomtom_slimbus_slave_port_cfg = {
	.minor_version = 1,
	.slimbus_dev_id = AFE_SLIMBUS_DEVICE_1,
@@ -461,6 +467,9 @@ struct tomtom_priv {

	/* handle to cpe core */
	struct wcd_cpe_core *cpe_core;

	/* UHQA (class AB) mode */
	u8 uhqa_mode;
};

static const u32 comp_shift[] = {
@@ -545,6 +554,47 @@ static unsigned short tx_digital_gain_reg[] = {
	TOMTOM_A_CDC_TX10_VOL_CTL_GAIN,
};

static int tomtom_get_sample_rate(struct snd_soc_codec *codec, int path)
{
	if (path == RX8_PATH)
		return snd_soc_read(codec, TOMTOM_A_CDC_RX8_B5_CTL);
	else
		return snd_soc_read(codec,
			(TOMTOM_A_CDC_RX1_B5_CTL + 8 * (path - 1)));
}

static int tomtom_compare_bit_format(struct snd_soc_codec *codec,
				int bit_format)
{
	int i = 0;
	int ret = 0;
	struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);

	for (i = 0; i < NUM_CODEC_DAIS; i++) {
		if (tomtom_p->dai[i].bit_width == bit_format) {
			ret = 1;
			break;
		}
	}
	return ret;
}

static int tomtom_update_uhqa_mode(struct snd_soc_codec *codec, int path)
{
	int ret = 0;
	struct tomtom_priv *tomtom_p = snd_soc_codec_get_drvdata(codec);

	/* UHQA path has fs=192KHz & bit=24 bit */
	if (((tomtom_get_sample_rate(codec, path) & 0xE0) == 0xA0) &&
		(tomtom_compare_bit_format(codec, 24))) {
		tomtom_p->uhqa_mode = 1;
	} else {
		tomtom_p->uhqa_mode = 0;
	}
	dev_dbg(codec->dev, "%s: uhqa_mode=%d", __func__, tomtom_p->uhqa_mode);
	return ret;
}

static int tomtom_get_anc_slot(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
@@ -3253,6 +3303,10 @@ static int tomtom_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
				  snd_soc_read(codec,
				  rx_digital_gain_reg[w->shift])
				  );
		/* Check for Rx1 and Rx2 paths for uhqa mode update */
		if (w->shift == 0 || w->shift == 1)
			tomtom_update_uhqa_mode(codec, (1 << w->shift));

		break;
	}
	return 0;
@@ -3347,10 +3401,16 @@ static int tomtom_hphl_dac_event(struct snd_soc_dapm_widget *w,

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		if (!high_perf_mode && !tomtom_p->uhqa_mode) {
			wcd9xxx_clsh_fsm(codec, &tomtom_p->clsh_d,
						 WCD9XXX_CLSH_STATE_HPHL,
						 WCD9XXX_CLSH_REQ_ENABLE,
						 WCD9XXX_CLSH_EVENT_PRE_DAC);
		} else {
			wcd9xxx_enable_high_perf_mode(codec, &tomtom_p->clsh_d,
						WCD9XXX_CLSAB_STATE_HPHL,
						WCD9XXX_CLSAB_REQ_ENABLE);
		}
		ret = wcd9xxx_mbhc_get_impedance(&tomtom_p->mbhc,
					&impedl, &impedr);
		if (!ret)
@@ -3376,10 +3436,16 @@ static int tomtom_hphr_dac_event(struct snd_soc_dapm_widget *w,
	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
		if (!high_perf_mode && !tomtom_p->uhqa_mode) {
			wcd9xxx_clsh_fsm(codec, &tomtom_p->clsh_d,
						 WCD9XXX_CLSH_STATE_HPHR,
						 WCD9XXX_CLSH_REQ_ENABLE,
						 WCD9XXX_CLSH_EVENT_PRE_DAC);
		} else {
			wcd9xxx_enable_high_perf_mode(codec, &tomtom_p->clsh_d,
						WCD9XXX_CLSAB_STATE_HPHR,
						WCD9XXX_CLSAB_REQ_ENABLE);
		}
		break;
	case SND_SOC_DAPM_POST_PMD:
		snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
@@ -3499,6 +3565,7 @@ static int tomtom_hph_pa_event(struct snd_soc_dapm_widget *w,
	struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
	enum wcd9xxx_notify_event e_pre_on, e_post_off;
	u8 req_clsh_state;
	u8 req_clsab_state;
	u32 pa_settle_time = TOMTOM_HPH_PA_SETTLE_COMP_OFF;

	pr_debug("%s: %s event = %d\n", __func__, w->name, event);
@@ -3506,10 +3573,12 @@ static int tomtom_hph_pa_event(struct snd_soc_dapm_widget *w,
		e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
		e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
		req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
		req_clsab_state = WCD9XXX_CLSAB_STATE_HPHL;
	} else if (w->shift == 4) {
		e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
		e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
		req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
		req_clsab_state = WCD9XXX_CLSAB_STATE_HPHR;
	} else {
		pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
		return -EINVAL;
@@ -3528,11 +3597,12 @@ static int tomtom_hph_pa_event(struct snd_soc_dapm_widget *w,
		usleep_range(pa_settle_time, pa_settle_time + 1000);
		pr_debug("%s: sleep %d us after %s PA enable\n", __func__,
				pa_settle_time, w->name);
		if (!high_perf_mode && !tomtom->uhqa_mode) {
			wcd9xxx_clsh_fsm(codec, &tomtom->clsh_d,
						 req_clsh_state,
						 WCD9XXX_CLSH_REQ_ENABLE,
						 WCD9XXX_CLSH_EVENT_POST_PA);

		}
		break;

	case SND_SOC_DAPM_POST_PMD:
@@ -3543,10 +3613,16 @@ static int tomtom_hph_pa_event(struct snd_soc_dapm_widget *w,
		/* Let MBHC module know PA turned off */
		wcd9xxx_resmgr_notifier_call(&tomtom->resmgr, e_post_off);

		if (!high_perf_mode && !tomtom->uhqa_mode) {
			wcd9xxx_clsh_fsm(codec, &tomtom->clsh_d,
						 req_clsh_state,
						 WCD9XXX_CLSH_REQ_DISABLE,
						 WCD9XXX_CLSH_EVENT_POST_PA);
		} else {
			wcd9xxx_enable_high_perf_mode(codec, &tomtom->clsh_d,
						req_clsab_state,
						WCD9XXX_CLSAB_REQ_DISABLE);
		}

		break;
	}
+41 −1
Original line number Diff line number Diff line
@@ -544,6 +544,46 @@ static void wcd9xxx_chargepump_request(struct snd_soc_codec *codec, bool on)
	}
}

void wcd9xxx_enable_high_perf_mode(struct snd_soc_codec *codec,
				struct wcd9xxx_clsh_cdc_data *clsh_d,
				u8 req_state, bool req_type)
{
	dev_dbg(codec->dev, "%s: users fclk8 %d, fclk5 %d", __func__,
			clsh_d->ncp_users[NCP_FCLK_LEVEL_8],
			clsh_d->ncp_users[NCP_FCLK_LEVEL_5]);

	if (req_type == WCD9XXX_CLSAB_REQ_ENABLE) {
		clsh_d->ncp_users[NCP_FCLK_LEVEL_8]++;
		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CHOP_CTL,
					0x20, 0x00);
		wcd9xxx_chargepump_request(codec, true);
		wcd9xxx_enable_anc_delay(codec, true);
		if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] > 0)
			snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
						0x0F, 0x08);
		snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x30, 0x30);

		/* Enable NCP and wait until settles down */
		if (snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN, 0x01, 0x01))
			usleep_range(NCP_SETTLE_TIME_US, NCP_SETTLE_TIME_US+10);
	} else {
		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CHOP_CTL,
					0x20, 0x20);
		wcd9xxx_chargepump_request(codec, false);
		wcd9xxx_enable_anc_delay(codec, false);
		clsh_d->ncp_users[NCP_FCLK_LEVEL_8]--;
		if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] == 0 &&
		    clsh_d->ncp_users[NCP_FCLK_LEVEL_5] == 0)
			snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN,
						0x01, 0x00);
		else if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] == 0)
			snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
						0x0F, 0x05);
	}
	dev_dbg(codec->dev, "%s: leave\n", __func__);
}
EXPORT_SYMBOL(wcd9xxx_enable_high_perf_mode);

static int get_impedance_index(u32 imped)
{
	int i = 0;
@@ -1090,7 +1130,7 @@ static void wcd9xxx_clsh_state_ear(struct snd_soc_codec *codec,
		dev_dbg(codec->dev, "%s: stub fallback to ear\n", __func__);
		wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
		wcd9xxx_enable_buck(codec, clsh_d, false);
		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR, true);
		wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR, false);
		wcd9xxx_chargepump_request(codec, false);
		wcd9xxx_enable_clsh_block(codec, clsh_d, false);
	}
+11 −0
Original line number Diff line number Diff line
@@ -37,6 +37,13 @@
#define	WCD9XXX_CLSH_STATE_LO (0x01 << 3)
#define NUM_CLSH_STATES (0x01 << 4)

#define	WCD9XXX_CLSAB_STATE_IDLE  0x00
#define WCD9XXX_CLSAB_STATE_HPHL (0x01 << 1)
#define WCD9XXX_CLSAB_STATE_HPHR (0x01 << 2)

#define WCD9XXX_CLSAB_REQ_ENABLE  true
#define WCD9XXX_CLSAB_REQ_DISABLE false

#define WCD9XXX_DMIC_SAMPLE_RATE_DIV_2    0x0
#define WCD9XXX_DMIC_SAMPLE_RATE_DIV_3    0x1
#define WCD9XXX_DMIC_SAMPLE_RATE_DIV_4    0x2
@@ -174,6 +181,10 @@ extern void wcd9xxx_clsh_fsm(struct snd_soc_codec *codec,
		struct wcd9xxx_clsh_cdc_data *cdc_clsh_d,
		u8 req_state, bool req_type, u8 clsh_event);

extern void wcd9xxx_enable_high_perf_mode(struct snd_soc_codec *codec,
				struct wcd9xxx_clsh_cdc_data *clsh_d,
				u8 req_state, bool req_type);

extern void wcd9xxx_clsh_init(struct wcd9xxx_clsh_cdc_data *clsh,
			      struct wcd9xxx_resmgr *resmgr);