mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-11-01 02:21:16 +00:00
ASoC: changes to fix codec nack issue
This change fixes codec HW issues, Slimbus master capability issue and codec NACK issues caused due to SIDO buck going down abruptly. Change-Id: I74e94630b2ba4c132d66315ceee5127e05f284c6 Signed-off-by: Yeleswarapu Nagaradhesh <nagaradh@codeaurora.org>
This commit is contained in:
parent
da26ec31d0
commit
07c2b1c579
8 changed files with 951 additions and 364 deletions
|
@ -1566,20 +1566,19 @@ static bool wcd9335_is_volatile_register(struct device *dev, unsigned int reg)
|
|||
case WCD9335_ANA_MBHC_ZDET:
|
||||
case WCD9335_ANA_MICB2:
|
||||
case WCD9335_CPE_SS_SS_ERROR_INT_STATUS:
|
||||
case WCD9335_CPE_SS_SS_ERROR_INT_MASK:
|
||||
case WCD9335_CPE_SS_SS_ERROR_INT_CLEAR:
|
||||
case WCD9335_CPE_SS_STATUS:
|
||||
case WCD9335_CPE_SS_BACKUP_INT:
|
||||
case WCD9335_FLYBACK_EN:
|
||||
case WCD9335_ANA_RX_SUPPLIES:
|
||||
case WCD9335_CPE_SS_CFG:
|
||||
case WCD9335_SOC_MAD_MAIN_CTL_1:
|
||||
case WCD9335_SOC_MAD_AUDIO_CTL_3:
|
||||
case WCD9335_SOC_MAD_AUDIO_CTL_4:
|
||||
case WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT10:
|
||||
case WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT11:
|
||||
case WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT12:
|
||||
case WCD9335_VBADC_ADC_DOUTMSB:
|
||||
case WCD9335_VBADC_ADC_DOUTLSB:
|
||||
case WCD9335_CDC_VBAT_VBAT_GAIN_MON_VAL:
|
||||
case WCD9335_FLYBACK_EN:
|
||||
case WCD9335_ANA_RX_SUPPLIES:
|
||||
case WCD9335_CDC_CLK_RST_CTRL_FS_CNT_CONTROL:
|
||||
case WCD9335_SIDO_SIDO_CCL_2:
|
||||
case WCD9335_SIDO_SIDO_CCL_4:
|
||||
case WCD9335_DATA_HUB_NATIVE_FIFO_STATUS:
|
||||
case WCD9335_MBHC_FSM_STATUS:
|
||||
case WCD9335_SPLINE_SRC0_STATUS:
|
||||
|
@ -1589,6 +1588,9 @@ static bool wcd9335_is_volatile_register(struct device *dev, unsigned int reg)
|
|||
case WCD9335_SIDO_SIDO_TEST_2:
|
||||
case WCD9335_SIDO_SIDO_CCL_8:
|
||||
case WCD9335_BIAS_VBG_FINE_ADJ:
|
||||
case WCD9335_VBADC_ADC_DOUTMSB:
|
||||
case WCD9335_VBADC_ADC_DOUTLSB:
|
||||
case WCD9335_CDC_VBAT_VBAT_GAIN_MON_VAL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -330,4 +330,9 @@
|
|||
#define WCD9XXX_A_ANA_HPH (0x609)
|
||||
#define WCD9XXX_A_CDC_CLSH_CRC (0xC01)
|
||||
#define WCD9XXX_FLYBACK_EN (0x6A4)
|
||||
#define WCD9XXX_RX_BIAS_FLYB_BUFF (0x6C7)
|
||||
#define WCD9XXX_HPH_L_EN (0x6D3)
|
||||
#define WCD9XXX_HPH_R_EN (0x6D6)
|
||||
#define WCD9XXX_HPH_REFBUFF_UHQA_CTL (0x6DD)
|
||||
#define WCD9XXX_CLASSH_CTRL_VCL_2 (0x69B)
|
||||
#endif
|
||||
|
|
|
@ -1241,17 +1241,6 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
|
|||
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MECH_DETECTION_TYPE,
|
||||
!detection_type);
|
||||
|
||||
/*
|
||||
* For faster pull-up, adjust the pull-up current to 3uA.
|
||||
* Possible that some codecs may choose not to update the
|
||||
* pull up current, in which case this callback function
|
||||
* will not be defined.
|
||||
*/
|
||||
if (mbhc->mbhc_cb->hph_pull_up_control) {
|
||||
mbhc->mbhc_cb->hph_pull_up_control(codec,
|
||||
(detection_type ? REMOVE : INSERT));
|
||||
}
|
||||
|
||||
pr_debug("%s: mbhc->current_plug: %d detection_type: %d\n", __func__,
|
||||
mbhc->current_plug, detection_type);
|
||||
wcd_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
|
||||
|
@ -1647,7 +1636,7 @@ static bool wcd_mbhc_fw_validate(const void *data, size_t size)
|
|||
return true;
|
||||
}
|
||||
|
||||
irqreturn_t wcd_mbhc_btn_press_handler(int irq, void *data)
|
||||
static irqreturn_t wcd_mbhc_btn_press_handler(int irq, void *data)
|
||||
{
|
||||
struct wcd_mbhc *mbhc = data;
|
||||
int mask;
|
||||
|
@ -1808,6 +1797,18 @@ static irqreturn_t wcd_mbhc_hphr_ocp_irq(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void wcd_mbhc_moisture_config(struct wcd_mbhc *mbhc)
|
||||
{
|
||||
if (mbhc->mbhc_cfg->moist_cfg.m_vref_ctl == V_OFF)
|
||||
return;
|
||||
|
||||
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MOISTURE_VREF,
|
||||
mbhc->mbhc_cfg->moist_cfg.m_vref_ctl);
|
||||
if (mbhc->mbhc_cb->hph_pull_up_control)
|
||||
mbhc->mbhc_cb->hph_pull_up_control(mbhc->codec,
|
||||
mbhc->mbhc_cfg->moist_cfg.m_iref_ctl);
|
||||
}
|
||||
|
||||
static int wcd_mbhc_initialise(struct wcd_mbhc *mbhc)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -1818,9 +1819,12 @@ static int wcd_mbhc_initialise(struct wcd_mbhc *mbhc)
|
|||
|
||||
/* enable HS detection */
|
||||
if (mbhc->mbhc_cb->hph_pull_up_control)
|
||||
mbhc->mbhc_cb->hph_pull_up_control(codec, INSERT);
|
||||
mbhc->mbhc_cb->hph_pull_up_control(codec, I_DEFAULT);
|
||||
else
|
||||
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, 3);
|
||||
|
||||
wcd_mbhc_moisture_config(mbhc);
|
||||
|
||||
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHL_PLUG_TYPE, mbhc->hphl_swh);
|
||||
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_GND_PLUG_TYPE, mbhc->gnd_swh);
|
||||
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_SW_HPH_LP_100K_TO_GND, 1);
|
||||
|
@ -1977,7 +1981,6 @@ int wcd_mbhc_set_keycode(struct wcd_mbhc *mbhc)
|
|||
WARN_ONCE(1, "Wrong button number:%d\n", i);
|
||||
result = -1;
|
||||
return result;
|
||||
break;
|
||||
}
|
||||
ret = snd_jack_set_key(mbhc->button_jack.jack,
|
||||
type,
|
||||
|
|
|
@ -55,6 +55,7 @@ enum wcd_mbhc_register_function {
|
|||
WCD_MBHC_HPHL_PA_EN,
|
||||
WCD_MBHC_HPH_PA_EN,
|
||||
WCD_MBHC_SWCH_LEVEL_REMOVE,
|
||||
WCD_MBHC_MOISTURE_VREF,
|
||||
WCD_MBHC_PULLDOWN_CTRL,
|
||||
WCD_MBHC_REG_FUNC_MAX,
|
||||
};
|
||||
|
@ -85,11 +86,6 @@ enum {
|
|||
MIC_BIAS_4
|
||||
};
|
||||
|
||||
enum {
|
||||
REMOVE = 0,
|
||||
INSERT,
|
||||
};
|
||||
|
||||
enum {
|
||||
MICB_PULLUP_ENABLE,
|
||||
MICB_PULLUP_DISABLE,
|
||||
|
@ -211,6 +207,31 @@ enum wcd_mbhc_hph_type {
|
|||
WCD_MBHC_HPH_STEREO,
|
||||
};
|
||||
|
||||
/*
|
||||
* These enum definitions are directly mapped to the register
|
||||
* definitions
|
||||
*/
|
||||
enum mbhc_moisture_vref {
|
||||
V_OFF,
|
||||
V_45_MV,
|
||||
V_100_MV,
|
||||
V_225_MV,
|
||||
};
|
||||
|
||||
enum mbhc_hs_pullup_iref {
|
||||
I_DEFAULT = -1,
|
||||
I_OFF = 0,
|
||||
I_1P0_UA,
|
||||
I_2P0_UA,
|
||||
I_3P0_UA,
|
||||
};
|
||||
|
||||
struct wcd_mbhc_moisture_cfg {
|
||||
enum mbhc_moisture_vref m_vref_ctl;
|
||||
enum mbhc_hs_pullup_iref m_iref_ctl;
|
||||
};
|
||||
|
||||
|
||||
struct wcd_mbhc_config {
|
||||
bool read_fw_bin;
|
||||
void *calibration;
|
||||
|
@ -218,9 +239,10 @@ struct wcd_mbhc_config {
|
|||
bool mono_stero_detection;
|
||||
bool (*swap_gnd_mic) (struct snd_soc_codec *codec);
|
||||
bool hs_ext_micbias;
|
||||
bool gnd_det_en;
|
||||
int key_code[WCD_MBHC_KEYCODE_NUM];
|
||||
uint32_t linein_th;
|
||||
bool gnd_det_en;
|
||||
struct wcd_mbhc_moisture_cfg moist_cfg;
|
||||
};
|
||||
|
||||
struct wcd_mbhc_intr {
|
||||
|
@ -263,14 +285,20 @@ struct wcd_mbhc_register {
|
|||
"%s: BCL should have acquired\n", __func__); \
|
||||
}
|
||||
|
||||
#define WCD_MBHC_REG_UPDATE_BITS(function, val) \
|
||||
do { \
|
||||
if (mbhc->wcd_mbhc_regs[function].reg) { \
|
||||
snd_soc_update_bits(mbhc->codec, \
|
||||
mbhc->wcd_mbhc_regs[function].reg, \
|
||||
mbhc->wcd_mbhc_regs[function].mask, \
|
||||
val << (mbhc->wcd_mbhc_regs[function].offset)); \
|
||||
} \
|
||||
/*
|
||||
* Macros to update and read mbhc register bits. Check for
|
||||
* "0" before updating or reading the register, because it
|
||||
* is possible that one codec wants to write to that bit and
|
||||
* other codec does not.
|
||||
*/
|
||||
#define WCD_MBHC_REG_UPDATE_BITS(function, val) \
|
||||
do { \
|
||||
if (mbhc->wcd_mbhc_regs[function].reg) { \
|
||||
snd_soc_update_bits(mbhc->codec, \
|
||||
mbhc->wcd_mbhc_regs[function].reg, \
|
||||
mbhc->wcd_mbhc_regs[function].mask, \
|
||||
val << (mbhc->wcd_mbhc_regs[function].offset)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define WCD_MBHC_REG_READ(function, val) \
|
||||
|
@ -313,7 +341,8 @@ struct wcd_mbhc_cb {
|
|||
bool (*hph_pa_on_status)(struct snd_soc_codec *);
|
||||
void (*set_btn_thr)(struct snd_soc_codec *, s16 *, s16 *,
|
||||
int num_btn, bool);
|
||||
void (*hph_pull_up_control)(struct snd_soc_codec *, bool);
|
||||
void (*hph_pull_up_control)(struct snd_soc_codec *,
|
||||
enum mbhc_hs_pullup_iref);
|
||||
int (*mbhc_micbias_control)(struct snd_soc_codec *, int req);
|
||||
void (*mbhc_micb_ramp_control)(struct snd_soc_codec *, bool);
|
||||
void (*skip_imped_detect)(struct snd_soc_codec *);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -99,6 +99,15 @@ struct tasha_reg_mask_val {
|
|||
u8 val;
|
||||
};
|
||||
|
||||
/* Selects compander and smart boost settings
|
||||
* for a given speaker mode
|
||||
*/
|
||||
enum {
|
||||
SPKR_MODE_DEFAULT,
|
||||
SPKR_MODE_1, /* COMP Gain = 12dB, Smartboost Max = 5.5V */
|
||||
};
|
||||
|
||||
|
||||
extern void *tasha_get_afe_config(struct snd_soc_codec *codec,
|
||||
enum afe_config_type config_type);
|
||||
extern int tasha_cdc_mclk_enable(struct snd_soc_codec *codec, int enable,
|
||||
|
@ -120,5 +129,5 @@ extern int tasha_codec_info_create_codec_entry(struct snd_info_entry *,
|
|||
extern int tasha_codec_enable_standalone_micbias(struct snd_soc_codec *codec,
|
||||
int micb_num,
|
||||
bool enable);
|
||||
|
||||
extern int tasha_set_spkr_mode(struct snd_soc_codec *codec, int mode);
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,25 @@
|
|||
|
||||
#define WCD_USLEEP_RANGE 50
|
||||
|
||||
enum {
|
||||
DAC_GAIN_0DB = 0,
|
||||
DAC_GAIN_0P2DB,
|
||||
DAC_GAIN_0P4DB,
|
||||
DAC_GAIN_0P6DB,
|
||||
DAC_GAIN_0P8DB,
|
||||
DAC_GAIN_M0P2DB,
|
||||
DAC_GAIN_M0P4DB,
|
||||
DAC_GAIN_M0P6DB,
|
||||
};
|
||||
|
||||
enum {
|
||||
VREF_FILT_R_0OHM = 0,
|
||||
VREF_FILT_R_25KOHM,
|
||||
VREF_FILT_R_50KOHM,
|
||||
VREF_FILT_R_100KOHM,
|
||||
};
|
||||
|
||||
|
||||
static void (*clsh_state_fp[NUM_CLSH_STATES_V2])(struct snd_soc_codec *,
|
||||
struct wcd_clsh_cdc_data *,
|
||||
u8 req_state, bool en, int mode);
|
||||
|
@ -215,25 +234,80 @@ static void wcd_clsh_flyback_ctrl(struct snd_soc_codec *codec,
|
|||
usleep_range(500, 500 + WCD_USLEEP_RANGE);
|
||||
}
|
||||
|
||||
static void wcd_clsh_set_hph_mode(struct snd_soc_codec *codec,
|
||||
int mode)
|
||||
static void wcd_clsh_set_gain_path(struct snd_soc_codec *codec,
|
||||
int mode)
|
||||
{
|
||||
u8 val;
|
||||
struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
|
||||
|
||||
if (!TASHA_IS_2_0(wcd9xxx->version))
|
||||
return;
|
||||
|
||||
switch (mode) {
|
||||
case CLS_H_NORMAL:
|
||||
case CLS_AB:
|
||||
val = 0x00;
|
||||
break;
|
||||
case CLS_H_HIFI:
|
||||
val = 0x02;
|
||||
break;
|
||||
case CLS_H_LP:
|
||||
val = 0x01;
|
||||
break;
|
||||
};
|
||||
snd_soc_update_bits(codec, WCD9XXX_HPH_L_EN, 0xC0, (val << 6));
|
||||
snd_soc_update_bits(codec, WCD9XXX_HPH_R_EN, 0xC0, (val << 6));
|
||||
}
|
||||
|
||||
static void wcd_clsh_set_hph_mode(struct snd_soc_codec *codec,
|
||||
int mode)
|
||||
{
|
||||
u8 val;
|
||||
u8 gain;
|
||||
u8 res_val = VREF_FILT_R_0OHM;
|
||||
|
||||
struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
|
||||
|
||||
switch (mode) {
|
||||
case CLS_H_NORMAL:
|
||||
res_val = VREF_FILT_R_50KOHM;
|
||||
val = 0x00;
|
||||
gain = DAC_GAIN_0DB;
|
||||
break;
|
||||
case CLS_AB:
|
||||
val = 0x00;
|
||||
gain = DAC_GAIN_0DB;
|
||||
break;
|
||||
case CLS_H_HIFI:
|
||||
val = 0x08;
|
||||
gain = DAC_GAIN_M0P2DB;
|
||||
break;
|
||||
case CLS_H_LP:
|
||||
val = 0x04;
|
||||
gain = DAC_GAIN_0P2DB;
|
||||
break;
|
||||
};
|
||||
|
||||
snd_soc_update_bits(codec, WCD9XXX_A_ANA_HPH, 0x0C, val);
|
||||
if (TASHA_IS_2_0(wcd9xxx->version)) {
|
||||
snd_soc_update_bits(codec, WCD9XXX_CLASSH_CTRL_VCL_2,
|
||||
0x30, (res_val << 4));
|
||||
snd_soc_update_bits(codec, WCD9XXX_HPH_REFBUFF_UHQA_CTL,
|
||||
0x07, gain);
|
||||
}
|
||||
}
|
||||
|
||||
static void wcd_clsh_set_flyback_current(struct snd_soc_codec *codec, int mode)
|
||||
{
|
||||
struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
|
||||
|
||||
if (!TASHA_IS_2_0(wcd9xxx->version))
|
||||
return;
|
||||
|
||||
snd_soc_update_bits(codec, WCD9XXX_RX_BIAS_FLYB_BUFF, 0x0F, 0x0A);
|
||||
snd_soc_update_bits(codec, WCD9XXX_RX_BIAS_FLYB_BUFF, 0xF0, 0xA0);
|
||||
/* Sleep needed to avoid click and pop as per HW requirement */
|
||||
usleep_range(100, 110);
|
||||
}
|
||||
|
||||
static void wcd_clsh_set_buck_regulator_mode(struct snd_soc_codec *codec,
|
||||
|
@ -265,6 +339,7 @@ static void wcd_clsh_state_lo(struct snd_soc_codec *codec,
|
|||
wcd_clsh_set_buck_mode(codec, mode);
|
||||
wcd_clsh_set_flyback_mode(codec, mode);
|
||||
wcd_clsh_flyback_ctrl(codec, clsh_d, mode, true);
|
||||
wcd_clsh_set_flyback_current(codec, mode);
|
||||
wcd_clsh_buck_ctrl(codec, clsh_d, mode, true);
|
||||
} else {
|
||||
wcd_clsh_buck_ctrl(codec, clsh_d, mode, false);
|
||||
|
@ -312,6 +387,7 @@ static void wcd_clsh_state_hph_ear(struct snd_soc_codec *codec,
|
|||
0x40, 0x40);
|
||||
if ((req_state == WCD_CLSH_STATE_HPHL) ||
|
||||
(req_state == WCD_CLSH_STATE_HPHR)) {
|
||||
wcd_clsh_set_gain_path(codec, mode);
|
||||
wcd_clsh_set_flyback_mode(codec, mode);
|
||||
wcd_clsh_set_buck_mode(codec, mode);
|
||||
}
|
||||
|
@ -412,6 +488,9 @@ static void wcd_clsh_state_hph_lo(struct snd_soc_codec *codec,
|
|||
else {
|
||||
wcd_clsh_set_flyback_mode(codec, mode);
|
||||
wcd_clsh_set_buck_mode(codec, mode);
|
||||
if ((req_state == WCD_CLSH_STATE_HPHL) ||
|
||||
(req_state == WCD_CLSH_STATE_HPHR))
|
||||
wcd_clsh_set_gain_path(codec, mode);
|
||||
}
|
||||
} else {
|
||||
if ((req_state == WCD_CLSH_STATE_HPHL) ||
|
||||
|
@ -537,7 +616,9 @@ static void wcd_clsh_state_hph_r(struct snd_soc_codec *codec,
|
|||
wcd_clsh_set_buck_mode(codec, mode);
|
||||
wcd_clsh_set_flyback_mode(codec, mode);
|
||||
wcd_clsh_flyback_ctrl(codec, clsh_d, mode, true);
|
||||
wcd_clsh_set_flyback_current(codec, mode);
|
||||
wcd_clsh_buck_ctrl(codec, clsh_d, mode, true);
|
||||
wcd_clsh_set_gain_path(codec, mode);
|
||||
wcd_clsh_set_hph_mode(codec, mode);
|
||||
} else {
|
||||
wcd_clsh_set_hph_mode(codec, CLS_H_NORMAL);
|
||||
|
@ -589,7 +670,9 @@ static void wcd_clsh_state_hph_l(struct snd_soc_codec *codec,
|
|||
wcd_clsh_set_buck_mode(codec, mode);
|
||||
wcd_clsh_set_flyback_mode(codec, mode);
|
||||
wcd_clsh_flyback_ctrl(codec, clsh_d, mode, true);
|
||||
wcd_clsh_set_flyback_current(codec, mode);
|
||||
wcd_clsh_buck_ctrl(codec, clsh_d, mode, true);
|
||||
wcd_clsh_set_gain_path(codec, mode);
|
||||
wcd_clsh_set_hph_mode(codec, mode);
|
||||
} else {
|
||||
wcd_clsh_set_hph_mode(codec, CLS_H_NORMAL);
|
||||
|
@ -630,6 +713,7 @@ static void wcd_clsh_state_ear(struct snd_soc_codec *codec,
|
|||
wcd_clsh_set_buck_mode(codec, mode);
|
||||
wcd_clsh_set_flyback_mode(codec, mode);
|
||||
wcd_clsh_flyback_ctrl(codec, clsh_d, mode, true);
|
||||
wcd_clsh_set_flyback_current(codec, mode);
|
||||
wcd_clsh_buck_ctrl(codec, clsh_d, mode, true);
|
||||
} else {
|
||||
snd_soc_update_bits(codec,
|
||||
|
@ -671,6 +755,12 @@ static bool wcd_clsh_is_state_valid(u8 state)
|
|||
case WCD_CLSH_STATE_HPHR:
|
||||
case WCD_CLSH_STATE_HPH_ST:
|
||||
case WCD_CLSH_STATE_LO:
|
||||
case WCD_CLSH_STATE_HPHL_EAR:
|
||||
case WCD_CLSH_STATE_HPHR_EAR:
|
||||
case WCD_CLSH_STATE_HPH_ST_EAR:
|
||||
case WCD_CLSH_STATE_HPHL_LO:
|
||||
case WCD_CLSH_STATE_HPHR_LO:
|
||||
case WCD_CLSH_STATE_HPH_ST_LO:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -45,6 +45,19 @@ static int wcd_resmgr_codec_reg_update_bits(struct wcd9xxx_resmgr_v2 *resmgr,
|
|||
return change;
|
||||
}
|
||||
|
||||
static int wcd_resmgr_codec_reg_read(struct wcd9xxx_resmgr_v2 *resmgr,
|
||||
unsigned int reg)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (resmgr->codec)
|
||||
val = snd_soc_read(resmgr->codec, reg);
|
||||
else
|
||||
val = wcd9xxx_reg_read(resmgr->core_res, reg);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* wcd_resmgr_get_clk_type()
|
||||
* Returns clk type that is currently enabled
|
||||
|
@ -185,12 +198,12 @@ static int wcd_resmgr_enable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
resmgr->clk_mclk_users++;
|
||||
if (++resmgr->clk_mclk_users == 1) {
|
||||
|
||||
if ((resmgr->clk_mclk_users == 1) &&
|
||||
(resmgr->clk_type == WCD_CLK_OFF)) {
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP,
|
||||
0x80, 0x80);
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP,
|
||||
0x08, 0x00);
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP,
|
||||
0x04, 0x04);
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr,
|
||||
|
@ -204,14 +217,8 @@ static int wcd_resmgr_enable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr)
|
|||
* as per HW requirement
|
||||
*/
|
||||
usleep_range(10, 15);
|
||||
} else if ((resmgr->clk_mclk_users == 1) &&
|
||||
(resmgr->clk_type == WCD_CLK_RCO)) {
|
||||
/* RCO to MCLK switch */
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP,
|
||||
0x80, 0x80);
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP,
|
||||
0x08, 0x00);
|
||||
}
|
||||
|
||||
resmgr->clk_type = WCD_CLK_MCLK;
|
||||
|
||||
pr_debug("%s: mclk_users: %d, clk_type: %s\n", __func__,
|
||||
|
@ -228,22 +235,24 @@ static int wcd_resmgr_disable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
resmgr->clk_mclk_users--;
|
||||
if ((resmgr->clk_mclk_users == 0) && (resmgr->clk_rco_users > 0)) {
|
||||
/* MCLK to RCO switch */
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr,
|
||||
WCD9335_ANA_CLK_TOP,
|
||||
0x08, 0x08);
|
||||
resmgr->clk_type = WCD_CLK_RCO;
|
||||
} else if ((resmgr->clk_mclk_users == 0) &&
|
||||
(resmgr->clk_rco_users == 0)) {
|
||||
/* Turn off MCLK */
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP,
|
||||
0x04, 0x00);
|
||||
if (--resmgr->clk_mclk_users == 0) {
|
||||
if (resmgr->clk_rco_users > 0) {
|
||||
/* MCLK to RCO switch */
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr,
|
||||
WCD9335_ANA_CLK_TOP,
|
||||
0x08, 0x08);
|
||||
resmgr->clk_type = WCD_CLK_RCO;
|
||||
} else {
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr,
|
||||
WCD9335_ANA_CLK_TOP,
|
||||
0x04, 0x00);
|
||||
resmgr->clk_type = WCD_CLK_OFF;
|
||||
}
|
||||
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_CLK_TOP,
|
||||
0x80, 0x00);
|
||||
resmgr->clk_type = WCD_CLK_OFF;
|
||||
}
|
||||
|
||||
pr_debug("%s: mclk_users: %d, clk_type: %s\n", __func__,
|
||||
resmgr->clk_mclk_users,
|
||||
wcd_resmgr_clk_type_to_str(resmgr->clk_type));
|
||||
|
@ -253,6 +262,8 @@ static int wcd_resmgr_disable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr)
|
|||
|
||||
static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr)
|
||||
{
|
||||
bool rco_cal_done = true;
|
||||
|
||||
resmgr->clk_rco_users++;
|
||||
if ((resmgr->clk_rco_users == 1) &&
|
||||
((resmgr->clk_type == WCD_CLK_OFF) ||
|
||||
|
@ -283,9 +294,16 @@ static int wcd_resmgr_enable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr)
|
|||
/* RCO Calibration */
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO,
|
||||
0x04, 0x04);
|
||||
wcd_resmgr_codec_reg_update_bits(resmgr, WCD9335_ANA_RCO,
|
||||
0x04, 0x00);
|
||||
|
||||
/* RCO calibration takes app. 5ms to complete */
|
||||
usleep_range(WCD9XXX_RCO_CALIBRATION_DELAY_INC_US,
|
||||
WCD9XXX_RCO_CALIBRATION_DELAY_INC_US + 100);
|
||||
if (wcd_resmgr_codec_reg_read(resmgr, WCD9335_ANA_RCO) & 0x02)
|
||||
rco_cal_done = false;
|
||||
|
||||
WARN((!rco_cal_done), "RCO Calibration failed\n");
|
||||
|
||||
/* Switch MUX to RCO */
|
||||
if (resmgr->clk_mclk_users == 1) {
|
||||
|
|
Loading…
Reference in a new issue