Prechádzať zdrojové kódy

asoc: add sys_usage automatically update function for tambora

Add sys_usage automatically update function for tambora,
and remove sys_usage set kcontrol,
optimize ear/aux path check logic.

Change-Id: I06a4676e22f73156f7e2f394c98ab3879aa00cad
Signed-off-by: Yuhui Zhao <[email protected]>
Yuhui Zhao 1 rok pred
rodič
commit
1624212a65

+ 3 - 5
asoc/codecs/wcd9378/internal.h

@@ -65,13 +65,14 @@ enum {
 struct wcd9378_priv {
 	struct device *dev;
 	u32 sys_usage;
+	/* to track the sys_usage status */
+	unsigned long sys_usage_status;
 	u32 wcd_mode;
 
 	int variant;
 	struct snd_soc_component *component;
 	struct device_node *rst_np;
 	struct regmap *regmap;
-	bool sjmic_support;
 
 	struct swr_device *rx_swr_dev;
 	struct swr_device *tx_swr_dev;
@@ -86,6 +87,7 @@ struct wcd9378_priv {
 
 	struct mutex micb_lock;
 	struct mutex wakeup_lock;
+	struct mutex sys_usage_lock;
 	s32 dmic_0_1_clk_cnt;
 	s32 dmic_2_3_clk_cnt;
 	s32 dmic_4_5_clk_cnt;
@@ -103,8 +105,6 @@ struct wcd9378_priv {
 	s32 adc_count;
 	bool comp1_enable;
 	bool comp2_enable;
-	bool ear_enable;
-	bool aux_enable;
 	bool ldoh;
 	bool bcs_dis;
 	bool dapm_bias_off;
@@ -138,8 +138,6 @@ struct wcd9378_priv {
 	struct snd_info_entry *version_entry;
 	struct snd_info_entry *variant_entry;
 	int flyback_cur_det_disable;
-	int ear_rx_path;
-	int aux_rx_path;
 	bool dev_up;
 	u8 tx_master_ch_map[WCD9378_MAX_SLAVE_CH_TYPES];
 	bool usbc_hs_status;

+ 2 - 1
asoc/codecs/wcd9378/wcd9378-registers.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef WCD9378_REGISTERS_H
@@ -873,6 +873,7 @@ enum {
 #define WCD9378_TX_NEW_TX_CH34_MUX_CH3_SEL_SHIFT                          0x00
 #define WCD9378_CDC_HPH_GAIN_CTL_HPHR_RX_EN_SHIFT                         0x03
 #define WCD9378_CDC_HPH_GAIN_CTL_HPHL_RX_EN_SHIFT                         0x02
+#define WCD9378_CDC_AUX_GAIN_CTL_AUX_EN_SHIFT                             0x00
 
 #define SWRS_SCP_BASE_CLK_BASE                 (0x004d)
 #define SWRS_SCP_BUSCLOCK_SCALE_BANK0          (0x0062)

+ 297 - 188
asoc/codecs/wcd9378/wcd9378.c

@@ -32,8 +32,6 @@
 
 #define WCD9378_VERSION_1_0 1
 #define WCD9378_VERSION_ENTRY_SIZE 32
-#define EAR_RX_PATH_RX0 1
-#define AUX_RX_PATH_RX1 1
 
 #define SWR_BASECLK_19P2MHZ      (0x01)
 #define SWR_BASECLK_24P576MHZ    (0x03)
@@ -101,7 +99,6 @@
 	.put = wcd9378_aux_pa_put_gain, \
 	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
 
-
 enum {
 	CODEC_TX = 0,
 	CODEC_RX,
@@ -112,6 +109,22 @@ enum {
 	RX2_NORMAL_MODE,
 };
 
+enum {
+	CLASS_AB_EN = 0,
+	TX1_FOR_JACK,
+	TX2_AMIC4_EN,
+	TX2_AMIC1_EN,
+	TX1_AMIC3_EN,
+	TX1_AMIC2_EN,
+	TX0_AMIC2_EN,
+	TX0_AMIC1_EN,
+	RX2_EAR_EN,
+	RX2_AUX_EN,
+	RX1_AUX_EN,
+	RX0_EAR_EN,
+	RX0_RX1_HPH_EN,
+};
+
 enum {
 	WCD_ADC1 = 0,
 	WCD_ADC2,
@@ -130,25 +143,23 @@ enum {
 	WCD_EAR_EN,
 };
 
-
 enum {
-	NOSJ_SA_STEREO_3SM = 0,
-	SJ_SA_AUX_2SM,
-	NOSJ_SA_STEREO_3SM_1HDR,
-	SJ_SA_AUX_2SM_1HDR,
-	NOSJ_SA_EAR_3SM,
-	SJ_SA_EAR_2SM,
-	NOSJ_SA_EAR_3SM_1HDR,
-	SJ_SA_EAR_2SM_1HDR,
-	SJ_1HDR_SA_AUX_1SM,
-	SJ_1HDR_SA_EAR_1SM,
-	SJ_SA_STEREO_2SM,
-	SJ_NOMIC_SA_EAR_3SM,
-	SJ_NOMIC_SA_AUX_3SM,
-	WCD_SYS_USAGE_MAX,
+	SYS_USAGE_0,
+	SYS_USAGE_1,
+	SYS_USAGE_2,
+	SYS_USAGE_3,
+	SYS_USAGE_4,
+	SYS_USAGE_5,
+	SYS_USAGE_6,
+	SYS_USAGE_7,
+	SYS_USAGE_8,
+	SYS_USAGE_9,
+	SYS_USAGE_10,
+	SYS_USAGE_11,
+	SYS_USAGE_12,
+	SYS_USAGE_NUM,
 };
 
-
 enum {
 	NO_MICB_USED,
 	MICB1,
@@ -173,6 +184,29 @@ static int wcd9378_reset_low(struct device *dev);
 static int wcd9378_swr_slave_clk_set(struct device *dev, int bank, int path, bool enable);
 static void wcd9378_class_load(struct snd_soc_component *component);
 
+/* sys_usage:
+ * rx0_rx1_hph_en,
+ * rx0_ear_en, rx1_aux_en, rx2_aux_en, rx2_ear_en,
+ * tx0_amic1_en, tx0_amic2_en, tx1_amic2_en, tx1_amic3_en,
+ * tx2_amic1_en, tx2_amic4_en, tx1_for_jack, class_ab_en;
+ */
+static const int sys_usage[SYS_USAGE_NUM] = {
+	[SYS_USAGE_0]         = 0x0c95,        /*0b0 1100 1001 0101*/
+	[SYS_USAGE_1]         = 0x12a7,        /*0b1 0010 1010 0111*/
+	[SYS_USAGE_2]         = 0x0c99,        /*0b0 1100 1001 1001*/
+	[SYS_USAGE_3]         = 0x1aab,        /*0b1 1010 1010 1011*/
+	[SYS_USAGE_4]         = 0x0894,        /*0b0 1000 1001 0100*/
+	[SYS_USAGE_5]         = 0x11a6,        /*0b1 0001 1010 0110*/
+	[SYS_USAGE_6]         = 0x0898,        /*0b0 1000 1001 1000*/
+	[SYS_USAGE_7]         = 0x11ab,        /*0b1 0001 1010 1011*/
+	[SYS_USAGE_8]         = 0x126a,        /*0b1 0010 0110 1010*/
+	[SYS_USAGE_9]         = 0x116b,        /*0b1 0001 0110 1011*/
+	[SYS_USAGE_10]        = 0x1ca7,        /*0b1 1100 1010 0111*/
+	[SYS_USAGE_11]        = 0x1195,        /*0b1 0001 1001 0101*/
+	[SYS_USAGE_12]        = 0x1296,        /*0b1 0010 1001 0101*/
+};
+
+
 static const struct regmap_irq wcd9378_regmap_irqs[WCD9378_NUM_IRQS] = {
 	REGMAP_IRQ_REG(WCD9378_IRQ_MBHC_BUTTON_PRESS_DET, 0, 0x01),
 	REGMAP_IRQ_REG(WCD9378_IRQ_MBHC_BUTTON_RELEASE_DET, 0, 0x02),
@@ -240,6 +274,8 @@ static int wcd9378_swr_slv_get_current_bank(struct swr_device *dev, u8 devnum)
 
 static int wcd9378_init_reg(struct snd_soc_component *component)
 {
+	struct wcd9378_priv *wcd9378 =
+			snd_soc_component_get_drvdata(component);
 	u32 val = 0;
 
 	val = snd_soc_component_read(component, WCD9378_EFUSE_REG_16);
@@ -339,13 +375,20 @@ static int wcd9378_init_reg(struct snd_soc_component *component)
 	/*SM0 MB SEL:MB1*/
 	snd_soc_component_update_bits(component, WCD9378_SM0_MB_SEL,
 			WCD9378_SM0_MB_SEL_SM0_MB_SEL_MASK, 0x01);
-	/*SM0 MB SEL:MB2*/
+	/*SM1 MB SEL:MB2*/
 	snd_soc_component_update_bits(component, WCD9378_SM1_MB_SEL,
 			WCD9378_SM1_MB_SEL_SM1_MB_SEL_MASK, 0x02);
-	/*SM0 MB SEL:MB3*/
+	/*SM2 MB SEL:MB3*/
 	snd_soc_component_update_bits(component, WCD9378_SM2_MB_SEL,
 			WCD9378_SM2_MB_SEL_SM2_MB_SEL_MASK, 0x03);
 
+	/*INIT SYS_USAGE*/
+	snd_soc_component_update_bits(component,
+		WCD9378_SYS_USAGE_CTRL,
+		WCD9378_SYS_USAGE_CTRL_SYS_USAGE_CTRL_MASK,
+		0);
+	wcd9378->sys_usage = 0;
+
 	wcd9378_class_load(component);
 	return 0;
 }
@@ -937,6 +980,150 @@ static int wcd9378_get_adc_mode_val(int mode)
 	return ret;
 }
 
+
+static int wcd9378_sys_usage_auto_udpate(struct snd_soc_component *component,
+					int sys_usage_bit, bool set_enable)
+{
+	struct wcd9378_priv *wcd9378 =
+			snd_soc_component_get_drvdata(component);
+	int i = 0;
+
+	dev_dbg(component->dev,
+		"%s: enter, current sys_usage: %d, sys_usage_status: 0x%x, sys_usage_bit: %d, set_enable: %d\n",
+			__func__, wcd9378->sys_usage,
+			wcd9378->sys_usage_status,
+			sys_usage_bit, set_enable);
+
+	mutex_lock(&wcd9378->sys_usage_lock);
+	if (set_enable) {
+		set_bit(sys_usage_bit, &wcd9378->sys_usage_status);
+
+		if ((sys_usage[wcd9378->sys_usage] &
+			wcd9378->sys_usage_status) == wcd9378->sys_usage_status)
+			goto exit;
+
+		for (i = 0; i < SYS_USAGE_NUM; i++) {
+			if ((sys_usage[i] & wcd9378->sys_usage_status)
+					== wcd9378->sys_usage_status) {
+				snd_soc_component_update_bits(component,
+					WCD9378_SYS_USAGE_CTRL,
+					WCD9378_SYS_USAGE_CTRL_SYS_USAGE_CTRL_MASK,
+					i);
+				wcd9378->sys_usage = i;
+				dev_dbg(component->dev, "%s: update sys_usage: %d\n",
+						__func__, wcd9378->sys_usage);
+				goto exit;
+			}
+		}
+
+		dev_dbg(component->dev, "%s: cannot find sys_usage\n",
+				__func__);
+	} else {
+		clear_bit(sys_usage_bit, &wcd9378->sys_usage_status);
+	}
+exit:
+	mutex_unlock(&wcd9378->sys_usage_lock);
+	return 0;
+}
+
+static int wcd9378_sys_usage_bit_get(
+		struct snd_soc_component *component, u32 w_shift,
+		int *sys_usage_bit, int event)
+{
+	struct wcd9378_priv *wcd9378 =
+			snd_soc_component_get_drvdata(component);
+
+	dev_dbg(component->dev, "%s: wshift: %d event: %d\n", __func__,
+			w_shift, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		switch (w_shift) {
+		case ADC1:
+			if ((snd_soc_component_read(component,
+					WCD9378_TX_NEW_TX_CH12_MUX) &
+					WCD9378_TX_NEW_TX_CH12_MUX_CH1_SEL_MASK) == 0x01) {
+				*sys_usage_bit = TX0_AMIC1_EN;
+			} else if ((snd_soc_component_read(component,
+					WCD9378_TX_NEW_TX_CH12_MUX) &
+					WCD9378_TX_NEW_TX_CH12_MUX_CH1_SEL_MASK) == 0x02) {
+				*sys_usage_bit = TX0_AMIC2_EN;
+			} else {
+				dev_err(component->dev, "%s: unsupport usecase, pls check\n",
+						__func__);
+				return -EINVAL;
+			}
+			break;
+		case ADC2:
+			if ((snd_soc_component_read(component,
+					WCD9378_TX_NEW_TX_CH12_MUX) &
+					WCD9378_TX_NEW_TX_CH12_MUX_CH2_SEL_MASK) == 0x10) {
+				*sys_usage_bit = TX1_AMIC2_EN;
+			} else if ((snd_soc_component_read(component,
+					WCD9378_TX_NEW_TX_CH12_MUX) &
+					WCD9378_TX_NEW_TX_CH12_MUX_CH2_SEL_MASK) == 0x18) {
+				*sys_usage_bit = TX1_AMIC3_EN;
+			} else {
+				dev_err(component->dev, "%s: unsupport usecase, pls check\n",
+						__func__);
+				return -EINVAL;
+			}
+			break;
+		case ADC3:
+			if ((snd_soc_component_read(component,
+					WCD9378_TX_NEW_TX_CH34_MUX) &
+					WCD9378_TX_NEW_TX_CH34_MUX_CH3_SEL_SHIFT) == 0x01) {
+				*sys_usage_bit = TX2_AMIC1_EN;
+			} else if ((snd_soc_component_read(component,
+					WCD9378_TX_NEW_TX_CH34_MUX) &
+					WCD9378_TX_NEW_TX_CH34_MUX_CH3_SEL_SHIFT) == 0x03) {
+				*sys_usage_bit = TX2_AMIC4_EN;
+			} else {
+				dev_err(component->dev, "%s: unsupport usecase, pls check\n",
+						__func__);
+				return -EINVAL;
+			}
+			break;
+		default:
+			break;
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		switch (w_shift) {
+		case ADC1:
+			if (test_bit(TX0_AMIC1_EN, &wcd9378->sys_usage_status))
+				*sys_usage_bit = TX0_AMIC1_EN;
+
+			if (test_bit(TX0_AMIC2_EN, &wcd9378->sys_usage_status))
+				*sys_usage_bit = TX0_AMIC2_EN;
+			break;
+		case ADC2:
+			if (test_bit(TX1_AMIC2_EN, &wcd9378->sys_usage_status))
+				*sys_usage_bit = TX1_AMIC2_EN;
+
+			if (test_bit(TX1_AMIC3_EN, &wcd9378->sys_usage_status))
+				*sys_usage_bit = TX1_AMIC3_EN;
+			break;
+		case ADC3:
+			if (test_bit(TX2_AMIC1_EN, &wcd9378->sys_usage_status))
+				*sys_usage_bit = TX2_AMIC1_EN;
+
+			if (test_bit(TX2_AMIC4_EN, &wcd9378->sys_usage_status))
+				*sys_usage_bit = TX2_AMIC4_EN;
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	dev_dbg(component->dev, "%s: done, event: %d, sys_usage_bit: %d\n",
+			__func__, event, *sys_usage_bit);
+	return 0;
+}
+
 static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 			       struct snd_kcontrol *kcontrol, int event)
 {
@@ -944,7 +1131,7 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 	struct wcd9378_priv *wcd9378 =
 				snd_soc_component_get_drvdata(component);
 	int mode_val = 0, bank = 0, ret = 0, rate = 0;
-	int act_ps = 0;
+	int act_ps = 0, sys_usage_bit = 0;
 
 	bank = (wcd9378_swr_slv_get_current_bank(wcd9378->tx_swr_dev,
 		wcd9378->tx_swr_dev->dev_num) ? 0 : 1);
@@ -952,8 +1139,15 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 	dev_dbg(component->dev, "%s wname: %s wshift: %d event: %d\n", __func__,
 		w->name, w->shift, event);
 
+	ret = wcd9378_sys_usage_bit_get(component, w->shift, &sys_usage_bit, event);
+	if (ret < 0)
+		return ret;
+
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
+		/*Update sys_usage*/
+		wcd9378_sys_usage_auto_udpate(component, sys_usage_bit, true);
+
 		mode_val = wcd9378_get_adc_mode_val(wcd9378->tx_mode[w->shift - ADC1]);
 		if (mode_val < 0) {
 			dev_dbg(component->dev,
@@ -990,10 +1184,12 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 			/*Power up TX0 sequencer*/
 			snd_soc_component_update_bits(component, WCD9378_PDE11_REQ_PS,
 					WCD9378_PDE11_REQ_PS_PDE11_REQ_PS_MASK, 0x00);
-
 			break;
 		case ADC2:
-			if (wcd9378->sjmic_support) {
+			/*Check if amic2 is connected to ADC2 MUX*/
+			if ((snd_soc_component_read(component,
+					WCD9378_TX_NEW_TX_CH12_MUX) &
+					WCD9378_TX_NEW_TX_CH12_MUX_CH2_SEL_MASK) == 0x10) {
 				/*SMP JACK IT31 USAGE SET*/
 				snd_soc_component_update_bits(component,
 						WCD9378_IT31_USAGE,
@@ -1003,7 +1199,6 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 						WCD9378_PDE34_REQ_PS,
 						WCD9378_PDE34_REQ_PS_PDE34_REQ_PS_MASK, 0x00);
 			} else {
-				/*SMP MIC1 IT11 USAGE SET*/
 				snd_soc_component_update_bits(component,
 						WCD9378_SMP_MIC_CTRL1_IT11_USAGE,
 						WCD9378_SMP_MIC_CTRL1_IT11_USAGE_IT11_USAGE_MASK,
@@ -1064,7 +1259,7 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 			snd_soc_component_update_bits(component, WCD9378_ANA_TX_CH2,
 						WCD9378_ANA_TX_CH2_HPF2_INIT_MASK, 0x00);
 
-			if (wcd9378->sjmic_support)
+			if (test_bit(TX1_AMIC2_EN, &wcd9378->sys_usage_status))
 				act_ps = snd_soc_component_read(component,
 							WCD9378_PDE34_ACT_PS);
 			else
@@ -1114,17 +1309,20 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 
 			break;
 		case ADC2:
-			/*tear down TX1 sequencer*/
-			snd_soc_component_update_bits(component, WCD9378_PDE34_REQ_PS,
-					WCD9378_PDE34_REQ_PS_PDE34_REQ_PS_MASK, 0x03);
+			if (test_bit(TX1_AMIC2_EN, &wcd9378->sys_usage_status))
+				/*tear down TX1 sequencer*/
+				snd_soc_component_update_bits(component, WCD9378_PDE34_REQ_PS,
+						WCD9378_PDE34_REQ_PS_PDE34_REQ_PS_MASK, 0x03);
 
-			/*Normal TXFE Startup*/
-			snd_soc_component_update_bits(component, WCD9378_ANA_TX_CH2,
-					WCD9378_ANA_TX_CH2_HPF1_INIT_MASK, 0x00);
+			if (test_bit(TX1_AMIC3_EN, &wcd9378->sys_usage_status)) {
+				/*Normal TXFE Startup*/
+				snd_soc_component_update_bits(component, WCD9378_ANA_TX_CH2,
+						WCD9378_ANA_TX_CH2_HPF1_INIT_MASK, 0x00);
 
-			/*tear down TX1 sequencer*/
-			snd_soc_component_update_bits(component, WCD9378_PDE11_REQ_PS,
-					WCD9378_PDE11_REQ_PS_PDE11_REQ_PS_MASK, 0x03);
+				/*tear down TX1 sequencer*/
+				snd_soc_component_update_bits(component, WCD9378_PDE11_REQ_PS,
+						WCD9378_PDE11_REQ_PS_PDE11_REQ_PS_MASK, 0x03);
+			}
 			break;
 		case ADC3:
 			/*Normal TXFE Startup*/
@@ -1147,6 +1345,8 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 				false);
 		wcd9378_swr_slave_clk_set(wcd9378->dev, bank, TX_PATH, false);
 
+		/*Disable sys_usage_status*/
+		wcd9378_sys_usage_auto_udpate(component, sys_usage_bit, false);
 		break;
 	default:
 		break;
@@ -1512,12 +1712,7 @@ static int wcd9378_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
 
 		wcd9378_swr_slave_clk_set(wcd9378->dev, !bank, RX_PATH, true);
 
-		wcd9378->aux_rx_path =
-			(snd_soc_component_read(
-				component, WCD9378_CDC_HPH_GAIN_CTL) &
-					WCD9378_CDC_HPH_GAIN_CTL_HPHR_RX_EN_MASK) >> 0x03;
-
-		if (wcd9378->aux_rx_path & AUX_RX_PATH_RX1) {
+		if (test_bit(RX1_AUX_EN, &wcd9378->sys_usage_status)) {
 			if (wcd9378->update_wcd_event)
 				wcd9378->update_wcd_event(wcd9378->handle,
 							SLV_BOLERO_EVT_RX_MUTE,
@@ -1539,7 +1734,7 @@ static int wcd9378_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
 							__func__, act_ps);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		if (wcd9378->aux_rx_path & AUX_RX_PATH_RX1) {
+		if (test_bit(RX1_AUX_EN, &wcd9378->sys_usage_status)) {
 			if (wcd9378->update_wcd_event)
 				wcd9378->update_wcd_event(wcd9378->handle,
 							SLV_BOLERO_EVT_RX_MUTE,
@@ -1581,12 +1776,7 @@ static int wcd9378_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
 
 		wcd9378_swr_slave_clk_set(wcd9378->dev, !bank, RX_PATH, true);
 
-		wcd9378->ear_rx_path =
-			(snd_soc_component_read(
-				component, WCD9378_CDC_HPH_GAIN_CTL) &
-					WCD9378_CDC_HPH_GAIN_CTL_HPHL_RX_EN_MASK) >> 0x02;
-
-		if (wcd9378->ear_rx_path & EAR_RX_PATH_RX0) {
+		if (test_bit(RX0_EAR_EN, &wcd9378->sys_usage_status)) {
 			if (wcd9378->update_wcd_event)
 				wcd9378->update_wcd_event(wcd9378->handle,
 						SLV_BOLERO_EVT_RX_MUTE,
@@ -1608,7 +1798,7 @@ static int wcd9378_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
 
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		if (wcd9378->ear_rx_path & EAR_RX_PATH_RX0) {
+		if (test_bit(RX0_EAR_EN, &wcd9378->sys_usage_status)) {
 			if (wcd9378->update_wcd_event)
 				wcd9378->update_wcd_event(wcd9378->handle,
 						SLV_BOLERO_EVT_RX_MUTE,
@@ -1731,6 +1921,8 @@ static int wcd9378_hph_sequencer_enable(struct snd_soc_dapm_widget *w,
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
+		wcd9378_sys_usage_auto_udpate(component, RX0_RX1_HPH_EN, true);
+
 		if ((!wcd9378->comp1_enable) || (!wcd9378->comp2_enable)) {
 			snd_soc_component_update_bits(component, WCD9378_HPH_UP_T7,
 				WCD9378_HPH_UP_T7_HPH_UP_T7_MASK, 0x07);
@@ -1775,6 +1967,11 @@ static int wcd9378_hph_sequencer_enable(struct snd_soc_dapm_widget *w,
 		snd_soc_component_update_bits(component, WCD9378_FU42_MUTE_CH2,
 				WCD9378_FU42_MUTE_CH2_FU42_MUTE_CH2_MASK, 0x00);
 
+		if (wcd9378->sys_usage == SYS_USAGE_10)
+			/*FU23 UNMUTE*/
+			snd_soc_component_update_bits(component, WCD9378_FU23_MUTE,
+					WCD9378_FU23_MUTE_FU23_MUTE_MASK, 0x00);
+
 		swr_write(swr_dev, swr_dev->dev_num, 0x004c, &scp_commit_val);
 
 		wcd9378_swr_slave_clk_set(wcd9378->dev, bank, RX_PATH, true);
@@ -1803,6 +2000,8 @@ static int wcd9378_hph_sequencer_enable(struct snd_soc_dapm_widget *w,
 		else
 			/*COMP delay is 11250us*/
 			usleep_range(11300, 11310);
+
+		wcd9378_sys_usage_auto_udpate(component, RX0_RX1_HPH_EN, false);
 		break;
 	default:
 		break;
@@ -1817,19 +2016,30 @@ static int wcd9378_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
 {
 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 	struct wcd9378_priv *wcd9378 = snd_soc_component_get_drvdata(component);
-	int ear_rx0 = 0;
+	int ear_rx2 = 0;
 
 	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
 		w->name, event);
 
-	ear_rx0 = snd_soc_component_read(component, WCD9378_CDC_HPH_GAIN_CTL) &
-				WCD9378_CDC_HPH_GAIN_CTL_HPHL_RX_EN_MASK;
+	ear_rx2 = snd_soc_component_read(component, WCD9378_CDC_AUX_GAIN_CTL) &
+				WCD9378_CDC_AUX_GAIN_CTL_AUX_EN_MASK;
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		/*CHECK IF EAR CONNET TO RX2*/
-		if (!ear_rx0) {
-			pr_debug("%s: ear rx2 enter\n", __func__);
+		if (!ear_rx2) {
+			/*RX0 ENABLE*/
+			snd_soc_component_update_bits(component, WCD9378_CDC_HPH_GAIN_CTL,
+				WCD9378_CDC_HPH_GAIN_CTL_HPHL_RX_EN_MASK, 0x04);
+
+			wcd9378_sys_usage_auto_udpate(component, RX0_EAR_EN, true);
+			if (wcd9378->comp1_enable) {
+				snd_soc_component_update_bits(component, WCD9378_CDC_COMP_CTL_0,
+					WCD9378_CDC_COMP_CTL_0_EAR_COMP_EN_MASK, 0x04);
+				wcd9378_rx_connect_port(component, COMP_L, true);
+			}
+			wcd9378_rx_connect_port(component, HPH_L, true);
+		} else {
+			wcd9378_sys_usage_auto_udpate(component, RX2_EAR_EN, true);
 			/*FORCE CLASS_AB EN*/
 			snd_soc_component_update_bits(component, WCD9378_SEQ_OVRRIDE_CTL0,
 				WCD9378_SEQ_OVRRIDE_CTL0_CLASSAB_EN_OVR_MASK, 0x20);
@@ -1837,29 +2047,15 @@ static int wcd9378_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
 			snd_soc_component_update_bits(component, WCD9378_CP_CP_DTOP_CTRL_14,
 				WCD9378_CP_CP_DTOP_CTRL_14_OVERRIDE_VREF_MASK, 0x80);
 
-			/*RX2 ENABLE*/
-			snd_soc_component_update_bits(component, WCD9378_CDC_AUX_GAIN_CTL,
-					WCD9378_CDC_AUX_GAIN_CTL_AUX_EN_MASK, 0x01);
-
 			if (wcd9378->rx2_clk_mode)
 				snd_soc_component_update_bits(component, WCD9378_CDC_PATH_MODE,
 					WCD9378_CDC_PATH_MODE_RX2_CLK_RATE_MASK, 0x40);
 
 			wcd9378_rx_connect_port(component, LO, true);
-		} else {
-			pr_debug("%s: ear rx0 enter\n", __func__);
-			if (wcd9378->comp1_enable) {
-				snd_soc_component_update_bits(component, WCD9378_CDC_COMP_CTL_0,
-					WCD9378_CDC_COMP_CTL_0_EAR_COMP_EN_MASK, 0x04);
-				wcd9378_rx_connect_port(component, COMP_L, true);
-			}
-
-			wcd9378_rx_connect_port(component, HPH_L, true);
 		}
-
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		if (ear_rx0) {
+		if (test_bit(RX0_EAR_EN, &wcd9378->sys_usage_status)) {
 			/*RX0 DISABLE*/
 			snd_soc_component_update_bits(component, WCD9378_CDC_HPH_GAIN_CTL,
 				WCD9378_CDC_HPH_GAIN_CTL_HPHL_RX_EN_MASK, 0x00);
@@ -1870,18 +2066,16 @@ static int wcd9378_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
 					WCD9378_CDC_COMP_CTL_0_EAR_COMP_EN_MASK, 0x00);
 				wcd9378_rx_connect_port(component, COMP_L, false);
 			}
-		} else {
-			/*RX1 DISABLE*/
-			snd_soc_component_update_bits(component, WCD9378_CDC_AUX_GAIN_CTL,
-					WCD9378_CDC_AUX_GAIN_CTL_AUX_EN_MASK, 0x00);
 
+			wcd9378_sys_usage_auto_udpate(component, RX0_EAR_EN, false);
+		} else {
 			wcd9378_rx_connect_port(component, LO, false);
+			wcd9378_sys_usage_auto_udpate(component, RX2_EAR_EN, false);
 		}
-
 		break;
 	};
-	return 0;
 
+	return 0;
 }
 
 static int wcd9378_codec_aux_dac_event(struct snd_soc_dapm_widget *w,
@@ -1890,22 +2084,25 @@ static int wcd9378_codec_aux_dac_event(struct snd_soc_dapm_widget *w,
 {
 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 	struct wcd9378_priv *wcd9378 = snd_soc_component_get_drvdata(component);
-	int aux_rx1 = 0;
+	int aux_rx2 = 0;
 
 	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
 		w->name, event);
 
-	aux_rx1 = snd_soc_component_read(component, WCD9378_CDC_HPH_GAIN_CTL) &
-				WCD9378_CDC_HPH_GAIN_CTL_HPHR_RX_EN_MASK;
+	aux_rx2 = snd_soc_component_read(component, WCD9378_CDC_AUX_GAIN_CTL) &
+					WCD9378_CDC_AUX_GAIN_CTL_AUX_EN_MASK;
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		if (aux_rx1) {
+		if (!aux_rx2) {
+			/*RX1 ENABLE*/
+			snd_soc_component_update_bits(component, WCD9378_CDC_HPH_GAIN_CTL,
+					WCD9378_CDC_HPH_GAIN_CTL_HPHR_RX_EN_MASK, 0x08);
+
+			wcd9378_sys_usage_auto_udpate(component, RX1_AUX_EN, true);
 			wcd9378_rx_connect_port(component, HPH_R, true);
 		} else {
-			/*RX2 ENABLE*/
-			snd_soc_component_update_bits(component, WCD9378_CDC_AUX_GAIN_CTL,
-					WCD9378_CDC_AUX_GAIN_CTL_AUX_EN_MASK, 0x01);
+			wcd9378_sys_usage_auto_udpate(component, RX2_AUX_EN, true);
 
 			if (wcd9378->rx2_clk_mode)
 				snd_soc_component_update_bits(component, WCD9378_CDC_PATH_MODE,
@@ -1915,17 +2112,17 @@ static int wcd9378_codec_aux_dac_event(struct snd_soc_dapm_widget *w,
 		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		if (aux_rx1) {
+		if (test_bit(RX1_AUX_EN, &wcd9378->sys_usage_status)) {
 			wcd9378_rx_connect_port(component, HPH_R, false);
+			wcd9378_sys_usage_auto_udpate(component, RX1_AUX_EN, false);
 		} else {
-			snd_soc_component_update_bits(component, WCD9378_CDC_AUX_GAIN_CTL,
-					WCD9378_CDC_AUX_GAIN_CTL_AUX_EN_MASK, 0x00);
-			wcd9378_rx_connect_port(component, LO, false);
+			wcd9378_rx_connect_port(component, LO, true);
+			wcd9378_sys_usage_auto_udpate(component, RX2_AUX_EN, false);
 		}
 		break;
 	};
-	return 0;
 
+	return 0;
 }
 
 static int wcd9378_sa_sequencer_enable(struct snd_soc_dapm_widget *w,
@@ -1948,7 +2145,6 @@ static int wcd9378_sa_sequencer_enable(struct snd_soc_dapm_widget *w,
 		/*FU23 UNMUTE*/
 		snd_soc_component_update_bits(component, WCD9378_FU23_MUTE,
 				WCD9378_FU23_MUTE_FU23_MUTE_MASK, 0x00);
-
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		/*FU23 MUTE*/
@@ -2045,7 +2241,7 @@ int wcd9378_micbias_control(struct snd_soc_component *component,
 			wcd9378->pullup_ref[micb_index]--;
 
 		if ((wcd9378->pullup_ref[micb_index] == 0) &&
-			    (wcd9378->micb_ref[micb_index] == 0))
+			    (wcd9378->micb_ref[micb_index] == 0)) {
 			snd_soc_component_update_bits(component, micb_usage, micb_mask, 0x01);
 
 			if (micb_num == MIC_BIAS_2) {
@@ -2445,82 +2641,6 @@ static int wcd9378_tx_mode_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static int wcd9378_sys_usage_get(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_component *component =
-			snd_soc_kcontrol_component(kcontrol);
-	u32 sys_usage_val = 0;
-
-	if (!component)
-		return -EINVAL;
-
-	sys_usage_val = (snd_soc_component_read(component, WCD9378_SYS_USAGE_CTRL) &
-				WCD9378_SYS_USAGE_CTRL_SYS_USAGE_CTRL_MASK);
-
-	ucontrol->value.integer.value[0] = sys_usage_val;
-	return 0;
-}
-
-static int wcd9378_sys_usage_put(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_component *component =
-			snd_soc_kcontrol_component(kcontrol);
-	struct wcd9378_priv *wcd9378 = NULL;
-	u32 sys_usage_val = 0;
-
-	if (!component)
-		return -EINVAL;
-
-	wcd9378  = snd_soc_component_get_drvdata(component);
-	if (!wcd9378)
-		return -EINVAL;
-
-	sys_usage_val = ucontrol->value.enumerated.item[0];
-	if (sys_usage_val >= WCD_SYS_USAGE_MAX) {
-		dev_err(component->dev, "%s: unsupport sys_usage_val: %d\n",
-			__func__, sys_usage_val);
-		return -EINVAL;
-	}
-
-	if (wcd9378->sys_usage != sys_usage_val)
-		snd_soc_component_update_bits(component,
-				WCD9378_SYS_USAGE_CTRL,
-				WCD9378_SYS_USAGE_CTRL_SYS_USAGE_CTRL_MASK,
-				sys_usage_val);
-
-	wcd9378->sys_usage = sys_usage_val;
-
-	switch (wcd9378->sys_usage) {
-	case SJ_SA_AUX_2SM:
-	case SJ_SA_AUX_2SM_1HDR:
-	case SJ_SA_EAR_2SM:
-	case SJ_SA_EAR_2SM_1HDR:
-	case SJ_1HDR_SA_AUX_1SM:
-	case SJ_1HDR_SA_EAR_1SM:
-		wcd9378->sjmic_support = true;
-		break;
-	case NOSJ_SA_STEREO_3SM:
-	case NOSJ_SA_STEREO_3SM_1HDR:
-	case NOSJ_SA_EAR_3SM:
-	case NOSJ_SA_EAR_3SM_1HDR:
-	case SJ_NOMIC_SA_EAR_3SM:
-	case SJ_NOMIC_SA_AUX_3SM:
-		wcd9378->sjmic_support = false;
-		break;
-	default:
-		dev_err(component->dev, "%s: unsupport sys_usage: %d\n",
-			__func__, wcd9378->sys_usage);
-		return -EINVAL;
-	}
-
-	dev_err(component->dev, "%s: sys_usage_val: %d, sjmic_support: %d\n",
-			__func__, wcd9378->sys_usage, wcd9378->sjmic_support);
-
-	return 0;
-}
-
 static int wcd9378_loopback_mode_get(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
@@ -3003,17 +3123,6 @@ static int wcd9378_bcs_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static const char * const sys_usage_text[] = {
-	"NOSJ_SA_STEREO_3SM", "SJ_SA_AUX_2SM", "NOSJ_SA_STEREO_3SM_1HDR",
-	"SJ_SA_AUX_2SM_1HDR", "NOSJ_SA_EAR_3SM", "SJ_SA_EAR_2SM", "NOSJ_SA_EAR_3SM_1HDR",
-	"SJ_SA_EAR_2SM_1HDR", "SJ_1HDR_SA_AUX_1SM", "SJ_1HDR_SA_EAR_1SM",
-	"SJ_SA_STEREO_2SM", "SJ_NOMIC_SA_EAR_3SM", "SJ_NOMIC_SA_AUX_3SM",
-};
-
-static const struct soc_enum sys_usage_enum =
-	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sys_usage_text),
-			    sys_usage_text);
-
 static const char * const loopback_mode_text[] = {
 	"NO_LP", "SWR_LP1", "SWR_LP2", "SWR_LP3",
 };
@@ -3071,9 +3180,6 @@ static const struct snd_kcontrol_new wcd9378_snd_controls[] = {
 	SOC_SINGLE_EXT("ADC2_BCS Disable", SND_SOC_NOPM, 0, 1, 0,
 		wcd9378_bcs_get, wcd9378_bcs_put),
 
-	SOC_ENUM_EXT("SYS_USAGE Mode", sys_usage_enum,
-		     wcd9378_sys_usage_get, wcd9378_sys_usage_put),
-
 	SOC_ENUM_EXT("LOOPBACK Mode", loopback_mode_enum,
 		     wcd9378_loopback_mode_get, wcd9378_loopback_mode_put),
 	SOC_ENUM_EXT("AUX_LB_IN SEL", aux_dsm_enum,
@@ -3194,15 +3300,15 @@ static const char * const adc2_mux_text[] = {
 };
 
 static const char * const adc3_mux_text[] = {
-	"CH3_AMIC_DISABLE", "CH3_AMIC1", "CH3_AMIC2", "CH3_AMIC3", "CH3_AMIC4"
+	"CH3_AMIC_DISABLE", "CH3_AMIC1", "CH3_AMIC3", "CH3_AMIC4"
 };
 
 static const char * const ear_mux_text[] = {
-	"RX2", "RX0"
+	"RX0", "RX2"
 };
 
 static const char * const aux_mux_text[] = {
-	"RX2", "RX1"
+	"RX1", "RX2"
 };
 
 static const struct soc_enum adc1_enum =
@@ -3221,13 +3327,13 @@ static const struct soc_enum adc3_enum =
 				ARRAY_SIZE(adc3_mux_text), adc3_mux_text);
 
 static const struct soc_enum ear_enum =
-		SOC_ENUM_SINGLE(WCD9378_CDC_HPH_GAIN_CTL,
-				WCD9378_CDC_HPH_GAIN_CTL_HPHL_RX_EN_SHIFT,
+		SOC_ENUM_SINGLE(WCD9378_CDC_AUX_GAIN_CTL,
+				WCD9378_CDC_AUX_GAIN_CTL_AUX_EN_SHIFT,
 				ARRAY_SIZE(ear_mux_text), ear_mux_text);
 
 static const struct soc_enum aux_enum =
-		SOC_ENUM_SINGLE(WCD9378_CDC_HPH_GAIN_CTL,
-				WCD9378_CDC_HPH_GAIN_CTL_HPHR_RX_EN_SHIFT,
+		SOC_ENUM_SINGLE(WCD9378_CDC_AUX_GAIN_CTL,
+				WCD9378_CDC_AUX_GAIN_CTL_AUX_EN_SHIFT,
 				ARRAY_SIZE(aux_mux_text), aux_mux_text);
 
 static const struct snd_kcontrol_new tx_adc1_mux =
@@ -3505,7 +3611,6 @@ static const struct snd_soc_dapm_route wcd9378_audio_map[] = {
 	{"ADC3_OUTPUT", NULL, "TX2 SEQUENCER"},
 	{"TX2 SEQUENCER", NULL, "ADC3 MUX"},
 	{"ADC3 MUX", "CH3_AMIC1", "AMIC1_MIXER"},
-	{"ADC3 MUX", "CH3_AMIC2", "AMIC2_MIXER"},
 	{"ADC3 MUX", "CH3_AMIC3", "AMIC3_MIXER"},
 	{"ADC3 MUX", "CH3_AMIC4", "AMIC4_MIXER"},
 
@@ -3842,6 +3947,7 @@ static int wcd9378_soc_codec_probe(struct snd_soc_component *component)
 			return ret;
 		}
 	}
+
 exit:
 	return ret;
 }
@@ -4327,6 +4433,7 @@ static int wcd9378_probe(struct platform_device *pdev)
 
 	mutex_init(&wcd9378->wakeup_lock);
 	mutex_init(&wcd9378->micb_lock);
+	mutex_init(&wcd9378->sys_usage_lock);
 	ret = wcd9378_add_slave_components(dev, &match);
 	if (ret)
 		goto err_lock_init;
@@ -4345,6 +4452,7 @@ static int wcd9378_probe(struct platform_device *pdev)
 err_lock_init:
 	mutex_destroy(&wcd9378->micb_lock);
 	mutex_destroy(&wcd9378->wakeup_lock);
+	mutex_destroy(&wcd9378->sys_usage_lock);
 err:
 	return ret;
 }
@@ -4357,6 +4465,7 @@ static int wcd9378_remove(struct platform_device *pdev)
 	component_master_del(&pdev->dev, &wcd9378_comp_ops);
 	mutex_destroy(&wcd9378->micb_lock);
 	mutex_destroy(&wcd9378->wakeup_lock);
+	mutex_destroy(&wcd9378->sys_usage_lock);
 	dev_set_drvdata(&pdev->dev, NULL);
 
 	return 0;