summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorXingyu Wu <xingyu.wu@starfivetech.com>2022-10-26 12:38:41 +0300
committermason.huo <mason.huo@starfivetech.com>2022-10-27 08:57:28 +0300
commit78f5ba02befae0d2041cf57d8e61b0544570518f (patch)
treee421c83252277383aa03a40602c77fed90fccc61 /sound
parentcc1a7edcd4757021deaee4d6c8cd2ca7cdb0c5df (diff)
downloadlinux-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.c97
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;