407 lines
13 KiB
Diff
407 lines
13 KiB
Diff
From 6ca6a6ad0b34ee1a04fe48f08d9b1345220b89fc Mon Sep 17 00:00:00 2001
|
|
From: denglei <denglei@eswincomputing.com>
|
|
Date: Mon, 15 Jul 2024 09:00:09 +0800
|
|
Subject: [PATCH 108/219] feat:I2s support low power.
|
|
|
|
Changelogs:
|
|
I2s support low power.
|
|
|
|
Signed-off-by: denglei <denglei@eswincomputing.com>
|
|
---
|
|
arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts | 3 -
|
|
arch/riscv/boot/dts/eswin/eic7700-evb.dts | 3 -
|
|
.../boot/dts/eswin/hifive-premier-550.dts | 2 -
|
|
drivers/gpu/drm/eswin/dw-hdmi.c | 2 +
|
|
sound/soc/eswin/esw-i2s.c | 154 +++++++-----------
|
|
sound/soc/eswin/esw-i2s.h | 1 -
|
|
6 files changed, 62 insertions(+), 103 deletions(-)
|
|
|
|
diff --git a/arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts b/arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts
|
|
index c95b68dafe7c..385c39c4395b 100644
|
|
--- a/arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts
|
|
+++ b/arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts
|
|
@@ -388,7 +388,6 @@ &dw_hdmi_hdcp2 {
|
|
|
|
&d0_i2s0 {
|
|
status = "okay";
|
|
- eswin-plat = <1>;
|
|
d0_i2s0_port: port {
|
|
d0_i2s0_endpoint: endpoint {
|
|
remote-endpoint = <&hdmi_in_i2s>;
|
|
@@ -399,7 +398,6 @@ d0_i2s0_endpoint: endpoint {
|
|
|
|
&d0_i2s1 {
|
|
status = "okay";
|
|
- eswin-plat = <1>;
|
|
d0_i2s1_port: port {
|
|
d0_i2s1_endpoint: endpoint {
|
|
remote-endpoint = <&d0_codec0_endpoint>;
|
|
@@ -410,7 +408,6 @@ d0_i2s1_endpoint: endpoint {
|
|
|
|
&d0_i2s2 {
|
|
status = "okay";
|
|
- eswin-plat = <1>;
|
|
d0_i2s2_port: port {
|
|
d0_i2s2_endpoint: endpoint {
|
|
remote-endpoint = <&d0_codec1_endpoint>;
|
|
diff --git a/arch/riscv/boot/dts/eswin/eic7700-evb.dts b/arch/riscv/boot/dts/eswin/eic7700-evb.dts
|
|
index bbabd938baef..fc7dd40a4bc4 100644
|
|
--- a/arch/riscv/boot/dts/eswin/eic7700-evb.dts
|
|
+++ b/arch/riscv/boot/dts/eswin/eic7700-evb.dts
|
|
@@ -349,7 +349,6 @@ &dw_hdmi_hdcp2 {
|
|
|
|
&d0_i2s0 {
|
|
status = "okay";
|
|
- eswin-plat = <1>;
|
|
ports {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
@@ -372,7 +371,6 @@ d0_i2s0_endpoint1: endpoint {
|
|
|
|
&d0_i2s1 {
|
|
status = "okay";
|
|
- eswin-plat = <1>;
|
|
d0_i2s1_port: port {
|
|
d0_i2s1_endpoint: endpoint {
|
|
remote-endpoint = <&d0_codec1_endpoint>;
|
|
@@ -383,7 +381,6 @@ d0_i2s1_endpoint: endpoint {
|
|
|
|
&d0_i2s2 {
|
|
status = "okay";
|
|
- eswin-plat = <1>;
|
|
d0_i2s2_port: port {
|
|
d0_i2s2_endpoint: endpoint {
|
|
remote-endpoint = <&d0_codec2_endpoint>;
|
|
diff --git a/arch/riscv/boot/dts/eswin/hifive-premier-550.dts b/arch/riscv/boot/dts/eswin/hifive-premier-550.dts
|
|
index 8bd614757b01..11ecf0bb3cd2 100644
|
|
--- a/arch/riscv/boot/dts/eswin/hifive-premier-550.dts
|
|
+++ b/arch/riscv/boot/dts/eswin/hifive-premier-550.dts
|
|
@@ -329,7 +329,6 @@ &dw_hdmi_hdcp2 {
|
|
&d0_i2s0 {
|
|
/* connect M.2 KEY E */
|
|
status = "okay";
|
|
- eswin-plat = <1>;
|
|
d0_i2s0_port: port {
|
|
d0_i2s0_endpoint: endpoint {
|
|
remote-endpoint = <&hdmi_in_i2s>;
|
|
@@ -340,7 +339,6 @@ d0_i2s0_endpoint: endpoint {
|
|
|
|
&d0_i2s1 {
|
|
status = "okay";
|
|
- eswin-plat = <1>;
|
|
d0_i2s1_port: port {
|
|
d0_i2s1_endpoint: endpoint {
|
|
remote-endpoint = <&d0_codec0_endpoint>;
|
|
diff --git a/drivers/gpu/drm/eswin/dw-hdmi.c b/drivers/gpu/drm/eswin/dw-hdmi.c
|
|
index 71c89e7e3bb5..7123022dfd0c 100644
|
|
--- a/drivers/gpu/drm/eswin/dw-hdmi.c
|
|
+++ b/drivers/gpu/drm/eswin/dw-hdmi.c
|
|
@@ -4548,6 +4548,7 @@ EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
|
|
|
|
void dw_hdmi_suspend(struct dw_hdmi *hdmi)
|
|
{
|
|
+ dev_dbg(hdmi->dev, "%s", __func__);
|
|
if (!hdmi) {
|
|
dev_warn(hdmi->dev, "HDMI has not been initialized\n");
|
|
return;
|
|
@@ -4578,6 +4579,7 @@ EXPORT_SYMBOL_GPL(dw_hdmi_suspend);
|
|
|
|
void dw_hdmi_resume(struct dw_hdmi *hdmi)
|
|
{
|
|
+ dev_dbg(hdmi->dev, "%s", __func__);
|
|
dw_hdmi_init_hw(hdmi);
|
|
}
|
|
EXPORT_SYMBOL_GPL(dw_hdmi_resume);
|
|
diff --git a/sound/soc/eswin/esw-i2s.c b/sound/soc/eswin/esw-i2s.c
|
|
index 8fe165ddb0d6..acf232996815 100755
|
|
--- a/sound/soc/eswin/esw-i2s.c
|
|
+++ b/sound/soc/eswin/esw-i2s.c
|
|
@@ -73,6 +73,8 @@
|
|
SNDRV_PCM_RATE_8000)
|
|
#define ESW_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
|
|
|
|
+static struct clk *g_mclk;
|
|
+
|
|
static u32 dmaen_txch[] = {
|
|
DMAEN_TXCH_0,
|
|
DMAEN_TXCH_1,
|
|
@@ -433,11 +435,6 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
|
|
{
|
|
struct i2s_dev *i2s_drvdata = snd_soc_dai_get_drvdata(dai);
|
|
struct i2s_clk_config_data *config = &i2s_drvdata->config;
|
|
- struct device_node *node = i2s_drvdata->dev->of_node;
|
|
- struct regmap *vo_mclk_sel_regmap;
|
|
- uint32_t vo_mclk_sel_reg;
|
|
- uint32_t vo_mclk_sel;
|
|
- int ret;
|
|
uint32_t div_num = 0;
|
|
uint32_t div_num_reg;
|
|
|
|
@@ -478,59 +475,25 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
|
|
i2s_write_reg(i2s_drvdata->i2s_base, CCR, i2s_drvdata->ccr);
|
|
config->sample_rate = params_rate(params);
|
|
if (i2s_drvdata->capability & DW_I2S_MASTER) {
|
|
- if (!i2s_drvdata->eswin_plat) {
|
|
- vo_mclk_sel_regmap =
|
|
- syscon_regmap_lookup_by_phandle(node, "vo_mclk_sel,syscrg");
|
|
- if (IS_ERR(vo_mclk_sel_regmap)) {
|
|
- dev_err(i2s_drvdata->dev, "No vo_mclk_sel,syscrg phandle specified\n");
|
|
- return PTR_ERR(vo_mclk_sel_regmap);
|
|
- }
|
|
- ret = of_property_read_u32_index(node, "vo_mclk_sel,syscrg", 1,
|
|
- &vo_mclk_sel_reg);
|
|
- if (ret) {
|
|
- dev_err(i2s_drvdata->dev, "can't get vo_mclk_sel_reg offset (%d)\n", ret);
|
|
- return ret;
|
|
- }
|
|
- regmap_read(vo_mclk_sel_regmap, vo_mclk_sel_reg, &vo_mclk_sel);
|
|
- vo_mclk_sel &= ~VO_MCLK_DIVSOR_MASK;
|
|
-
|
|
- switch (config->sample_rate) {
|
|
- case 96000:
|
|
- vo_mclk_sel |= (0x10 << VO_MCLK_DIVSOR_OFFSET);
|
|
- break;
|
|
- case 48000:
|
|
- vo_mclk_sel |= (0x12 << VO_MCLK_DIVSOR_OFFSET);
|
|
- break;
|
|
- case 44100:
|
|
- vo_mclk_sel |= (0x11 << VO_MCLK_DIVSOR_OFFSET);
|
|
- break;
|
|
- default:
|
|
- dev_err(i2s_drvdata->dev, "Can't support sample rate: %d\n",
|
|
- config->sample_rate);
|
|
+ if (MAX_SAMPLE_RATE_SUPPORT % config->sample_rate != 0) {
|
|
+ dev_err(i2s_drvdata->dev, "Not support sample rate: %d\n", config->sample_rate);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ div_num = MAX_SAMPLE_RATE_SUPPORT / config->sample_rate - 1;
|
|
+
|
|
+ if (i2s_drvdata->active) {
|
|
+ if (i2s_drvdata->i2s_div_num != div_num) {
|
|
+ dev_err(i2s_drvdata->dev, "Not support the playback and capture clocks are different\n");
|
|
return -EINVAL;
|
|
}
|
|
- regmap_write(vo_mclk_sel_regmap, vo_mclk_sel_reg, vo_mclk_sel);
|
|
} else {
|
|
- if (MAX_SAMPLE_RATE_SUPPORT % config->sample_rate != 0) {
|
|
- dev_err(i2s_drvdata->dev, "Not support sample rate: %d\n", config->sample_rate);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- div_num = MAX_SAMPLE_RATE_SUPPORT / config->sample_rate - 1;
|
|
+ div_num_reg = i2s_read_reg(i2s_drvdata->i2s_div_base, 0) & ~DIV_NUM_MASK;
|
|
+ div_num_reg |= div_num;
|
|
|
|
- if (i2s_drvdata->active) {
|
|
- if (i2s_drvdata->i2s_div_num != div_num) {
|
|
- dev_err(i2s_drvdata->dev, "Not support the playback and capture clocks are different\n");
|
|
- return -EINVAL;
|
|
- }
|
|
- } else {
|
|
- div_num_reg = i2s_read_reg(i2s_drvdata->i2s_div_base, 0) & ~DIV_NUM_MASK;
|
|
- div_num_reg |= div_num;
|
|
-
|
|
- dev_dbg(i2s_drvdata->dev, "div num:0x%x\n", div_num);
|
|
- i2s_drvdata->i2s_div_num = div_num;
|
|
- i2s_write_reg(i2s_drvdata->i2s_div_base, 0, div_num_reg);
|
|
- }
|
|
+ dev_dbg(i2s_drvdata->dev, "div num:0x%x\n", div_num);
|
|
+ i2s_drvdata->i2s_div_num = div_num;
|
|
+ i2s_write_reg(i2s_drvdata->i2s_div_base, 0, div_num_reg);
|
|
}
|
|
}
|
|
|
|
@@ -630,12 +593,13 @@ static const struct snd_soc_dai_ops i2s_dai_ops = {
|
|
.set_fmt = i2s_set_fmt,
|
|
};
|
|
|
|
-#ifdef CONFIG_PM
|
|
static int i2s_runtime_suspend(struct device *dev)
|
|
{
|
|
struct i2s_dev *i2s_drvdata = dev_get_drvdata(dev);
|
|
- if (i2s_drvdata->capability & DW_I2S_MASTER)
|
|
- clk_disable(i2s_drvdata->clk);
|
|
+
|
|
+ dev_dbg(i2s_drvdata->dev, "%s\n", __func__);
|
|
+
|
|
+ clk_disable(g_mclk);
|
|
|
|
return 0;
|
|
}
|
|
@@ -643,8 +607,9 @@ static int i2s_runtime_suspend(struct device *dev)
|
|
static int i2s_runtime_resume(struct device *dev)
|
|
{
|
|
struct i2s_dev *i2s_drvdata = dev_get_drvdata(dev);
|
|
- if (i2s_drvdata->capability & DW_I2S_MASTER)
|
|
- clk_enable(i2s_drvdata->clk);
|
|
+
|
|
+ dev_dbg(i2s_drvdata->dev, "%s\n", __func__);
|
|
+ clk_enable(g_mclk);
|
|
|
|
return 0;
|
|
}
|
|
@@ -652,9 +617,13 @@ static int i2s_runtime_resume(struct device *dev)
|
|
static int i2s_suspend(struct snd_soc_component *component)
|
|
{
|
|
struct i2s_dev *i2s_drvdata = snd_soc_component_get_drvdata(component);
|
|
- if (i2s_drvdata->capability & DW_I2S_MASTER) {
|
|
- clk_disable(i2s_drvdata->clk);
|
|
+
|
|
+ dev_dbg(i2s_drvdata->dev, "%s\n", __func__);
|
|
+ if(!pm_runtime_suspended(i2s_drvdata->dev)) {
|
|
+ dev_dbg(i2s_drvdata->dev, "disable clk\n");
|
|
+ clk_disable(g_mclk);
|
|
}
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -664,22 +633,20 @@ static int i2s_resume(struct snd_soc_component *component)
|
|
struct snd_soc_dai *dai = NULL;
|
|
int stream;
|
|
|
|
- if (i2s_drvdata->capability & DW_I2S_MASTER)
|
|
- clk_enable(i2s_drvdata->clk);
|
|
-
|
|
- for_each_component_dais(component, dai) {
|
|
- for_each_pcm_streams(stream)
|
|
- if (snd_soc_dai_stream_active(dai, stream))
|
|
- i2s_config(i2s_drvdata, stream);
|
|
+ dev_dbg(i2s_drvdata->dev, "%s\n", __func__);
|
|
+ if(!pm_runtime_suspended(i2s_drvdata->dev)) {
|
|
+ dev_dbg(i2s_drvdata->dev, "enable clk\n");
|
|
+ clk_enable(g_mclk);
|
|
+ for_each_component_dais(component, dai) {
|
|
+ for_each_pcm_streams(stream)
|
|
+ if (snd_soc_dai_stream_active(dai, stream))
|
|
+ i2s_config(i2s_drvdata, stream);
|
|
+ }
|
|
}
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
-#else
|
|
-#define i2s_suspend NULL
|
|
-#define i2s_resume NULL
|
|
-#endif
|
|
-
|
|
static int i2s_reset(struct platform_device *pdev, struct i2s_dev *i2s)
|
|
{
|
|
struct reset_control *rst;
|
|
@@ -731,7 +698,7 @@ static int i2s_open(struct snd_soc_component *component,
|
|
}
|
|
|
|
static const struct snd_soc_component_driver i2s_component = {
|
|
- .name = "i2s",
|
|
+ .name = "i2s0",
|
|
.open = i2s_open,
|
|
.suspend = i2s_suspend,
|
|
.resume = i2s_resume,
|
|
@@ -847,13 +814,14 @@ static int i2s_probe(struct platform_device *pdev)
|
|
|
|
clk_id = "mclk";
|
|
if (of_node_name_prefix(pdev->dev.of_node, "i2s0")) {
|
|
- i2s_drvdata->clk = devm_clk_get(&pdev->dev, clk_id);
|
|
- if (IS_ERR(i2s_drvdata->clk))
|
|
- return PTR_ERR(i2s_drvdata->clk);
|
|
- ret = clk_prepare_enable(i2s_drvdata->clk);
|
|
+ g_mclk = devm_clk_get(&pdev->dev, clk_id);
|
|
+ if (IS_ERR(g_mclk))
|
|
+ return PTR_ERR(g_mclk);
|
|
+ ret = clk_prepare_enable(g_mclk);
|
|
if (ret < 0)
|
|
return ret;
|
|
- ret = clk_set_rate(i2s_drvdata->clk, MAX_SAMPLE_RATE_CLK);
|
|
+ i2s_drvdata->clk = g_mclk;
|
|
+ ret = clk_set_rate(g_mclk, MAX_SAMPLE_RATE_CLK);
|
|
if (ret) {
|
|
dev_err(i2s_drvdata->dev, "Can't set I2S clock rate: %d\n", ret);
|
|
}
|
|
@@ -871,7 +839,8 @@ static int i2s_probe(struct platform_device *pdev)
|
|
i2s_drvdata->i2s_div_base = devm_ioremap(i2s_drvdata->dev, VO_TOP_CSR + VO_I2S0_DIV_NUM, 4);
|
|
if (!i2s_drvdata->i2s_div_base) {
|
|
dev_err(&pdev->dev, "failed to remap i2s0 div config\n");
|
|
- return -ENOMEM;
|
|
+ ret = -ENOMEM;
|
|
+ goto err_probe;
|
|
}
|
|
ret = devm_snd_soc_register_component(&pdev->dev, &i2s_component,
|
|
&i2s_dai[0], 2);
|
|
@@ -879,7 +848,8 @@ static int i2s_probe(struct platform_device *pdev)
|
|
i2s_drvdata->i2s_div_base = devm_ioremap(i2s_drvdata->dev, VO_TOP_CSR + VO_I2S1_DIV_NUM, 4);
|
|
if (!i2s_drvdata->i2s_div_base) {
|
|
dev_err(&pdev->dev, "failed to remap i2s1 div config\n");
|
|
- return -ENOMEM;
|
|
+ ret = -ENOMEM;
|
|
+ goto err_probe;
|
|
}
|
|
ret = devm_snd_soc_register_component(&pdev->dev, &i2s_component,
|
|
&i2s_dai[2], 1);
|
|
@@ -887,7 +857,8 @@ static int i2s_probe(struct platform_device *pdev)
|
|
i2s_drvdata->i2s_div_base = devm_ioremap(i2s_drvdata->dev, VO_TOP_CSR + VO_I2S2_DIV_NUM, 4);
|
|
if (!i2s_drvdata->i2s_div_base) {
|
|
dev_err(&pdev->dev, "failed to remap i2s2 div config\n");
|
|
- return -ENOMEM;
|
|
+ ret = -ENOMEM;
|
|
+ goto err_probe;
|
|
}
|
|
ret = devm_snd_soc_register_component(&pdev->dev, &i2s_component,
|
|
&i2s_dai[3], 1);
|
|
@@ -909,32 +880,27 @@ static int i2s_probe(struct platform_device *pdev)
|
|
ret = i2s_configure_dai_by_dt(i2s_drvdata, &i2s_dai[0], res);
|
|
if (ret < 0) {
|
|
dev_err(&pdev->dev, "i2s_configure_dai_by_dt failed\n");
|
|
- return ret;
|
|
+ goto err_probe;
|
|
}
|
|
|
|
- ret = device_property_read_u32(&pdev->dev, "eswin-plat", &i2s_drvdata->eswin_plat);
|
|
- if (0 != ret) {
|
|
- dev_warn(&pdev->dev, "Failed to get eswin platform\n");
|
|
- i2s_drvdata->eswin_plat = 0;
|
|
- }
|
|
- dev_info(&pdev->dev, "eswin platform:%d\n", i2s_drvdata->eswin_plat);
|
|
-
|
|
pm_runtime_enable(&pdev->dev);
|
|
|
|
audio_proc_module_init();
|
|
|
|
+ clk_disable(i2s_drvdata->clk);
|
|
+
|
|
return 0;
|
|
err_probe:
|
|
- if (i2s_drvdata->capability & DW_I2S_MASTER)
|
|
- clk_disable_unprepare(i2s_drvdata->clk);
|
|
+ clk_disable_unprepare(i2s_drvdata->clk);
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
static int i2s_remove(struct platform_device *pdev)
|
|
{
|
|
struct i2s_dev *i2s_drvdata = dev_get_drvdata(&pdev->dev);
|
|
- if (i2s_drvdata->capability & DW_I2S_MASTER)
|
|
- clk_disable_unprepare(i2s_drvdata->clk);
|
|
+
|
|
+ clk_disable_unprepare(i2s_drvdata->clk);
|
|
|
|
pm_runtime_disable(&pdev->dev);
|
|
|
|
diff --git a/sound/soc/eswin/esw-i2s.h b/sound/soc/eswin/esw-i2s.h
|
|
index 14c4980c8267..6c1a243223a4 100644
|
|
--- a/sound/soc/eswin/esw-i2s.h
|
|
+++ b/sound/soc/eswin/esw-i2s.h
|
|
@@ -175,7 +175,6 @@ struct i2s_dev {
|
|
u32 i2s_div_num;
|
|
bool playback_active;
|
|
bool capture_active;
|
|
- u32 eswin_plat;
|
|
};
|
|
|
|
#endif /* __I2S_H */
|
|
--
|
|
2.47.0
|
|
|