diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c index 6f81fbaf45a8..971f4c6697a5 100644 --- a/asoc/codecs/wsa883x/wsa883x.c +++ b/asoc/codecs/wsa883x/wsa883x.c @@ -510,8 +510,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; } @@ -1050,6 +1075,7 @@ 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); wcd_enable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO); /* Force remove group */ swr_remove_from_group(wsa883x->swr_slave, @@ -1076,9 +1102,16 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w, 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(component, WSA883X_PDM_WD_CTL, 0x01, 0x00); wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO); + 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; @@ -1652,7 +1685,7 @@ static int wsa883x_swr_probe(struct swr_device *pdev) wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO); 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);