Merge "asoc: codecs: Change TX tuning and reduce RX click and pop"

This commit is contained in:
qctecmdr 2019-07-04 05:54:56 -07:00 • committed by Gerrit - the friendly Code Review server
commit 5257151bb6
4 changed files with 148 additions and 37 deletions

View file

@ -243,7 +243,14 @@ static void wcd_clsh_flyback_ctrl(struct snd_soc_component *component,
__func__, clsh_d->flyback_users, enable, mode_to_str(mode));
}
static void wcd_clsh_set_hph_mode(struct snd_soc_component *component,
/*
* Function: wcd_clsh_set_hph_mode
* Params: soc component, hph mode class
* Description:
* This function updates class H mode configuration based on
* the input mode.
*/
void wcd_clsh_set_hph_mode(struct snd_soc_component *component,
int mode)
{
u8 val = 0;
@ -273,6 +280,7 @@ static void wcd_clsh_set_hph_mode(struct snd_soc_component *component,
snd_soc_component_update_bits(component, WCD9XXX_ANA_HPH, 0x0C, val);
}
EXPORT_SYMBOL(wcd_clsh_set_hph_mode);
static void wcd_clsh_set_flyback_current(struct snd_soc_component *component,
int mode)

View file

@ -144,6 +144,7 @@ enum {
WCD_BOLERO_EVT_RX_MUTE = 1, /* for RX mute/unmute */
WCD_BOLERO_EVT_IMPED_TRUE, /* for imped true */
WCD_BOLERO_EVT_IMPED_FALSE, /* for imped false */
WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
};
enum {

View file

@ -173,6 +173,16 @@ static int wcd938x_init_reg(struct snd_soc_component *component)
snd_soc_component_update_bits(component,
WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP,
0x1F, 0x08);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_TX_REQ_FB_CTL_0, 0xFF, 0x55);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_TX_REQ_FB_CTL_1, 0xFF, 0x44);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_TX_REQ_FB_CTL_2, 0xFF, 0x11);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_TX_REQ_FB_CTL_3, 0xFF, 0x00);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_TX_REQ_FB_CTL_4, 0xFF, 0x00);
return 0;
}
@ -618,6 +628,10 @@ static int wcd938x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (wcd938x->update_wcd_event)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_MUTE,
(WCD_RX2 << 0x10 | 0x1));
ret = swr_slvdev_datapath_control(wcd938x->rx_swr_dev,
wcd938x->rx_swr_dev->dev_num,
true);
@ -625,8 +639,10 @@ static int wcd938x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
WCD_CLSH_EVENT_PRE_DAC,
WCD_CLSH_STATE_HPHR,
hph_mode);
wcd_clsh_set_hph_mode(component, CLS_H_HIFI);
snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
0x10, 0x10);
wcd_clsh_set_hph_mode(component, hph_mode);
/* 100 usec delay as per HW requirement */
usleep_range(100, 110);
set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
@ -656,26 +672,61 @@ static int wcd938x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_MUTE,
(WCD_RX2 << 0x10));
wcd_enable_irq(&wcd938x->irq_info,
WCD938X_IRQ_HPHR_PDM_WD_INT);
break;
case SND_SOC_DAPM_PRE_PMD:
wcd_disable_irq(&wcd938x->irq_info,
WCD938X_IRQ_HPHR_PDM_WD_INT);
if (wcd938x->update_wcd_event)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_MUTE,
(WCD_RX2 << 0x10 | 0x1));
if (wcd938x->update_wcd_event)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
(WCD_RX2 << 0x10));
/* 7 msec delay as per HW requirement */
usleep_range(7000, 7100);
if (wcd938x->update_wcd_event)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_MUTE,
(WCD_RX2 << 0x10 | 0x0));
/* 20 msec delay as per HW requirement */
usleep_range(21000, 21100);
if (wcd938x->update_wcd_event)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_MUTE,
(WCD_RX2 << 0x10 | 0x1));
snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
0x40, 0x00);
blocking_notifier_call_chain(&wcd938x->mbhc->notifier,
WCD_EVENT_PRE_HPHR_PA_OFF,
&wcd938x->mbhc->wcd_mbhc);
set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
break;
case SND_SOC_DAPM_POST_PMD:
/* 7 msec delay as per HW requirement */
usleep_range(7000, 7010);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_PDM_WD_CTL1, 0x17, 0x00);
/*
* 7ms sleep is required if compander is enabled as per
* HW requirement. If compander is disabled, then
* 20ms delay is required.
*/
if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) {
if (!wcd938x->comp2_enable)
usleep_range(20000, 20100);
else
usleep_range(7000, 7100);
clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);
}
blocking_notifier_call_chain(&wcd938x->mbhc->notifier,
WCD_EVENT_POST_HPHR_PA_OFF,
&wcd938x->mbhc->wcd_mbhc);
snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
0x10, 0x00);
/* 20 msec delay as per HW requirement */
usleep_range(20000, 20100);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_PDM_WD_CTL1, 0x17, 0x00);
wcd_cls_h_fsm(component, &wcd938x->clsh_info,
WCD_CLSH_EVENT_POST_PA,
WCD_CLSH_STATE_HPHR,
@ -699,6 +750,10 @@ static int wcd938x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (wcd938x->update_wcd_event)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_MUTE,
(WCD_RX1 << 0x10 | 0x01));
ret = swr_slvdev_datapath_control(wcd938x->rx_swr_dev,
wcd938x->rx_swr_dev->dev_num,
true);
@ -706,8 +761,10 @@ static int wcd938x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
WCD_CLSH_EVENT_PRE_DAC,
WCD_CLSH_STATE_HPHL,
hph_mode);
wcd_clsh_set_hph_mode(component, CLS_H_HIFI);
snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
0x20, 0x20);
wcd_clsh_set_hph_mode(component, hph_mode);
/* 100 usec delay as per HW requirement */
usleep_range(100, 110);
set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
@ -737,26 +794,61 @@ static int wcd938x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_MUTE,
(WCD_RX1 << 0x10));
wcd_enable_irq(&wcd938x->irq_info,
WCD938X_IRQ_HPHL_PDM_WD_INT);
break;
case SND_SOC_DAPM_PRE_PMD:
wcd_disable_irq(&wcd938x->irq_info,
WCD938X_IRQ_HPHL_PDM_WD_INT);
if (wcd938x->update_wcd_event)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_MUTE,
(WCD_RX1 << 0x10 | 0x1));
if (wcd938x->update_wcd_event)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
(WCD_RX1 << 0x10));
/* 7 msec delay as per HW requirement */
usleep_range(7000, 7100);
if (wcd938x->update_wcd_event)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_MUTE,
(WCD_RX1 << 0x10 | 0x0));
/* 20 msec delay as per HW requirement */
usleep_range(21000, 21100);
if (wcd938x->update_wcd_event)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_MUTE,
(WCD_RX1 << 0x10 | 0x1));
snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
0x80, 0x00);
blocking_notifier_call_chain(&wcd938x->mbhc->notifier,
WCD_EVENT_PRE_HPHL_PA_OFF,
&wcd938x->mbhc->wcd_mbhc);
set_bit(HPH_PA_DELAY, &wcd938x->status_mask);
break;
case SND_SOC_DAPM_POST_PMD:
/* 7 msec delay as per HW requirement */
usleep_range(7000, 7010);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_PDM_WD_CTL0, 0x17, 0x00);
/*
* 7ms sleep is required if compander is enabled as per
* HW requirement. If compander is disabled, then
* 20ms delay is required.
*/
if (test_bit(HPH_PA_DELAY, &wcd938x->status_mask)) {
if (!wcd938x->comp1_enable)
usleep_range(21000, 21100);
else
usleep_range(7000, 7100);
clear_bit(HPH_PA_DELAY, &wcd938x->status_mask);
}
blocking_notifier_call_chain(&wcd938x->mbhc->notifier,
WCD_EVENT_POST_HPHL_PA_OFF,
&wcd938x->mbhc->wcd_mbhc);
snd_soc_component_update_bits(component, WCD938X_ANA_HPH,
0x20, 0x00);
/* 20 msec delay as per HW requirement */
usleep_range(21000, 21100);
snd_soc_component_update_bits(component,
WCD938X_DIGITAL_PDM_WD_CTL0, 0x17, 0x00);
wcd_cls_h_fsm(component, &wcd938x->clsh_info,
WCD_CLSH_EVENT_POST_PA,
WCD_CLSH_STATE_HPHL,
@ -799,8 +891,11 @@ static int wcd938x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_MUTE,
(WCD_RX3 << 0x10));
wcd_enable_irq(&wcd938x->irq_info, WCD938X_IRQ_AUX_PDM_WD_INT);
break;
case SND_SOC_DAPM_PRE_PMD:
wcd_disable_irq(&wcd938x->irq_info,
WCD938X_IRQ_AUX_PDM_WD_INT);
if (wcd938x->update_wcd_event)
wcd938x->update_wcd_event(wcd938x->handle,
WCD_BOLERO_EVT_RX_MUTE,
@ -1684,10 +1779,10 @@ static int wcd938x_codec_enable_micbias(struct snd_soc_dapm_widget *w,
return __wcd938x_codec_enable_micbias(w, event);
}
static inline int wcd938x_tx_path_get(const char *wname)
static inline int wcd938x_tx_path_get(const char *wname,
unsigned int *path_num)
{
int ret = 0;
unsigned int path_num;
char *widget_name = NULL;
char *w_name = NULL;
char *path_num_char = NULL;
@ -1706,7 +1801,6 @@ static inline int wcd938x_tx_path_get(const char *wname)
ret = -EINVAL;
goto err;
}
path_name = widget_name;
path_num_char = strpbrk(path_name, "0123");
if (!path_num_char) {
pr_err("%s: tx path index not found\n",
@ -1714,7 +1808,7 @@ static inline int wcd938x_tx_path_get(const char *wname)
ret = -EINVAL;
goto err;
}
ret = kstrtouint(path_num_char, 10, &path_num);
ret = kstrtouint(path_num_char, 10, path_num);
if (ret < 0)
pr_err("%s: Invalid tx path = %s\n",
__func__, w_name);
@ -1727,24 +1821,23 @@ err:
static int wcd938x_tx_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_widget *widget =
snd_soc_dapm_kcontrol_widget(kcontrol);
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct wcd938x_priv *wcd938x = NULL;
int path = 0;
int ret = 0;
unsigned int path = 0;
if (!component)
return -EINVAL;
wcd938x = snd_soc_component_get_drvdata(component);
if (!widget || !widget->name || !wcd938x)
if (!wcd938x)
return -EINVAL;
path = wcd938x_tx_path_get(widget->name);
if (path < 0 || path >= TX_ADC_MAX)
return -EINVAL;
ret = wcd938x_tx_path_get(kcontrol->id.name, &path);
if (ret < 0)
return ret;
ucontrol->value.integer.value[0] = wcd938x->tx_mode[path];
@ -1754,25 +1847,24 @@ static int wcd938x_tx_mode_get(struct snd_kcontrol *kcontrol,
static int wcd938x_tx_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_widget *widget =
snd_soc_dapm_kcontrol_widget(kcontrol);
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct wcd938x_priv *wcd938x = NULL;
u32 mode_val;
int path = 0;
unsigned int path = 0;
int ret = 0;
if (!component)
return -EINVAL;
wcd938x = snd_soc_component_get_drvdata(component);
if (!widget || !widget->name || !wcd938x)
if (!wcd938x)
return -EINVAL;
path = wcd938x_tx_path_get(widget->name);
if (path < 0 || path >= TX_ADC_MAX)
return -EINVAL;
ret = wcd938x_tx_path_get(kcontrol->id.name, &path);
if (ret)
return ret;
mode_val = ucontrol->value.enumerated.item[0];
@ -2199,19 +2291,19 @@ static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = {
SND_SOC_DAPM_PGA_E("EAR PGA", WCD938X_ANA_EAR, 7, 0, NULL, 0,
wcd938x_codec_enable_ear_pa,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("AUX PGA", WCD938X_AUX_AUXPA, 7, 0, NULL, 0,
wcd938x_codec_enable_aux_pa,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("HPHL PGA", WCD938X_ANA_HPH, 7, 0, NULL, 0,
wcd938x_codec_enable_hphl_pa,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("HPHR PGA", WCD938X_ANA_HPH, 6, 0, NULL, 0,
wcd938x_codec_enable_hphr_pa,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_DAC_E("RDAC1", NULL, SND_SOC_NOPM, 0, 0,
wcd938x_codec_hphl_dac_event,
@ -2840,10 +2932,10 @@ static int wcd938x_bind(struct device *dev)
"HPHL PDM WD INT", wcd938x_wd_handle_irq, NULL);
wcd_request_irq(&wcd938x->irq_info, WCD938X_IRQ_AUX_PDM_WD_INT,
"AUX PDM WD INT", wcd938x_wd_handle_irq, NULL);
/* Enable watchdog interrupt for HPH and AUX */
wcd_enable_irq(&wcd938x->irq_info, WCD938X_IRQ_HPHR_PDM_WD_INT);
wcd_enable_irq(&wcd938x->irq_info, WCD938X_IRQ_HPHL_PDM_WD_INT);
wcd_enable_irq(&wcd938x->irq_info, WCD938X_IRQ_AUX_PDM_WD_INT);
/* Disable watchdog interrupt for HPH and AUX */
wcd_disable_irq(&wcd938x->irq_info, WCD938X_IRQ_HPHR_PDM_WD_INT);
wcd_disable_irq(&wcd938x->irq_info, WCD938X_IRQ_HPHL_PDM_WD_INT);
wcd_disable_irq(&wcd938x->irq_info, WCD938X_IRQ_AUX_PDM_WD_INT);
ret = snd_soc_register_component(dev, &soc_codec_dev_wcd938x,
NULL, 0);
@ -2865,6 +2957,9 @@ static void wcd938x_unbind(struct device *dev)
{
struct wcd938x_priv *wcd938x = dev_get_drvdata(dev);
wcd_free_irq(&wcd938x->irq_info, WCD938X_IRQ_HPHR_PDM_WD_INT, NULL);
wcd_free_irq(&wcd938x->irq_info, WCD938X_IRQ_HPHL_PDM_WD_INT, NULL);
wcd_free_irq(&wcd938x->irq_info, WCD938X_IRQ_AUX_PDM_WD_INT, NULL);
wcd_irq_exit(&wcd938x->irq_info, wcd938x->virq);
snd_soc_unregister_component(dev);
component_unbind_all(dev, wcd938x);

View file

@ -82,15 +82,22 @@ extern void wcd_cls_h_fsm(struct snd_soc_component *component,
int int_mode);
extern void wcd_cls_h_init(struct wcd_clsh_cdc_info *clsh);
extern void wcd_clsh_set_hph_mode(struct snd_soc_component *component,
int mode);
#else
extern void wcd_cls_h_fsm(struct snd_soc_component *component,
static inline void wcd_cls_h_fsm(struct snd_soc_component *component,
struct wcd_clsh_cdc_info *cdc_clsh_d,
u8 clsh_event, u8 req_state,
int int_mode)
{
}
extern void wcd_cls_h_init(struct wcd_clsh_cdc_info *clsh)
static inline extern void wcd_cls_h_init(struct wcd_clsh_cdc_info *clsh)
{
}
static inline extern void wcd_clsh_set_hph_mode(struct snd_soc_component *component,
int mode)
{
}
#endif /* CONFIG_SND_SOC_WCD9XXX_V2 */