From 481df435bdbf56b3140370e67ff6f47771e1a83a Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Tue, 25 Aug 2020 21:37:39 +0800 Subject: [PATCH] media: rockchip: ispp: add clk rate set for rv1126 Change-Id: I1aec52812324285285bdff9524d55ef1197384ab Signed-off-by: Cai YiWei --- .../media/platform/rockchip/isp/isp_ispp.h | 1 - drivers/media/platform/rockchip/ispp/common.h | 1 + drivers/media/platform/rockchip/ispp/dev.c | 7 ++++ drivers/media/platform/rockchip/ispp/hw.c | 37 ++++++++++++++++++- drivers/media/platform/rockchip/ispp/hw.h | 7 ++++ drivers/media/platform/rockchip/ispp/ispp.c | 26 ++++++------- drivers/media/platform/rockchip/ispp/stream.c | 1 - 7 files changed, 64 insertions(+), 16 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/isp_ispp.h b/drivers/media/platform/rockchip/isp/isp_ispp.h index 9f9473b4c2e5..c219ee6da6d9 100644 --- a/drivers/media/platform/rockchip/isp/isp_ispp.h +++ b/drivers/media/platform/rockchip/isp/isp_ispp.h @@ -48,7 +48,6 @@ struct max_input { }; struct rkisp_ispp_mode { - struct max_input max_in; u8 work_mode; u8 buf_num; }; diff --git a/drivers/media/platform/rockchip/ispp/common.h b/drivers/media/platform/rockchip/ispp/common.h index cc4a39d1fb85..b76f51803033 100644 --- a/drivers/media/platform/rockchip/ispp/common.h +++ b/drivers/media/platform/rockchip/ispp/common.h @@ -95,6 +95,7 @@ static inline struct vb2_queue *to_vb2_queue(struct file *file) } extern int rkispp_debug; +extern bool rkispp_clk_dbg; extern struct platform_driver rkispp_plat_drv; void rkispp_write(struct rkispp_device *dev, u32 reg, u32 val); diff --git a/drivers/media/platform/rockchip/ispp/dev.c b/drivers/media/platform/rockchip/ispp/dev.c index 847534752ae5..7af2a55204c8 100644 --- a/drivers/media/platform/rockchip/ispp/dev.c +++ b/drivers/media/platform/rockchip/ispp/dev.c @@ -27,6 +27,10 @@ int rkispp_debug; module_param_named(debug, rkispp_debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-3)"); +bool rkispp_clk_dbg; +module_param_named(clk_dbg, rkispp_clk_dbg, bool, 0644); +MODULE_PARM_DESC(clk_dbg, "rkispp clk set by user"); + static int rkisp_ispp_mode = ISP_ISPP_FBC; module_param_named(mode, rkisp_ispp_mode, int, 0644); MODULE_PARM_DESC(mode, "isp->ispp mode: bit0 fbc, bit1 yuv422, bit2 quick"); @@ -65,6 +69,9 @@ static void get_remote_node_dev(struct rkispp_device *ispp_dev) } else { ispp_dev->ispp_sdev.remote_sd = sd; v4l2_set_subdev_hostdata(sd, &ispp_dev->ispp_sdev.sd); + if (ispp_dev->hw_dev->max_in.w && ispp_dev->hw_dev->max_in.h) + v4l2_subdev_call(sd, core, ioctl, RKISP_ISPP_CMD_SET_FMT, + &ispp_dev->hw_dev->max_in); break; } } diff --git a/drivers/media/platform/rockchip/ispp/hw.c b/drivers/media/platform/rockchip/ispp/hw.c index 9535d4675f76..19480c34517e 100644 --- a/drivers/media/platform/rockchip/ispp/hw.c +++ b/drivers/media/platform/rockchip/ispp/hw.c @@ -36,6 +36,8 @@ struct irqs_data { struct match_data { int clks_num; const char * const *clks; + int clk_rate_tbl_num; + const struct ispp_clk_info *clk_rate_tbl; enum rkispp_ver ispp_ver; struct irqs_data *irqs; int num_irqs; @@ -94,6 +96,8 @@ static void disable_sys_clk(struct rkispp_hw_dev *dev) static int enable_sys_clk(struct rkispp_hw_dev *dev) { + struct rkispp_device *ispp = dev->ispp[dev->cur_dev_id]; + u32 w = dev->max_in.w ? dev->max_in.w : ispp->ispp_sdev.in_fmt.width; int i, ret = -EINVAL; for (i = 0; i < dev->clks_num; i++) { @@ -102,6 +106,17 @@ static int enable_sys_clk(struct rkispp_hw_dev *dev) goto err; } + if (rkispp_clk_dbg) + return 0; + for (i = 0; i < dev->clk_rate_tbl_num; i++) + if (w <= dev->clk_rate_tbl[i].refer_data) + break; + if (!dev->is_single) + i++; + if (i > dev->clk_rate_tbl_num - 1) + i = dev->clk_rate_tbl_num - 1; + clk_set_rate(dev->clks[0], dev->clk_rate_tbl[i].clk_rate * 1000000UL); + dev_dbg(dev->dev, "set ispp clk:%luHz\n", clk_get_rate(dev->clks[0])); return 0; err: for (--i; i >= 0; --i) @@ -129,9 +144,25 @@ static irqreturn_t irq_hdl(int irq, void *ctx) } static const char * const rv1126_ispp_clks[] = { + "clk_ispp", "aclk_ispp", "hclk_ispp", - "clk_ispp", +}; + +static const struct ispp_clk_info rv1126_ispp_clk_rate[] = { + { + .clk_rate = 250, + .refer_data = 1920 //width + }, { + .clk_rate = 350, + .refer_data = 2688, + }, { + .clk_rate = 400, + .refer_data = 3072, + }, { + .clk_rate = 500, + .refer_data = 3840, + } }; static struct irqs_data rv1126_ispp_irqs[] = { @@ -142,6 +173,8 @@ static struct irqs_data rv1126_ispp_irqs[] = { static const struct match_data rv1126_ispp_match_data = { .clks = rv1126_ispp_clks, .clks_num = ARRAY_SIZE(rv1126_ispp_clks), + .clk_rate_tbl = rv1126_ispp_clk_rate, + .clk_rate_tbl_num = ARRAY_SIZE(rv1126_ispp_clk_rate), .irqs = rv1126_ispp_irqs, .num_irqs = ARRAY_SIZE(rv1126_ispp_irqs), .ispp_ver = ISPP_V10, @@ -239,6 +272,8 @@ static int rkispp_hw_probe(struct platform_device *pdev) hw_dev->clks[i] = clk; } hw_dev->clks_num = match_data->clks_num; + hw_dev->clk_rate_tbl = match_data->clk_rate_tbl; + hw_dev->clk_rate_tbl_num = match_data->clk_rate_tbl_num; hw_dev->dev_num = 0; hw_dev->cur_dev_id = 0; diff --git a/drivers/media/platform/rockchip/ispp/hw.h b/drivers/media/platform/rockchip/ispp/hw.h index cce69f0a5808..75222cd020dd 100644 --- a/drivers/media/platform/rockchip/ispp/hw.h +++ b/drivers/media/platform/rockchip/ispp/hw.h @@ -8,14 +8,21 @@ #define ISPP_MAX_BUS_CLK 4 +struct ispp_clk_info { + u32 clk_rate; + u32 refer_data; +}; + struct rkispp_hw_dev { struct device *dev; void __iomem *base_addr; + const struct ispp_clk_info *clk_rate_tbl; struct clk *clks[ISPP_MAX_BUS_CLK]; struct rkispp_device *ispp[DEV_MAX]; struct rkispp_isp_buf_pool pool[RKISPP_BUF_POOL_MAX]; struct max_input max_in; struct list_head list; + int clk_rate_tbl_num; int clks_num; int dev_num; int cur_dev_id; diff --git a/drivers/media/platform/rockchip/ispp/ispp.c b/drivers/media/platform/rockchip/ispp/ispp.c index e4f74db43135..d9cc35c98ef1 100644 --- a/drivers/media/platform/rockchip/ispp/ispp.c +++ b/drivers/media/platform/rockchip/ispp/ispp.c @@ -290,13 +290,6 @@ static int rkispp_sd_s_power(struct v4l2_subdev *sd, int on) v4l2_dbg(1, rkispp_debug, &ispp_dev->v4l2_dev, "s_power on:%d\n", on); if (on) { - ret = pm_runtime_get_sync(ispp_dev->dev); - if (ret < 0) { - v4l2_err(&ispp_dev->v4l2_dev, - "%s runtime get failed:%d\n", - __func__, ret); - return ret; - } atomic_set(&ispp_sdev->frm_sync_seq, 0); if (ispp_dev->inp == INP_ISP) { struct v4l2_subdev_format fmt; @@ -310,7 +303,7 @@ static int rkispp_sd_s_power(struct v4l2_subdev *sd, int on) v4l2_err(&ispp_dev->v4l2_dev, "%s get format fail:%d\n", __func__, ret); - goto err; + return ret; } sel.pad = RKISPP_PAD_SINK; sel.target = V4L2_SEL_TGT_CROP; @@ -321,7 +314,7 @@ static int rkispp_sd_s_power(struct v4l2_subdev *sd, int on) v4l2_err(&ispp_dev->v4l2_dev, "%s get crop fail:%d\n", __func__, ret); - goto err; + return ret; } ret = v4l2_subdev_call(ispp_sdev->remote_sd, @@ -330,9 +323,19 @@ static int rkispp_sd_s_power(struct v4l2_subdev *sd, int on) v4l2_err(&ispp_dev->v4l2_dev, "%s set isp power on fail:%d\n", __func__, ret); - goto err; + return ret; } } + ret = pm_runtime_get_sync(ispp_dev->dev); + if (ret < 0) { + v4l2_err(&ispp_dev->v4l2_dev, + "%s runtime get failed:%d\n", + __func__, ret); + if (ispp_dev->inp == INP_ISP) + v4l2_subdev_call(ispp_sdev->remote_sd, + core, s_power, 0); + return ret; + } } else { if (ispp_dev->inp == INP_ISP) v4l2_subdev_call(ispp_sdev->remote_sd, core, s_power, 0); @@ -343,9 +346,6 @@ static int rkispp_sd_s_power(struct v4l2_subdev *sd, int on) __func__, ret); } - return ret; -err: - pm_runtime_put(ispp_dev->dev); return ret; } diff --git a/drivers/media/platform/rockchip/ispp/stream.c b/drivers/media/platform/rockchip/ispp/stream.c index 41affe01f93e..37cb32e868b0 100644 --- a/drivers/media/platform/rockchip/ispp/stream.c +++ b/drivers/media/platform/rockchip/ispp/stream.c @@ -1471,7 +1471,6 @@ static int start_isp(struct rkispp_device *dev) mutex_lock(&dev->hw_dev->dev_lock); mode.work_mode = dev->isp_mode; - mode.max_in = dev->hw_dev->max_in; mode.buf_num = (dev->isp_mode & ISP_ISPP_QUICK) ? 1 : RKISPP_BUF_MAX; i = 1;