diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index c46bcad0cd1b..32a3380f8832 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/asoc/codecs/bolero/bolero-cdc.c @@ -1094,7 +1094,7 @@ EXPORT_SYMBOL(bolero_tx_mclk_enable); * Returns 0 on success or -EINVAL on error. */ int bolero_register_event_listener(struct snd_soc_component *component, - bool enable) + bool enable, bool is_dmic_sva) { struct bolero_priv *priv = NULL; int ret = 0; @@ -1113,7 +1113,8 @@ int bolero_register_event_listener(struct snd_soc_component *component, if (priv->macro_params[TX_MACRO].reg_evt_listener) ret = priv->macro_params[TX_MACRO].reg_evt_listener(component, - enable); + enable, + is_dmic_sva); return ret; } diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h index 1f21fd69c877..ba0f3ce57a91 100644 --- a/asoc/codecs/bolero/bolero-cdc.h +++ b/asoc/codecs/bolero/bolero-cdc.h @@ -77,7 +77,8 @@ struct macro_ops { u32 size, void *data); int (*clk_div_get)(struct snd_soc_component *component); int (*clk_switch)(struct snd_soc_component *component, int clk_src); - int (*reg_evt_listener)(struct snd_soc_component *component, bool en); + int (*reg_evt_listener)(struct snd_soc_component *component, + bool en, bool is_dmic_sva); int (*clk_enable)(struct snd_soc_component *c, bool en); char __iomem *io_base; u16 clk_id_req; @@ -104,7 +105,7 @@ int bolero_runtime_suspend(struct device *dev); int bolero_set_port_map(struct snd_soc_component *component, u32 size, void *data); int bolero_tx_clk_switch(struct snd_soc_component *component, int clk_src); int bolero_register_event_listener(struct snd_soc_component *component, - bool enable); + bool enable, bool is_dmic_sva); void bolero_wsa_pa_on(struct device *dev); bool bolero_check_core_votes(struct device *dev); int bolero_tx_mclk_enable(struct snd_soc_component *c, bool enable); @@ -178,7 +179,7 @@ static inline int bolero_tx_clk_switch(struct snd_soc_component *component, static inline int bolero_register_event_listener( struct snd_soc_component *component, - bool enable) + bool enable, bool is_dmic_sva) { return 0; } diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 87c9477ad17d..46c0937ea40b 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -378,6 +378,7 @@ struct rx_swr_ctrl_platform_data { void *data), void *swrm_handle, int action); + int (*pinctrl_setup)(void *handle, bool enable); }; enum { @@ -4104,6 +4105,7 @@ static int rx_macro_probe(struct platform_device *pdev) rx_priv->swr_plat_data.clk = rx_swrm_clock; rx_priv->swr_plat_data.core_vote = rx_macro_core_vote; rx_priv->swr_plat_data.handle_irq = NULL; + rx_priv->swr_plat_data.pinctrl_setup = NULL; ret = of_property_read_u8_array(pdev->dev.of_node, "qcom,rx-bcl-pmic-params", bcl_pmic_params, diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index 55b2c3017bba..6fb76a93626a 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -81,6 +81,7 @@ struct tx_macro_swr_ctrl_platform_data { void *data), void *swrm_handle, int action); + int (*pinctrl_setup)(void *handle, bool enable); }; enum { @@ -2496,12 +2497,30 @@ static const struct snd_kcontrol_new tx_macro_snd_controls[] = { tx_macro_get_bcs, tx_macro_set_bcs), }; +static int tx_macro_pinctrl_setup(void *handle, bool enable) +{ + struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle; + + if (tx_priv == NULL) { + pr_err("%s: tx priv data is NULL\n", __func__); + return -EINVAL; + } + if (enable) + msm_cdc_pinctrl_set_wakeup_capable( + tx_priv->tx_swr_gpio_p, true); + else + msm_cdc_pinctrl_set_wakeup_capable( + tx_priv->tx_swr_gpio_p, false); + return 0; +} + static int tx_macro_register_event_listener(struct snd_soc_component *component, - bool enable) + bool enable, bool is_dmic_sva) { struct device *tx_dev = NULL; struct tx_macro_priv *tx_priv = NULL; int ret = 0; + u32 dmic_sva = is_dmic_sva; if (!component) return -EINVAL; @@ -2523,15 +2542,17 @@ static int tx_macro_register_event_listener(struct snd_soc_component *component, if (enable) { ret = swrm_wcd_notify( tx_priv->swr_ctrl_data[0].tx_swr_pdev, - SWR_REGISTER_WAKEUP, NULL); + SWR_REGISTER_WAKEUP, &dmic_sva); msm_cdc_pinctrl_set_wakeup_capable( - tx_priv->tx_swr_gpio_p, false); + tx_priv->tx_swr_gpio_p, false); } else { + /* while teardown we can reset the flag */ + dmic_sva = 0; msm_cdc_pinctrl_set_wakeup_capable( - tx_priv->tx_swr_gpio_p, true); + tx_priv->tx_swr_gpio_p, true); ret = swrm_wcd_notify( tx_priv->swr_ctrl_data[0].tx_swr_pdev, - SWR_DEREGISTER_WAKEUP, NULL); + SWR_DEREGISTER_WAKEUP, &dmic_sva); } } @@ -3322,6 +3343,7 @@ static int tx_macro_probe(struct platform_device *pdev) tx_priv->swr_plat_data.clk = tx_macro_swrm_clock; tx_priv->swr_plat_data.core_vote = tx_macro_core_vote; tx_priv->swr_plat_data.handle_irq = NULL; + tx_priv->swr_plat_data.pinctrl_setup = tx_macro_pinctrl_setup; mutex_init(&tx_priv->swr_clk_lock); } tx_priv->is_used_tx_swr_gpio = is_used_tx_swr_gpio; diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index 710eb7190dc9..760537b62320 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -130,6 +130,7 @@ struct va_macro_swr_ctrl_platform_data { void *data), void *swrm_handle, int action); + int (*pinctrl_setup)(void *handle, bool enable); }; struct va_macro_priv { @@ -459,14 +460,14 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, dev_dbg(va_dev, "%s: clock switch failed\n", __func__); if (va_priv->lpi_enable) { - bolero_register_event_listener(component, true); + bolero_register_event_listener(component, true, false); va_priv->register_event_listener = true; } break; case SND_SOC_DAPM_POST_PMD: if (va_priv->register_event_listener) { va_priv->register_event_listener = false; - bolero_register_event_listener(component, false); + bolero_register_event_listener(component, false, false); } if (bolero_tx_clk_switch(component, CLK_SRC_TX_RCG)) dev_dbg(va_dev, "%s: clock switch failed\n",__func__); @@ -482,6 +483,45 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, return ret; } +static int va_macro_swr_intr_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + int ret = 0; + struct device *va_dev = NULL; + struct va_macro_priv *va_priv = NULL; + + if (!va_macro_get_data(component, &va_dev, &va_priv, __func__)) + return -EINVAL; + + dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n", + __func__, event, va_priv->lpi_enable); + + if (!va_priv->lpi_enable) + return ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (va_priv->lpi_enable) { + bolero_register_event_listener(component, true, true); + va_priv->register_event_listener = true; + } + break; + case SND_SOC_DAPM_POST_PMD: + if (va_priv->register_event_listener) { + va_priv->register_event_listener = false; + bolero_register_event_listener(component, false, true); + } + break; + default: + dev_err(va_priv->dev, + "%s: invalid DAPM event %d\n", __func__, event); + ret = -EINVAL; + } + return ret; +} + static int va_macro_tx_swr_clk_event_v2(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -1989,6 +2029,10 @@ static const struct snd_soc_dapm_widget va_macro_dapm_widgets_v3[] = { SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", -1, SND_SOC_NOPM, 0, 0, va_macro_swr_pwr_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_SWR_INTR", 0, SND_SOC_NOPM, 0, 0, + va_macro_swr_intr_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), }; static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = { @@ -2133,6 +2177,10 @@ static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0, va_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_SWR_INTR", 0, SND_SOC_NOPM, 0, 0, + va_macro_swr_intr_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), }; static const struct snd_soc_dapm_widget va_macro_wod_dapm_widgets[] = { @@ -2279,6 +2327,15 @@ static const struct snd_soc_dapm_route va_audio_map_v3[] = { {"VA SMIC MUX3", "SWR_MIC9", "VA SWR_INPUT"}, {"VA SMIC MUX3", "SWR_MIC10", "VA SWR_INPUT"}, {"VA SMIC MUX3", "SWR_MIC11", "VA SWR_INPUT"}, + + {"VA DMIC0", NULL, "VA_SWR_INTR"}, + {"VA DMIC1", NULL, "VA_SWR_INTR"}, + {"VA DMIC2", NULL, "VA_SWR_INTR"}, + {"VA DMIC3", NULL, "VA_SWR_INTR"}, + {"VA DMIC4", NULL, "VA_SWR_INTR"}, + {"VA DMIC5", NULL, "VA_SWR_INTR"}, + {"VA DMIC6", NULL, "VA_SWR_INTR"}, + {"VA DMIC7", NULL, "VA_SWR_INTR"}, }; static const struct snd_soc_dapm_route va_audio_map_v2[] = { @@ -2515,6 +2572,15 @@ static const struct snd_soc_dapm_route va_audio_map[] = { {"VA SMIC MUX7", "SWR_DMIC6", "VA SWR_MIC6"}, {"VA SMIC MUX7", "SWR_DMIC7", "VA SWR_MIC7"}, + {"VA DMIC0", NULL, "VA_SWR_INTR"}, + {"VA DMIC1", NULL, "VA_SWR_INTR"}, + {"VA DMIC2", NULL, "VA_SWR_INTR"}, + {"VA DMIC3", NULL, "VA_SWR_INTR"}, + {"VA DMIC4", NULL, "VA_SWR_INTR"}, + {"VA DMIC5", NULL, "VA_SWR_INTR"}, + {"VA DMIC6", NULL, "VA_SWR_INTR"}, + {"VA DMIC7", NULL, "VA_SWR_INTR"}, + {"VA SWR_ADC0", NULL, "VA_SWR_PWR"}, {"VA SWR_ADC1", NULL, "VA_SWR_PWR"}, {"VA SWR_ADC2", NULL, "VA_SWR_PWR"}, @@ -3164,6 +3230,7 @@ static int va_macro_probe(struct platform_device *pdev) va_priv->swr_plat_data.clk = va_macro_swrm_clock; va_priv->swr_plat_data.core_vote = va_macro_core_vote; va_priv->swr_plat_data.handle_irq = NULL; + va_priv->swr_plat_data.pinctrl_setup = NULL; mutex_init(&va_priv->swr_clk_lock); } va_priv->is_used_va_swr_gpio = is_used_va_swr_gpio; diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c index 41981aa593ed..9ac809b19896 100644 --- a/asoc/codecs/bolero/wsa-macro.c +++ b/asoc/codecs/bolero/wsa-macro.c @@ -166,6 +166,7 @@ struct wsa_macro_swr_ctrl_platform_data { void *data), void *swrm_handle, int action); + int (*pinctrl_setup)(void *handle, bool enable); }; struct wsa_macro_bcl_pmic_params { @@ -3194,6 +3195,7 @@ static int wsa_macro_probe(struct platform_device *pdev) wsa_priv->swr_plat_data.clk = wsa_swrm_clock; wsa_priv->swr_plat_data.core_vote = wsa_macro_core_vote; wsa_priv->swr_plat_data.handle_irq = NULL; + wsa_priv->swr_plat_data.pinctrl_setup = NULL; ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id", &default_clk_id); diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 8a49f5acae54..a2b912518ab6 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -2469,6 +2469,8 @@ static int swrm_probe(struct platform_device *pdev) ret = -EINVAL; goto err_pdata_fail; } + swrm->pinctrl_setup = pdata->pinctrl_setup; + if (of_property_read_u32(pdev->dev.of_node, "qcom,swr-clock-stop-mode0", &swrm->clk_stop_mode0_supp)) { @@ -2801,7 +2803,6 @@ static int swrm_runtime_resume(struct device *dev) int ret = 0; bool swrm_clk_req_err = false; bool hw_core_err = false; - bool aud_core_err = false; struct swr_master *mstr = &swrm->master; struct swr_device *swr_dev; u32 temp = 0; @@ -2820,7 +2821,7 @@ static int swrm_runtime_resume(struct device *dev) if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) { dev_err(dev, "%s:lpass audio hw enable failed\n", __func__); - aud_core_err = true; + swrm->aud_core_err = true; } if ((swrm->state == SWR_MSTR_DOWN) || @@ -2839,6 +2840,9 @@ static int swrm_runtime_resume(struct device *dev) irq_get_irq_data(swrm->wake_irq))) disable_irq_nosync(swrm->wake_irq); mutex_unlock(&swrm->irq_lock); + if (swrm->dmic_sva && swrm->pinctrl_setup) + swrm->pinctrl_setup(swrm->handle, + false); } if (swrm->ipc_wakeup) msm_aud_evt_blocking_notifier_call_chain( @@ -2912,7 +2916,7 @@ static int swrm_runtime_resume(struct device *dev) swrm->state = SWR_MSTR_UP; } exit: - if (!aud_core_err) + if (ret && !swrm->aud_core_err) swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false); if (!hw_core_err) swrm_request_hw_vote(swrm, LPASS_HW_CORE, false); @@ -2935,7 +2939,6 @@ static int swrm_runtime_suspend(struct device *dev) struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev); int ret = 0; bool hw_core_err = false; - bool aud_core_err = false; struct swr_master *mstr = &swrm->master; struct swr_device *swr_dev; int current_state = 0; @@ -2954,11 +2957,6 @@ static int swrm_runtime_suspend(struct device *dev) __func__); hw_core_err = true; } - if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) { - dev_err(dev, "%s:lpass audio hw enable failed\n", - __func__); - aud_core_err = true; - } if ((current_state == SWR_MSTR_UP) || (current_state == SWR_MSTR_SSR)) { @@ -3027,6 +3025,8 @@ static int swrm_runtime_suspend(struct device *dev) if (swrm->clk_stop_mode0_supp) { if (swrm->wake_irq > 0) { + if (swrm->dmic_sva && swrm->pinctrl_setup) + swrm->pinctrl_setup(swrm->handle, true); enable_irq(swrm->wake_irq); } else if (swrm->ipc_wakeup) { msm_aud_evt_blocking_notifier_call_chain( @@ -3040,10 +3040,11 @@ static int swrm_runtime_suspend(struct device *dev) if (current_state != SWR_MSTR_SSR) swrm->state = SWR_MSTR_DOWN; exit: - if (!aud_core_err) + if (!swrm->aud_core_err) swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false); if (!hw_core_err) swrm_request_hw_vote(swrm, LPASS_HW_CORE, false); + swrm->aud_core_err = false; mutex_unlock(&swrm->reslock); trace_printk("%s: pm_runtime: suspend done state: %d\n", __func__, swrm->state); @@ -3375,10 +3376,12 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) case SWR_REGISTER_WAKEUP: msm_aud_evt_blocking_notifier_call_chain( SWR_WAKE_IRQ_REGISTER, (void *)swrm); + swrm->dmic_sva = *(u32 *)data; break; case SWR_DEREGISTER_WAKEUP: msm_aud_evt_blocking_notifier_call_chain( SWR_WAKE_IRQ_DEREGISTER, (void *)swrm); + swrm->dmic_sva = 0; break; case SWR_SET_PORT_MAP: if (!data) { diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h index c8444032d8a3..f6d5a186d66d 100644 --- a/soc/swr-mstr-ctrl.h +++ b/soc/swr-mstr-ctrl.h @@ -115,6 +115,7 @@ struct swr_ctrl_platform_data { int (*core_vote)(void *handle, bool enable); int (*reg_irq)(void *handle, irqreturn_t(*irq_handler)(int irq, void *data), void *swr_handle, int type); + int (*pinctrl_setup)(void *handle, bool enable); }; struct swr_mstr_ctrl { @@ -148,6 +149,7 @@ struct swr_mstr_ctrl { int (*core_vote)(void *handle, bool enable); int (*reg_irq)(void *handle, irqreturn_t(*irq_handler)(int irq, void *data), void *swr_handle, int type); + int (*pinctrl_setup)(void *handle, bool enable); int irq; int wake_irq; int version; @@ -173,8 +175,10 @@ struct swr_mstr_ctrl { u32 clk_stop_mode0_supp; struct work_struct wakeup_work; u32 ipc_wakeup; + u32 dmic_sva; bool dev_up; bool ipc_wakeup_triggered; + bool aud_core_err; struct pm_qos_request pm_qos_req; enum swrm_pm_state pm_state; wait_queue_head_t pm_wq;