diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 19f4c76ceaffa..cd4b3a21a8cb3 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -670,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; @@ -3686,11 +3733,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 +3753,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) @@ -3881,28 +3926,23 @@ 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; - - ret = clk_prepare_enable(rx->mclk); - if (ret) - goto err_mclk; + 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 +3959,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", @@ -3989,12 +4008,9 @@ static int rx_macro_runtime_suspend(struct device *dev) struct rx_macro *rx = dev_get_drvdata(dev); regcache_cache_only(rx->regmap, true); + rx_macro_disable_clocks(rx); regcache_mark_dirty(rx->regmap); - clk_disable_unprepare(rx->fsgen); - clk_disable_unprepare(rx->npl); - clk_disable_unprepare(rx->mclk); - return 0; } @@ -4003,38 +4019,27 @@ 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 = rx_macro_enable_clocks(rx); 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); + rx_macro_disable_clocks(rx); + 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 = { - 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 = { @@ -4044,7 +4049,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 c7d4dc553e6aa..e7fb5339f107c 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -288,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[] = { @@ -2149,17 +2196,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 +2222,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) @@ -2315,29 +2365,23 @@ 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); - if (ret) - goto err_dcodec; - - ret = clk_prepare_enable(tx->mclk); - if (ret) - goto err_mclk; - - ret = clk_prepare_enable(tx->npl); + ret = clk_set_rate(tx->npl, MCLK_FREQ); if (ret) - goto err_npl; + 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 */ if (tx->data->flags & LPASS_MACRO_FLAG_RESET_SWR) @@ -2356,30 +2400,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,12 +2425,6 @@ 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); } @@ -2404,12 +2433,9 @@ static int tx_macro_runtime_suspend(struct device *dev) struct tx_macro *tx = dev_get_drvdata(dev); regcache_cache_only(tx->regmap, true); + tx_macro_disable_clocks(tx); regcache_mark_dirty(tx->regmap); - clk_disable_unprepare(tx->fsgen); - clk_disable_unprepare(tx->npl); - clk_disable_unprepare(tx->mclk); - return 0; } @@ -2418,39 +2444,27 @@ 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 = tx_macro_enable_clocks(tx); 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); + tx_macro_disable_clocks(tx); + 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 = { - 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 | diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 74fb6b62307f2..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); @@ -1814,7 +1838,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,13 +1849,11 @@ 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); - if (ret) - goto err_rpm_disable; - pm_runtime_set_autosuspend_delay(dev, 3000); pm_runtime_use_autosuspend(dev); pm_runtime_enable(dev); @@ -1917,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) @@ -1927,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 }, diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index a720bcc608566..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), @@ -2767,7 +2813,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; @@ -2884,17 +2930,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 = devm_pm_clk_create(dev); + ret = clk_set_rate(wsa->mclk, WSA_MACRO_MCLK_FREQ); if (ret) return ret; - ret = of_pm_clk_add_clks(dev); - if (ret < 0) - return ret; + if (wsa->npl) { + ret = clk_set_rate(wsa->npl, WSA_MACRO_MCLK_FREQ); + if (ret) + return ret; + } pm_runtime_set_autosuspend_delay(dev, 3000); pm_runtime_use_autosuspend(dev); @@ -2948,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) @@ -2959,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[] = { {