summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/starfive/clk-starfive-jh7110-gen.c184
-rw-r--r--[-rwxr-xr-x]drivers/clk/starfive/clk-starfive-jh7110.h1
-rw-r--r--drivers/input/touchscreen/tinker_ft5406.c43
-rw-r--r--drivers/media/platform/starfive/v4l2_driver/stf_video.c88
-rw-r--r--drivers/media/platform/starfive/v4l2_driver/stf_video.h1
-rw-r--r--drivers/media/platform/starfive/v4l2_driver/stf_vin.h4
-rw-r--r--drivers/media/platform/starfive/v4l2_driver/stfcamss.c98
-rwxr-xr-xdrivers/pinctrl/starfive/pinctrl-starfive-jh7110.c37
-rw-r--r--drivers/pinctrl/starfive/pinctrl-starfive.c19
-rw-r--r--drivers/pinctrl/starfive/pinctrl-starfive.h7
-rw-r--r--drivers/usb/cdns3/cdns3-starfive.c49
-rw-r--r--[-rwxr-xr-x]sound/soc/starfive/pwmdac.h9
-rw-r--r--sound/soc/starfive/starfive_pwmdac.c15
-rw-r--r--sound/soc/starfive/starfive_spdif.c25
-rw-r--r--sound/soc/starfive/starfive_spdif.h4
-rw-r--r--sound/soc/starfive/starfive_spdif_pcm.c4
-rw-r--r--sound/soc/starfive/starfive_tdm.c48
-rw-r--r--sound/soc/starfive/starfive_tdm.h1
18 files changed, 448 insertions, 189 deletions
diff --git a/drivers/clk/starfive/clk-starfive-jh7110-gen.c b/drivers/clk/starfive/clk-starfive-jh7110-gen.c
index d852c0a2d01f..26cbe0710b43 100644
--- a/drivers/clk/starfive/clk-starfive-jh7110-gen.c
+++ b/drivers/clk/starfive/clk-starfive-jh7110-gen.c
@@ -239,11 +239,145 @@ static void jh7110_clk_debug_init(struct clk_hw *hw, struct dentry *dentry)
#define jh7110_clk_debug_init NULL
#endif
+#ifdef CONFIG_PM_SLEEP
+static int jh7110_clk_save_context(struct clk_hw *hw)
+{
+ struct jh7110_clk *clk = jh7110_clk_from(hw);
+ void __iomem *reg = jh7110_clk_reg_addr_get(clk);
+ struct jh7110_clk_priv *priv = jh7110_priv_from(clk);
+
+ if (!clk || !priv)
+ return 0;
+
+ if ((clk->reg_flags == JH7110_CLK_ISP_FLAG) || (clk->reg_flags == JH7110_CLK_VOUT_FLAG))
+ return 0;
+
+ if (clk->idx >= JH7110_CLK_REG_END)
+ return 0;
+
+ spin_lock(&priv->rmw_lock);
+ clk->saved_reg_value = readl_relaxed(reg);
+ spin_unlock(&priv->rmw_lock);
+
+ return 0;
+}
+
+static void jh7110_clk_gate_restore_context(struct clk_hw *hw)
+{
+ struct jh7110_clk *clk = jh7110_clk_from(hw);
+
+ if (!clk)
+ return;
+
+ if ((clk->reg_flags == JH7110_CLK_ISP_FLAG) || (clk->reg_flags == JH7110_CLK_VOUT_FLAG))
+ return;
+
+ if (clk->idx >= JH7110_CLK_REG_END)
+ return;
+
+ jh7110_clk_reg_rmw(clk, JH7110_CLK_ENABLE, clk->saved_reg_value);
+
+ return;
+}
+
+static void jh7110_clk_div_restore_context(struct clk_hw *hw)
+{
+ struct jh7110_clk *clk = jh7110_clk_from(hw);
+
+ if (!clk)
+ return;
+
+ if ((clk->reg_flags == JH7110_CLK_ISP_FLAG) || (clk->reg_flags == JH7110_CLK_VOUT_FLAG))
+ return;
+
+ if (clk->idx >= JH7110_CLK_REG_END)
+ return;
+
+ jh7110_clk_reg_rmw(clk, JH7110_CLK_DIV_MASK, clk->saved_reg_value);
+
+ return;
+}
+
+static void jh7110_clk_mux_restore_context(struct clk_hw *hw)
+{
+ struct jh7110_clk *clk = jh7110_clk_from(hw);
+
+ if (!clk)
+ return;
+
+ if ((clk->reg_flags == JH7110_CLK_ISP_FLAG) || (clk->reg_flags == JH7110_CLK_VOUT_FLAG))
+ return;
+
+ if (clk->idx >= JH7110_CLK_REG_END)
+ return;
+
+ jh7110_clk_reg_rmw(clk, JH7110_CLK_MUX_MASK, clk->saved_reg_value);
+
+ return;
+}
+
+static void jh7110_clk_inv_restore_context(struct clk_hw *hw)
+{
+ struct jh7110_clk *clk = jh7110_clk_from(hw);
+
+ if (!clk)
+ return;
+
+ if ((clk->reg_flags == JH7110_CLK_ISP_FLAG) || (clk->reg_flags == JH7110_CLK_VOUT_FLAG))
+ return;
+
+ if (clk->idx >= JH7110_CLK_REG_END)
+ return;
+
+ jh7110_clk_reg_rmw(clk, JH7110_CLK_INVERT, clk->saved_reg_value);
+
+ return;
+}
+
+static void jh7110_clk_gdiv_restore_context(struct clk_hw *hw)
+{
+ jh7110_clk_div_restore_context(hw);
+ jh7110_clk_gate_restore_context(hw);
+
+ return;
+}
+
+static void jh7110_clk_gmux_restore_context(struct clk_hw *hw)
+{
+ jh7110_clk_mux_restore_context(hw);
+ jh7110_clk_gate_restore_context(hw);
+
+ return;
+}
+
+static void jh7110_clk_mdiv_restore_context(struct clk_hw *hw)
+{
+ jh7110_clk_mux_restore_context(hw);
+ jh7110_clk_div_restore_context(hw);
+
+ return;
+}
+
+static void jh7110_clk_gmd_restore_context(struct clk_hw *hw)
+{
+ jh7110_clk_mux_restore_context(hw);
+ jh7110_clk_div_restore_context(hw);
+ jh7110_clk_gate_restore_context(hw);
+
+ return;
+}
+
+#endif
+
static const struct clk_ops jh7110_clk_gate_ops = {
.enable = jh7110_clk_enable,
.disable = jh7110_clk_disable,
.is_enabled = jh7110_clk_is_enabled,
.debug_init = jh7110_clk_debug_init,
+#ifdef CONFIG_PM_SLEEP
+ .save_context = jh7110_clk_save_context,
+ .restore_context = jh7110_clk_gate_restore_context,
+#endif
};
static const struct clk_ops jh7110_clk_div_ops = {
@@ -251,6 +385,10 @@ static const struct clk_ops jh7110_clk_div_ops = {
.determine_rate = jh7110_clk_determine_rate,
.set_rate = jh7110_clk_set_rate,
.debug_init = jh7110_clk_debug_init,
+#ifdef CONFIG_PM_SLEEP
+ .save_context = jh7110_clk_save_context,
+ .restore_context = jh7110_clk_div_restore_context,
+#endif
};
static const struct clk_ops jh7110_clk_gdiv_ops = {
@@ -261,6 +399,10 @@ static const struct clk_ops jh7110_clk_gdiv_ops = {
.determine_rate = jh7110_clk_determine_rate,
.set_rate = jh7110_clk_set_rate,
.debug_init = jh7110_clk_debug_init,
+#ifdef CONFIG_PM_SLEEP
+ .save_context = jh7110_clk_save_context,
+ .restore_context = jh7110_clk_gdiv_restore_context,
+#endif
};
static const struct clk_ops jh7110_clk_mux_ops = {
@@ -268,6 +410,10 @@ static const struct clk_ops jh7110_clk_mux_ops = {
.set_parent = jh7110_clk_set_parent,
.get_parent = jh7110_clk_get_parent,
.debug_init = jh7110_clk_debug_init,
+#ifdef CONFIG_PM_SLEEP
+ .save_context = jh7110_clk_save_context,
+ .restore_context = jh7110_clk_mux_restore_context,
+#endif
};
static const struct clk_ops jh7110_clk_gmux_ops = {
@@ -278,6 +424,10 @@ static const struct clk_ops jh7110_clk_gmux_ops = {
.set_parent = jh7110_clk_set_parent,
.get_parent = jh7110_clk_get_parent,
.debug_init = jh7110_clk_debug_init,
+#ifdef CONFIG_PM_SLEEP
+ .save_context = jh7110_clk_save_context,
+ .restore_context = jh7110_clk_gmux_restore_context,
+#endif
};
static const struct clk_ops jh7110_clk_mdiv_ops = {
@@ -287,6 +437,10 @@ static const struct clk_ops jh7110_clk_mdiv_ops = {
.set_parent = jh7110_clk_set_parent,
.set_rate = jh7110_clk_set_rate,
.debug_init = jh7110_clk_debug_init,
+#ifdef CONFIG_PM_SLEEP
+ .save_context = jh7110_clk_save_context,
+ .restore_context = jh7110_clk_mdiv_restore_context,
+#endif
};
static const struct clk_ops jh7110_clk_gmd_ops = {
@@ -299,12 +453,20 @@ static const struct clk_ops jh7110_clk_gmd_ops = {
.set_parent = jh7110_clk_set_parent,
.set_rate = jh7110_clk_set_rate,
.debug_init = jh7110_clk_debug_init,
+#ifdef CONFIG_PM_SLEEP
+ .save_context = jh7110_clk_save_context,
+ .restore_context = jh7110_clk_gmd_restore_context,
+#endif
};
static const struct clk_ops jh7110_clk_inv_ops = {
.get_phase = jh7110_clk_get_phase,
.set_phase = jh7110_clk_set_phase,
.debug_init = jh7110_clk_debug_init,
+#ifdef CONFIG_PM_SLEEP
+ .save_context = jh7110_clk_save_context,
+ .restore_context = jh7110_clk_inv_restore_context,
+#endif
};
const struct clk_ops *starfive_jh7110_clk_ops(u32 max)
@@ -335,6 +497,25 @@ const struct clk_ops *starfive_jh7110_clk_ops(u32 max)
}
EXPORT_SYMBOL_GPL(starfive_jh7110_clk_ops);
+#ifdef CONFIG_PM_SLEEP
+static int clk_starfive_jh7110_gen_system_suspend(struct device *dev)
+{
+ return clk_save_context();
+}
+
+static int clk_starfive_jh7110_gen_system_resume(struct device *dev)
+{
+ clk_restore_context();
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops clk_starfive_jh7110_gen_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(clk_starfive_jh7110_gen_system_suspend,
+ clk_starfive_jh7110_gen_system_resume)
+};
+
static struct clk_hw *jh7110_clk_get(struct of_phandle_args *clkspec,
void *data)
{
@@ -369,6 +550,8 @@ static int __init clk_starfive_jh7110_probe(struct platform_device *pdev)
spin_lock_init(&priv->rmw_lock);
priv->dev = &pdev->dev;
+ pm_runtime_enable(priv->dev);
+
#ifdef CONFIG_CLK_STARFIVE_JH7110_PLL
ret = clk_starfive_jh7110_pll_init(pdev, priv->pll_priv);
if (ret)
@@ -439,6 +622,7 @@ static struct platform_driver clk_starfive_jh7110_driver = {
.driver = {
.name = "clk-starfive-jh7110",
.of_match_table = clk_starfive_jh7110_match,
+ .pm = &clk_starfive_jh7110_gen_pm_ops,
},
};
builtin_platform_driver_probe(clk_starfive_jh7110_driver,
diff --git a/drivers/clk/starfive/clk-starfive-jh7110.h b/drivers/clk/starfive/clk-starfive-jh7110.h
index 4560b75f52c9..c776ab38a7b3 100755..100644
--- a/drivers/clk/starfive/clk-starfive-jh7110.h
+++ b/drivers/clk/starfive/clk-starfive-jh7110.h
@@ -59,6 +59,7 @@ struct jh7110_clk {
unsigned int idx;
unsigned int max_div;
unsigned int reg_flags;
+ u32 saved_reg_value;
};
struct jh7110_clk_priv {
diff --git a/drivers/input/touchscreen/tinker_ft5406.c b/drivers/input/touchscreen/tinker_ft5406.c
index 256e2bac82e7..64ba05715631 100644
--- a/drivers/input/touchscreen/tinker_ft5406.c
+++ b/drivers/input/touchscreen/tinker_ft5406.c
@@ -26,10 +26,6 @@
#include <linux/module.h>
#include <linux/workqueue.h>
-#define LOG_DBG(fmt, arg...) pr_debug("tinker-ft5406: %s: "fmt, __func__, ##arg)
-#define LOG_INFO(fmt, arg...) pr_info("tinker-ft5406: %s: "fmt, __func__, ##arg)
-#define LOG_ERR(fmt, arg...) pr_err("tinker-ft5406: %s: "fmt, __func__, ##arg)
-
#define RETRY_COUNT 10
#define FT_ONE_TCH_LEN 6
@@ -38,7 +34,7 @@
#define FT_REG_FW_SUB_MIN_VER 0xB3
#define VALID_TD_STATUS_VAL 10
-#define MAX_TOUCH_POINTS 1
+#define MAX_TOUCH_POINTS 5
#define FT_PRESS 0x7F
#define FT_MAX_ID 0x0F
@@ -110,7 +106,7 @@ static int fts_i2c_read(struct i2c_client *client, char *writebuf,
};
ret = i2c_transfer(client->adapter, msgs, 2);
if (ret < 0)
- LOG_ERR("i2c read error, %d\n", ret);
+ dev_err(&client->dev, "i2c read error, %d\n", ret);
} else {
struct i2c_msg msgs[] = {
{
@@ -122,7 +118,7 @@ static int fts_i2c_read(struct i2c_client *client, char *writebuf,
};
ret = i2c_transfer(client->adapter, msgs, 1);
if (ret < 0)
- LOG_ERR("i2c read error, %d\n", ret);
+ dev_err(&client->dev, "i2c read error, %d\n", ret);
}
return ret;
@@ -153,7 +149,8 @@ static int fts_check_fw_ver(struct i2c_client *client)
if (ret < 0)
goto error;
- LOG_INFO("Firmware version = %d.%d.%d\n", fw_ver[0], fw_ver[1], fw_ver[2]);
+ dev_info(&client->dev, "Firmware version = %d.%d.%d\n",
+ fw_ver[0], fw_ver[1], fw_ver[2]);
return 0;
error:
@@ -167,7 +164,8 @@ static int fts_read_td_status(struct tinker_ft5406_data *ts_data)
ret = fts_read_reg(ts_data->client, FT_TD_STATUS_REG, &td_status);
if (ret < 0) {
- LOG_ERR("get reg td_status failed, %d\n", ret);
+ dev_err(&ts_data->client->dev,
+ "Get reg td_status failed, %d\n", ret);
return ret;
}
return (int)td_status;
@@ -184,7 +182,7 @@ static int fts_read_touchdata(struct tinker_ft5406_data *ts_data)
reg_addr = FT_TOUCH_X_H_REG + (i * FT_ONE_TCH_LEN);
ret = fts_i2c_read(ts_data->client, &reg_addr, 1, buf, FT_ONE_TCH_LEN-2);
if (ret < 0) {
- LOG_ERR("read touchdata failed.\n");
+ dev_err(&ts_data->client->dev, "Read touchdata failed.\n");
return ret;
}
@@ -226,7 +224,7 @@ static void fts_report_value(struct tinker_ft5406_data *ts_data)
event->au16_y[i]);
if (!((1 << event->au8_finger_id[i]) & ts_data->known_ids))
- LOG_DBG("Touch id-%d: x = %d, y = %d\n",
+ dev_dbg(&ts_data->client->dev, "Touch id-%d: x = %d, y = %d\n",
event->au8_finger_id[i],
event->au16_x[i],
event->au16_y[i]);
@@ -236,7 +234,7 @@ static void fts_report_value(struct tinker_ft5406_data *ts_data)
released_ids = ts_data->known_ids & ~modified_ids;
for (i = 0; released_ids && i < MAX_TOUCH_POINTS; i++) {
if (released_ids & (1<<i)) {
- LOG_DBG("Release id-%d, known = %x modified = %x\n",
+ dev_dbg(&ts_data->client->dev, "Release id-%d, known = %x modified = %x\n",
i, ts_data->known_ids, modified_ids);
input_mt_slot(ts_data->input_dev, i);
input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER, false);
@@ -257,12 +255,13 @@ static void fts_retry_clear(struct tinker_ft5406_data *ts_data)
static int fts_retry_wait(struct tinker_ft5406_data *ts_data)
{
if (ts_data->retry_count < RETRY_COUNT) {
- LOG_INFO("wait and retry, count = %d\n", ts_data->retry_count);
+ dev_info(&ts_data->client->dev,
+ "Wait and retry, count = %d\n", ts_data->retry_count);
ts_data->retry_count++;
msleep(1000);
return 1;
}
- LOG_ERR("attach retry count\n");
+ dev_err(&ts_data->client->dev, "Attach retry count\n");
return 0;
}
@@ -277,7 +276,7 @@ static void tinker_ft5406_work(struct work_struct *work)
if (td_status < 0) {
ret = fts_retry_wait(g_ts_data);
if (ret == 0) {
- LOG_ERR("stop touch polling\n");
+ dev_err(&g_ts_data->client->dev, "Stop touch polling\n");
break;
}
} else if (td_status < VALID_TD_STATUS_VAL + 1 &&
@@ -312,11 +311,11 @@ static int tinker_ft5406_probe(struct i2c_client *client,
struct input_dev *input_dev;
int ret = 0;
- LOG_INFO("address = 0x%x\n", client->addr);
+ dev_info(&client->dev, "Address = 0x%x\n", client->addr);
g_ts_data = kzalloc(sizeof(struct tinker_ft5406_data), GFP_KERNEL);
if (g_ts_data == NULL) {
- LOG_ERR("no memory for device\n");
+ dev_err(&client->dev, "No memory for device\n");
return -ENOMEM;
}
@@ -327,18 +326,18 @@ static int tinker_ft5406_probe(struct i2c_client *client,
g_ts_data->screen_height = 480;
g_ts_data->xy_reverse = 1;
- LOG_INFO("width = %d, height = %d, reverse = %d\n",
+ dev_info(&client->dev, "width = %d, height = %d, reverse = %d\n",
g_ts_data->screen_width, g_ts_data->screen_height, g_ts_data->xy_reverse);
ret = fts_check_fw_ver(g_ts_data->client);
if (ret) {
- LOG_ERR("checking touch ic failed\n");
+ dev_err(&client->dev, "Checking touch ic failed\n");
goto check_fw_err;
}
input_dev = input_allocate_device();
if (!input_dev) {
- LOG_ERR("failed to allocate input device\n");
+ dev_err(&client->dev, "Failed to allocate input device\n");
goto input_allocate_failed;
}
input_dev->name = "fts_ts";
@@ -361,7 +360,7 @@ static int tinker_ft5406_probe(struct i2c_client *client,
ret = input_register_device(input_dev);
if (ret) {
- LOG_ERR("Input device registration failed\n");
+ dev_err(&client->dev, "Input device registration failed\n");
goto input_register_failed;
}
@@ -371,8 +370,6 @@ static int tinker_ft5406_probe(struct i2c_client *client,
return 0;
-check_fw_failed:
- input_unregister_device(g_ts_data->input_dev);
input_register_failed:
input_free_device(input_dev);
input_allocate_failed:
diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_video.c b/drivers/media/platform/starfive/v4l2_driver/stf_video.c
index 7a634e91fc6a..9aef386e9b54 100644
--- a/drivers/media/platform/starfive/v4l2_driver/stf_video.c
+++ b/drivers/media/platform/starfive/v4l2_driver/stf_video.c
@@ -11,8 +11,6 @@
#include <media/videobuf2-vmalloc.h>
#include <media/videobuf2-dma-contig.h>
-#define USE_MEDIA_PIPELINE
-
static const struct stfcamss_format_info formats_pix_st7110_wr[] = {
{ MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1,
{ { 1, 1 } }, { { 1, 1 } }, { 16 } },
@@ -552,15 +550,13 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count)
struct v4l2_subdev *subdev;
int ret;
-#ifdef USE_MEDIA_PIPELINE
- // ret = media_pipeline_start(&vdev->entity, &video->pipe);
ret = media_pipeline_start(&vdev->entity, &video->stfcamss->pipe);
if (ret < 0) {
st_err(ST_VIDEO,
"Failed to media_pipeline_start: %d\n", ret);
return ret;
}
-#endif
+
ret = video_check_format(video);
if (ret < 0)
goto error;
@@ -584,9 +580,7 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count)
return 0;
error:
-#ifdef USE_MEDIA_PIPELINE
media_pipeline_stop(&vdev->entity);
-#endif
video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED);
return ret;
}
@@ -615,9 +609,7 @@ static void video_stop_streaming(struct vb2_queue *q)
v4l2_subdev_call(subdev, video, s_stream, 0);
}
-#ifdef USE_MEDIA_PIPELINE
media_pipeline_stop(&vdev->entity);
-#endif
video->ops->flush_buffers(video, VB2_BUF_STATE_ERROR);
}
@@ -1619,59 +1611,21 @@ static int video_open(struct file *file)
file->private_data = vfh;
-#ifdef USE_MEDIA_PIPELINE
- ret = v4l2_pipeline_pm_get(&vdev->entity);
- if (ret < 0) {
- st_err(ST_VIDEO,
- "Failed to power up pipeline: %d\n", ret);
- goto error_pm_use;
+ if (!video->pm_count) {
+ ret = v4l2_pipeline_pm_get(&vdev->entity);
+ if (ret < 0) {
+ st_err(ST_VIDEO,
+ "Failed to power up pipeline: %d\n", ret);
+ goto error_pm_use;
+ }
}
-#else
- struct media_entity *entity;
- struct media_pad *pad;
- struct v4l2_subdev *subdev;
- int i = 0;
-
- entity = &vdev->entity;
- while (1) {
- pad = &entity->pads[0];
- if (!(pad->flags & MEDIA_PAD_FL_SINK))
- break;
- pad = media_entity_remote_pad(pad);
- if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
- break;
+ video->pm_count++;
- entity = pad->entity;
- subdev = media_entity_to_v4l2_subdev(entity);
-
- ret = v4l2_subdev_call(subdev, core, s_power, 1);
- if (ret < 0 && ret != -ENOIOCTLCMD)
- goto error_power;
- i++;
- }
-#endif
mutex_unlock(&video->lock);
return 0;
-#ifndef USE_MEDIA_PIPELINE
-error_power:
- entity = &vdev->entity;
- while (i--) {
- pad = &entity->pads[0];
- if (!(pad->flags & MEDIA_PAD_FL_SINK))
- break;
- pad = media_entity_remote_pad(pad);
- if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
- break;
-
- entity = pad->entity;
- subdev = media_entity_to_v4l2_subdev(entity);
-
- v4l2_subdev_call(subdev, core, s_power, 0);
- }
-#endif
error_pm_use:
v4l2_fh_release(file);
error_alloc:
@@ -1682,31 +1636,15 @@ error_alloc:
static int video_release(struct file *file)
{
struct video_device *vdev = video_devdata(file);
+ struct stfcamss_video *video = video_drvdata(file);
vb2_fop_release(file);
-#ifdef USE_MEDIA_PIPELINE
- v4l2_pipeline_pm_put(&vdev->entity);
-#else
- struct media_entity *entity;
- struct media_pad *pad;
- struct v4l2_subdev *subdev;
- entity = &vdev->entity;
- while (1) {
- pad = &entity->pads[0];
- if (!(pad->flags & MEDIA_PAD_FL_SINK))
- break;
-
- pad = media_entity_remote_pad(pad);
- if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
- break;
+ video->pm_count--;
- entity = pad->entity;
- subdev = media_entity_to_v4l2_subdev(entity);
+ if (!video->pm_count)
+ v4l2_pipeline_pm_put(&vdev->entity);
- v4l2_subdev_call(subdev, core, s_power, 0);
- }
-#endif
file->private_data = NULL;
return 0;
diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_video.h b/drivers/media/platform/starfive/v4l2_driver/stf_video.h
index d134ee69c34e..6037d0ec7ac5 100644
--- a/drivers/media/platform/starfive/v4l2_driver/stf_video.h
+++ b/drivers/media/platform/starfive/v4l2_driver/stf_video.h
@@ -69,6 +69,7 @@ struct stfcamss_video {
const struct stfcamss_format_info *formats;
unsigned int nformats;
unsigned int is_mp;
+ unsigned int pm_count;
};
int stf_video_register(struct stfcamss_video *video,
diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_vin.h b/drivers/media/platform/starfive/v4l2_driver/stf_vin.h
index 5625621c1544..492bffe27d17 100644
--- a/drivers/media/platform/starfive/v4l2_driver/stf_vin.h
+++ b/drivers/media/platform/starfive/v4l2_driver/stf_vin.h
@@ -82,6 +82,10 @@ struct vin_line {
spinlock_t output_lock;
const struct vin2_format *formats;
unsigned int nformats;
+#ifdef CONFIG_PM_SLEEP
+ int pm_stream_count;
+ int pm_power_count;
+#endif
};
struct stf_vin2_dev;
diff --git a/drivers/media/platform/starfive/v4l2_driver/stfcamss.c b/drivers/media/platform/starfive/v4l2_driver/stfcamss.c
index 11dbb85c5e5e..d9213cbf64fb 100644
--- a/drivers/media/platform/starfive/v4l2_driver/stfcamss.c
+++ b/drivers/media/platform/starfive/v4l2_driver/stfcamss.c
@@ -1201,31 +1201,43 @@ static int stfcamss_suspend(struct device *dev)
struct stfcamss_video *video;
struct video_device *vdev;
int i = 0;
+ int pm_power_count;
+ int pm_stream_count;
for (i = 0; i < VIN_LINE_MAX; i++) {
- if (vin_dev->line[i].stream_count) {
- vin_dev->line[i].stream_count ++;
- video = &vin_dev->line[i].video_out;
- vdev = &vin_dev->line[i].video_out.vdev;
- entity = &vdev->entity;
- while (1) {
- pad = &entity->pads[0];
- if (!(pad->flags & MEDIA_PAD_FL_SINK))
- break;
-
- pad = media_entity_remote_pad(pad);
- if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
- break;
-
- entity = pad->entity;
- subdev = media_entity_to_v4l2_subdev(entity);
-
- v4l2_subdev_call(subdev, video, s_stream, 0);
+ video = &vin_dev->line[i].video_out;
+ vdev = &vin_dev->line[i].video_out.vdev;
+ vin_dev->line[i].pm_power_count = vin_dev->line[i].power_count;
+ vin_dev->line[i].pm_stream_count = vin_dev->line[i].stream_count;
+ pm_power_count = vin_dev->line[i].pm_power_count;
+ pm_stream_count = vin_dev->line[i].pm_stream_count;
+
+ if (pm_stream_count) {
+ while (pm_stream_count--) {
+ entity = &vdev->entity;
+ while (1) {
+ pad = &entity->pads[0];
+ if (!(pad->flags & MEDIA_PAD_FL_SINK))
+ break;
+
+ pad = media_entity_remote_pad(pad);
+ if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
+ break;
+
+ entity = pad->entity;
+ subdev = media_entity_to_v4l2_subdev(entity);
+
+ v4l2_subdev_call(subdev, video, s_stream, 0);
+ }
}
media_pipeline_stop(&vdev->entity);
video->ops->flush_buffers(video, VB2_BUF_STATE_ERROR);
- v4l2_pipeline_pm_put(&vdev->entity);
}
+
+ if (!pm_power_count)
+ continue;
+
+ v4l2_pipeline_pm_put(&vdev->entity);
}
return pm_runtime_force_suspend(dev);
@@ -1241,40 +1253,48 @@ static int stfcamss_resume(struct device *dev)
struct stfcamss_video *video;
struct video_device *vdev;
int i = 0;
+ int pm_power_count;
+ int pm_stream_count;
int ret = 0;
pm_runtime_force_resume(dev);
for (i = 0; i < VIN_LINE_MAX; i++) {
- if (vin_dev->line[i].stream_count) {
- vin_dev->line[i].stream_count--;
- video = &vin_dev->line[i].video_out;
- vdev = &vin_dev->line[i].video_out.vdev;
+ video = &vin_dev->line[i].video_out;
+ vdev = &vin_dev->line[i].video_out.vdev;
+ pm_power_count = vin_dev->line[i].pm_power_count;
+ pm_stream_count = vin_dev->line[i].pm_stream_count;
- ret = v4l2_pipeline_pm_get(&vdev->entity);
- if (ret < 0)
- goto err;
+ if (!pm_power_count)
+ continue;
+ ret = v4l2_pipeline_pm_get(&vdev->entity);
+ if (ret < 0)
+ goto err;
+
+ if (pm_stream_count) {
ret = media_pipeline_start(&vdev->entity, &video->stfcamss->pipe);
if (ret < 0)
goto err_pm_put;
- entity = &vdev->entity;
- while (1) {
- pad = &entity->pads[0];
- if (!(pad->flags & MEDIA_PAD_FL_SINK))
- break;
+ while (pm_stream_count--) {
+ entity = &vdev->entity;
+ while (1) {
+ pad = &entity->pads[0];
+ if (!(pad->flags & MEDIA_PAD_FL_SINK))
+ break;
- pad = media_entity_remote_pad(pad);
- if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
- break;
+ pad = media_entity_remote_pad(pad);
+ if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
+ break;
- entity = pad->entity;
- subdev = media_entity_to_v4l2_subdev(entity);
+ entity = pad->entity;
+ subdev = media_entity_to_v4l2_subdev(entity);
- ret = v4l2_subdev_call(subdev, video, s_stream, 1);
- if (ret < 0 && ret != -ENOIOCTLCMD)
- goto err_pipeline_stop;
+ ret = v4l2_subdev_call(subdev, video, s_stream, 1);
+ if (ret < 0 && ret != -ENOIOCTLCMD)
+ goto err_pipeline_stop;
+ }
}
}
}
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c
index d7adf8b3332d..091f36649512 100755
--- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c
@@ -1663,6 +1663,43 @@ static int starfive_jh7110_pinctrl_probe(struct platform_device *pdev)
return starfive_pinctrl_probe(pdev, pinctrl_info);
}
+static int __maybe_unused starfive_pinctrl_suspend(struct device *dev)
+{
+ struct starfive_pinctrl *pctl = dev_get_drvdata(dev);
+ u8 i;
+
+ for (i = 0 ; i < SYS_IRQ_REG_SUSPENDED_NUM ; i++)
+ pctl->sys_irq_reg_suspended[i] =
+ readl_relaxed(pctl->padctl_base + GPIO_EN + OFFSET_PER_REG * i);
+
+ for (i = 0 ; i < AON_IRQ_REG_SUSPENDED_NUM ; i++)
+ pctl->aon_irq_reg_suspended[i] =
+ readl_relaxed(pctl->padctl_base + AON_GPIO_EN_REG + OFFSET_PER_REG * i);
+
+ return pinctrl_force_sleep(pctl->pctl_dev);
+}
+
+static int __maybe_unused starfive_pinctrl_resume(struct device *dev)
+{
+ struct starfive_pinctrl *pctl = dev_get_drvdata(dev);
+ u8 i;
+
+ for (i = 0 ; i < SYS_IRQ_REG_SUSPENDED_NUM ; i++)
+ writel_relaxed(pctl->sys_irq_reg_suspended[i],
+ pctl->padctl_base + GPIO_EN + OFFSET_PER_REG * i);
+
+ for (i = 0 ; i < AON_IRQ_REG_SUSPENDED_NUM ; i++)
+ writel_relaxed(pctl->aon_irq_reg_suspended[i],
+ pctl->padctl_base + AON_GPIO_EN_REG + OFFSET_PER_REG * i);
+
+ return pinctrl_force_default(pctl->pctl_dev);
+}
+
+const struct dev_pm_ops starfive_pinctrl_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(starfive_pinctrl_suspend,
+ starfive_pinctrl_resume)
+};
+
static struct platform_driver starfive_jh7110_pinctrl_driver = {
.driver = {
.name = "starfive_jh7110-pinctrl",
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive.c b/drivers/pinctrl/starfive/pinctrl-starfive.c
index 262f573bc370..127053fe096b 100644
--- a/drivers/pinctrl/starfive/pinctrl-starfive.c
+++ b/drivers/pinctrl/starfive/pinctrl-starfive.c
@@ -474,25 +474,6 @@ int starfive_pinctrl_probe(struct platform_device *pdev,
}
EXPORT_SYMBOL_GPL(starfive_pinctrl_probe);
-static int __maybe_unused starfive_pinctrl_suspend(struct device *dev)
-{
- struct starfive_pinctrl *pctl = dev_get_drvdata(dev);
-
- return pinctrl_force_sleep(pctl->pctl_dev);
-}
-
-static int __maybe_unused starfive_pinctrl_resume(struct device *dev)
-{
- struct starfive_pinctrl *pctl = dev_get_drvdata(dev);
-
- return pinctrl_force_default(pctl->pctl_dev);
-}
-
-const struct dev_pm_ops starfive_pinctrl_pm_ops = {
- SET_LATE_SYSTEM_SLEEP_PM_OPS(starfive_pinctrl_suspend,
- starfive_pinctrl_resume)
-};
-EXPORT_SYMBOL_GPL(starfive_pinctrl_pm_ops);
MODULE_DESCRIPTION("Pinctrl driver for StarFive JH7110 SoC");
MODULE_AUTHOR("jenny.zhang <jenny.zhang@starfivetech.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive.h b/drivers/pinctrl/starfive/pinctrl-starfive.h
index 2db9df9550af..ed79d72aaea3 100644
--- a/drivers/pinctrl/starfive/pinctrl-starfive.h
+++ b/drivers/pinctrl/starfive/pinctrl-starfive.h
@@ -17,10 +17,12 @@
#define STARFIVE_USE_SCU BIT(0)
+#define SYS_IRQ_REG_SUSPENDED_NUM 11
+#define AON_IRQ_REG_SUSPENDED_NUM 6
+
struct platform_device;
extern const struct pinmux_ops starfive_pmx_ops;
-extern const struct dev_pm_ops starfive_pinctrl_pm_ops;
struct starfive_pin_config {
unsigned long io_config;
@@ -75,6 +77,9 @@ struct starfive_pinctrl {
struct pinctrl_gpio_range gpios;
unsigned long enabled;
unsigned int trigger[MAX_GPIO];
+
+ u32 sys_irq_reg_suspended[SYS_IRQ_REG_SUSPENDED_NUM];
+ u32 aon_irq_reg_suspended[AON_IRQ_REG_SUSPENDED_NUM];
};
struct starfive_pinctrl_soc_info {
diff --git a/drivers/usb/cdns3/cdns3-starfive.c b/drivers/usb/cdns3/cdns3-starfive.c
index 9d1147b7067f..d05bf61b8052 100644
--- a/drivers/usb/cdns3/cdns3-starfive.c
+++ b/drivers/usb/cdns3/cdns3-starfive.c
@@ -74,6 +74,8 @@ struct cdns_starfive {
u32 stg_offset_500;
bool usb2_only;
enum usb_dr_mode mode;
+ void __iomem *phybase_20;
+ void __iomem *phybase_30;
};
static int cdns_mode_init(struct platform_device *pdev,
@@ -194,39 +196,44 @@ exit:
return ret;
}
+static void cdns_starfive_set_phy(struct cdns_starfive *data)
+{
+ unsigned int val;
+
+ if (data->mode != USB_DR_MODE_PERIPHERAL) {
+ /* Enable the LS speed keep-alive signal */
+ val = readl(data->phybase_20 + USB_LS_KEEPALIVE_OFF);
+ val |= BIT(USB_LS_KEEPALIVE_ENABLE);
+ writel(val, data->phybase_20 + USB_LS_KEEPALIVE_OFF);
+ }
+
+ if (!data->usb2_only) {
+ /* Configuare spread-spectrum mode: down-spread-spectrum */
+ writel(BIT(4), data->phybase_30 + PCIE_USB3_PHY_PLL_CTL_OFF);
+ }
+}
+
static int cdns_starfive_phy_init(struct platform_device *pdev,
struct cdns_starfive *data)
{
struct device *dev = &pdev->dev;
- void __iomem *phybase_20, *phybase_30;
- unsigned int val;
int ret = 0;
- phybase_20 = devm_platform_ioremap_resource(pdev, USB2_PHY_RES_INDEX);
- if (IS_ERR(phybase_20)) {
+ data->phybase_20 = devm_platform_ioremap_resource(pdev, USB2_PHY_RES_INDEX);
+ if (IS_ERR(data->phybase_20)) {
dev_err(dev, "Can't map phybase_20 IOMEM resource\n");
- ret = PTR_ERR(phybase_20);
+ ret = PTR_ERR(data->phybase_20);
goto get_res_err;
}
- phybase_30 = devm_platform_ioremap_resource(pdev, USB3_PHY_RES_INDEX);
- if (IS_ERR(phybase_30)) {
+ data->phybase_30 = devm_platform_ioremap_resource(pdev, USB3_PHY_RES_INDEX);
+ if (IS_ERR(data->phybase_30)) {
dev_err(dev, "Can't map phybase_30 IOMEM resource\n");
- ret = PTR_ERR(phybase_30);
+ ret = PTR_ERR(data->phybase_30);
goto get_res_err;
}
- if (data->mode != USB_DR_MODE_PERIPHERAL) {
- /* Enable the LS speed keep-alive signal */
- val = readl(phybase_20 + USB_LS_KEEPALIVE_OFF);
- val |= BIT(USB_LS_KEEPALIVE_ENABLE);
- writel(val, phybase_20 + USB_LS_KEEPALIVE_OFF);
- }
-
- if (!data->usb2_only) {
- /* Configuare spread-spectrum mode: down-spread-spectrum */
- writel(BIT(4), (phybase_30 + PCIE_USB3_PHY_PLL_CTL_OFF));
- }
+ cdns_starfive_set_phy(data);
get_res_err:
return ret;
@@ -351,6 +358,10 @@ static int cdns_starfive_resume(struct device *dev)
goto err;
ret = reset_control_deassert(data->resets);
+ if (ret)
+ goto err;
+
+ cdns_starfive_set_phy(data);
err:
return ret;
}
diff --git a/sound/soc/starfive/pwmdac.h b/sound/soc/starfive/pwmdac.h
index 8b93d7dd9a7f..d4742f99a51b 100755..100644
--- a/sound/soc/starfive/pwmdac.h
+++ b/sound/soc/starfive/pwmdac.h
@@ -34,9 +34,6 @@
#define PWMDAC_DUTY_CYCLE_LOW 2
#define PWMDAC_DUTY_CYCLE_HIGH 3
-
-
-
#define PWMDAC_MCLK 4096000
enum pwmdac_lr_change{
@@ -86,7 +83,6 @@ enum pwmdac_sample_count{
PWMDAC_SAMPLE_CNT_511 = 511,
};
-
enum data_shift{
PWMDAC_DATA_LEFT_SHIFT_BIT_0 = 0,
PWMDAC_DATA_LEFT_SHIFT_BIT_1,
@@ -144,11 +140,10 @@ struct sf_pwmdac_dev {
struct clk *audio_src;
struct clk *pwmdac_apb;
struct clk *pwmdac_mclk;
+ unsigned int pwmdac_ctrl_data;
};
-
-
-#if IS_ENABLED(CONFIG_SND_STARFIVE_PWMDAC_PCM)
+#if IS_ENABLED(CONFIG_SND_SOC_STARFIVE_PWMDAC_PCM)
void sf_pwmdac_pcm_push_tx(struct sf_pwmdac_dev *dev);
void sf_pwmdac_pcm_pop_rx(struct sf_pwmdac_dev *dev);
int sf_pwmdac_pcm_register(struct platform_device *pdev);
diff --git a/sound/soc/starfive/starfive_pwmdac.c b/sound/soc/starfive/starfive_pwmdac.c
index 1e7a4384e6cb..fba58e22d7ef 100644
--- a/sound/soc/starfive/starfive_pwmdac.c
+++ b/sound/soc/starfive/starfive_pwmdac.c
@@ -761,12 +761,25 @@ static int sf_pwmdac_dai_probe(struct snd_soc_dai *dai)
#ifdef CONFIG_PM_SLEEP
static int starfive_pwmdac_system_suspend(struct device *dev)
{
+ struct sf_pwmdac_dev *pwmdac = dev_get_drvdata(dev);
+
+ /* save the register value */
+ pwmdac->pwmdac_ctrl_data = pwmdc_read_reg(pwmdac->pwmdac_base, PWMDAC_CTRL);
return pm_runtime_force_suspend(dev);
}
static int starfive_pwmdac_system_resume(struct device *dev)
{
- return pm_runtime_force_resume(dev);
+ struct sf_pwmdac_dev *pwmdac = dev_get_drvdata(dev);
+ int ret;
+
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ /* restore the register value */
+ pwmdc_write_reg(pwmdac->pwmdac_base, PWMDAC_CTRL, pwmdac->pwmdac_ctrl_data);
+ return 0;
}
#endif
diff --git a/sound/soc/starfive/starfive_spdif.c b/sound/soc/starfive/starfive_spdif.c
index ee97627507bf..d7886d3639ed 100644
--- a/sound/soc/starfive/starfive_spdif.c
+++ b/sound/soc/starfive/starfive_spdif.c
@@ -423,12 +423,34 @@ static const struct snd_soc_dai_ops sf_spdif_dai_ops = {
#ifdef CONFIG_PM_SLEEP
static int spdif_system_suspend(struct device *dev)
{
+ struct sf_spdif_dev *spdif = dev_get_drvdata(dev);
+
+ /* save the register value */
+ regmap_read(spdif->regmap, SPDIF_CTRL, &spdif->reg_spdif_ctrl);
+ regmap_read(spdif->regmap, SPDIF_INT_REG, &spdif->reg_spdif_int);
+ regmap_read(spdif->regmap, SPDIF_FIFO_CTRL, &spdif->reg_spdif_fifo_ctrl);
+
return pm_runtime_force_suspend(dev);
}
static int spdif_system_resume(struct device *dev)
{
- return pm_runtime_force_resume(dev);
+ struct sf_spdif_dev *spdif = dev_get_drvdata(dev);
+ int ret;
+
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ /* restore the register value */
+ regmap_update_bits(spdif->regmap, SPDIF_CTRL,
+ ALLBITMASK, spdif->reg_spdif_ctrl);
+ regmap_update_bits(spdif->regmap, SPDIF_INT_REG,
+ ALLBITMASK, spdif->reg_spdif_int);
+ regmap_update_bits(spdif->regmap, SPDIF_FIFO_CTRL,
+ ALLBITMASK, spdif->reg_spdif_fifo_ctrl);
+
+ return 0;
}
#endif
@@ -453,7 +475,6 @@ static const struct dev_pm_ops spdif_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(spdif_system_suspend, spdif_system_resume)
};
-
#define SF_PCM_RATE_44100_192000 (SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_96000 | \
diff --git a/sound/soc/starfive/starfive_spdif.h b/sound/soc/starfive/starfive_spdif.h
index bc1cc9631c75..a0c91ae804d6 100644
--- a/sound/soc/starfive/starfive_spdif.h
+++ b/sound/soc/starfive/starfive_spdif.h
@@ -156,6 +156,9 @@ struct sf_spdif_dev {
struct clk *mclk;
struct clk *mclk_ext;
struct reset_control *rst_apb;
+ unsigned int reg_spdif_ctrl;
+ unsigned int reg_spdif_int;
+ unsigned int reg_spdif_fifo_ctrl;
struct snd_dmaengine_dai_dma_data dma_data;
};
@@ -173,5 +176,4 @@ int sf_spdif_pcm_register(struct platform_device *pdev)
}
#endif
-
#endif /* __SND_SOC_STARFIVE_SPDIF_H */
diff --git a/sound/soc/starfive/starfive_spdif_pcm.c b/sound/soc/starfive/starfive_spdif_pcm.c
index 582383765a5d..78ed55a046aa 100644
--- a/sound/soc/starfive/starfive_spdif_pcm.c
+++ b/sound/soc/starfive/starfive_spdif_pcm.c
@@ -149,7 +149,9 @@ static const struct snd_pcm_hardware sf_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_BLOCK_TRANSFER,
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
.rates = SNDRV_PCM_RATE_8000 |
SNDRV_PCM_RATE_11025 |
SNDRV_PCM_RATE_16000 |
diff --git a/sound/soc/starfive/starfive_tdm.c b/sound/soc/starfive/starfive_tdm.c
index bd7372ed6a0d..a3506e7d838d 100644
--- a/sound/soc/starfive/starfive_tdm.c
+++ b/sound/soc/starfive/starfive_tdm.c
@@ -30,6 +30,22 @@ static inline void sf_tdm_writel(struct sf_tdm_dev *dev, u16 reg, u32 val)
writel_relaxed(val, dev->tdm_base + reg);
}
+static void sf_tdm_save_context(struct sf_tdm_dev *dev)
+{
+ dev->saved_reg_value[0] = sf_tdm_readl(dev, TDM_PCMGBCR);
+ dev->saved_reg_value[1] = sf_tdm_readl(dev, TDM_PCMTXCR);
+ dev->saved_reg_value[2] = sf_tdm_readl(dev, TDM_PCMRXCR);
+ dev->saved_reg_value[3] = sf_tdm_readl(dev, TDM_PCMDIV);
+}
+
+static void sf_tdm_restore_context(struct sf_tdm_dev *dev)
+{
+ sf_tdm_writel(dev, TDM_PCMGBCR, dev->saved_reg_value[0]);
+ sf_tdm_writel(dev, TDM_PCMTXCR, dev->saved_reg_value[1]);
+ sf_tdm_writel(dev, TDM_PCMRXCR, dev->saved_reg_value[2]);
+ sf_tdm_writel(dev, TDM_PCMDIV, dev->saved_reg_value[3]);
+}
+
static void sf_tdm_start(struct sf_tdm_dev *dev, struct snd_pcm_substream *substream)
{
u32 data;
@@ -60,6 +76,10 @@ static void sf_tdm_stop(struct sf_tdm_dev *dev, struct snd_pcm_substream *substr
val &= ~PCMRXCR_RXEN;
sf_tdm_writel(dev, TDM_PCMRXCR, val);
}
+
+ val = sf_tdm_readl(dev, TDM_PCMGBCR);
+ val &= ~PCMGBCR_ENABLE;
+ sf_tdm_writel(dev, TDM_PCMGBCR, val);
}
static int sf_tdm_syncdiv(struct sf_tdm_dev *dev)
@@ -129,7 +149,9 @@ static void sf_tdm_clk_disable(struct sf_tdm_dev *priv)
clk_disable_unprepare(priv->clk_tdm_ext);
clk_disable_unprepare(priv->clk_tdm_internal);
clk_disable_unprepare(priv->clk_tdm_apb);
+ clk_disable_unprepare(priv->clk_apb0);
clk_disable_unprepare(priv->clk_tdm_ahb);
+ clk_disable_unprepare(priv->clk_ahb0);
clk_disable_unprepare(priv->clk_mclk_inner);
}
@@ -153,12 +175,24 @@ static int sf_tdm_runtime_resume(struct device *dev)
return ret;
}
+ ret = clk_prepare_enable(priv->clk_ahb0);
+ if (ret) {
+ dev_err(dev, "Failed to prepare enable clk_ahb0\n");
+ return ret;
+ }
+
ret = clk_prepare_enable(priv->clk_tdm_ahb);
if (ret) {
dev_err(dev, "Failed to prepare enable clk_tdm_ahb\n");
goto dis_mclk_inner;
}
+ ret = clk_prepare_enable(priv->clk_apb0);
+ if (ret) {
+ dev_err(dev, "Failed to prepare enable clk_apb0\n");
+ return ret;
+ }
+
ret = clk_prepare_enable(priv->clk_tdm_apb);
if (ret) {
dev_err(dev, "Failed to prepare enable clk_tdm_apb\n");
@@ -183,8 +217,16 @@ static int sf_tdm_runtime_resume(struct device *dev)
goto dis_tdm_ext;
}
+ ret = reset_control_deassert(priv->resets);
+ if (ret) {
+ dev_err(dev, "Failed to deassert tdm resets\n");
+ goto err_reset;
+ }
+
return 0;
+err_reset:
+ clk_disable_unprepare(priv->clk_tdm);
dis_tdm_ext:
clk_disable_unprepare(priv->clk_tdm_ext);
dis_tdm_internal:
@@ -385,6 +427,7 @@ static int sf_tdm_hw_params(struct snd_pcm_substream *substream,
}
sf_tdm_config(dev, substream);
+ sf_tdm_save_context(dev);
return 0;
}
@@ -400,6 +443,7 @@ static int sf_tdm_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
dev->active++;
+ sf_tdm_restore_context(dev);
sf_tdm_start(dev, substream);
break;
@@ -485,6 +529,8 @@ static struct snd_soc_dai_driver sf_tdm_dai = {
static const struct snd_pcm_hardware jh71xx_pcm_hardware = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER),
.buffer_bytes_max = 192512,
@@ -628,7 +674,7 @@ static int sf_tdm_clk_reset_init(struct platform_device *pdev, struct sf_tdm_dev
dev_err(&pdev->dev, "Failed to deassert tdm resets\n");
goto dis_tdm_clk;
}
-
+
return 0;
dis_tdm_clk:
diff --git a/sound/soc/starfive/starfive_tdm.h b/sound/soc/starfive/starfive_tdm.h
index dfba82f2782f..e435e1edce21 100644
--- a/sound/soc/starfive/starfive_tdm.h
+++ b/sound/soc/starfive/starfive_tdm.h
@@ -149,6 +149,7 @@ struct sf_tdm_dev {
/* data related to DMA transfers b/w tdm and DMAC */
struct snd_dmaengine_dai_dma_data play_dma_data;
struct snd_dmaengine_dai_dma_data capture_dma_data;
+ u32 saved_reg_value[4];
};
#endif /* __SND_SOC_STARFIVE_TDM_H */