diff options
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, ®_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 */ |