diff options
author | Xingyu Wu <xingyu.wu@starfivetech.com> | 2022-10-26 12:38:41 +0300 |
---|---|---|
committer | mason.huo <mason.huo@starfivetech.com> | 2022-10-27 08:57:28 +0300 |
commit | 78f5ba02befae0d2041cf57d8e61b0544570518f (patch) | |
tree | e421c83252277383aa03a40602c77fed90fccc61 /sound | |
parent | cc1a7edcd4757021deaee4d6c8cd2ca7cdb0c5df (diff) | |
download | linux-78f5ba02befae0d2041cf57d8e61b0544570518f.tar.xz |
sound:starfive:Add hibernation in I2S
Add hibernation in starfive I2S driver.
Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/starfive/starfive_i2s.c | 97 |
1 files changed, 29 insertions, 68 deletions
diff --git a/sound/soc/starfive/starfive_i2s.c b/sound/soc/starfive/starfive_i2s.c index 9b2ef6e7b536..00dbdae033bb 100644 --- a/sound/soc/starfive/starfive_i2s.c +++ b/sound/soc/starfive/starfive_i2s.c @@ -434,8 +434,8 @@ static int dw_i2s_runtime_suspend(struct device *dev) struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev); if (dw_dev->capability & DW_I2S_MASTER) { - clk_disable_unprepare(dw_dev->clk_i2s_lrck); - clk_disable_unprepare(dw_dev->clk_i2s_bclk); + clk_disable_unprepare(dw_dev->clk_i2s_bclk_mst); + clk_disable_unprepare(dw_dev->clk_i2s_apb); } return 0; @@ -447,13 +447,13 @@ static int dw_i2s_runtime_resume(struct device *dev) int ret; if (dw_dev->capability & DW_I2S_MASTER) { - ret = clk_prepare_enable(dw_dev->clk_i2s_bclk); + ret = clk_prepare_enable(dw_dev->clk_i2s_apb); if (ret) { - dev_err(dw_dev->dev, "Failed to enable clk_i2s_bclk\n"); + dev_err(dw_dev->dev, "Failed to enable clk_i2s_apb\n"); return ret; } - ret = clk_prepare_enable(dw_dev->clk_i2s_lrck); + ret = clk_prepare_enable(dw_dev->clk_i2s_bclk_mst); if (ret) { dev_err(dw_dev->dev, "Failed to enable clk_i2s_lrck\n"); return ret; @@ -465,14 +465,7 @@ static int dw_i2s_runtime_resume(struct device *dev) static int dw_i2s_suspend(struct snd_soc_component *component) { - struct dw_i2s_dev *dev = snd_soc_component_get_drvdata(component); - - if (dev->capability & DW_I2S_MASTER) { - clk_disable_unprepare(dev->clk_i2s_lrck); - clk_disable_unprepare(dev->clk_i2s_bclk); - } - - return 0; + return pm_runtime_force_suspend(component->dev); } static int dw_i2s_resume(struct snd_soc_component *component) @@ -482,19 +475,9 @@ static int dw_i2s_resume(struct snd_soc_component *component) int stream; int ret; - if (dev->capability & DW_I2S_MASTER) { - ret = clk_prepare_enable(dev->clk_i2s_bclk); - if (ret) { - dev_err(dev->dev, "Failed to enable clk_i2s_bclk\n"); - return ret; - } - - ret = clk_prepare_enable(dev->clk_i2s_lrck); - if (ret) { - dev_err(dev->dev, "Failed to enable clk_i2s_lrck\n"); - return ret; - } - } + ret = pm_runtime_force_resume(component->dev); + if (ret) + return ret; for_each_component_dais(component, dai) { for_each_pcm_streams(stream) @@ -521,7 +504,6 @@ static int dw_i2srx_clk_init(struct platform_device *pdev, struct dw_i2s_dev *de int ret = 0; static struct clk_bulk_data clks[] = { - { .id = "apb0" }, { .id = "i2srx_apb" }, { .id = "i2srx_bclk_mst" }, { .id = "i2srx_lrck_mst" }, @@ -535,12 +517,11 @@ static int dw_i2srx_clk_init(struct platform_device *pdev, struct dw_i2s_dev *de goto exit; } - dev->clk_apb0 = clks[0].clk; - dev->clk_i2s_apb = clks[1].clk; - dev->clk_i2s_bclk_mst = clks[2].clk; - dev->clk_i2s_lrck_mst = clks[3].clk; - dev->clk_i2s_bclk = clks[4].clk; - dev->clk_i2s_lrck = clks[5].clk; + dev->clk_i2s_apb = clks[0].clk; + dev->clk_i2s_bclk_mst = clks[1].clk; + dev->clk_i2s_lrck_mst = clks[2].clk; + dev->clk_i2s_bclk = clks[3].clk; + dev->clk_i2s_lrck = clks[4].clk; dev->rst_i2s_apb = devm_reset_control_get_exclusive(&pdev->dev, "rst_apb_rx"); if (IS_ERR(dev->rst_i2s_apb)) { @@ -559,16 +540,10 @@ static int dw_i2srx_clk_init(struct platform_device *pdev, struct dw_i2s_dev *de reset_control_assert(dev->rst_i2s_apb); reset_control_assert(dev->rst_i2s_bclk); - ret = clk_prepare_enable(dev->clk_apb0); - if (ret) { - dev_err(&pdev->dev, "failed to prepare enable clk_apb0\n"); - goto exit; - } - ret = clk_prepare_enable(dev->clk_i2s_apb); if (ret) { dev_err(&pdev->dev, "failed to prepare enable clk_i2srx_apb\n"); - goto err_dis_i2srx_apb; + goto exit; } ret = clk_prepare_enable(dev->clk_i2s_bclk_mst); @@ -577,24 +552,6 @@ static int dw_i2srx_clk_init(struct platform_device *pdev, struct dw_i2s_dev *de goto err_dis_bclk_mst; } - ret = clk_prepare_enable(dev->clk_i2s_lrck_mst); - if (ret) { - dev_err(&pdev->dev, "failed to prepare enable clk_i2srx_3ch_lrck_mst\n"); - goto err_dis_lrck_mst; - } - - ret = clk_prepare_enable(dev->clk_i2s_bclk); - if (ret) { - dev_err(&pdev->dev, "failed to prepare enable clk_i2srx_3ch_bclk\n"); - goto err_dis_bclk; - } - - ret = clk_prepare_enable(dev->clk_i2s_lrck); - if (ret) { - dev_err(&pdev->dev, "failed to prepare enable clk_i2srx_3ch_lrck\n"); - goto err_dis_lrck; - } - reset_control_deassert(dev->rst_i2s_apb); reset_control_deassert(dev->rst_i2s_bclk); @@ -602,16 +559,8 @@ static int dw_i2srx_clk_init(struct platform_device *pdev, struct dw_i2s_dev *de I2SRX_3CH_ADC_MASK, I2SRX_3CH_ADC_EN); return 0; -err_dis_i2srx_apb: - clk_disable_unprepare(dev->clk_apb0); err_dis_bclk_mst: clk_disable_unprepare(dev->clk_i2s_apb); -err_dis_lrck_mst: - clk_disable_unprepare(dev->clk_i2s_bclk_mst); -err_dis_bclk: - clk_disable_unprepare(dev->clk_i2s_lrck_mst); -err_dis_lrck: - clk_disable_unprepare(dev->clk_i2s_bclk); exit: return ret; } @@ -1022,11 +971,21 @@ static int dw_i2s_probe(struct platform_device *pdev) } pm_runtime_enable(&pdev->dev); + +#ifdef CONFIG_PM + if (dev->capability & DW_I2S_MASTER) { + clk_disable_unprepare(dev->clk_i2s_bclk_mst); + clk_disable_unprepare(dev->clk_i2s_apb); + } +#endif + return 0; err_clk_disable: - if (dev->capability & DW_I2S_MASTER) + if (dev->capability & DW_I2S_MASTER) { clk_disable_unprepare(dev->clk_i2s_bclk_mst); + clk_disable_unprepare(dev->clk_i2s_apb); + } return ret; } @@ -1034,8 +993,10 @@ static int dw_i2s_remove(struct platform_device *pdev) { struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev); - if (dev->capability & DW_I2S_MASTER) + if (dev->capability & DW_I2S_MASTER) { clk_disable_unprepare(dev->clk_i2s_bclk_mst); + clk_disable_unprepare(dev->clk_i2s_apb); + } pm_runtime_disable(&pdev->dev); return 0; |