From 3ed15210142f5a53f3845af1be458eca17f53116 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 15:41:40 +0530 Subject: [PATCH 1/5] 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 6f6a533a7fa62..bf8287c25c85b 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 @@ -670,6 +669,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; @@ -3883,14 +3929,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); @@ -3964,16 +4002,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; @@ -3984,7 +4015,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); @@ -3996,16 +4027,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 79e442e173d55a4c4b8edecf9cea94c192c10e89 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 15:41:41 +0530 Subject: [PATCH 2/5] 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 8484134bf9d11..fc9be258cdf77 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[] = { @@ -2328,14 +2374,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); @@ -2346,7 +2384,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, @@ -2395,16 +2432,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; @@ -2415,7 +2445,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); @@ -2427,16 +2457,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 a81e57e76b992dcbe8818cc6aec8a7783df157be Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 16:14:42 +0530 Subject: [PATCH 3/5] 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 | 78 +++++++++++++++++++------------ 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index f0797715ab545..de327cedb36f8 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 @@ -233,6 +232,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; @@ -1621,14 +1660,6 @@ static int va_macro_probe(struct platform_device *pdev) 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); @@ -1719,16 +1750,9 @@ static void va_macro_remove(struct platform_device *pdev) static int va_macro_runtime_suspend(struct device *dev) { struct va_macro *va = dev_get_drvdata(dev); - int ret; regcache_cache_only(va->regmap, true); - - ret = pm_clk_suspend(dev); - if (ret) { - regcache_cache_only(va->regmap, false); - return ret; - } - + va_macro_disable_clocks(va); regcache_mark_dirty(va->regmap); return 0; @@ -1737,14 +1761,11 @@ static int va_macro_runtime_suspend(struct device *dev) static int va_macro_runtime_resume(struct device *dev) { struct va_macro *va = dev_get_drvdata(dev); - int ret, sret; + int ret; - ret = pm_clk_resume(dev); - if (ret) { - regcache_cache_only(va->regmap, true); - regcache_mark_dirty(va->regmap); + ret = va_macro_enable_clocks(va); + if (ret) return ret; - } regcache_cache_only(va->regmap, false); @@ -1752,11 +1773,7 @@ static int va_macro_runtime_resume(struct device *dev) if (ret) { regcache_cache_only(va->regmap, true); regcache_mark_dirty(va->regmap); - sret = pm_clk_suspend(dev); - if (sret) - dev_err(va->dev, - "failed to suspend clocks after regcache sync failure: %d\n", - sret); + va_macro_disable_clocks(va); return ret; } @@ -1764,9 +1781,8 @@ static int va_macro_runtime_resume(struct device *dev) } -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 885c2db6e33d9818f301c6a6ccaf133fe9b1f142 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 16:14:50 +0530 Subject: [PATCH 4/5] 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 | 86 +++++++++++++++++++----------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 0e83a1ad77e53..eb6db15f1d2ea 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -424,6 +423,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), @@ -2783,14 +2829,6 @@ static int wsa_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); @@ -2836,16 +2874,9 @@ static int wsa_macro_probe(struct platform_device *pdev) static int wsa_macro_runtime_suspend(struct device *dev) { struct wsa_macro *wsa = dev_get_drvdata(dev); - int ret; regcache_cache_only(wsa->regmap, true); - - ret = pm_clk_suspend(dev); - if (ret) { - regcache_cache_only(wsa->regmap, false); - return ret; - } - + wsa_macro_disable_clocks(wsa); regcache_mark_dirty(wsa->regmap); return 0; @@ -2854,34 +2885,27 @@ static int wsa_macro_runtime_suspend(struct device *dev) static int wsa_macro_runtime_resume(struct device *dev) { struct wsa_macro *wsa = dev_get_drvdata(dev); - int ret, sret; + int ret; - ret = pm_clk_resume(dev); - if (ret) { - regcache_cache_only(wsa->regmap, true); - regcache_mark_dirty(wsa->regmap); + ret = wsa_macro_enable_clocks(wsa); + if (ret) return ret; - } + regcache_cache_only(wsa->regmap, false); ret = regcache_sync(wsa->regmap); if (ret) { regcache_cache_only(wsa->regmap, true); regcache_mark_dirty(wsa->regmap); - sret = pm_clk_suspend(dev); - if (sret) - dev_err(dev, - "failed to suspend clocks after regcache sync failure: %d\n", - sret); + 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 c09a405f528c8e4d1faad9898e4f0ea8725499dd Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 16:14:58 +0530 Subject: [PATCH 5/5] 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 ad66ec525e4cc..c030bac8e8887 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2936,28 +2936,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)"