diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index a41d0f50825a..76e90144ea91 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2911,12 +2911,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-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 550fc76109c6..282a6aaa9986 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 @@ -3674,11 +3675,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; - } ret = rx_macro_mclk_enable(rx, true); if (ret) { @@ -3700,7 +3699,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) @@ -3871,28 +3870,31 @@ 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_prepare_enable(rx->macro); + ret = clk_set_rate(rx->mclk, MCLK_FREQ); if (ret) return ret; - ret = clk_prepare_enable(rx->dcodec); + ret = clk_set_rate(rx->npl, MCLK_FREQ); if (ret) - goto err_dcodec; + return ret; - ret = clk_prepare_enable(rx->mclk); + ret = devm_pm_clk_create(dev); if (ret) - goto err_mclk; + return ret; - ret = clk_prepare_enable(rx->npl); - if (ret) - goto err_npl; + ret = of_pm_clk_add_clks(dev); + if (ret < 0) + return ret; - ret = clk_prepare_enable(rx->fsgen); + pm_runtime_set_autosuspend_delay(dev, 100); + pm_runtime_use_autosuspend(dev); + ret = devm_pm_runtime_enable(dev); if (ret) - goto err_fsgen; + return ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; /* reset swr block */ regmap_update_bits(rx->regmap, CDC_RX_CLK_RST_CTRL_SWR_CONTROL, @@ -3909,46 +3911,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", @@ -3976,13 +3957,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; } @@ -3992,39 +3977,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); - if (ret) { - dev_err(dev, "unable to prepare fsgen\n"); - goto err_fsgen; - } regcache_cache_only(rx->regmap, false); ret = regcache_sync(rx->regmap); - if (ret) - goto err_sync; + if (ret) { + regcache_cache_only(rx->regmap, true); + regcache_mark_dirty(rx->regmap); + pm_clk_suspend(dev); + return ret; + } return 0; -err_sync: - regcache_cache_only(rx->regmap, true); - regcache_mark_dirty(rx->regmap); - clk_disable_unprepare(rx->fsgen); -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 = { @@ -4039,7 +4008,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); diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index b6b5ef802035..9c5c95fda2b1 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 @@ -2150,21 +2151,20 @@ static int swclk_gate_enable(struct clk_hw *hw) struct regmap *regmap = tx->regmap; int ret; - ret = clk_prepare_enable(tx->mclk); - if (ret) { - dev_err(tx->dev, "failed to enable mclk\n"); + ret = pm_runtime_resume_and_get(tx->dev); + if (ret < 0) return ret; - } ret = tx_macro_mclk_enable(tx, true); if (ret) { - clk_disable_unprepare(tx->mclk); + pm_runtime_put_autosuspend(tx->dev); return ret; } regmap_update_bits(regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, CDC_TX_SWR_CLK_EN_MASK, CDC_TX_SWR_CLK_ENABLE); + return 0; } @@ -2177,7 +2177,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) @@ -2320,28 +2320,31 @@ 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_prepare_enable(tx->macro); + ret = clk_set_rate(tx->mclk, MCLK_FREQ); if (ret) goto err; - ret = clk_prepare_enable(tx->dcodec); + ret = clk_set_rate(tx->npl, MCLK_FREQ); if (ret) - goto err_dcodec; + goto err; - ret = clk_prepare_enable(tx->mclk); + ret = devm_pm_clk_create(dev); if (ret) - goto err_mclk; + goto err; - ret = clk_prepare_enable(tx->npl); - if (ret) - goto err_npl; + ret = of_pm_clk_add_clks(dev); + if (ret < 0) + goto err; - ret = clk_prepare_enable(tx->fsgen); + pm_runtime_set_autosuspend_delay(dev, 100); + pm_runtime_use_autosuspend(dev); + ret = devm_pm_runtime_enable(dev); if (ret) - goto err_fsgen; + goto err; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + goto err; /* reset soundwire block */ @@ -2361,30 +2364,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); @@ -2395,25 +2389,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; } @@ -2423,40 +2415,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); - if (ret) { - dev_err(dev, "unable to prepare fsgen\n"); - goto err_fsgen; - } - regcache_cache_only(tx->regmap, false); ret = regcache_sync(tx->regmap); - if (ret) - goto err_sync; + if (ret) { + regcache_cache_only(tx->regmap, true); + regcache_mark_dirty(tx->regmap); + pm_clk_suspend(dev); + return ret; + } return 0; -err_sync: - regcache_cache_only(tx->regmap, true); - regcache_mark_dirty(tx->regmap); - clk_disable_unprepare(tx->fsgen); -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 = {