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

Commit 91956c1a authored by Yeleswarapu Nagaradhesh's avatar Yeleswarapu Nagaradhesh
Browse files

ASoC: wcd: ensure regulator is on during plug detection



To detect special headset we need MICBIAS at 2.7V,
so ensure that the required regulator is on before
going for special headset plugtype determination.

CRs-fixed: 676589
Change-Id: Ib18db2b11f18fc88fb67d60717ca06eafb2fc277
Signed-off-by: default avatarYeleswarapu Nagaradhesh <nagaradh@codeaurora.org>
parent 847cc4f1
Loading
Loading
Loading
Loading
+33 −1
Original line number Original line Diff line number Diff line
@@ -188,6 +188,8 @@ static int msm8x16_wcd_dt_parse_vreg_info(struct device *dev,
	const char *vreg_name, bool ondemand);
	const char *vreg_name, bool ondemand);
static struct msm8x16_wcd_pdata *msm8x16_wcd_populate_dt_pdata(
static struct msm8x16_wcd_pdata *msm8x16_wcd_populate_dt_pdata(
	struct device *dev);
	struct device *dev);
static int msm8x16_wcd_enable_ext_mb_source(struct snd_soc_codec *codec,
					    bool turn_on);


struct msm8x16_wcd_spmi msm8x16_wcd_modules[MAX_MSM8X16_WCD_DEVICE];
struct msm8x16_wcd_spmi msm8x16_wcd_modules[MAX_MSM8X16_WCD_DEVICE];


@@ -195,6 +197,11 @@ static void *modem_state_notifier;


static struct snd_soc_codec *registered_codec;
static struct snd_soc_codec *registered_codec;


static const struct wcd_mbhc_cb mbhc_cb = {
	.enable_mb_source = msm8x16_wcd_enable_ext_mb_source,
};


static int get_spmi_msm8x16_wcd_device_info(u16 *reg,
static int get_spmi_msm8x16_wcd_device_info(u16 *reg,
			struct msm8x16_wcd_spmi **msm8x16_wcd)
			struct msm8x16_wcd_spmi **msm8x16_wcd)
{
{
@@ -1760,6 +1767,30 @@ static int msm8x16_wcd_codec_enable_dmic(struct snd_soc_dapm_widget *w,
	return 0;
	return 0;
}
}


static int msm8x16_wcd_enable_ext_mb_source(struct snd_soc_codec *codec,
					    bool turn_on)
{
	int ret = 0;

	if (turn_on)
		ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
				"MICBIAS_REGULATOR");
	else
		ret = snd_soc_dapm_disable_pin(&codec->dapm,
				"MICBIAS_REGULATOR");

	snd_soc_dapm_sync(&codec->dapm);

	if (ret)
		dev_err(codec->dev, "%s: Failed to %s external micbias source\n",
			__func__, turn_on ? "enable" : "disabled");
	else
		dev_dbg(codec->dev, "%s: %s external micbias source\n",
			 __func__, turn_on ? "Enabled" : "Disabled");

	return ret;
}

static int msm8x16_wcd_codec_enable_micbias(struct snd_soc_dapm_widget *w,
static int msm8x16_wcd_codec_enable_micbias(struct snd_soc_dapm_widget *w,
	struct snd_kcontrol *kcontrol, int event)
	struct snd_kcontrol *kcontrol, int event)
{
{
@@ -3115,7 +3146,8 @@ static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
				on_demand_supply_name[ON_DEMAND_MICBIAS]);
				on_demand_supply_name[ON_DEMAND_MICBIAS]);
	atomic_set(&msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].ref, 0);
	atomic_set(&msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].ref, 0);


	wcd_mbhc_init(&msm8x16_wcd_priv->mbhc, codec, &intr_ids, true);
	wcd_mbhc_init(&msm8x16_wcd_priv->mbhc, codec, &mbhc_cb, &intr_ids,
			false);


	msm8x16_wcd_priv->mclk_enabled = false;
	msm8x16_wcd_priv->mclk_enabled = false;
	msm8x16_wcd_priv->clock_active = false;
	msm8x16_wcd_priv->clock_active = false;
+18 −0
Original line number Original line Diff line number Diff line
@@ -607,6 +607,9 @@ static void wcd_correct_swch_plug(struct work_struct *work)
		plug_type = MBHC_PLUG_TYPE_INVALID;
		plug_type = MBHC_PLUG_TYPE_INVALID;


	if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH) {
	if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH) {
		/* Enable external voltage source to micbias if present */
		if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mb_source)
			mbhc->mbhc_cb->enable_mb_source(codec, true);


		/* Enable micbias if not already enabled*/
		/* Enable micbias if not already enabled*/
		snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_MICB_2_EN,
		snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_MICB_2_EN,
@@ -663,6 +666,10 @@ static void wcd_correct_swch_plug(struct work_struct *work)
		if (!mbhc->micbias_enable)
		if (!mbhc->micbias_enable)
			snd_soc_write(codec, MSM8X16_WCD_A_ANALOG_MICB_1_VAL,
			snd_soc_write(codec, MSM8X16_WCD_A_ANALOG_MICB_1_VAL,
			0x20);
			0x20);

		/* Disable external voltage source to micbias if present */
		if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mb_source)
			mbhc->mbhc_cb->enable_mb_source(codec, false);
	}
	}


	wcd_mbhc_find_plug_and_report(mbhc, plug_type);
	wcd_mbhc_find_plug_and_report(mbhc, plug_type);
@@ -685,6 +692,11 @@ static void wcd_mbhc_detect_plug_type(struct wcd_mbhc *mbhc)
	snd_soc_update_bits(codec,
	snd_soc_update_bits(codec,
			MSM8X16_WCD_A_ANALOG_MICB_2_EN,
			MSM8X16_WCD_A_ANALOG_MICB_2_EN,
			0x80, 0x80);
			0x80, 0x80);

	/* Enable external voltage source to micbias if present */
	if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mb_source)
		mbhc->mbhc_cb->enable_mb_source(codec, true);

	/*
	/*
	 * Wait for 50msec for FSM to complete its task.
	 * Wait for 50msec for FSM to complete its task.
	 * wakeup if btn pres intr occurs
	 * wakeup if btn pres intr occurs
@@ -769,6 +781,10 @@ eu_us_switch:
	snd_soc_update_bits(codec,
	snd_soc_update_bits(codec,
		MSM8X16_WCD_A_ANALOG_MICB_2_EN,
		MSM8X16_WCD_A_ANALOG_MICB_2_EN,
		0x80, 0x00);
		0x80, 0x00);
	/* Disable external voltage source to micbias if present */
	if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mb_source)
		mbhc->mbhc_cb->enable_mb_source(codec, false);

	pr_debug("%s: Valid plug found, plug type is %d\n",
	pr_debug("%s: Valid plug found, plug type is %d\n",
			 __func__, plug_type);
			 __func__, plug_type);
	if (plug_type != MBHC_PLUG_TYPE_HIGH_HPH &&
	if (plug_type != MBHC_PLUG_TYPE_HIGH_HPH &&
@@ -1173,6 +1189,7 @@ EXPORT_SYMBOL(wcd_mbhc_stop);
 * NOTE: mbhc->mbhc_cfg is not YET configure so shouldn't be used
 * NOTE: mbhc->mbhc_cfg is not YET configure so shouldn't be used
 */
 */
int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec,
int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec,
		      const struct wcd_mbhc_cb *mbhc_cb,
		      const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
		      const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
		      bool impedance_det_en)
		      bool impedance_det_en)
{
{
@@ -1207,6 +1224,7 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec,
	mbhc->hphl_swh = hph_swh;
	mbhc->hphl_swh = hph_swh;
	mbhc->gnd_swh = gnd_swh;
	mbhc->gnd_swh = gnd_swh;
	mbhc->micbias_enable = false;
	mbhc->micbias_enable = false;
	mbhc->mbhc_cb = mbhc_cb;


	if (mbhc->intr_ids == NULL) {
	if (mbhc->intr_ids == NULL) {
		pr_err("%s: Interrupt mapping not provided\n", __func__);
		pr_err("%s: Interrupt mapping not provided\n", __func__);
+6 −0
Original line number Original line Diff line number Diff line
@@ -61,9 +61,14 @@ struct wcd_mbhc_intr {
	int hph_right_ocp;
	int hph_right_ocp;
};
};


struct wcd_mbhc_cb {
	int (*enable_mb_source) (struct snd_soc_codec *, bool);
};

struct wcd_mbhc {
struct wcd_mbhc {
	int buttons_pressed;
	int buttons_pressed;
	struct wcd_mbhc_config *mbhc_cfg;
	struct wcd_mbhc_config *mbhc_cfg;
	const struct wcd_mbhc_cb *mbhc_cb;


	u32 hph_status; /* track headhpone status */
	u32 hph_status; /* track headhpone status */
	u8 hphlocp_cnt; /* headphone left ocp retry */
	u8 hphlocp_cnt; /* headphone left ocp retry */
@@ -107,6 +112,7 @@ int wcd_mbhc_start(struct wcd_mbhc *mbhc,
		       struct wcd_mbhc_config *mbhc_cfg);
		       struct wcd_mbhc_config *mbhc_cfg);
void wcd_mbhc_stop(struct wcd_mbhc *mbhc);
void wcd_mbhc_stop(struct wcd_mbhc *mbhc);
int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec,
int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec,
		      const struct wcd_mbhc_cb *mbhc_cb,
		      const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
		      const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
		      bool impedance_det_en);
		      bool impedance_det_en);
void wcd_mbhc_deinit(struct wcd_mbhc *mbhc);
void wcd_mbhc_deinit(struct wcd_mbhc *mbhc);