From 32f0f8d96d750e95677dc682b13ce4c2c9d26248 Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Thu, 9 Jun 2022 01:12:33 +0530 Subject: [PATCH] asoc: lpass: add pm stay awake to avoid suspend add pm stay awake before the queue delayed work to avoid the when apps suspend. Change-Id: Iad4d55d509e800b352ac7cb8afb0824a89c80c40 Signed-off-by: Prasad Kumpatla --- asoc/codecs/lpass-cdc/lpass-cdc-tx-macro.c | 35 +++++++++++++++++++ asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c | 39 +++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-tx-macro.c b/asoc/codecs/lpass-cdc/lpass-cdc-tx-macro.c index 526e4fdcdc..879d7e4091 100644 --- a/asoc/codecs/lpass-cdc/lpass-cdc-tx-macro.c +++ b/asoc/codecs/lpass-cdc/lpass-cdc-tx-macro.c @@ -129,6 +129,7 @@ struct lpass_cdc_tx_macro_priv { int tx_mclk_users; bool dapm_mclk_enable; struct mutex mclk_lock; + struct mutex wlock; struct snd_soc_component *component; struct hpf_work tx_hpf_work[NUM_DECIMATORS]; struct tx_mute_work tx_mute_dwork[NUM_DECIMATORS]; @@ -147,8 +148,32 @@ struct lpass_cdc_tx_macro_priv { bool hs_slow_insert_complete; int pcm_rate[NUM_DECIMATORS]; bool swr_dmic_enable; + int wlock_holders; }; +static int lpass_cdc_tx_macro_wake_enable(struct lpass_cdc_tx_macro_priv *tx_priv, + bool wake_enable) +{ + int ret = 0; + + mutex_lock(&tx_priv->wlock); + if (wake_enable) { + if (tx_priv->wlock_holders++ == 0) { + dev_dbg(tx_priv->dev, "%s: pm wake\n", __func__); + pm_stay_awake(tx_priv->dev); + } + } else { + if (--tx_priv->wlock_holders == 0) { + dev_dbg(tx_priv->dev, "%s: pm release\n", __func__); + pm_relax(tx_priv->dev); + } + if (tx_priv->wlock_holders < 0) + tx_priv->wlock_holders = 0; + } + mutex_unlock(&tx_priv->wlock); + return ret; +} + static bool lpass_cdc_tx_macro_get_data(struct snd_soc_component *component, struct device **tx_dev, struct lpass_cdc_tx_macro_priv **tx_priv, @@ -431,6 +456,7 @@ static void lpass_cdc_tx_macro_tx_hpf_corner_freq_callback(struct work_struct *w snd_soc_component_update_bits(component, hpf_gate_reg, 0x02, 0x00); } + lpass_cdc_tx_macro_wake_enable(tx_priv, 0); } static void lpass_cdc_tx_macro_mute_update_callback(struct work_struct *work) @@ -454,6 +480,7 @@ static void lpass_cdc_tx_macro_mute_update_callback(struct work_struct *work) snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00); dev_dbg(tx_priv->dev, "%s: decimator %u unmute\n", __func__, decimator); + lpass_cdc_tx_macro_wake_enable(tx_priv, 0); } static int lpass_cdc_tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol, @@ -941,12 +968,14 @@ static int lpass_cdc_tx_macro_enable_dec(struct snd_soc_dapm_widget *w, } if (tx_unmute_delay < unmute_delay) tx_unmute_delay = unmute_delay; + lpass_cdc_tx_macro_wake_enable(tx_priv, 1); /* schedule work queue to Remove Mute */ queue_delayed_work(system_freezable_wq, &tx_priv->tx_mute_dwork[decimator].dwork, msecs_to_jiffies(tx_unmute_delay)); if (tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq != CF_MIN_3DB_150HZ) { + lpass_cdc_tx_macro_wake_enable(tx_priv, 1); queue_delayed_work(system_freezable_wq, &tx_priv->tx_hpf_work[decimator].dwork, msecs_to_jiffies(hpf_delay)); @@ -1011,8 +1040,10 @@ static int lpass_cdc_tx_macro_enable_dec(struct snd_soc_dapm_widget *w, 0x03, 0x01); } } + lpass_cdc_tx_macro_wake_enable(tx_priv, 0); cancel_delayed_work_sync( &tx_priv->tx_mute_dwork[decimator].dwork); + lpass_cdc_tx_macro_wake_enable(tx_priv, 0); if (snd_soc_component_read(component, adc_mux_reg) & SWR_MIC) @@ -2039,6 +2070,7 @@ static int lpass_cdc_tx_macro_probe(struct platform_device *pdev) } tx_priv->tx_io_base = tx_io_base; tx_priv->swr_dmic_enable = false; + tx_priv->wlock_holders = 0; ret = of_property_read_u32(pdev->dev.of_node, dmic_sample_rate, &sample_rate); if (ret) { @@ -2053,6 +2085,7 @@ static int lpass_cdc_tx_macro_probe(struct platform_device *pdev) } mutex_init(&tx_priv->mclk_lock); + mutex_init(&tx_priv->wlock); lpass_cdc_tx_macro_init_ops(&ops, tx_io_base); ops.clk_id_req = TX_CORE_CLK; ops.default_clk_id = TX_CORE_CLK; @@ -2071,6 +2104,7 @@ static int lpass_cdc_tx_macro_probe(struct platform_device *pdev) return 0; err_reg_macro: mutex_destroy(&tx_priv->mclk_lock); + mutex_destroy(&tx_priv->wlock); return ret; } @@ -2086,6 +2120,7 @@ static int lpass_cdc_tx_macro_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); mutex_destroy(&tx_priv->mclk_lock); + mutex_destroy(&tx_priv->wlock); lpass_cdc_unregister_macro(&pdev->dev, TX_MACRO); return 0; } diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c b/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c index 1aae9d3ae7..e53c51c96b 100644 --- a/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c +++ b/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c @@ -138,6 +138,7 @@ struct lpass_cdc_va_macro_priv { struct clk *lpass_audio_hw_vote; struct mutex mclk_lock; struct mutex swr_clk_lock; + struct mutex wlock; struct snd_soc_component *component; struct hpf_work va_hpf_work[LPASS_CDC_VA_MACRO_NUM_DECIMATORS]; struct va_mute_work va_mute_dwork[LPASS_CDC_VA_MACRO_NUM_DECIMATORS]; @@ -179,8 +180,33 @@ struct lpass_cdc_va_macro_priv { bool pre_dev_up; bool swr_dmic_enable; bool use_lpi_mixer_control; + int wlock_holders; }; + +static int lpass_cdc_va_macro_wake_enable(struct lpass_cdc_va_macro_priv *va_priv, + bool wake_enable) +{ + int ret = 0; + + mutex_lock(&va_priv->wlock); + if (wake_enable) { + if (va_priv->wlock_holders++ == 0) { + dev_dbg(va_priv->dev, "%s: pm wake\n", __func__); + pm_stay_awake(va_priv->dev); + } + } else { + if (--va_priv->wlock_holders == 0) { + dev_dbg(va_priv->dev, "%s: pm release\n", __func__); + pm_relax(va_priv->dev); + } + if (va_priv->wlock_holders < 0) + va_priv->wlock_holders = 0; + } + mutex_unlock(&va_priv->wlock); + return ret; +} + static bool lpass_cdc_va_macro_get_data(struct snd_soc_component *component, struct device **va_dev, struct lpass_cdc_va_macro_priv **va_priv, @@ -949,6 +975,7 @@ static void lpass_cdc_va_macro_tx_hpf_corner_freq_callback( snd_soc_component_update_bits(component, hpf_gate_reg, 0x02, 0x00); } + lpass_cdc_va_macro_wake_enable(va_priv, 0); } static void lpass_cdc_va_macro_mute_update_callback(struct work_struct *work) @@ -971,6 +998,7 @@ static void lpass_cdc_va_macro_mute_update_callback(struct work_struct *work) snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00); dev_dbg(va_priv->dev, "%s: decimator %u unmute\n", __func__, decimator); + lpass_cdc_va_macro_wake_enable(va_priv, 0); } static int lpass_cdc_va_macro_put_dec_enum(struct snd_kcontrol *kcontrol, @@ -1297,14 +1325,17 @@ static int lpass_cdc_va_macro_enable_dec(struct snd_soc_dapm_widget *w, */ usleep_range(6000, 6010); /* schedule work queue to Remove Mute */ + lpass_cdc_va_macro_wake_enable(va_priv, 1); queue_delayed_work(system_freezable_wq, &va_priv->va_mute_dwork[decimator].dwork, msecs_to_jiffies(va_tx_unmute_delay)); if (va_priv->va_hpf_work[decimator].hpf_cut_off_freq != - CF_MIN_3DB_150HZ) + CF_MIN_3DB_150HZ) { + lpass_cdc_va_macro_wake_enable(va_priv, 1); queue_delayed_work(system_freezable_wq, &va_priv->va_hpf_work[decimator].dwork, msecs_to_jiffies(hpf_delay)); + } /* apply gain after decimator is enabled */ snd_soc_component_write(component, tx_gain_ctl_reg, snd_soc_component_read(component, tx_gain_ctl_reg)); @@ -1339,8 +1370,10 @@ static int lpass_cdc_va_macro_enable_dec(struct snd_soc_dapm_widget *w, 0x03, 0x01); } } + lpass_cdc_va_macro_wake_enable(va_priv, 0); cancel_delayed_work_sync( &va_priv->va_mute_dwork[decimator].dwork); + lpass_cdc_va_macro_wake_enable(va_priv, 0); break; case SND_SOC_DAPM_POST_PMD: /* Disable TX CLK */ @@ -2519,6 +2552,7 @@ static int lpass_cdc_va_macro_probe(struct platform_device *pdev) } va_priv->default_clk_id = default_clk_id; va_priv->current_clk_id = TX_CORE_CLK; + va_priv->wlock_holders = 0; va_priv->use_lpi_mixer_control = false; if (of_find_property(pdev->dev.of_node, "use-lpi-control", NULL)) { @@ -2544,6 +2578,7 @@ static int lpass_cdc_va_macro_probe(struct platform_device *pdev) va_priv->pre_dev_up = true; mutex_init(&va_priv->mclk_lock); + mutex_init(&va_priv->wlock); dev_set_drvdata(&pdev->dev, va_priv); lpass_cdc_va_macro_init_ops(&ops, va_io_base); ops.clk_id_req = va_priv->default_clk_id; @@ -2564,6 +2599,7 @@ static int lpass_cdc_va_macro_probe(struct platform_device *pdev) reg_macro_fail: mutex_destroy(&va_priv->mclk_lock); + mutex_destroy(&va_priv->wlock); if (is_used_va_swr_gpio) mutex_destroy(&va_priv->swr_clk_lock); return ret; @@ -2591,6 +2627,7 @@ static int lpass_cdc_va_macro_remove(struct platform_device *pdev) pm_runtime_set_suspended(&pdev->dev); lpass_cdc_unregister_macro(&pdev->dev, VA_MACRO); mutex_destroy(&va_priv->mclk_lock); + mutex_destroy(&va_priv->wlock); if (va_priv->is_used_va_swr_gpio) mutex_destroy(&va_priv->swr_clk_lock); return 0;