Unverified Commit d5add08f authored by Srinivas Kandagatla's avatar Srinivas Kandagatla Committed by Mark Brown
Browse files

ASoC: codecs: wcd938x: add capture dapm widgets

parent 8da9db0c
Loading
Loading
Loading
Loading
+756 −0
Original line number Diff line number Diff line
@@ -157,6 +157,16 @@ enum {
	NUM_CODEC_DAIS,
};

static u8 tx_mode_bit[] = {
	[ADC_MODE_INVALID] = 0x00,
	[ADC_MODE_HIFI] = 0x01,
	[ADC_MODE_LO_HIF] = 0x02,
	[ADC_MODE_NORMAL] = 0x04,
	[ADC_MODE_LP] = 0x08,
	[ADC_MODE_ULP1] = 0x10,
	[ADC_MODE_ULP2] = 0x20,
};

struct wcd938x_priv {
	struct sdw_slave *tx_sdw_dev;
	struct wcd938x_sdw_priv *sdw_priv[NUM_CODEC_DAIS];
@@ -1240,6 +1250,61 @@ static struct regmap_irq_chip wcd938x_regmap_irq_chip = {
	.irq_drv_data = NULL,
};

static int wcd938x_get_clk_rate(int mode)
{
	int rate;

	switch (mode) {
	case ADC_MODE_ULP2:
		rate = SWR_CLK_RATE_0P6MHZ;
		break;
	case ADC_MODE_ULP1:
		rate = SWR_CLK_RATE_1P2MHZ;
		break;
	case ADC_MODE_LP:
		rate = SWR_CLK_RATE_4P8MHZ;
		break;
	case ADC_MODE_NORMAL:
	case ADC_MODE_LO_HIF:
	case ADC_MODE_HIFI:
	case ADC_MODE_INVALID:
	default:
		rate = SWR_CLK_RATE_9P6MHZ;
		break;
	}

	return rate;
}

static int wcd938x_set_swr_clk_rate(struct snd_soc_component *component, int rate, int bank)
{
	u8 mask = (bank ? 0xF0 : 0x0F);
	u8 val = 0;

	switch (rate) {
	case SWR_CLK_RATE_0P6MHZ:
		val = (bank ? 0x60 : 0x06);
		break;
	case SWR_CLK_RATE_1P2MHZ:
		val = (bank ? 0x50 : 0x05);
		break;
	case SWR_CLK_RATE_2P4MHZ:
		val = (bank ? 0x30 : 0x03);
		break;
	case SWR_CLK_RATE_4P8MHZ:
		val = (bank ? 0x10 : 0x01);
		break;
	case SWR_CLK_RATE_9P6MHZ:
	default:
		val = 0x00;
		break;
	}
	snd_soc_component_update_bits(component, WCD938X_DIGITAL_SWR_TX_CLK_RATE,
				      mask, val);

	return 0;
}

static int wcd938x_io_init(struct wcd938x_priv *wcd938x)
{
	struct regmap *rm = wcd938x->regmap;
@@ -1915,6 +1980,455 @@ static int wcd938x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
	return 0;
}

static int wcd938x_codec_enable_dmic(struct snd_soc_dapm_widget *w,
				     struct snd_kcontrol *kcontrol,
				     int event)
{
	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
	u16 dmic_clk_reg, dmic_clk_en_reg;
	u8 dmic_sel_mask, dmic_clk_mask;

	switch (w->shift) {
	case 0:
	case 1:
		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_1_2;
		dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC1_CTL;
		dmic_clk_mask = WCD938X_DMIC1_RATE_MASK;
		dmic_sel_mask = WCD938X_AMIC1_IN_SEL_MASK;
		break;
	case 2:
	case 3:
		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_1_2;
		dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC2_CTL;
		dmic_clk_mask = WCD938X_DMIC2_RATE_MASK;
		dmic_sel_mask = WCD938X_AMIC3_IN_SEL_MASK;
		break;
	case 4:
	case 5:
		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_3_4;
		dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC3_CTL;
		dmic_clk_mask = WCD938X_DMIC3_RATE_MASK;
		dmic_sel_mask = WCD938X_AMIC4_IN_SEL_MASK;
		break;
	case 6:
	case 7:
		dmic_clk_reg = WCD938X_DIGITAL_CDC_DMIC_RATE_3_4;
		dmic_clk_en_reg = WCD938X_DIGITAL_CDC_DMIC4_CTL;
		dmic_clk_mask = WCD938X_DMIC4_RATE_MASK;
		dmic_sel_mask = WCD938X_AMIC5_IN_SEL_MASK;
		break;
	default:
		dev_err(component->dev, "%s: Invalid DMIC Selection\n",
			__func__);
		return -EINVAL;
	}

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_AMIC_CTL,
				dmic_sel_mask,
				WCD938X_AMIC1_IN_SEL_DMIC);
		/* 250us sleep as per HW requirement */
		usleep_range(250, 260);
		/* Setting DMIC clock rate to 2.4MHz */
		snd_soc_component_write_field(component, dmic_clk_reg,
					      dmic_clk_mask,
					      WCD938X_DMIC4_RATE_2P4MHZ);
		snd_soc_component_write_field(component, dmic_clk_en_reg,
					      WCD938X_DMIC_CLK_EN_MASK, 1);
		/* enable clock scaling */
		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_DMIC_CTL,
					      WCD938X_DMIC_CLK_SCALING_EN_MASK, 0x3);
		break;
	case SND_SOC_DAPM_POST_PMD:
		snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_AMIC_CTL,
				dmic_sel_mask, WCD938X_AMIC1_IN_SEL_AMIC);
		snd_soc_component_write_field(component, dmic_clk_en_reg,
					      WCD938X_DMIC_CLK_EN_MASK, 0);
		break;
	}
	return 0;
}

static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
			       struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
	int bank;
	int rate;

	bank = (wcd938x_swr_get_current_bank(wcd938x->sdw_priv[AIF1_CAP]->sdev)) ? 0 : 1;
	bank = bank ? 0 : 1;

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		if (strnstr(w->name, "ADC", sizeof("ADC"))) {
			int i = 0, mode = 0;

			if (test_bit(WCD_ADC1, &wcd938x->status_mask))
				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC1]];
			if (test_bit(WCD_ADC2, &wcd938x->status_mask))
				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC2]];
			if (test_bit(WCD_ADC3, &wcd938x->status_mask))
				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC3]];
			if (test_bit(WCD_ADC4, &wcd938x->status_mask))
				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC4]];

			if (mode != 0) {
				for (i = 0; i < ADC_MODE_ULP2; i++) {
					if (mode & (1 << i)) {
						i++;
						break;
					}
				}
			}
			rate = wcd938x_get_clk_rate(i);
			wcd938x_set_swr_clk_rate(component, rate, bank);
		}

		if (strnstr(w->name, "ADC", sizeof("ADC")))
			/* Copy clk settings to active bank */
			wcd938x_set_swr_clk_rate(component, rate, !bank);
		break;
	case SND_SOC_DAPM_POST_PMD:
		if (strnstr(w->name, "ADC", sizeof("ADC"))) {
			rate = wcd938x_get_clk_rate(ADC_MODE_INVALID);
			wcd938x_set_swr_clk_rate(component, rate, !bank);
			wcd938x_set_swr_clk_rate(component, rate, bank);
		}
		break;
	}

	return 0;
}

static int wcd938x_get_adc_mode(int val)
{
	int ret = 0;

	switch (val) {
	case ADC_MODE_INVALID:
		ret = ADC_MODE_VAL_NORMAL;
		break;
	case ADC_MODE_HIFI:
		ret = ADC_MODE_VAL_HIFI;
		break;
	case ADC_MODE_LO_HIF:
		ret = ADC_MODE_VAL_LO_HIF;
		break;
	case ADC_MODE_NORMAL:
		ret = ADC_MODE_VAL_NORMAL;
		break;
	case ADC_MODE_LP:
		ret = ADC_MODE_VAL_LP;
		break;
	case ADC_MODE_ULP1:
		ret = ADC_MODE_VAL_ULP1;
		break;
	case ADC_MODE_ULP2:
		ret = ADC_MODE_VAL_ULP2;
		break;
	default:
		ret = -EINVAL;
		break;
	}
	return ret;
}

static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w,
				    struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		snd_soc_component_write_field(component,
					      WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
					      WCD938X_ANA_TX_CLK_EN_MASK, 1);
		snd_soc_component_write_field(component,
					      WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
					      WCD938X_ANA_TX_DIV2_CLK_EN_MASK, 1);
		set_bit(w->shift, &wcd938x->status_mask);
		break;
	case SND_SOC_DAPM_POST_PMD:
		snd_soc_component_write_field(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
					      WCD938X_ANA_TX_CLK_EN_MASK, 0);
		clear_bit(w->shift, &wcd938x->status_mask);
		break;
	}

	return 0;
}

static void wcd938x_tx_channel_config(struct snd_soc_component *component,
				     int channel, int mode)
{
	int reg, mask;

	switch (channel) {
	case 0:
		reg = WCD938X_ANA_TX_CH2;
		mask = WCD938X_HPF1_INIT_MASK;
		break;
	case 1:
		reg = WCD938X_ANA_TX_CH2;
		mask = WCD938X_HPF2_INIT_MASK;
		break;
	case 2:
		reg = WCD938X_ANA_TX_CH4;
		mask = WCD938X_HPF3_INIT_MASK;
		break;
	case 3:
		reg = WCD938X_ANA_TX_CH4;
		mask = WCD938X_HPF4_INIT_MASK;
		break;
	}

	snd_soc_component_write_field(component, reg, mask, mode);
}

static int wcd938x_adc_enable_req(struct snd_soc_dapm_widget *w,
				  struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
	int mode;

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_REQ_CTL,
				WCD938X_FS_RATE_4P8_MASK, 1);
		snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_REQ_CTL,
				WCD938X_NO_NOTCH_MASK, 0);
		wcd938x_tx_channel_config(component, w->shift, 1);
		mode = wcd938x_get_adc_mode(wcd938x->tx_mode[w->shift]);
		if (mode < 0) {
			dev_info(component->dev, "Invalid ADC mode\n");
			return -EINVAL;
		}
		switch (w->shift) {
		case 0:
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,
				WCD938X_TXD0_MODE_MASK, mode);
			snd_soc_component_write_field(component,
						WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
						WCD938X_TXD0_CLK_EN_MASK, 1);
			break;
		case 1:
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,
				WCD938X_TXD1_MODE_MASK, mode);
			snd_soc_component_write_field(component,
					      WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
					      WCD938X_TXD1_CLK_EN_MASK, 1);
			break;
		case 2:
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,
				WCD938X_TXD2_MODE_MASK, mode);
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
				WCD938X_TXD2_CLK_EN_MASK, 1);
			break;
		case 3:
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,
				WCD938X_TXD3_MODE_MASK, mode);
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
				WCD938X_TXD3_CLK_EN_MASK, 1);
			break;
		default:
			break;
		}

		wcd938x_tx_channel_config(component, w->shift, 0);
		break;
	case SND_SOC_DAPM_POST_PMD:
		switch (w->shift) {
		case 0:
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,
				WCD938X_TXD0_MODE_MASK, 0);
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
				WCD938X_TXD0_CLK_EN_MASK, 0);
			break;
		case 1:
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1,
				WCD938X_TXD1_MODE_MASK, 0);
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
				WCD938X_TXD1_CLK_EN_MASK, 0);
			break;
		case 2:
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,
				WCD938X_TXD2_MODE_MASK, 0);
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
				WCD938X_TXD2_CLK_EN_MASK, 0);
			break;
		case 3:
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3,
				WCD938X_TXD3_MODE_MASK, 0);
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
				WCD938X_TXD3_CLK_EN_MASK, 0);
			break;
		default:
			break;
		}
		snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
				WCD938X_ANA_TX_DIV2_CLK_EN_MASK, 0);
		break;
	}

	return 0;
}

static int wcd938x_micbias_control(struct snd_soc_component *component,
				   int micb_num, int req, bool is_dapm)
{
	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
	int micb_index = micb_num - 1;
	u16 micb_reg;

	switch (micb_num) {
	case MIC_BIAS_1:
		micb_reg = WCD938X_ANA_MICB1;
		break;
	case MIC_BIAS_2:
		micb_reg = WCD938X_ANA_MICB2;
		break;
	case MIC_BIAS_3:
		micb_reg = WCD938X_ANA_MICB3;
		break;
	case MIC_BIAS_4:
		micb_reg = WCD938X_ANA_MICB4;
		break;
	default:
		dev_err(component->dev, "%s: Invalid micbias number: %d\n",
			__func__, micb_num);
		return -EINVAL;
	}

	switch (req) {
	case MICB_PULLUP_ENABLE:
		wcd938x->pullup_ref[micb_index]++;
		if ((wcd938x->pullup_ref[micb_index] == 1) &&
		    (wcd938x->micb_ref[micb_index] == 0))
			snd_soc_component_write_field(component, micb_reg,
						      WCD938X_MICB_EN_MASK,
						      WCD938X_MICB_PULL_UP);
		break;
	case MICB_PULLUP_DISABLE:
		if (wcd938x->pullup_ref[micb_index] > 0)
			wcd938x->pullup_ref[micb_index]--;

		if ((wcd938x->pullup_ref[micb_index] == 0) &&
		    (wcd938x->micb_ref[micb_index] == 0))
			snd_soc_component_write_field(component, micb_reg,
						      WCD938X_MICB_EN_MASK, 0);
		break;
	case MICB_ENABLE:
		wcd938x->micb_ref[micb_index]++;
		if (wcd938x->micb_ref[micb_index] == 1) {
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_DIG_CLK_CTL,
				WCD938X_TX_CLK_EN_MASK, 0xF);
			snd_soc_component_write_field(component,
				WCD938X_DIGITAL_CDC_ANA_CLK_CTL,
				WCD938X_ANA_TX_DIV2_CLK_EN_MASK, 1);
			snd_soc_component_write_field(component,
			       WCD938X_DIGITAL_CDC_ANA_TX_CLK_CTL,
			       WCD938X_TX_SC_CLK_EN_MASK, 1);

			snd_soc_component_write_field(component, micb_reg,
						      WCD938X_MICB_EN_MASK,
						      WCD938X_MICB_ENABLE);
		}

		break;
	case MICB_DISABLE:
		if (wcd938x->micb_ref[micb_index] > 0)
			wcd938x->micb_ref[micb_index]--;

		if ((wcd938x->micb_ref[micb_index] == 0) &&
		    (wcd938x->pullup_ref[micb_index] > 0))
			snd_soc_component_write_field(component, micb_reg,
						      WCD938X_MICB_EN_MASK,
						      WCD938X_MICB_PULL_UP);
		else if ((wcd938x->micb_ref[micb_index] == 0) &&
			 (wcd938x->pullup_ref[micb_index] == 0)) {

			snd_soc_component_write_field(component, micb_reg,
						      WCD938X_MICB_EN_MASK, 0);
		}
		break;
	}

	return 0;
}

static int wcd938x_codec_enable_micbias(struct snd_soc_dapm_widget *w,
					struct snd_kcontrol *kcontrol,
					int event)
{
	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
	int micb_num = w->shift;

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		wcd938x_micbias_control(component, micb_num, MICB_ENABLE, true);
		break;
	case SND_SOC_DAPM_POST_PMU:
		/* 1 msec delay as per HW requirement */
		usleep_range(1000, 1100);
		break;
	case SND_SOC_DAPM_POST_PMD:
		wcd938x_micbias_control(component, micb_num, MICB_DISABLE, true);
		break;
	}

	return 0;
}

static int wcd938x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,
					       struct snd_kcontrol *kcontrol,
					       int event)
{
	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
	int micb_num = w->shift;

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		wcd938x_micbias_control(component, micb_num,
					MICB_PULLUP_ENABLE, true);
		break;
	case SND_SOC_DAPM_POST_PMU:
		/* 1 msec delay as per HW requirement */
		usleep_range(1000, 1100);
		break;
	case SND_SOC_DAPM_POST_PMD:
		wcd938x_micbias_control(component, micb_num,
					MICB_PULLUP_DISABLE, true);
		break;
	}

	return 0;
}

static int wcd938x_tx_mode_get(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_value *ucontrol)
{
@@ -2157,10 +2671,78 @@ static const struct soc_enum rx_hph_mode_mux_enum =
		SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
				    rx_hph_mode_mux_text);

static const struct soc_enum adc2_enum =
		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 7,
				ARRAY_SIZE(adc2_mux_text), adc2_mux_text);

static const struct soc_enum adc3_enum =
		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 6,
				ARRAY_SIZE(adc3_mux_text), adc3_mux_text);

static const struct soc_enum adc4_enum =
		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 5,
				ARRAY_SIZE(adc4_mux_text), adc4_mux_text);

static const struct soc_enum hdr12_enum =
		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 4,
				ARRAY_SIZE(hdr12_mux_text), hdr12_mux_text);

static const struct soc_enum hdr34_enum =
		SOC_ENUM_SINGLE(WCD938X_TX_NEW_AMIC_MUX_CFG, 3,
				ARRAY_SIZE(hdr34_mux_text), hdr34_mux_text);

static const struct soc_enum rdac3_enum =
		SOC_ENUM_SINGLE(WCD938X_DIGITAL_CDC_EAR_PATH_CTL, 0,
				ARRAY_SIZE(rdac3_mux_text), rdac3_mux_text);

static const struct snd_kcontrol_new adc1_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new adc2_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new adc3_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new adc4_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new dmic1_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new dmic2_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new dmic3_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new dmic4_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new dmic5_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new dmic6_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new dmic7_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new dmic8_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new ear_rdac_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};
@@ -2177,6 +2759,21 @@ static const struct snd_kcontrol_new hphr_rdac_switch[] = {
	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
};

static const struct snd_kcontrol_new tx_adc2_mux =
	SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum);

static const struct snd_kcontrol_new tx_adc3_mux =
	SOC_DAPM_ENUM("ADC3 MUX Mux", adc3_enum);

static const struct snd_kcontrol_new tx_adc4_mux =
	SOC_DAPM_ENUM("ADC4 MUX Mux", adc4_enum);

static const struct snd_kcontrol_new tx_hdr12_mux =
	SOC_DAPM_ENUM("HDR12 MUX Mux", hdr12_enum);

static const struct snd_kcontrol_new tx_hdr34_mux =
	SOC_DAPM_ENUM("HDR34 MUX Mux", hdr34_enum);

static const struct snd_kcontrol_new rx_rdac3_mux =
	SOC_DAPM_ENUM("RDAC3_MUX Mux", rdac3_enum);

@@ -2309,6 +2906,165 @@ static const struct snd_kcontrol_new wcd938x_snd_controls[] = {
};

static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = {

	/*input widgets*/
	SND_SOC_DAPM_INPUT("AMIC1"),
	SND_SOC_DAPM_INPUT("AMIC2"),
	SND_SOC_DAPM_INPUT("AMIC3"),
	SND_SOC_DAPM_INPUT("AMIC4"),
	SND_SOC_DAPM_INPUT("AMIC5"),
	SND_SOC_DAPM_INPUT("AMIC6"),
	SND_SOC_DAPM_INPUT("AMIC7"),
	SND_SOC_DAPM_MIC("Analog Mic1", NULL),
	SND_SOC_DAPM_MIC("Analog Mic2", NULL),
	SND_SOC_DAPM_MIC("Analog Mic3", NULL),
	SND_SOC_DAPM_MIC("Analog Mic4", NULL),
	SND_SOC_DAPM_MIC("Analog Mic5", NULL),

	/*tx widgets*/
	SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0,
			   wcd938x_codec_enable_adc,
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_ADC_E("ADC2", NULL, SND_SOC_NOPM, 1, 0,
			   wcd938x_codec_enable_adc,
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_ADC_E("ADC3", NULL, SND_SOC_NOPM, 2, 0,
			   wcd938x_codec_enable_adc,
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_ADC_E("ADC4", NULL, SND_SOC_NOPM, 3, 0,
			   wcd938x_codec_enable_adc,
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
			   wcd938x_codec_enable_dmic,
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 1, 0,
			   wcd938x_codec_enable_dmic,
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 2, 0,
			   wcd938x_codec_enable_dmic,
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 3, 0,
			   wcd938x_codec_enable_dmic,
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 4, 0,
			   wcd938x_codec_enable_dmic,
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 5, 0,
			   wcd938x_codec_enable_dmic,
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_ADC_E("DMIC7", NULL, SND_SOC_NOPM, 6, 0,
			   wcd938x_codec_enable_dmic,
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_ADC_E("DMIC8", NULL, SND_SOC_NOPM, 7, 0,
			   wcd938x_codec_enable_dmic,
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),

	SND_SOC_DAPM_MIXER_E("ADC1 REQ", SND_SOC_NOPM, 0, 0,
			     NULL, 0, wcd938x_adc_enable_req,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("ADC2 REQ", SND_SOC_NOPM, 1, 0,
			     NULL, 0, wcd938x_adc_enable_req,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("ADC3 REQ", SND_SOC_NOPM, 2, 0,
			     NULL, 0, wcd938x_adc_enable_req,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("ADC4 REQ", SND_SOC_NOPM, 3, 0, NULL, 0,
			     wcd938x_adc_enable_req,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),

	SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0, &tx_adc2_mux),
	SND_SOC_DAPM_MUX("ADC3 MUX", SND_SOC_NOPM, 0, 0, &tx_adc3_mux),
	SND_SOC_DAPM_MUX("ADC4 MUX", SND_SOC_NOPM, 0, 0, &tx_adc4_mux),
	SND_SOC_DAPM_MUX("HDR12 MUX", SND_SOC_NOPM, 0, 0, &tx_hdr12_mux),
	SND_SOC_DAPM_MUX("HDR34 MUX", SND_SOC_NOPM, 0, 0, &tx_hdr34_mux),

	/*tx mixers*/
	SND_SOC_DAPM_MIXER_E("ADC1_MIXER", SND_SOC_NOPM, 0, 0, adc1_switch,
			     ARRAY_SIZE(adc1_switch), wcd938x_tx_swr_ctrl,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("ADC2_MIXER", SND_SOC_NOPM, 0, 0, adc2_switch,
			     ARRAY_SIZE(adc2_switch), wcd938x_tx_swr_ctrl,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("ADC3_MIXER", SND_SOC_NOPM, 0, 0, adc3_switch,
			     ARRAY_SIZE(adc3_switch), wcd938x_tx_swr_ctrl,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("ADC4_MIXER", SND_SOC_NOPM, 0, 0, adc4_switch,
			     ARRAY_SIZE(adc4_switch), wcd938x_tx_swr_ctrl,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("DMIC1_MIXER", SND_SOC_NOPM, 0, 0, dmic1_switch,
			     ARRAY_SIZE(dmic1_switch), wcd938x_tx_swr_ctrl,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("DMIC2_MIXER", SND_SOC_NOPM, 0, 0, dmic2_switch,
			     ARRAY_SIZE(dmic2_switch), wcd938x_tx_swr_ctrl,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("DMIC3_MIXER", SND_SOC_NOPM, 0, 0, dmic3_switch,
			     ARRAY_SIZE(dmic3_switch), wcd938x_tx_swr_ctrl,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("DMIC4_MIXER", SND_SOC_NOPM, 0, 0, dmic4_switch,
			     ARRAY_SIZE(dmic4_switch), wcd938x_tx_swr_ctrl,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("DMIC5_MIXER", SND_SOC_NOPM, 0, 0, dmic5_switch,
			     ARRAY_SIZE(dmic5_switch), wcd938x_tx_swr_ctrl,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("DMIC6_MIXER", SND_SOC_NOPM, 0, 0, dmic6_switch,
			     ARRAY_SIZE(dmic6_switch), wcd938x_tx_swr_ctrl,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("DMIC7_MIXER", SND_SOC_NOPM, 0, 0, dmic7_switch,
			     ARRAY_SIZE(dmic7_switch), wcd938x_tx_swr_ctrl,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_MIXER_E("DMIC8_MIXER", SND_SOC_NOPM, 0, 0, dmic8_switch,
			     ARRAY_SIZE(dmic8_switch), wcd938x_tx_swr_ctrl,
			     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
	/* micbias widgets*/
	SND_SOC_DAPM_SUPPLY("MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0,
			    wcd938x_codec_enable_micbias,
			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
			    SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_SUPPLY("MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0,
			    wcd938x_codec_enable_micbias,
			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
			    SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_SUPPLY("MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0,
			    wcd938x_codec_enable_micbias,
			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
			    SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_SUPPLY("MIC BIAS4", SND_SOC_NOPM, MIC_BIAS_4, 0,
			    wcd938x_codec_enable_micbias,
			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
			    SND_SOC_DAPM_POST_PMD),

	/* micbias pull up widgets*/
	SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0,
				wcd938x_codec_enable_micbias_pullup,
				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
				SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_SUPPLY("VA MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0,
				wcd938x_codec_enable_micbias_pullup,
				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
				SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_SUPPLY("VA MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0,
				wcd938x_codec_enable_micbias_pullup,
				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
				SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_SUPPLY("VA MIC BIAS4", SND_SOC_NOPM, MIC_BIAS_4, 0,
				wcd938x_codec_enable_micbias_pullup,
				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
				SND_SOC_DAPM_POST_PMD),

	/*output widgets tx*/
	SND_SOC_DAPM_OUTPUT("ADC1_OUTPUT"),
	SND_SOC_DAPM_OUTPUT("ADC2_OUTPUT"),
	SND_SOC_DAPM_OUTPUT("ADC3_OUTPUT"),
	SND_SOC_DAPM_OUTPUT("ADC4_OUTPUT"),
	SND_SOC_DAPM_OUTPUT("DMIC1_OUTPUT"),
	SND_SOC_DAPM_OUTPUT("DMIC2_OUTPUT"),
	SND_SOC_DAPM_OUTPUT("DMIC3_OUTPUT"),
	SND_SOC_DAPM_OUTPUT("DMIC4_OUTPUT"),
	SND_SOC_DAPM_OUTPUT("DMIC5_OUTPUT"),
	SND_SOC_DAPM_OUTPUT("DMIC6_OUTPUT"),
	SND_SOC_DAPM_OUTPUT("DMIC7_OUTPUT"),
	SND_SOC_DAPM_OUTPUT("DMIC8_OUTPUT"),

	SND_SOC_DAPM_INPUT("IN1_HPHL"),
	SND_SOC_DAPM_INPUT("IN2_HPHR"),
	SND_SOC_DAPM_INPUT("IN3_AUX"),