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

Commit b9323680 authored by Kiran Kandi's avatar Kiran Kandi
Browse files

ASoC: wcd9320: remove hard coded mad mic bias



Currently MICBIAS1 is hard coded as bias needs to be turned on
by MAD HW. Expose a control to user space to set MIC input needs
be used by MAD. Based on the mic, set the correct mic bias to be
used by MAD HW by scanning machine audio routes.

CRs-Fixed: 538266
Change-Id: Ib85be87e50554b9587f7bafb5b58333a88df6766
Signed-off-by: default avatarKiran Kandi <kkandi@codeaurora.org>
parent 4b2d5f30
Loading
Loading
Loading
Loading
+124 −2
Original line number Diff line number Diff line
@@ -1143,6 +1143,124 @@ static const struct soc_enum class_h_dsm_enum =
static const struct snd_kcontrol_new class_h_dsm_mux =
	SOC_DAPM_ENUM("CLASS_H_DSM MUX Mux", class_h_dsm_enum);

static const char *const taiko_conn_mad_text[] = {
	"ADC_MB", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "NOTUSED1",
	"DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6", "NOTUSED2",
	"NOTUSED3"};

static const struct soc_enum taiko_conn_mad_enum =
	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(taiko_conn_mad_text),
			taiko_conn_mad_text);


static int taiko_mad_input_get(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	u8 taiko_mad_input;
	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);

	taiko_mad_input = snd_soc_read(codec, TAIKO_A_CDC_CONN_MAD);

	taiko_mad_input = taiko_mad_input & 0x0F;

	ucontrol->value.integer.value[0] = taiko_mad_input;

	pr_debug("%s: taiko_mad_input = %s\n", __func__,
			taiko_conn_mad_text[taiko_mad_input]);

	return 0;
}

static int taiko_mad_input_put(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	u8 taiko_mad_input;
	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
	struct snd_soc_card *card = codec->card;
	char mad_amic_input_widget[6];
	u32 adc;
	const char *mad_input_widget;
	u32  mic_bias_found = 0;
	u32 i;
	int ret = 0;

	taiko_mad_input = ucontrol->value.integer.value[0];

	pr_debug("%s: taiko_mad_input = %s\n", __func__,
			taiko_conn_mad_text[taiko_mad_input]);

	if (!strcmp(taiko_conn_mad_text[taiko_mad_input], "NOTUSED1") ||
		!strcmp(taiko_conn_mad_text[taiko_mad_input], "NOTUSED2") ||
		!strcmp(taiko_conn_mad_text[taiko_mad_input], "NOTUSED3") ||
		!strcmp(taiko_conn_mad_text[taiko_mad_input], "ADC_MB")) {
		pr_info("%s: taiko mad input is set to unsupported input = %s\n",
				__func__, taiko_conn_mad_text[taiko_mad_input]);
		return -EINVAL;
	}

	if (strnstr(taiko_conn_mad_text[taiko_mad_input],
				"ADC", sizeof("ADC"))) {
		ret = kstrtouint(strpbrk(taiko_conn_mad_text[taiko_mad_input]
					, "123456"), 10, &adc);
		if ((ret < 0) || (adc > 6)) {
			pr_err("%s: Invalid ADC = %s\n", __func__,
				taiko_conn_mad_text[taiko_mad_input]);
			ret =  -EINVAL;
		}

		snprintf(mad_amic_input_widget, 6, "%s%u", "AMIC", adc);

		mad_input_widget = mad_amic_input_widget;
		pr_debug("%s: taiko amic input widget = %s\n", __func__,
			  mad_amic_input_widget);
	} else {
		/* DMIC type input widget*/
		mad_input_widget = taiko_conn_mad_text[taiko_mad_input];
	}

	pr_debug("%s: taiko input widget = %s\n", __func__, mad_input_widget);

	for (i = 0; i < card->num_dapm_routes; i++) {

		if (!strcmp(card->dapm_routes[i].sink, mad_input_widget)) {

			if (strnstr(card->dapm_routes[i].source,
				"MIC BIAS1", sizeof("MIC BIAS1"))) {
				mic_bias_found = 1;
				break;
			} else if (strnstr(card->dapm_routes[i].source,
				"MIC BIAS2", sizeof("MIC BIAS2"))) {
				mic_bias_found = 2;
				break;
			} else if (strnstr(card->dapm_routes[i].source,
				"MIC BIAS3", sizeof("MIC BIAS3"))) {
				mic_bias_found = 3;
				break;
			} else if (strnstr(card->dapm_routes[i].source,
				"MIC BIAS4", sizeof("MIC BIAS4"))) {
				mic_bias_found = 4;
				break;
			}
		}
	}

	if (mic_bias_found) {
		pr_debug("%s: source mic bias = %s. sink = %s\n", __func__,
				card->dapm_routes[i].source,
				card->dapm_routes[i].sink);

		snd_soc_update_bits(codec, TAIKO_A_CDC_CONN_MAD,
					0x0F, taiko_mad_input);
		snd_soc_update_bits(codec, TAIKO_A_MAD_ANA_CTRL,
					0x07, mic_bias_found);
		return 0;
	} else {
		pr_err("%s: mic bias source not found for input = %s\n",
				__func__, mad_input_widget);
		return -EINVAL;
	}
}


static const struct snd_kcontrol_new taiko_snd_controls[] = {

@@ -1291,6 +1409,9 @@ static const struct snd_kcontrol_new taiko_snd_controls[] = {
	SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
		       taiko_get_compander, taiko_set_compander),

	SOC_ENUM_EXT("MAD Input", taiko_conn_mad_enum,
			taiko_mad_input_get, taiko_mad_input_put),

};

static int taiko_pa_gain_get(struct snd_kcontrol *kcontrol,
@@ -2560,8 +2681,6 @@ static int taiko_codec_config_mad(struct snd_soc_codec *codec)
		return -EINVAL;
	}

	snd_soc_update_bits(codec, TAIKO_A_CDC_CONN_MAD,
			    0x0F, mad_cal->microphone_info.input_microphone);
	snd_soc_write(codec, TAIKO_A_CDC_MAD_MAIN_CTL_2,
		      mad_cal->microphone_info.cycle_time);
	snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_MAIN_CTL_1, 0xFF << 3,
@@ -6128,6 +6247,9 @@ static const struct wcd9xxx_reg_mask_val taiko_codec_reg_init_val[] = {

	/* Program the 0.85 volt VBG_REFERENCE */
	{TAIKO_A_BIAS_CURR_CTL_2, 0xFF, 0x04},

	/* set MAD input MIC to DMIC1 */
	{TAIKO_A_CDC_CONN_MAD, 0x0F, 0x08},
};

static void taiko_codec_init_reg(struct snd_soc_codec *codec)