diff --git a/asoc/codecs/wcd9378/internal.h b/asoc/codecs/wcd9378/internal.h index e9161837cd..cbee1b0ae8 100644 --- a/asoc/codecs/wcd9378/internal.h +++ b/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; diff --git a/asoc/codecs/wcd9378/wcd9378-registers.h b/asoc/codecs/wcd9378/wcd9378-registers.h index 001e317c62..91dfa80ab8 100644 --- a/asoc/codecs/wcd9378/wcd9378-registers.h +++ b/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) diff --git a/asoc/codecs/wcd9378/wcd9378.c b/asoc/codecs/wcd9378/wcd9378.c index a3bd0c9e81..f2848b8c86 100644 --- a/asoc/codecs/wcd9378/wcd9378.c +++ b/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); } + + wcd9378_sys_usage_auto_udpate(component, RX0_EAR_EN, 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_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;