diff --git a/asoc/codecs/wsa884x/wsa884x.c b/asoc/codecs/wsa884x/wsa884x.c index 15ed60fac6..b04f4c526f 100644 --- a/asoc/codecs/wsa884x/wsa884x.c +++ b/asoc/codecs/wsa884x/wsa884x.c @@ -39,6 +39,7 @@ #define HIGH_TEMP_THRESHOLD 45 #define TEMP_INVALID 0xFFFF #define WSA884X_TEMP_RETRY 3 +#define WSA884X_IRQ_RETRY 2 #define PBR_MAX_VOLTAGE 20 #define PBR_MAX_CODE 255 #define WSA884X_IDLE_DETECT_NG_BLOCK_MASK 0x38 @@ -191,13 +192,41 @@ static int wsa884x_handle_post_irq(void *data) { struct wsa884x_priv *wsa884x = data; u32 sts1 = 0, sts2 = 0; + int retry = WSA884X_IRQ_RETRY; - regmap_read(wsa884x->regmap, WSA884X_INTR_STATUS0, &sts1); - regmap_read(wsa884x->regmap, WSA884X_INTR_STATUS1, &sts2); + struct snd_soc_component *component = NULL; - wsa884x->swr_slave->slave_irq_pending = - ((sts1 || sts2) ? true : false); + if (!wsa884x) + return IRQ_NONE; + component = wsa884x->component; + if (!wsa884x->pa_mute) { + do { + wsa884x->pa_mute = 0; + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PA_FSM_EN, GLOBAL_PA_EN, 0x01)); + usleep_range(1000, 1100); + + regmap_read(wsa884x->regmap, WSA884X_INTR_STATUS0, &sts1); + regmap_read(wsa884x->regmap, WSA884X_INTR_STATUS1, &sts2); + + wsa884x->swr_slave->slave_irq_pending = + ((sts1 || sts2) ? true : false); + pr_debug("%s: IRQs Sts0: %x, Sts1: %x\n", __func__, + sts1, sts2); + if (wsa884x->swr_slave->slave_irq_pending) { + pr_debug("%s: IRQ retries left: %0d\n", + __func__, retry); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PA_FSM_EN, GLOBAL_PA_EN, 0x00)); + wsa884x->pa_mute = 1; + if (retry--) + usleep_range(1000, 1100); + } else { + break; + } + } while (retry); + } return IRQ_HANDLED; } @@ -493,6 +522,17 @@ static irqreturn_t wsa884x_clip_handle_irq(int irq, void *data) static irqreturn_t wsa884x_pdm_wd_handle_irq(int irq, void *data) { + struct wsa884x_priv *wsa884x = data; + struct snd_soc_component *component = NULL; + + if (!wsa884x) + return IRQ_NONE; + component = wsa884x->component; + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PDM_WD_CTL, PDM_WD_EN, 0x00)); + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PDM_WD_CTL, PDM_WD_EN, 0x01)); + pr_err_ratelimited("%s: interrupt for irq =%d triggered\n", __func__, irq); return IRQ_HANDLED; @@ -532,6 +572,8 @@ static irqreturn_t wsa884x_pa_on_err_handle_irq(int irq, void *data) if (!component) return IRQ_NONE; + snd_soc_component_update_bits(component, + REG_FIELD_VALUE(PA_FSM_EN, GLOBAL_PA_EN, 0x00)); pa_fsm_sta = (snd_soc_component_read(component, WSA884X_PA_FSM_STA1) & 0x1F); if (pa_fsm_sta) @@ -1383,7 +1425,8 @@ static int wsa884x_spkr_event(struct snd_soc_dapm_widget *w, /* Force remove group */ swr_remove_from_group(wsa884x->swr_slave, wsa884x->swr_slave->dev_num); - if (test_bit(SPKR_ADIE_LB, &wsa884x->status_mask)) + if (test_bit(SPKR_ADIE_LB, &wsa884x->status_mask) && + !wsa884x->pa_mute) snd_soc_component_update_bits(component, REG_FIELD_VALUE(PA_FSM_EN, GLOBAL_PA_EN, 0x01)); break; @@ -1394,6 +1437,7 @@ static int wsa884x_spkr_event(struct snd_soc_dapm_widget *w, REG_FIELD_VALUE(PDM_WD_CTL, PDM_WD_EN, 0x00)); clear_bit(SPKR_STATUS, &wsa884x->status_mask); clear_bit(SPKR_ADIE_LB, &wsa884x->status_mask); + wsa884x->pa_mute = 0; break; } return 0;