diff options
Diffstat (limited to 'asoc/codecs/wsa883x/wsa883x.c')
-rw-r--r-- | asoc/codecs/wsa883x/wsa883x.c | 80 |
1 files changed, 74 insertions, 6 deletions
diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c index 8a5e99e4..31ba5ba7 100644 --- a/asoc/codecs/wsa883x/wsa883x.c +++ b/asoc/codecs/wsa883x/wsa883x.c @@ -481,8 +481,33 @@ static irqreturn_t wsa883x_uvlo_handle_irq(int irq, void *data) static irqreturn_t wsa883x_pa_on_err_handle_irq(int irq, void *data) { - pr_err_ratelimited("%s: interrupt for irq =%d triggered\n", - __func__, irq); + u8 pa_fsm_sta = 0, pa_fsm_err = 0; + struct wsa883x_priv *wsa883x = data; + struct snd_soc_component *component = NULL; + + if (!wsa883x) + return IRQ_NONE; + + component = wsa883x->component; + if (!component) + return IRQ_NONE; + + pa_fsm_sta = (snd_soc_component_read32(component, WSA883X_PA_FSM_STA) + & 0x70); + + if (pa_fsm_sta) + pa_fsm_err = snd_soc_component_read32(component, + WSA883X_PA_FSM_ERR_COND); + pr_err_ratelimited("%s: irq: %d, pa_fsm_sta: %d, pa_fsm_err: %d\n", + __func__, irq, pa_fsm_sta, pa_fsm_err); + + snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL, + 0x10, 0x00); + snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL, + 0x10, 0x10); + snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL, + 0x10, 0x00); + return IRQ_HANDLED; } @@ -770,6 +795,30 @@ int wsa883x_codec_info_create_codec_entry(struct snd_info_entry *codec_root, } EXPORT_SYMBOL(wsa883x_codec_info_create_codec_entry); +/* + * wsa883x_codec_get_dev_num - returns swr device number + * @component: Codec instance + * + * Return: swr device number on success or negative error + * code on failure. + */ +int wsa883x_codec_get_dev_num(struct snd_soc_component *component) +{ + struct wsa883x_priv *wsa883x; + + if (!component) + return -EINVAL; + + wsa883x = snd_soc_component_get_drvdata(component); + if (!wsa883x) { + pr_err("%s: wsa883x component is NULL\n", __func__); + return -EINVAL; + } + + return wsa883x->swr_slave->dev_num; +} +EXPORT_SYMBOL(wsa883x_codec_get_dev_num); + static int wsa883x_get_compander(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -993,9 +1042,16 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w, 0x01, 0x01); /* Added delay as per HW sequence */ usleep_range(250, 300); + wcd_enable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR); /* Force remove group */ swr_remove_from_group(wsa883x->swr_slave, wsa883x->swr_slave->dev_num); + snd_soc_component_update_bits(component, + WSA883X_VBAT_ADC_FLT_CTL, + 0x0E, 0x06); + snd_soc_component_update_bits(component, + WSA883X_VBAT_ADC_FLT_CTL, + 0x01, 0x01); if (test_bit(SPKR_ADIE_LB, &wsa883x->status_mask)) snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL, 0x01, 0x01); @@ -1004,11 +1060,23 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w, if (!test_bit(SPKR_ADIE_LB, &wsa883x->status_mask)) wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD); + snd_soc_component_update_bits(component, + WSA883X_VBAT_ADC_FLT_CTL, + 0x01, 0x00); + snd_soc_component_update_bits(component, + WSA883X_VBAT_ADC_FLT_CTL, + 0x0E, 0x00); + snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL, + 0x01, 0x00); + snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL, + 0x10, 0x00); + snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL, + 0x10, 0x10); snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL, + 0x10, 0x00); + snd_soc_component_update_bits(wsa883x->component, WSA883X_PDM_WD_CTL, 0x01, 0x00); - snd_soc_component_update_bits(wsa883x->component, - WSA883X_PDM_WD_CTL, - 0x01, 0x00); + wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR); clear_bit(SPKR_STATUS, &wsa883x->status_mask); clear_bit(SPKR_ADIE_LB, &wsa883x->status_mask); break; @@ -1558,7 +1626,7 @@ static int wsa883x_swr_probe(struct swr_device *pdev) "WSA UVLO", wsa883x_uvlo_handle_irq, NULL); wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR, - "WSA PA ERR", wsa883x_pa_on_err_handle_irq, NULL); + "WSA PA ERR", wsa883x_pa_on_err_handle_irq, wsa883x); wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR); |