kernel/0108-feat-I2s-support-low-power.patch
2024-12-19 16:34:44 -05:00

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