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

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

Merge "ASoC: wcd: enable regulator when micbias is needed"

parents 52c2768c 1b43c6c7
Loading
Loading
Loading
Loading
+140 −0
Original line number Diff line number Diff line
@@ -142,6 +142,12 @@ MODULE_PARM_DESC(cpe_debug_mode, "boot cpe in debug mode");

#define TASHA_DIG_CORE_COLLAPSE_TIMER_MS  (5 * 1000)

#define MAX_ON_DEMAND_SUPPLY_NAME_LENGTH    64

static char on_demand_supply_name[][MAX_ON_DEMAND_SUPPLY_NAME_LENGTH] = {
	"cdc-vdd-mic-bias",
};

enum {
	POWER_COLLAPSE,
	POWER_RESUME,
@@ -772,6 +778,8 @@ struct tasha_priv {
	struct snd_info_entry *version_entry;
	int power_active_ref;

	struct on_demand_supply on_demand_list[ON_DEMAND_SUPPLIES_MAX];

	int (*machine_codec_event_cb)(struct snd_soc_codec *codec,
				      enum wcd9335_codec_event);
	int spkr_gain_offset;
@@ -1280,6 +1288,53 @@ static void tasha_mbhc_hph_l_pull_up_control(struct snd_soc_codec *codec,
			    0xC0, 0x40);
}

static int tasha_enable_ext_mb_source(struct snd_soc_codec *codec,
		bool turn_on)
{
	struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
	int ret = 0;
	struct on_demand_supply *supply;

	if (!tasha)
		return -EINVAL;

	supply =  &tasha->on_demand_list[ON_DEMAND_MICBIAS];
	if (!supply->supply) {
		dev_dbg(codec->dev, "%s: warning supply not present ond for %s\n",
				__func__, "onDemand Micbias");
		return ret;
	}

	dev_dbg(codec->dev, "%s turn_on: %d count: %d\n", __func__, turn_on,
		supply->ondemand_supply_count);

	if (turn_on) {
		if (!(supply->ondemand_supply_count)) {
			ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
				"MICBIAS_REGULATOR");
			snd_soc_dapm_sync(&codec->dapm);
		}
		supply->ondemand_supply_count++;
	} else {
		if (supply->ondemand_supply_count > 0)
			supply->ondemand_supply_count--;
		if (!(supply->ondemand_supply_count)) {
			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 tasha_micbias_control(struct snd_soc_codec *codec,
				 int micb_num,
				 int req, bool is_dapm)
@@ -1902,6 +1957,7 @@ static const struct wcd_mbhc_cb mbhc_cb = {
	.free_irq = tasha_mbhc_free_irq,
	.clk_setup = tasha_mbhc_clk_setup,
	.map_btn_code_to_num = tasha_mbhc_btn_to_num,
	.enable_mb_source = tasha_enable_ext_mb_source,
	.mbhc_bias = tasha_mbhc_mbhc_bias_control,
	.set_btn_thr = tasha_mbhc_program_btn_thr,
	.lock_sleep = tasha_mbhc_lock_sleep,
@@ -4930,6 +4986,57 @@ static int tasha_codec_set_iir_gain(struct snd_soc_dapm_widget *w,
	return 0;
}

static int tasha_codec_enable_on_demand_supply(
	struct snd_soc_dapm_widget *w,
	struct snd_kcontrol *kcontrol, int event)
{
	int ret = 0;
	struct snd_soc_codec *codec = w->codec;
	struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
	struct on_demand_supply *supply;

	if (w->shift >= ON_DEMAND_SUPPLIES_MAX) {
		dev_err(codec->dev, "%s: error index > MAX Demand supplies",
			__func__);
		ret = -EINVAL;
		goto out;
	}

	dev_dbg(codec->dev, "%s: supply: %s event: %d\n",
		__func__, on_demand_supply_name[w->shift], event);

	supply = &tasha->on_demand_list[w->shift];
	WARN_ONCE(!supply->supply, "%s isn't defined\n",
		on_demand_supply_name[w->shift]);
	if (!supply->supply) {
		dev_err(codec->dev, "%s: err supply not present ond for %d",
			__func__, w->shift);
		goto out;
	}

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		ret = regulator_enable(supply->supply);
		if (ret)
			dev_err(codec->dev, "%s: Failed to enable %s\n",
				__func__,
				on_demand_supply_name[w->shift]);
		break;
	case SND_SOC_DAPM_POST_PMD:
		ret = regulator_disable(supply->supply);
		if (ret)
			dev_err(codec->dev, "%s: Failed to disable %s\n",
				__func__,
				on_demand_supply_name[w->shift]);
		break;
	default:
		break;
	};

out:
	return ret;
}

static int tasha_codec_find_amic_input(struct snd_soc_codec *codec,
				       int adc_mux_n)
{
@@ -9994,6 +10101,10 @@ static const struct snd_soc_dapm_widget tasha_dapm_widgets[] = {
	SND_SOC_DAPM_OUTPUT("LINEOUT4"),
	SND_SOC_DAPM_OUTPUT("ANC LINEOUT1"),
	SND_SOC_DAPM_OUTPUT("ANC LINEOUT2"),
	SND_SOC_DAPM_SUPPLY("MICBIAS_REGULATOR", SND_SOC_NOPM,
		ON_DEMAND_MICBIAS, 0,
		tasha_codec_enable_on_demand_supply,
		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),

	SND_SOC_DAPM_SWITCH("ADC US MUX0", WCD9335_CDC_TX0_TX_PATH_192_CTL, 0,
			    0, &adc_us_mux0_switch),
@@ -12206,6 +12317,26 @@ err:
	return ret;
}

static struct regulator *tasha_codec_find_ondemand_regulator(
		struct snd_soc_codec *codec, const char *name)
{
	int i;
	struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
	struct wcd9xxx *wcd9xxx = tasha->wcd9xxx;
	struct wcd9xxx_pdata *pdata = dev_get_platdata(codec->dev->parent);

	for (i = 0; i < wcd9xxx->num_of_supplies; ++i) {
		if (pdata->regulator[i].ondemand &&
			wcd9xxx->supplies[i].supply &&
			!strcmp(wcd9xxx->supplies[i].supply, name))
			return wcd9xxx->supplies[i].consumer;
	}

	dev_dbg(tasha->dev, "Warning: regulator not found:%s\n",
		name);
	return NULL;
}

static int tasha_codec_probe(struct snd_soc_codec *codec)
{
	struct wcd9xxx *control;
@@ -12214,6 +12345,7 @@ static int tasha_codec_probe(struct snd_soc_codec *codec)
	struct snd_soc_dapm_context *dapm = &codec->dapm;
	int i, ret;
	void *ptr = NULL;
	struct regulator *supply;

	control = dev_get_drvdata(codec->dev->parent);

@@ -12264,6 +12396,14 @@ static int tasha_codec_probe(struct snd_soc_codec *codec)
		goto err;
	}

	supply = tasha_codec_find_ondemand_regulator(codec,
		on_demand_supply_name[ON_DEMAND_MICBIAS]);
	if (supply) {
		tasha->on_demand_list[ON_DEMAND_MICBIAS].supply = supply;
		tasha->on_demand_list[ON_DEMAND_MICBIAS].ondemand_supply_count =
				0;
	}

	tasha->fw_data = devm_kzalloc(codec->dev,
				      sizeof(*(tasha->fw_data)), GFP_KERNEL);
	if (!tasha->fw_data) {
+14 −0
Original line number Diff line number Diff line
@@ -86,6 +86,20 @@ enum wcd9335_codec_event {
	WCD9335_CODEC_EVENT_CODEC_UP = 0,
};

enum tasha_on_demand_supply {
	ON_DEMAND_MICBIAS = 0,
	ON_DEMAND_SUPPLIES_MAX,
};

/* structure used to put the defined
 * ondemand supply for codec
 * and count being used.
 */
struct on_demand_supply {
	struct regulator *supply;
	int ondemand_supply_count;
};

/* Dai data structure holds the
 * dai specific info like rate,
 * channel number etc.