* [PATCH 0/5] ASoC: codecs: lpass-macro: manage clocks in runtime PM
@ 2026-09-28 10:32 Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 1/5] ASoC: codecs: lpass-rx-macro: " Ajay Kumar Nandam
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Ajay Kumar Nandam @ 2026-09-28 10:32 UTC (permalink / raw)
To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai
Cc: linux-sound, linux-arm-msm, linux-kernel, Ajay Kumar Nandam
The LPASS macro codec drivers currently rely on the PM clock framework
to manage their clocks. The PM clock framework is useful for the common
case where drivers only need clocks enabled while the device is active,
but its lifecycle is not a good fit for these codec clocks.
The PM clock framework separates the prepare and enable lifetimes:
- of_pm_clk_add_clks() adds the DT clocks to the device PM clock list.
- pm_clk_acquire() is called while adding each clock.
- for normal clocks, pm_clk_acquire() calls clk_prepare() immediately
and marks the clock as PCE_STATUS_PREPARED.
- runtime resume calls pm_clk_resume(), which calls clk_enable() for
clocks already in PCE_STATUS_PREPARED.
- runtime suspend calls pm_clk_suspend(), which calls clk_disable() and
returns the clock to PCE_STATUS_PREPARED.
- clk_unprepare() is not called on normal runtime suspend; it happens
when the PM clock entry is removed/destroyed. For a codec device this
usually means driver remove or reboot, not the end of an audio use
case.
PM-clk does have a different runtime suspend path for clocks that report
clk_is_enabled_when_prepared(), where suspend uses
clk_disable_unprepare(). The issue described here is for normal clocks
with separate enable/disable operations, which remain prepared across
runtime suspend.
That prepare/enable split is problematic for platforms where the audio
macro clocks are sourced from an XO-backed clock tree. Preparing a child
clock walks the parent tree. If the parent path reaches an RPM/RPMh
managed XO clock, the provider may vote for the XO resource during
prepare. Therefore a non-zero prepare count can be sufficient to keep
the XO resource voted at the provider level, even when the corresponding
enable count is zero.
In other words, after the codec runtime suspends, PM-clk has disabled the
LPASS macro clocks, but it has intentionally kept them prepared. On
XO-backed clock trees that remaining prepared state can still hold the
parent XO vote and prevent XO shutdown. This is expected behaviour from
the PM clock framework, but it does not match the power requirement for
these audio macro clocks.
For the LPASS macro drivers the required clock lifetime is simpler: the
macro register block needs these clocks only while the device is runtime
active. Move RX, TX, VA and WSA macro clock handling into the existing
runtime PM callbacks using clk_prepare_enable() on runtime resume and
clk_disable_unprepare() on runtime suspend. This makes both prepare and
enable counts follow the device runtime PM active state and releases
parent XO votes when the macro runtime suspends.
Each macro driver is converted independently so the series remains
bisectable. The final patch drops the now-unused PM_CLK dependency from
the LPASS macro Kconfig symbols.
Signed-off-by: Ajay Kumar Nandam <ajay.nandam@oss.qualcomm.com>
---
Ajay Kumar Nandam (5):
ASoC: codecs: lpass-rx-macro: manage clocks in runtime PM
ASoC: codecs: lpass-tx-macro: manage clocks in runtime PM
ASoC: codecs: lpass-va-macro: manage clocks in runtime PM
ASoC: codecs: lpass-wsa-macro: manage clocks in runtime PM
ASoC: codecs: lpass-macro: drop PM_CLK dependency
sound/soc/codecs/Kconfig | 4 --
sound/soc/codecs/lpass-rx-macro.c | 74 ++++++++++++++++++++++++-----------
sound/soc/codecs/lpass-tx-macro.c | 75 ++++++++++++++++++++++++-----------
sound/soc/codecs/lpass-va-macro.c | 74 ++++++++++++++++++++++-------------
sound/soc/codecs/lpass-wsa-macro.c | 80 +++++++++++++++++++++++++-------------
5 files changed, 203 insertions(+), 104 deletions(-)
---
base-commit: f5f84daefcd92d7a630066635ecea1433ed5eac7
change-id: 20260925-xo-sd-runtimepm-v1-final-37ebcf40aecb
Best regards,
--
Ajay Kumar Nandam <ajay.nandam@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/5] ASoC: codecs: lpass-rx-macro: manage clocks in runtime PM
2026-09-28 10:32 [PATCH 0/5] ASoC: codecs: lpass-macro: manage clocks in runtime PM Ajay Kumar Nandam
@ 2026-09-28 10:32 ` Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 2/5] ASoC: codecs: lpass-tx-macro: " Ajay Kumar Nandam
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Ajay Kumar Nandam @ 2026-09-28 10:32 UTC (permalink / raw)
To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai
Cc: linux-sound, linux-arm-msm, linux-kernel, Ajay Kumar Nandam
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.
Signed-off-by: Ajay Kumar Nandam <ajay.nandam@oss.qualcomm.com>
---
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 c41eb8de6160..3cfaf4fe0ab2 100644
--- a/sound/soc/codecs/lpass-rx-macro.c
+++ b/sound/soc/codecs/lpass-rx-macro.c
@@ -6,7 +6,6 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/platform_device.h>
-#include <linux/pm_clock.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <sound/soc.h>
@@ -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;
@@ -3880,14 +3926,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);
@@ -3959,16 +3997,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;
@@ -3979,7 +4010,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);
@@ -3991,16 +4022,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 = {
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/5] ASoC: codecs: lpass-tx-macro: manage clocks in runtime PM
2026-09-28 10:32 [PATCH 0/5] ASoC: codecs: lpass-macro: manage clocks in runtime PM Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 1/5] ASoC: codecs: lpass-rx-macro: " Ajay Kumar Nandam
@ 2026-09-28 10:32 ` Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 3/5] ASoC: codecs: lpass-va-macro: " Ajay Kumar Nandam
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Ajay Kumar Nandam @ 2026-09-28 10:32 UTC (permalink / raw)
To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai
Cc: linux-sound, linux-arm-msm, linux-kernel, Ajay Kumar Nandam
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.
Signed-off-by: Ajay Kumar Nandam <ajay.nandam@oss.qualcomm.com>
---
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 6deaaabe43af..c9601f84c35e 100644
--- a/sound/soc/codecs/lpass-tx-macro.c
+++ b/sound/soc/codecs/lpass-tx-macro.c
@@ -6,7 +6,6 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/platform_device.h>
-#include <linux/pm_clock.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <sound/soc.h>
@@ -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 |
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/5] ASoC: codecs: lpass-va-macro: manage clocks in runtime PM
2026-09-28 10:32 [PATCH 0/5] ASoC: codecs: lpass-macro: manage clocks in runtime PM Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 1/5] ASoC: codecs: lpass-rx-macro: " Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 2/5] ASoC: codecs: lpass-tx-macro: " Ajay Kumar Nandam
@ 2026-09-28 10:32 ` Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 4/5] ASoC: codecs: lpass-wsa-macro: " Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 5/5] ASoC: codecs: lpass-macro: drop PM_CLK dependency Ajay Kumar Nandam
4 siblings, 0 replies; 6+ messages in thread
From: Ajay Kumar Nandam @ 2026-09-28 10:32 UTC (permalink / raw)
To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai
Cc: linux-sound, linux-arm-msm, linux-kernel, Ajay Kumar Nandam
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.
Signed-off-by: Ajay Kumar Nandam <ajay.nandam@oss.qualcomm.com>
---
sound/soc/codecs/lpass-va-macro.c | 74 ++++++++++++++++++++++++---------------
1 file changed, 46 insertions(+), 28 deletions(-)
diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c
index 03d6434a4a12..1197ca7210e6 100644
--- a/sound/soc/codecs/lpass-va-macro.c
+++ b/sound/soc/codecs/lpass-va-macro.c
@@ -10,7 +10,6 @@
#include <linux/of_clk.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
-#include <linux/pm_clock.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -260,6 +259,46 @@ static const struct va_macro_data sm8550_va_data = {
.has_npl_clk = false,
};
+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;
+}
+
static bool va_is_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -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,9 +1761,9 @@ 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);
+ ret = va_macro_enable_clocks(va);
if (ret) {
regcache_cache_only(va->regmap, true);
regcache_mark_dirty(va->regmap);
@@ -1752,21 +1776,15 @@ 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;
}
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 },
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 4/5] ASoC: codecs: lpass-wsa-macro: manage clocks in runtime PM
2026-09-28 10:32 [PATCH 0/5] ASoC: codecs: lpass-macro: manage clocks in runtime PM Ajay Kumar Nandam
` (2 preceding siblings ...)
2026-09-28 10:32 ` [PATCH 3/5] ASoC: codecs: lpass-va-macro: " Ajay Kumar Nandam
@ 2026-09-28 10:32 ` Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 5/5] ASoC: codecs: lpass-macro: drop PM_CLK dependency Ajay Kumar Nandam
4 siblings, 0 replies; 6+ messages in thread
From: Ajay Kumar Nandam @ 2026-09-28 10:32 UTC (permalink / raw)
To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai
Cc: linux-sound, linux-arm-msm, linux-kernel, Ajay Kumar Nandam
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.
Signed-off-by: Ajay Kumar Nandam <ajay.nandam@oss.qualcomm.com>
---
sound/soc/codecs/lpass-wsa-macro.c | 80 +++++++++++++++++++++++++-------------
1 file changed, 53 insertions(+), 27 deletions(-)
diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c
index 4242366601a5..bc0ff467c822 100644
--- a/sound/soc/codecs/lpass-wsa-macro.c
+++ b/sound/soc/codecs/lpass-wsa-macro.c
@@ -12,7 +12,6 @@
#include <linux/clk-provider.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
-#include <linux/pm_clock.h>
#include <linux/pm_runtime.h>
#include <linux/of_platform.h>
#include <sound/tlv.h>
@@ -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),
@@ -2791,14 +2837,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);
@@ -2844,16 +2882,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;
@@ -2862,9 +2893,9 @@ 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);
+ ret = wsa_macro_enable_clocks(wsa);
if (ret) {
regcache_cache_only(wsa->regmap, true);
regcache_mark_dirty(wsa->regmap);
@@ -2876,20 +2907,15 @@ static int wsa_macro_runtime_resume(struct device *dev)
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[] = {
{
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 5/5] ASoC: codecs: lpass-macro: drop PM_CLK dependency
2026-09-28 10:32 [PATCH 0/5] ASoC: codecs: lpass-macro: manage clocks in runtime PM Ajay Kumar Nandam
` (3 preceding siblings ...)
2026-09-28 10:32 ` [PATCH 4/5] ASoC: codecs: lpass-wsa-macro: " Ajay Kumar Nandam
@ 2026-09-28 10:32 ` Ajay Kumar Nandam
4 siblings, 0 replies; 6+ messages in thread
From: Ajay Kumar Nandam @ 2026-09-28 10:32 UTC (permalink / raw)
To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai
Cc: linux-sound, linux-arm-msm, linux-kernel, Ajay Kumar Nandam
The LPASS macro drivers no longer use the PM clock framework after moving
clock prepare/enable and disable/unprepare handling into their runtime PM
callbacks.
Drop the PM_CLK dependency from the RX, TX, VA and WSA macro Kconfig
symbols.
Signed-off-by: Ajay Kumar Nandam <ajay.nandam@oss.qualcomm.com>
---
sound/soc/codecs/Kconfig | 4 ----
1 file changed, 4 deletions(-)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 3cce95528dbf..1fbb077b63f3 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -2961,28 +2961,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)"
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-09-28 10:32 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-28 10:32 [PATCH 0/5] ASoC: codecs: lpass-macro: manage clocks in runtime PM Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 1/5] ASoC: codecs: lpass-rx-macro: " Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 2/5] ASoC: codecs: lpass-tx-macro: " Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 3/5] ASoC: codecs: lpass-va-macro: " Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 4/5] ASoC: codecs: lpass-wsa-macro: " Ajay Kumar Nandam
2026-09-28 10:32 ` [PATCH 5/5] ASoC: codecs: lpass-macro: drop PM_CLK dependency Ajay Kumar Nandam
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®