diff --git a/asoc/codecs/wsa883x/internal.h b/asoc/codecs/wsa883x/internal.h index 509fc83708..2384043fb2 100644 --- a/asoc/codecs/wsa883x/internal.h +++ b/asoc/codecs/wsa883x/internal.h @@ -55,6 +55,20 @@ enum { SWR_VISENSE_PORT, }; +enum { + BOLERO_WSA_EVT_TX_CH_HOLD_CLEAR = 1, + BOLERO_WSA_EVT_PA_OFF_PRE_SSR, + BOLERO_WSA_EVT_SSR_DOWN, + BOLERO_WSA_EVT_SSR_UP, +}; + +struct wsa_ctrl_platform_data { + void *handle, + int (*update_wsa_event)(void *handle, u16 event, u32 data); + int (*register_notifier)(void *handle, struct notifer_block *nblock, + bool enable); +}; + struct swr_port { u8 port_id; u8 ch_mask; @@ -96,6 +110,12 @@ struct wsa883x_priv { struct dentry *debugfs_reg_dump; unsigned int read_data; #endif + struct device_node *parent_np; + struct platform_device *parent_dev; + struct notifier_block parent_nblock; + void *handle; + int (*register_notifier)(void *handle, + struct notifier_block *nblock, bool enable); }; static int32_t wsa883x_resource_acquire(struct snd_soc_component *component, diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c index 7869a2b01f..08f6858f73 100644 --- a/asoc/codecs/wsa883x/wsa883x.c +++ b/asoc/codecs/wsa883x/wsa883x.c @@ -1055,12 +1055,39 @@ static int wsa883x_gpio_ctrl(struct wsa883x_priv *wsa883x, bool enable) return ret; } +static int wsa883x_event_notify(struct notifier_block *nb, + unsigned long val, void *ptr) +{ + u16 event = (val & 0xffff); + struct wsa883x_priv *wsa883x = container_of(nb, struct wsa883x_priv, + parent_nblock); + + if (!wsa883x) + return -EINVAL; + + switch (event) { + case BOLERO_WSA_EVT_PA_OFF_PRE_SSR: + snd_soc_component_update_bits(wsa883x->component, + WSA883X_SPKR_DRV_GAIN, + 0xF0, 0xC0); + snd_soc_component_update_bits(wsa883x->component, + WSA883X_SPKR_DRV_EN, + 0x80, 0x00); + break; + default: + break; + } + + return 0; +} + static int wsa883x_swr_probe(struct swr_device *pdev) { int ret = 0; struct wsa883x_priv *wsa883x; u8 devnum = 0; bool pin_state_current = false; + struct wsa_ctrl_platform_data *plat_data = NULL; wsa883x = devm_kzalloc(&pdev->dev, sizeof(struct wsa883x_priv), GFP_KERNEL); @@ -1156,6 +1183,37 @@ static int wsa883x_swr_probe(struct swr_device *pdev) __func__); goto err_irq; } + + wsa883x->parent_np = of_parse_phandle(pdev->dev.of_node, + "qcom,bolero-handle", 0); + if (wsa883x->parent_np) { + wsa883x->parent_dev = + of_find_device_by_node(wsa883x->parent_np); + if (wsa883x->parent_dev) { + plat_data = dev_get_platdata(&wsa883x->parent_dev->dev); + if (plat_data) { + wsa883x->parent_nblock.notifier_call = + wsa883x_event_notify; + if (plat_data->register_notifier) + plat_data->register_notifier( + plat_data->handle, + &wsa883x->parent_nblock, + true); + wsa883x->register_notifier = + plat_data->register_notifier; + wsa883x->handle = plat_data->handle; + } else { + dev_err(&pdev->dev, "%s: plat data not found\n", + __func__); + } + } else { + dev_err(&pdev->dev, "%s: parent dev not found\n", + __func__); + } + } else { + dev_info(&pdev->dev, "%s: parent node not found\n", __func__); + } + mutex_init(&wsa883x->res_lock); #ifdef CONFIG_DEBUG_FS @@ -1230,6 +1288,10 @@ static int wsa883x_swr_remove(struct swr_device *pdev) wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_INTR_PIN, NULL); wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO, NULL); wcd_free_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR, NULL); + + if (wsa883x->register_notifier) + wsa883x->register_notifier(wsa883x->handle, + &wsa883x->parent_nblock, false); #ifdef CONFIG_DEBUG_FS debugfs_remove_recursive(wsa883x->debugfs_dent); wsa883x->debugfs_dent = NULL;