summaryrefslogtreecommitdiff
path: root/asoc/codecs/wsa883x/wsa883x.c
diff options
context:
space:
mode:
Diffstat (limited to 'asoc/codecs/wsa883x/wsa883x.c')
-rw-r--r--asoc/codecs/wsa883x/wsa883x.c80
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);