From 92d80f9374c4ae1b178a574a13098dc7e7e97a31 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 21 Sep 2026 12:30:12 +0530 Subject: [PATCH 01/12] FROMGIT: ASoC: codecs: lpass-{wsa,va}-macro: depend on PM_CLK The WSA and VA macro drivers use PM clock framework APIs after the runtime PM clock conversion. Add the matching Kconfig dependency for build configurations where PM_CLK is not otherwise selected. This is a 6.18 backport carrying only the PM_CLK Kconfig dependency from the merged WSA and VA PM clock framework changes. Link: https://patch.msgid.link/20260702-xo-sd-codec-v7-b4-v8-1-d39d0fdb7859@oss.qualcomm.com Link: https://patch.msgid.link/20260702-xo-sd-codec-v7-b4-v8-2-d39d0fdb7859@oss.qualcomm.com Signed-off-by: Ajay Kumar Nandam Signed-off-by: Aiyaz Patel --- sound/soc/codecs/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 2932eb9915606..e3c3e42e0d9e4 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2777,12 +2777,14 @@ config SND_SOC_LPASS_MACRO_COMMON config SND_SOC_LPASS_WSA_MACRO depends on COMMON_CLK + depends on PM_CLK select REGMAP_MMIO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm WSA Macro in LPASS(Low Power Audio SubSystem)" config SND_SOC_LPASS_VA_MACRO depends on COMMON_CLK + depends on PM_CLK select REGMAP_MMIO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm VA Macro in LPASS(Low Power Audio SubSystem)" From ffad402b474f18f196cceab1d9d9fbb8b80e95a0 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Thu, 2 Jul 2026 00:14:59 +0530 Subject: [PATCH 02/12] FROMGIT: ASoC: codecs: lpass-wsa-macro: Use devm_clk_hw_register() for MCLK output Switch WSA MCLK output registration to devm_clk_hw_register() so the clk hw is automatically unregistered on probe failure and remove. Reviewed-by: Konrad Dybcio Signed-off-by: Ajay Kumar Nandam Reviewed-by: Srinivas Kandagatla Tested-by: Srinivas Kandagatla Link: https://patch.msgid.link/20260702-xo-sd-codec-v7-b4-v8-3-d39d0fdb7859@oss.qualcomm.com Signed-off-by: Mark Brown Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-wsa-macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index a720bcc608566..394f76ec4f6fa 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -2767,7 +2767,7 @@ static int wsa_macro_register_mclk_output(struct wsa_macro *wsa) init.num_parents = 1; wsa->hw.init = &init; hw = &wsa->hw; - ret = clk_hw_register(wsa->dev, hw); + ret = devm_clk_hw_register(wsa->dev, hw); if (ret) return ret; From faf098a71c1da7b1d234099c3f9f22c67a7d0076 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Tue, 7 Jul 2026 15:13:11 +0530 Subject: [PATCH 03/12] FROMGIT: ASoC: codecs: lpass-tx-macro: switch to PM clock framework for runtime PM Convert the LPASS TX macro codec driver to runtime PM clock management using the PM clock framework. Replace manual macro/dcodec/mclk/npl/fsgen clock toggling with PM clock helpers and runtime PM callbacks. Keep the SWR gate runtime PM reference from SWR clock enable until disable so autosuspend does not gate clocks while SWR is still prepared. Set autosuspend delay to 100 ms so PM-clock-managed votes are dropped soon after idle while still avoiding suspend/resume churn on short gaps. Add a PM_CLK dependency to SND_SOC_LPASS_TX_MACRO since this patch introduces PM clock APIs. Tighten error unwind by checking pm_runtime_put_sync_suspend() in probe and by restoring regcache state if pm_clk_resume()/regcache_sync() fails. Co-developed-by: Ravi Hothi Signed-off-by: Ravi Hothi Signed-off-by: Ajay Kumar Nandam Link: https://patch.msgid.link/20260707-xo-sd-codec-tx-rx-v2-1-f61b4622f97f@oss.qualcomm.com Signed-off-by: Mark Brown Signed-off-by: Aiyaz Patel --- sound/soc/codecs/Kconfig | 2 + sound/soc/codecs/lpass-tx-macro.c | 112 ++++++++++++------------------ 2 files changed, 48 insertions(+), 66 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index e3c3e42e0d9e4..05c9f412ff704 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2791,12 +2791,14 @@ config SND_SOC_LPASS_VA_MACRO config SND_SOC_LPASS_RX_MACRO depends on COMMON_CLK + depends on PM_CLK select REGMAP_MMIO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm RX Macro in LPASS(Low Power Audio SubSystem)" config SND_SOC_LPASS_TX_MACRO depends on COMMON_CLK + depends on PM_CLK select REGMAP_MMIO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm TX Macro in LPASS(Low Power Audio SubSystem)" diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index c7d4dc553e6aa..543f00dd9b8b8 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -2149,17 +2150,20 @@ static int swclk_gate_enable(struct clk_hw *hw) struct regmap *regmap = tx->regmap; int ret; - ret = clk_prepare_enable(tx->mclk); + ret = pm_runtime_resume_and_get(tx->dev); + if (ret < 0) + return ret; + + ret = tx_macro_mclk_enable(tx, true); if (ret) { - dev_err(tx->dev, "failed to enable mclk\n"); + pm_runtime_put_autosuspend(tx->dev); return ret; } - tx_macro_mclk_enable(tx, true); - regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, CDC_TX_SWR_CLK_EN_MASK, CDC_TX_SWR_CLK_ENABLE); + return 0; } @@ -2172,7 +2176,7 @@ static void swclk_gate_disable(struct clk_hw *hw) CDC_TX_SWR_CLK_EN_MASK, 0x0); tx_macro_mclk_enable(tx, false); - clk_disable_unprepare(tx->mclk); + pm_runtime_put_autosuspend(tx->dev); } static int swclk_gate_is_enabled(struct clk_hw *hw) @@ -2318,25 +2322,23 @@ static int tx_macro_probe(struct platform_device *pdev) clk_set_rate(tx->mclk, MCLK_FREQ); clk_set_rate(tx->npl, MCLK_FREQ); - ret = clk_prepare_enable(tx->macro); + ret = devm_pm_clk_create(dev); if (ret) goto err; - ret = clk_prepare_enable(tx->dcodec); - if (ret) - goto err_dcodec; - - ret = clk_prepare_enable(tx->mclk); - if (ret) - goto err_mclk; + ret = of_pm_clk_add_clks(dev); + if (ret < 0) + goto err; - ret = clk_prepare_enable(tx->npl); + pm_runtime_set_autosuspend_delay(dev, 100); + pm_runtime_use_autosuspend(dev); + ret = devm_pm_runtime_enable(dev); if (ret) - goto err_npl; + goto err; - ret = clk_prepare_enable(tx->fsgen); - if (ret) - goto err_fsgen; + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + goto err; /* reset soundwire block */ @@ -2356,30 +2358,21 @@ static int tx_macro_probe(struct platform_device *pdev) tx_macro_dai, ARRAY_SIZE(tx_macro_dai)); if (ret) - goto err_clkout; - - pm_runtime_set_autosuspend_delay(dev, 3000); - pm_runtime_use_autosuspend(dev); - pm_runtime_mark_last_busy(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); + goto err_rpm_put; ret = tx_macro_register_mclk_output(tx); if (ret) - goto err_clkout; + goto err_rpm_put; + + ret = pm_runtime_put_autosuspend(dev); + if (ret < 0) + dev_warn(dev, "runtime PM put failed after probe: %d\n", ret); return 0; -err_clkout: - clk_disable_unprepare(tx->fsgen); -err_fsgen: - clk_disable_unprepare(tx->npl); -err_npl: - clk_disable_unprepare(tx->mclk); -err_mclk: - clk_disable_unprepare(tx->dcodec); -err_dcodec: - clk_disable_unprepare(tx->macro); +err_rpm_put: + if (pm_runtime_put_sync_suspend(dev) < 0) + dev_warn(dev, "runtime PM sync suspend failed in probe unwind\n"); err: lpass_macro_pds_exit(tx->pds); @@ -2390,25 +2383,23 @@ static void tx_macro_remove(struct platform_device *pdev) { struct tx_macro *tx = dev_get_drvdata(&pdev->dev); - clk_disable_unprepare(tx->macro); - clk_disable_unprepare(tx->dcodec); - clk_disable_unprepare(tx->mclk); - clk_disable_unprepare(tx->npl); - clk_disable_unprepare(tx->fsgen); - lpass_macro_pds_exit(tx->pds); } static int tx_macro_runtime_suspend(struct device *dev) { struct tx_macro *tx = dev_get_drvdata(dev); + int ret; regcache_cache_only(tx->regmap, true); - regcache_mark_dirty(tx->regmap); - clk_disable_unprepare(tx->fsgen); - clk_disable_unprepare(tx->npl); - clk_disable_unprepare(tx->mclk); + ret = pm_clk_suspend(dev); + if (ret) { + regcache_cache_only(tx->regmap, false); + return ret; + } + + regcache_mark_dirty(tx->regmap); return 0; } @@ -2418,34 +2409,23 @@ static int tx_macro_runtime_resume(struct device *dev) struct tx_macro *tx = dev_get_drvdata(dev); int ret; - ret = clk_prepare_enable(tx->mclk); + ret = pm_clk_resume(dev); if (ret) { - dev_err(dev, "unable to prepare mclk\n"); + regcache_cache_only(tx->regmap, true); + regcache_mark_dirty(tx->regmap); return ret; } - ret = clk_prepare_enable(tx->npl); - if (ret) { - dev_err(dev, "unable to prepare npl\n"); - goto err_npl; - } - - ret = clk_prepare_enable(tx->fsgen); + regcache_cache_only(tx->regmap, false); + ret = regcache_sync(tx->regmap); if (ret) { - dev_err(dev, "unable to prepare fsgen\n"); - goto err_fsgen; + regcache_cache_only(tx->regmap, true); + regcache_mark_dirty(tx->regmap); + pm_clk_suspend(dev); + return ret; } - regcache_cache_only(tx->regmap, false); - regcache_sync(tx->regmap); - return 0; -err_fsgen: - clk_disable_unprepare(tx->npl); -err_npl: - clk_disable_unprepare(tx->mclk); - - return ret; } static const struct dev_pm_ops tx_macro_pm_ops = { From 266fce83dcc9104e72aed2f00eab931b02cf58d7 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Tue, 7 Jul 2026 15:13:12 +0530 Subject: [PATCH 04/12] FROMGIT: ASoC: codecs: lpass-rx-macro: switch to PM clock framework for runtime PM Convert the LPASS RX macro codec driver to runtime PM clock management using the PM clock framework. Replace manual macro/dcodec/mclk/npl/fsgen clock toggling with PM clock helpers and runtime PM callbacks. Keep the SWR gate runtime PM reference from SWR clock enable until disable so autosuspend does not gate clocks while SWR is still prepared. Set autosuspend delay to 100 ms so PM-clock-managed votes are dropped soon after idle while still avoiding suspend/resume churn on short gaps. Add a PM_CLK dependency to SND_SOC_LPASS_RX_MACRO since this patch introduces PM clock APIs. Tighten error unwind by checking pm_runtime_put_sync_suspend() in probe and by restoring regcache state if pm_clk_resume()/regcache_sync() fails. Drop the now-empty rx_macro_remove() callback since all clock cleanup is handled by PM clock framework and devm. Co-developed-by: Ravi Hothi Signed-off-by: Ravi Hothi Signed-off-by: Ajay Kumar Nandam Link: https://patch.msgid.link/20260707-xo-sd-codec-tx-rx-v2-2-f61b4622f97f@oss.qualcomm.com Signed-off-by: Mark Brown Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-rx-macro.c | 111 +++++++++++------------------- 1 file changed, 40 insertions(+), 71 deletions(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 19f4c76ceaffa..b4fb5bfe9c495 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -3686,11 +3687,9 @@ static int swclk_gate_enable(struct clk_hw *hw) struct rx_macro *rx = to_rx_macro(hw); int ret; - ret = clk_prepare_enable(rx->mclk); - if (ret) { - dev_err(rx->dev, "unable to prepare mclk\n"); + ret = pm_runtime_resume_and_get(rx->dev); + if (ret < 0) return ret; - } rx_macro_mclk_enable(rx, true); @@ -3708,7 +3707,7 @@ static void swclk_gate_disable(struct clk_hw *hw) CDC_RX_SWR_CLK_EN_MASK, 0); rx_macro_mclk_enable(rx, false); - clk_disable_unprepare(rx->mclk); + pm_runtime_put_autosuspend(rx->dev); } static int swclk_gate_is_enabled(struct clk_hw *hw) @@ -3884,25 +3883,23 @@ static int rx_macro_probe(struct platform_device *pdev) clk_set_rate(rx->mclk, MCLK_FREQ); clk_set_rate(rx->npl, MCLK_FREQ); - ret = clk_prepare_enable(rx->macro); + ret = devm_pm_clk_create(dev); if (ret) return ret; - ret = clk_prepare_enable(rx->dcodec); - if (ret) - goto err_dcodec; - - ret = clk_prepare_enable(rx->mclk); - if (ret) - goto err_mclk; + ret = of_pm_clk_add_clks(dev); + if (ret < 0) + return ret; - ret = clk_prepare_enable(rx->npl); + pm_runtime_set_autosuspend_delay(dev, 100); + pm_runtime_use_autosuspend(dev); + ret = devm_pm_runtime_enable(dev); if (ret) - goto err_npl; + return ret; - ret = clk_prepare_enable(rx->fsgen); + ret = pm_runtime_resume_and_get(dev); if (ret) - goto err_fsgen; + return ret; /* reset swr block */ regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, @@ -3919,46 +3916,25 @@ static int rx_macro_probe(struct platform_device *pdev) rx_macro_dai, ARRAY_SIZE(rx_macro_dai)); if (ret) - goto err_clkout; - - - pm_runtime_set_autosuspend_delay(dev, 3000); - pm_runtime_use_autosuspend(dev); - pm_runtime_mark_last_busy(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); + goto err_rpm_put; ret = rx_macro_register_mclk_output(rx); if (ret) - goto err_clkout; + goto err_rpm_put; + + ret = pm_runtime_put_autosuspend(dev); + if (ret < 0) + dev_warn(dev, "runtime PM put failed after probe: %d\n", ret); return 0; -err_clkout: - clk_disable_unprepare(rx->fsgen); -err_fsgen: - clk_disable_unprepare(rx->npl); -err_npl: - clk_disable_unprepare(rx->mclk); -err_mclk: - clk_disable_unprepare(rx->dcodec); -err_dcodec: - clk_disable_unprepare(rx->macro); +err_rpm_put: + if (pm_runtime_put_sync_suspend(dev) < 0) + dev_warn(dev, "runtime PM sync suspend failed in probe unwind\n"); return ret; } -static void rx_macro_remove(struct platform_device *pdev) -{ - struct rx_macro *rx = dev_get_drvdata(&pdev->dev); - - clk_disable_unprepare(rx->mclk); - clk_disable_unprepare(rx->npl); - clk_disable_unprepare(rx->fsgen); - clk_disable_unprepare(rx->macro); - clk_disable_unprepare(rx->dcodec); -} - static const struct of_device_id rx_macro_dt_match[] = { { .compatible = "qcom,sc7280-lpass-rx-macro", @@ -3987,13 +3963,17 @@ MODULE_DEVICE_TABLE(of, rx_macro_dt_match); static int rx_macro_runtime_suspend(struct device *dev) { struct rx_macro *rx = dev_get_drvdata(dev); + int ret; regcache_cache_only(rx->regmap, true); - regcache_mark_dirty(rx->regmap); - clk_disable_unprepare(rx->fsgen); - clk_disable_unprepare(rx->npl); - clk_disable_unprepare(rx->mclk); + ret = pm_clk_suspend(dev); + if (ret) { + regcache_cache_only(rx->regmap, false); + return ret; + } + + regcache_mark_dirty(rx->regmap); return 0; } @@ -4003,33 +3983,23 @@ static int rx_macro_runtime_resume(struct device *dev) struct rx_macro *rx = dev_get_drvdata(dev); int ret; - ret = clk_prepare_enable(rx->mclk); + ret = pm_clk_resume(dev); if (ret) { - dev_err(dev, "unable to prepare mclk\n"); + regcache_cache_only(rx->regmap, true); + regcache_mark_dirty(rx->regmap); return ret; } - ret = clk_prepare_enable(rx->npl); - if (ret) { - dev_err(dev, "unable to prepare mclkx2\n"); - goto err_npl; - } - - ret = clk_prepare_enable(rx->fsgen); + regcache_cache_only(rx->regmap, false); + ret = regcache_sync(rx->regmap); if (ret) { - dev_err(dev, "unable to prepare fsgen\n"); - goto err_fsgen; + regcache_cache_only(rx->regmap, true); + regcache_mark_dirty(rx->regmap); + pm_clk_suspend(dev); + return ret; } - regcache_cache_only(rx->regmap, false); - regcache_sync(rx->regmap); return 0; -err_fsgen: - clk_disable_unprepare(rx->npl); -err_npl: - clk_disable_unprepare(rx->mclk); - - return ret; } static const struct dev_pm_ops rx_macro_pm_ops = { @@ -4044,7 +4014,6 @@ static struct platform_driver rx_macro_driver = { .pm = pm_ptr(&rx_macro_pm_ops), }, .probe = rx_macro_probe, - .remove = rx_macro_remove, }; module_platform_driver(rx_macro_driver); From 99ce5b565ae7338c1cad5edf11dd98d609387cd2 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Tue, 7 Jul 2026 15:13:13 +0530 Subject: [PATCH 05/12] FROMGIT: ASoC: codecs: lpass-{tx,rx}-macro: check clk_set_rate() return value clk_set_rate() returns 0 on success or a negative errno on failure but the TX and RX macro probe functions were ignoring it. Check the return value and bail out of probe on failure. Suggested-by: Konrad Dybcio Co-developed-by: Ravi Hothi Signed-off-by: Ravi Hothi Signed-off-by: Ajay Kumar Nandam Link: https://patch.msgid.link/20260707-xo-sd-codec-tx-rx-v2-3-f61b4622f97f@oss.qualcomm.com Signed-off-by: Mark Brown Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-rx-macro.c | 9 +++++++-- sound/soc/codecs/lpass-tx-macro.c | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index b4fb5bfe9c495..cea3d20f73986 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -3880,8 +3880,13 @@ static int rx_macro_probe(struct platform_device *pdev) rx->dev = dev; /* set MCLK and NPL rates */ - clk_set_rate(rx->mclk, MCLK_FREQ); - clk_set_rate(rx->npl, MCLK_FREQ); + ret = clk_set_rate(rx->mclk, MCLK_FREQ); + if (ret) + return ret; + + ret = clk_set_rate(rx->npl, MCLK_FREQ); + if (ret) + return ret; ret = devm_pm_clk_create(dev); if (ret) diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 543f00dd9b8b8..c9ff3e5621d45 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -2319,8 +2319,13 @@ static int tx_macro_probe(struct platform_device *pdev) tx->active_decimator[TX_MACRO_AIF3_CAP] = -1; /* set MCLK and NPL rates */ - clk_set_rate(tx->mclk, MCLK_FREQ); - clk_set_rate(tx->npl, MCLK_FREQ); + ret = clk_set_rate(tx->mclk, MCLK_FREQ); + if (ret) + goto err; + + ret = clk_set_rate(tx->npl, MCLK_FREQ); + if (ret) + goto err; ret = devm_pm_clk_create(dev); if (ret) From 6d247c60d05b663b0860c987630a13d58852f94b Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Wed, 15 Jul 2026 17:11:31 +0530 Subject: [PATCH 06/12] FROMGIT: ASoC: codecs: lpass-wsa-macro: check clk_set_rate() return value clk_set_rate() returns 0 on success or a negative errno on failure but the WSA macro probe function is ignoring it. Check the return value and bail out of probe on failure. This is rebased for the Qualcomm 6.18 tree, which already guards the optional NPL clock before programming it. Reviewed-by: Konrad Dybcio Signed-off-by: Ajay Kumar Nandam Reviewed-by: Cezary Rojewski Link: https://patch.msgid.link/20260715-xo-sd-codec-wsa-va-clk-set-rate-v2-1-16ca64c2b929@oss.qualcomm.com Signed-off-by: Mark Brown Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-wsa-macro.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 394f76ec4f6fa..637c464b6c56b 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -2884,9 +2884,15 @@ static int wsa_macro_probe(struct platform_device *pdev) wsa->dev = dev; /* set MCLK and NPL rates */ - clk_set_rate(wsa->mclk, WSA_MACRO_MCLK_FREQ); - if (wsa->npl) - clk_set_rate(wsa->npl, WSA_MACRO_MCLK_FREQ); + ret = clk_set_rate(wsa->mclk, WSA_MACRO_MCLK_FREQ); + if (ret) + return ret; + + if (wsa->npl) { + ret = clk_set_rate(wsa->npl, WSA_MACRO_MCLK_FREQ); + if (ret) + return ret; + } ret = devm_pm_clk_create(dev); if (ret) From e28e42d09eea7b70434592506e97cf0eaa333a39 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Wed, 15 Jul 2026 17:11:32 +0530 Subject: [PATCH 07/12] FROMGIT: ASoC: codecs: lpass-va-macro: check clk_set_rate() return value clk_set_rate() returns 0 on success or a negative errno on failure but the VA macro probe function is ignoring it. Check the return value and bail out of probe on failure. This is rebased for the Qualcomm 6.18 tree, which has additional Shikra-specific VA macro data fields. Reviewed-by: Konrad Dybcio Signed-off-by: Ajay Kumar Nandam Reviewed-by: Cezary Rojewski Link: https://patch.msgid.link/20260715-xo-sd-codec-wsa-va-clk-set-rate-v2-2-16ca64c2b929@oss.qualcomm.com Signed-off-by: Mark Brown Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-va-macro.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 74fb6b62307f2..3389da1eb0ae9 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -1814,7 +1814,9 @@ static int va_macro_probe(struct platform_device *pdev) dev_set_drvdata(dev, va); /* mclk rate */ - clk_set_rate(va->mclk, 2 * VA_MACRO_MCLK_FREQ); + ret = clk_set_rate(va->mclk, 2 * VA_MACRO_MCLK_FREQ); + if (ret) + goto err; if (va->has_npl_clk) { va->npl = devm_clk_get(dev, "npl"); @@ -1823,7 +1825,9 @@ static int va_macro_probe(struct platform_device *pdev) goto err; } - clk_set_rate(va->npl, 2 * VA_MACRO_MCLK_FREQ); + ret = clk_set_rate(va->npl, 2 * VA_MACRO_MCLK_FREQ); + if (ret) + goto err; } ret = va_macro_setup_pm_clocks(dev, va); From 3e653683731d37eabc090a6d49230f201a14bfc2 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 15:41:40 +0530 Subject: [PATCH 08/12] FROMLIST: ASoC: codecs: lpass-rx-macro: manage clocks in runtime PM Replace PM clock framework usage with explicit clock prepare/enable and disable/unprepare operations from runtime PM callbacks. This keeps the RX macro clock prepare state tied to the runtime PM active state, so idle suspend can release parent clock votes. Use DEFINE_RUNTIME_DEV_PM_OPS() so system suspend forces the same runtime suspend path for an active device. Link: https://lore.kernel.org/all/20260928-xo-sd-runtimepm-v1-final-v1-1-e3ebade3aeb7@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-rx-macro.c | 74 ++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index cea3d20f73986..cd4b3a21a8cb3 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -671,6 +670,53 @@ struct rx_macro { }; #define to_rx_macro(_hw) container_of(_hw, struct rx_macro, hw) +static void rx_macro_disable_clocks(struct rx_macro *rx) +{ + clk_disable_unprepare(rx->fsgen); + clk_disable_unprepare(rx->npl); + clk_disable_unprepare(rx->mclk); + clk_disable_unprepare(rx->dcodec); + clk_disable_unprepare(rx->macro); +} + +static int rx_macro_enable_clocks(struct rx_macro *rx) +{ + int ret; + + ret = clk_prepare_enable(rx->macro); + if (ret) + return ret; + + ret = clk_prepare_enable(rx->dcodec); + if (ret) + goto err_dcodec; + + ret = clk_prepare_enable(rx->mclk); + if (ret) + goto err_mclk; + + ret = clk_prepare_enable(rx->npl); + if (ret) + goto err_npl; + + ret = clk_prepare_enable(rx->fsgen); + if (ret) + goto err_fsgen; + + return 0; + +err_fsgen: + clk_disable_unprepare(rx->npl); +err_npl: + clk_disable_unprepare(rx->mclk); +err_mclk: + clk_disable_unprepare(rx->dcodec); +err_dcodec: + clk_disable_unprepare(rx->macro); + + return ret; +} + struct wcd_iir_filter_ctl { unsigned int iir_idx; unsigned int band_idx; @@ -3888,14 +3934,6 @@ static int rx_macro_probe(struct platform_device *pdev) if (ret) return ret; - ret = devm_pm_clk_create(dev); - if (ret) - return ret; - - ret = of_pm_clk_add_clks(dev); - if (ret < 0) - return ret; - pm_runtime_set_autosuspend_delay(dev, 100); pm_runtime_use_autosuspend(dev); ret = devm_pm_runtime_enable(dev); @@ -3968,16 +4006,9 @@ MODULE_DEVICE_TABLE(of, rx_macro_dt_match); static int rx_macro_runtime_suspend(struct device *dev) { struct rx_macro *rx = dev_get_drvdata(dev); - int ret; regcache_cache_only(rx->regmap, true); - - ret = pm_clk_suspend(dev); - if (ret) { - regcache_cache_only(rx->regmap, false); - return ret; - } - + rx_macro_disable_clocks(rx); regcache_mark_dirty(rx->regmap); return 0; @@ -3988,7 +4019,7 @@ static int rx_macro_runtime_resume(struct device *dev) struct rx_macro *rx = dev_get_drvdata(dev); int ret; - ret = pm_clk_resume(dev); + ret = rx_macro_enable_clocks(rx); if (ret) { regcache_cache_only(rx->regmap, true); regcache_mark_dirty(rx->regmap); @@ -4000,16 +4031,15 @@ static int rx_macro_runtime_resume(struct device *dev) if (ret) { regcache_cache_only(rx->regmap, true); regcache_mark_dirty(rx->regmap); - pm_clk_suspend(dev); + rx_macro_disable_clocks(rx); return ret; } return 0; } -static const struct dev_pm_ops rx_macro_pm_ops = { - RUNTIME_PM_OPS(rx_macro_runtime_suspend, rx_macro_runtime_resume, NULL) -}; +static DEFINE_RUNTIME_DEV_PM_OPS(rx_macro_pm_ops, rx_macro_runtime_suspend, + rx_macro_runtime_resume, NULL); static struct platform_driver rx_macro_driver = { .driver = { From 9c3112a4e55afd600b6dc384cfd7718ab1a7ce67 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 15:41:41 +0530 Subject: [PATCH 09/12] FROMLIST: ASoC: codecs: lpass-tx-macro: manage clocks in runtime PM Replace PM clock framework usage with explicit clock prepare/enable and disable/unprepare operations from runtime PM callbacks. This keeps the TX macro clock prepare state tied to the runtime PM active state, so idle suspend can release parent clock votes. Use DEFINE_RUNTIME_DEV_PM_OPS() so system suspend forces the same runtime suspend path for an active device. Link: https://lore.kernel.org/all/20260928-xo-sd-runtimepm-v1-final-v1-2-e3ebade3aeb7@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-tx-macro.c | 75 +++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index c9ff3e5621d45..e7fb5339f107c 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -289,6 +288,53 @@ struct tx_macro { }; #define to_tx_macro(_hw) container_of(_hw, struct tx_macro, hw) +static void tx_macro_disable_clocks(struct tx_macro *tx) +{ + clk_disable_unprepare(tx->fsgen); + clk_disable_unprepare(tx->npl); + clk_disable_unprepare(tx->mclk); + clk_disable_unprepare(tx->dcodec); + clk_disable_unprepare(tx->macro); +} + +static int tx_macro_enable_clocks(struct tx_macro *tx) +{ + int ret; + + ret = clk_prepare_enable(tx->macro); + if (ret) + return ret; + + ret = clk_prepare_enable(tx->dcodec); + if (ret) + goto err_dcodec; + + ret = clk_prepare_enable(tx->mclk); + if (ret) + goto err_mclk; + + ret = clk_prepare_enable(tx->npl); + if (ret) + goto err_npl; + + ret = clk_prepare_enable(tx->fsgen); + if (ret) + goto err_fsgen; + + return 0; + +err_fsgen: + clk_disable_unprepare(tx->npl); +err_npl: + clk_disable_unprepare(tx->mclk); +err_mclk: + clk_disable_unprepare(tx->dcodec); +err_dcodec: + clk_disable_unprepare(tx->macro); + + return ret; +} + static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); static struct reg_default tx_defaults[] = { @@ -2327,14 +2373,6 @@ static int tx_macro_probe(struct platform_device *pdev) if (ret) goto err; - ret = devm_pm_clk_create(dev); - if (ret) - goto err; - - ret = of_pm_clk_add_clks(dev); - if (ret < 0) - goto err; - pm_runtime_set_autosuspend_delay(dev, 100); pm_runtime_use_autosuspend(dev); ret = devm_pm_runtime_enable(dev); @@ -2345,7 +2383,6 @@ static int tx_macro_probe(struct platform_device *pdev) if (ret < 0) goto err; - /* reset soundwire block */ if (tx->data->flags & LPASS_MACRO_FLAG_RESET_SWR) regmap_update_bits(tx->regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, @@ -2394,16 +2431,9 @@ static void tx_macro_remove(struct platform_device *pdev) static int tx_macro_runtime_suspend(struct device *dev) { struct tx_macro *tx = dev_get_drvdata(dev); - int ret; regcache_cache_only(tx->regmap, true); - - ret = pm_clk_suspend(dev); - if (ret) { - regcache_cache_only(tx->regmap, false); - return ret; - } - + tx_macro_disable_clocks(tx); regcache_mark_dirty(tx->regmap); return 0; @@ -2414,7 +2444,7 @@ static int tx_macro_runtime_resume(struct device *dev) struct tx_macro *tx = dev_get_drvdata(dev); int ret; - ret = pm_clk_resume(dev); + ret = tx_macro_enable_clocks(tx); if (ret) { regcache_cache_only(tx->regmap, true); regcache_mark_dirty(tx->regmap); @@ -2426,16 +2456,15 @@ static int tx_macro_runtime_resume(struct device *dev) if (ret) { regcache_cache_only(tx->regmap, true); regcache_mark_dirty(tx->regmap); - pm_clk_suspend(dev); + tx_macro_disable_clocks(tx); return ret; } return 0; } -static const struct dev_pm_ops tx_macro_pm_ops = { - RUNTIME_PM_OPS(tx_macro_runtime_suspend, tx_macro_runtime_resume, NULL) -}; +static DEFINE_RUNTIME_DEV_PM_OPS(tx_macro_pm_ops, tx_macro_runtime_suspend, + tx_macro_runtime_resume, NULL); static const struct tx_macro_data lpass_ver_9 = { .flags = LPASS_MACRO_FLAG_HAS_NPL_CLOCK | From 1b8753db08eb3c249d8eecb6b41766997d16c3a4 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 16:14:42 +0530 Subject: [PATCH 10/12] FROMLIST: ASoC: codecs: lpass-va-macro: manage clocks in runtime PM Replace PM clock framework usage with explicit clock prepare/enable and disable/unprepare operations from runtime PM callbacks. This keeps the VA macro clock prepare state tied to the runtime PM active state, so idle suspend can release parent clock votes. Use DEFINE_RUNTIME_DEV_PM_OPS() so system suspend forces the same runtime suspend path for an active device. Link: https://lore.kernel.org/all/20260928-xo-sd-runtimepm-v1-final-v1-3-e3ebade3aeb7@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-va-macro.c | 80 +++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 26 deletions(-) diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 3389da1eb0ae9..79fee3dc56247 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -277,6 +276,46 @@ struct va_macro { #define to_va_macro(_hw) container_of(_hw, struct va_macro, hw) +static void va_macro_disable_clocks(struct va_macro *va) +{ + clk_disable_unprepare(va->npl); + clk_disable_unprepare(va->mclk); + clk_disable_unprepare(va->dcodec); + clk_disable_unprepare(va->macro); +} + +static int va_macro_enable_clocks(struct va_macro *va) +{ + int ret; + + ret = clk_prepare_enable(va->macro); + if (ret) + return ret; + + ret = clk_prepare_enable(va->dcodec); + if (ret) + goto err_dcodec; + + ret = clk_prepare_enable(va->mclk); + if (ret) + goto err_mclk; + + ret = clk_prepare_enable(va->npl); + if (ret) + goto err_npl; + + return 0; + +err_npl: + clk_disable_unprepare(va->mclk); +err_mclk: + clk_disable_unprepare(va->dcodec); +err_dcodec: + clk_disable_unprepare(va->macro); + + return ret; +} + struct va_macro_data { bool has_swr_master; bool has_npl_clk; @@ -1602,21 +1641,6 @@ static void fsgen_gate_disable(struct clk_hw *hw) pm_runtime_put_autosuspend(va->dev); } -static int va_macro_setup_pm_clocks(struct device *dev, struct va_macro *va) -{ - int ret; - - ret = devm_pm_clk_create(dev); - if (ret) - return ret; - - ret = of_pm_clk_add_clks(dev); - if (ret < 0) - return ret; - - return 0; -} - static int fsgen_gate_is_enabled(struct clk_hw *hw) { struct va_macro *va = to_va_macro(hw); @@ -1830,10 +1854,6 @@ static int va_macro_probe(struct platform_device *pdev) goto err; } - ret = va_macro_setup_pm_clocks(dev, va); - if (ret) - goto err_rpm_disable; - pm_runtime_set_autosuspend_delay(dev, 3000); pm_runtime_use_autosuspend(dev); pm_runtime_enable(dev); @@ -1921,9 +1941,10 @@ static int va_macro_runtime_suspend(struct device *dev) struct va_macro *va = dev_get_drvdata(dev); regcache_cache_only(va->regmap, true); + va_macro_disable_clocks(va); regcache_mark_dirty(va->regmap); - return pm_clk_suspend(dev); + return 0; } static int va_macro_runtime_resume(struct device *dev) @@ -1931,20 +1952,27 @@ static int va_macro_runtime_resume(struct device *dev) struct va_macro *va = dev_get_drvdata(dev); int ret; - ret = pm_clk_resume(dev); + ret = va_macro_enable_clocks(va); if (ret) return ret; regcache_cache_only(va->regmap, false); - return regcache_sync(va->regmap); + ret = regcache_sync(va->regmap); + if (ret) { + regcache_cache_only(va->regmap, true); + regcache_mark_dirty(va->regmap); + va_macro_disable_clocks(va); + return ret; + } + + return 0; } -static const struct dev_pm_ops va_macro_pm_ops = { - RUNTIME_PM_OPS(va_macro_runtime_suspend, va_macro_runtime_resume, NULL) -}; +static DEFINE_RUNTIME_DEV_PM_OPS(va_macro_pm_ops, va_macro_runtime_suspend, + va_macro_runtime_resume, NULL); static const struct of_device_id va_macro_dt_match[] = { { .compatible = "qcom,sc7280-lpass-va-macro", .data = &sc7280_va_data }, From 2f2543a9c555eb175d1516a8cba692ef6a3a4ba6 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 16:14:50 +0530 Subject: [PATCH 11/12] FROMLIST: ASoC: codecs: lpass-wsa-macro: manage clocks in runtime PM Replace PM clock framework usage with explicit clock prepare/enable and disable/unprepare operations from runtime PM callbacks. This keeps the WSA macro clock prepare state tied to the runtime PM active state, so idle suspend can release parent clock votes. Use DEFINE_RUNTIME_DEV_PM_OPS() so system suspend forces the same runtime suspend path for an active device. Link: https://lore.kernel.org/all/20260928-xo-sd-runtimepm-v1-final-v1-4-e3ebade3aeb7@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-wsa-macro.c | 76 ++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 637c464b6c56b..d7f4e2ad5750a 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include "lpass-macro-common.h" @@ -425,6 +424,53 @@ struct wsa_macro { }; #define to_wsa_macro(_hw) container_of(_hw, struct wsa_macro, hw) +static void wsa_macro_disable_clocks(struct wsa_macro *wsa) +{ + clk_disable_unprepare(wsa->fsgen); + clk_disable_unprepare(wsa->npl); + clk_disable_unprepare(wsa->mclk); + clk_disable_unprepare(wsa->dcodec); + clk_disable_unprepare(wsa->macro); +} + +static int wsa_macro_enable_clocks(struct wsa_macro *wsa) +{ + int ret; + + ret = clk_prepare_enable(wsa->macro); + if (ret) + return ret; + + ret = clk_prepare_enable(wsa->dcodec); + if (ret) + goto err_dcodec; + + ret = clk_prepare_enable(wsa->mclk); + if (ret) + goto err_mclk; + + ret = clk_prepare_enable(wsa->npl); + if (ret) + goto err_npl; + + ret = clk_prepare_enable(wsa->fsgen); + if (ret) + goto err_fsgen; + + return 0; + +err_fsgen: + clk_disable_unprepare(wsa->npl); +err_npl: + clk_disable_unprepare(wsa->mclk); +err_mclk: + clk_disable_unprepare(wsa->dcodec); +err_dcodec: + clk_disable_unprepare(wsa->macro); + + return ret; +} + static const struct wsa_reg_layout wsa_codec_v2_1 = { .rx_intx_1_mix_inp0_sel_mask = GENMASK(2, 0), .rx_intx_1_mix_inp1_sel_mask = GENMASK(5, 3), @@ -2894,14 +2940,6 @@ static int wsa_macro_probe(struct platform_device *pdev) return ret; } - ret = devm_pm_clk_create(dev); - if (ret) - return ret; - - ret = of_pm_clk_add_clks(dev); - if (ret < 0) - return ret; - pm_runtime_set_autosuspend_delay(dev, 3000); pm_runtime_use_autosuspend(dev); pm_runtime_enable(dev); @@ -2954,9 +2992,10 @@ static int wsa_macro_runtime_suspend(struct device *dev) struct wsa_macro *wsa = dev_get_drvdata(dev); regcache_cache_only(wsa->regmap, true); + wsa_macro_disable_clocks(wsa); regcache_mark_dirty(wsa->regmap); - return pm_clk_suspend(dev); + return 0; } static int wsa_macro_runtime_resume(struct device *dev) @@ -2965,16 +3004,23 @@ static int wsa_macro_runtime_resume(struct device *dev) int ret; regcache_cache_only(wsa->regmap, false); - ret = pm_clk_resume(dev); + ret = wsa_macro_enable_clocks(wsa); if (ret) return ret; - return regcache_sync(wsa->regmap); + ret = regcache_sync(wsa->regmap); + if (ret) { + regcache_cache_only(wsa->regmap, true); + regcache_mark_dirty(wsa->regmap); + wsa_macro_disable_clocks(wsa); + return ret; + } + + return 0; } -static const struct dev_pm_ops wsa_macro_pm_ops = { - RUNTIME_PM_OPS(wsa_macro_runtime_suspend, wsa_macro_runtime_resume, NULL) -}; +static DEFINE_RUNTIME_DEV_PM_OPS(wsa_macro_pm_ops, wsa_macro_runtime_suspend, + wsa_macro_runtime_resume, NULL); static const struct of_device_id wsa_macro_dt_match[] = { { From 5b5d42f2fb1d89f0c1ba162389a4daa11b1684dd Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 16:14:58 +0530 Subject: [PATCH 12/12] FROMLIST: ASoC: codecs: lpass-macro: drop PM_CLK dependency The LPASS macro codec drivers no longer use PM clock framework helpers after moving clock handling into runtime PM callbacks. Drop the PM_CLK dependency from RX, TX, VA and WSA macro Kconfig symbols. Link: https://lore.kernel.org/all/20260928-xo-sd-runtimepm-v1-final-v1-5-e3ebade3aeb7@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam Signed-off-by: Aiyaz Patel --- sound/soc/codecs/Kconfig | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 05c9f412ff704..2932eb9915606 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2777,28 +2777,24 @@ config SND_SOC_LPASS_MACRO_COMMON config SND_SOC_LPASS_WSA_MACRO depends on COMMON_CLK - depends on PM_CLK select REGMAP_MMIO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm WSA Macro in LPASS(Low Power Audio SubSystem)" config SND_SOC_LPASS_VA_MACRO depends on COMMON_CLK - depends on PM_CLK select REGMAP_MMIO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm VA Macro in LPASS(Low Power Audio SubSystem)" config SND_SOC_LPASS_RX_MACRO depends on COMMON_CLK - depends on PM_CLK select REGMAP_MMIO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm RX Macro in LPASS(Low Power Audio SubSystem)" config SND_SOC_LPASS_TX_MACRO depends on COMMON_CLK - depends on PM_CLK select REGMAP_MMIO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm TX Macro in LPASS(Low Power Audio SubSystem)"