From a9ed7b93e657b49420dc7c02c3ce9ce810e9b7d3 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Wed, 21 Dec 2022 10:19:50 +0800 Subject: [PATCH] media: rockchip: vicap compatible with rk3588s2 Signed-off-by: Zefa Chen Change-Id: Idd8312275b97b690de378094116d558e85b4cb00 --- drivers/media/platform/rockchip/cif/capture.c | 50 +++++++++++------ .../media/platform/rockchip/cif/cif-scale.c | 4 +- .../media/platform/rockchip/cif/cif-tools.c | 4 +- drivers/media/platform/rockchip/cif/dev.c | 15 +++++- drivers/media/platform/rockchip/cif/dev.h | 3 +- drivers/media/platform/rockchip/cif/hw.c | 54 +++++++++++++++++++ drivers/media/platform/rockchip/cif/hw.h | 1 + 7 files changed, 110 insertions(+), 21 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 2b76a5f17c0e..3d5a1d55123c 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -847,10 +847,11 @@ static int get_csi_crop_align(const struct cif_input_fmt *fmt_in) } const struct -cif_input_fmt *get_input_fmt(struct v4l2_subdev *sd, struct v4l2_rect *rect, +cif_input_fmt *rkcif_get_input_fmt(struct rkcif_device *dev, struct v4l2_rect *rect, u32 pad_id, struct csi_channel_info *csi_info) { struct v4l2_subdev_format fmt; + struct v4l2_subdev *sd = dev->terminal_sensor.sd; struct rkmodule_channel_info ch_info = {0}; struct rkmodule_capture_info capture_info; int ret; @@ -914,8 +915,22 @@ cif_input_fmt *get_input_fmt(struct v4l2_subdev *sd, struct v4l2_rect *rect, core, ioctl, RKMODULE_GET_CAPTURE_MODE, &capture_info); - if (!ret) + if (!ret) { + if (capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE && + dev->hw_dev->is_rk3588s2) { + for (i = 0; i < capture_info.multi_dev.dev_num; i++) { + if (capture_info.multi_dev.dev_idx[i] == 0) + capture_info.multi_dev.dev_idx[i] = 2; + else if (capture_info.multi_dev.dev_idx[i] == 2) + capture_info.multi_dev.dev_idx[i] = 4; + else if (capture_info.multi_dev.dev_idx[i] == 3) + capture_info.multi_dev.dev_idx[i] = 5; + } + } csi_info->capture_info = capture_info; + } else { + csi_info->capture_info.mode = RKMODULE_CAPTURE_MODE_NONE; + } for (i = 0; i < ARRAY_SIZE(in_fmts); i++) if (fmt.format.code == in_fmts[i].mbus_code && fmt.format.field == in_fmts[i].field) @@ -5362,9 +5377,9 @@ static int rkcif_sanity_check_fmt(struct rkcif_stream *stream, struct v4l2_rect input, *crop; if (dev->terminal_sensor.sd) { - stream->cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd, - &input, stream->id, - &dev->channels[stream->id]); + stream->cif_fmt_in = rkcif_get_input_fmt(dev, + &input, stream->id, + &dev->channels[stream->id]); if (!stream->cif_fmt_in) { v4l2_err(v4l2_dev, "Input fmt is invalid\n"); return -EINVAL; @@ -6146,10 +6161,15 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode) csi_info.csi_num, RKCIF_MAX_CSI_NUM); goto out; } - for (i = 0; i < csi_info.csi_num; i++) + for (i = 0; i < csi_info.csi_num; i++) { csi_info.csi_idx[i] = dev->channels[0].capture_info.multi_dev.dev_idx[i]; + if (dev->hw_dev->is_rk3588s2) + v4l2_info(v4l2_dev, "rk3588s2 combine mode attach to mipi%d\n", + csi_info.csi_idx[i]); + } } else { csi_info.csi_num = 1; + dev->csi_host_idx = dev->csi_host_idx_def; csi_info.csi_idx[0] = dev->csi_host_idx; } ret = v4l2_subdev_call(dev->active_sensor->sd, @@ -6350,9 +6370,9 @@ int rkcif_set_fmt(struct rkcif_stream *stream, input_rect.height = RKCIF_DEFAULT_HEIGHT; if (dev->terminal_sensor.sd) { - cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd, - &input_rect, stream->id, - channel_info); + cif_fmt_in = rkcif_get_input_fmt(dev, + &input_rect, stream->id, + channel_info); stream->cif_fmt_in = cif_fmt_in; } else { v4l2_err(&stream->cifdev->v4l2_dev, @@ -6720,9 +6740,9 @@ static int rkcif_enum_framesizes(struct file *file, void *prov, input_rect.height = RKCIF_DEFAULT_HEIGHT; if (dev->terminal_sensor.sd) - get_input_fmt(dev->terminal_sensor.sd, - &input_rect, stream->id, - &csi_info); + rkcif_get_input_fmt(dev, + &input_rect, stream->id, + &csi_info); if (dev->hw_dev->adapt_to_usbcamerahal) { fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; @@ -6801,7 +6821,7 @@ static int rkcif_enum_fmt_vid_cap_mplane(struct file *file, void *priv, return -EINVAL; if (dev->terminal_sensor.sd) { - cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd, + cif_fmt_in = rkcif_get_input_fmt(dev, &input_rect, stream->id, &dev->channels[stream->id]); stream->cif_fmt_in = cif_fmt_in; @@ -7187,8 +7207,8 @@ static long rkcif_ioctl_default(struct file *file, void *fh, break; case RKCIF_CMD_SET_CSI_MEMORY_MODE: if (dev->terminal_sensor.sd) { - in_fmt = get_input_fmt(dev->terminal_sensor.sd, - &rect, 0, &csi_info); + in_fmt = rkcif_get_input_fmt(dev, + &rect, 0, &csi_info); if (in_fmt == NULL) { v4l2_err(&dev->v4l2_dev, "can't get sensor input format\n"); return -EINVAL; diff --git a/drivers/media/platform/rockchip/cif/cif-scale.c b/drivers/media/platform/rockchip/cif/cif-scale.c index 7ea3404258f0..3beede6ee93f 100644 --- a/drivers/media/platform/rockchip/cif/cif-scale.c +++ b/drivers/media/platform/rockchip/cif/cif-scale.c @@ -364,8 +364,8 @@ static int rkcif_scale_enum_framesizes(struct file *file, void *prov, input_rect.height = RKCIF_DEFAULT_HEIGHT; if (terminal_sensor && terminal_sensor->sd) - get_input_fmt(terminal_sensor->sd, - &input_rect, 0, &csi_info); + rkcif_get_input_fmt(dev, + &input_rect, 0, &csi_info); switch (fsize->index) { case SCALE_8TIMES: diff --git a/drivers/media/platform/rockchip/cif/cif-tools.c b/drivers/media/platform/rockchip/cif/cif-tools.c index e3a676c04b4b..60103bf71402 100644 --- a/drivers/media/platform/rockchip/cif/cif-tools.c +++ b/drivers/media/platform/rockchip/cif/cif-tools.c @@ -300,8 +300,8 @@ static int rkcif_tools_enum_framesizes(struct file *file, void *prov, input_rect.height = RKCIF_DEFAULT_HEIGHT; if (terminal_sensor && terminal_sensor->sd) - get_input_fmt(terminal_sensor->sd, - &input_rect, 0, &csi_info); + rkcif_get_input_fmt(dev, + &input_rect, 0, &csi_info); fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; s->width = input_rect.width; diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index e931dc61389d..6f41ab36a23a 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -1998,6 +1998,17 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int cif_dev->csi_host_idx = of_alias_get_id(node, "rkcif_mipi_lvds"); if (cif_dev->csi_host_idx < 0 || cif_dev->csi_host_idx > 5) cif_dev->csi_host_idx = 0; + if (cif_dev->hw_dev->is_rk3588s2) { + if (cif_dev->csi_host_idx == 0) + cif_dev->csi_host_idx = 2; + else if (cif_dev->csi_host_idx == 2) + cif_dev->csi_host_idx = 4; + else if (cif_dev->csi_host_idx == 3) + cif_dev->csi_host_idx = 5; + v4l2_info(&cif_dev->v4l2_dev, "rk3588s2 attach to mipi%d\n", + cif_dev->csi_host_idx); + } + cif_dev->csi_host_idx_def = cif_dev->csi_host_idx; cif_dev->media_dev.dev = dev; v4l2_dev = &cif_dev->v4l2_dev; v4l2_dev->mdev = &cif_dev->media_dev; @@ -2160,7 +2171,9 @@ static int rkcif_plat_probe(struct platform_device *pdev) if (sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp)) return -ENODEV; - rkcif_attach_hw(cif_dev); + ret = rkcif_attach_hw(cif_dev); + if (ret) + return ret; rkcif_parse_dts(cif_dev); diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index c0974a8c7719..b5d4c0315e8c 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -845,6 +845,7 @@ struct rkcif_device { struct rkcif_work_struct reset_work; int id_use_cnt; unsigned int csi_host_idx; + unsigned int csi_host_idx_def; unsigned int dvp_sof_in_oneframe; unsigned int wait_line; unsigned int wait_line_bak; @@ -887,7 +888,7 @@ void rkcif_vb_done_tasklet(struct rkcif_stream *stream, struct rkcif_buffer *buf int rkcif_scale_start(struct rkcif_scale_vdev *scale_vdev); const struct -cif_input_fmt *get_input_fmt(struct v4l2_subdev *sd, +cif_input_fmt *rkcif_get_input_fmt(struct rkcif_device *dev, struct v4l2_rect *rect, u32 pad_id, struct csi_channel_info *csi_info); diff --git a/drivers/media/platform/rockchip/cif/hw.c b/drivers/media/platform/rockchip/cif/hw.c index af0f0633e7bb..bf5653961509 100644 --- a/drivers/media/platform/rockchip/cif/hw.c +++ b/drivers/media/platform/rockchip/cif/hw.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -1252,6 +1253,51 @@ void rkcif_hw_soft_reset(struct rkcif_hw *cif_hw, bool is_rst_iommu) rkcif_iommu_enable(cif_hw); } +static int rkcif_get_efuse_value(struct device_node *np, char *porp_name, + u8 *value) +{ + struct nvmem_cell *cell; + unsigned char *buf; + size_t len; + + cell = of_nvmem_cell_get(np, porp_name); + if (IS_ERR(cell)) + return PTR_ERR(cell); + + buf = (unsigned char *)nvmem_cell_read(cell, &len); + + nvmem_cell_put(cell); + + if (IS_ERR(buf)) + return PTR_ERR(buf); + + *value = buf[0]; + + kfree(buf); + + return 0; +} + +static int rkcif_get_speciand_package_number(struct device_node *np) +{ + u8 spec = 0, package = 0, low = 0, high = 0; + + if (rkcif_get_efuse_value(np, "specification", &spec)) + return -EINVAL; + if (rkcif_get_efuse_value(np, "package_low", &low)) + return -EINVAL; + if (rkcif_get_efuse_value(np, "package_high", &high)) + return -EINVAL; + + package = ((high & 0x1) << 3) | low; + + /* RK3588S */ + if (spec == 0x13) + return package; + + return -EINVAL; +} + static int rkcif_plat_hw_probe(struct platform_device *pdev) { const struct of_device_id *match; @@ -1265,6 +1311,7 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev) int i, ret, irq; bool is_mem_reserved = false; struct notifier_block *notifier; + int package = 0; match = of_match_node(rkcif_plat_of_match, node); if (IS_ERR(match)) @@ -1278,6 +1325,13 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev) dev_set_drvdata(dev, cif_hw); cif_hw->dev = dev; + package = rkcif_get_speciand_package_number(node); + if (package == 0x2) { + cif_hw->is_rk3588s2 = true; + dev_info(dev, "attach rk3588s2\n"); + } else { + cif_hw->is_rk3588s2 = false; + } irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; diff --git a/drivers/media/platform/rockchip/cif/hw.h b/drivers/media/platform/rockchip/cif/hw.h index 56bc785cdd82..4faa9c46e085 100644 --- a/drivers/media/platform/rockchip/cif/hw.h +++ b/drivers/media/platform/rockchip/cif/hw.h @@ -150,6 +150,7 @@ struct rkcif_hw { bool is_dma_contig; bool adapt_to_usbcamerahal; u64 irq_time; + bool is_rk3588s2; }; void rkcif_hw_soft_reset(struct rkcif_hw *cif_hw, bool is_rst_iommu);