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

Commit a06bf3e1 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: wcd9xxx: Enable headset in high performance"

parents f9a62269 9a11d5dd
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);