From da2794bb29e82de7242ce559d69c331a11f17f11 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Mon, 5 Jul 2021 09:10:36 +0800 Subject: [PATCH] media: rockchip: isp: dual isp unite process image Change-Id: Ia85adab95cce029ea0967c00bd7d0d51863d7d76 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/capture.c | 4 +- drivers/media/platform/rockchip/isp/capture.h | 2 +- .../media/platform/rockchip/isp/capture_v1x.c | 7 +- .../media/platform/rockchip/isp/capture_v20.c | 7 +- .../media/platform/rockchip/isp/capture_v21.c | 7 +- .../media/platform/rockchip/isp/capture_v30.c | 195 ++++++--- drivers/media/platform/rockchip/isp/common.c | 44 ++ drivers/media/platform/rockchip/isp/common.h | 33 ++ drivers/media/platform/rockchip/isp/csi.c | 16 +- drivers/media/platform/rockchip/isp/dev.c | 25 +- drivers/media/platform/rockchip/isp/dmarx.c | 24 +- drivers/media/platform/rockchip/isp/hw.c | 109 +++-- drivers/media/platform/rockchip/isp/hw.h | 3 + drivers/media/platform/rockchip/isp/regs.c | 131 +++++- drivers/media/platform/rockchip/isp/regs.h | 59 ++- .../media/platform/rockchip/isp/regs_v2x.h | 5 + .../media/platform/rockchip/isp/regs_v3x.h | 5 + drivers/media/platform/rockchip/isp/rkisp.c | 382 +++++++++++++----- drivers/media/platform/rockchip/isp/rkisp.h | 2 + include/uapi/linux/rk-camera-module.h | 2 + 20 files changed, 788 insertions(+), 274 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/capture.c b/drivers/media/platform/rockchip/isp/capture.c index 01cc876e7598..89423487d701 100644 --- a/drivers/media/platform/rockchip/isp/capture.c +++ b/drivers/media/platform/rockchip/isp/capture.c @@ -890,8 +890,8 @@ static void restrict_rsz_resolution(struct rkisp_device *dev, struct v4l2_rect *input_win; input_win = rkisp_get_isp_sd_win(&dev->isp_sdev); - max_rsz->width = min_t(int, input_win->width, config->max_rsz_width); - max_rsz->height = min_t(int, input_win->height, config->max_rsz_height); + max_rsz->width = max_t(int, input_win->width, config->max_rsz_width); + max_rsz->height = max_t(int, input_win->height, config->max_rsz_height); } static int rkisp_set_fmt(struct rkisp_stream *stream, diff --git a/drivers/media/platform/rockchip/isp/capture.h b/drivers/media/platform/rockchip/isp/capture.h index 6e0e737d281b..2712543e500d 100644 --- a/drivers/media/platform/rockchip/isp/capture.h +++ b/drivers/media/platform/rockchip/isp/capture.h @@ -200,7 +200,7 @@ struct streams_ops { void (*stop_mi)(struct rkisp_stream *stream); void (*enable_mi)(struct rkisp_stream *stream); void (*disable_mi)(struct rkisp_stream *stream); - void (*set_data_path)(void __iomem *base); + void (*set_data_path)(struct rkisp_stream *stream); bool (*is_stream_stopped)(void __iomem *base); void (*update_mi)(struct rkisp_stream *stream); int (*frame_end)(struct rkisp_stream *stream); diff --git a/drivers/media/platform/rockchip/isp/capture_v1x.c b/drivers/media/platform/rockchip/isp/capture_v1x.c index 7e1ade4dfd46..b829bd5e512a 100644 --- a/drivers/media/platform/rockchip/isp/capture_v1x.c +++ b/drivers/media/platform/rockchip/isp/capture_v1x.c @@ -380,7 +380,7 @@ static struct streams_ops rkisp_mp_streams_ops = { .enable_mi = mp_enable_mi, .disable_mi = mp_disable_mi, .stop_mi = mp_stop_mi, - .set_data_path = mp_set_data_path, + .set_data_path = stream_data_path, .is_stream_stopped = mp_is_stream_stopped, .update_mi = update_mi, .frame_end = mi_frame_end, @@ -391,7 +391,7 @@ static struct streams_ops rkisp_sp_streams_ops = { .enable_mi = sp_enable_mi, .disable_mi = sp_disable_mi, .stop_mi = sp_stop_mi, - .set_data_path = sp_set_data_path, + .set_data_path = stream_data_path, .is_stream_stopped = sp_is_stream_stopped, .update_mi = update_mi, .frame_end = mi_frame_end, @@ -517,11 +517,10 @@ static void rkisp_stream_stop(struct rkisp_stream *stream) */ static int rkisp_start(struct rkisp_stream *stream) { - void __iomem *base = stream->ispdev->base_addr; int ret; if (stream->ops->set_data_path) - stream->ops->set_data_path(base); + stream->ops->set_data_path(stream); ret = stream->ops->config_mi(stream); if (ret) return ret; diff --git a/drivers/media/platform/rockchip/isp/capture_v20.c b/drivers/media/platform/rockchip/isp/capture_v20.c index 3acaffaa5b8b..4dbb87110d54 100644 --- a/drivers/media/platform/rockchip/isp/capture_v20.c +++ b/drivers/media/platform/rockchip/isp/capture_v20.c @@ -836,7 +836,7 @@ static struct streams_ops rkisp_mp_streams_ops = { .enable_mi = mp_enable_mi, .disable_mi = mp_disable_mi, .stop_mi = mp_stop_mi, - .set_data_path = mp_set_data_path, + .set_data_path = stream_data_path, .is_stream_stopped = mp_is_stream_stopped, .update_mi = update_mi, .frame_end = mi_frame_end, @@ -847,7 +847,7 @@ static struct streams_ops rkisp_sp_streams_ops = { .enable_mi = sp_enable_mi, .disable_mi = sp_disable_mi, .stop_mi = sp_stop_mi, - .set_data_path = sp_set_data_path, + .set_data_path = stream_data_path, .is_stream_stopped = sp_is_stream_stopped, .update_mi = update_mi, .frame_end = mi_frame_end, @@ -1215,7 +1215,6 @@ static void rkisp_stream_stop(struct rkisp_stream *stream) */ static int rkisp_start(struct rkisp_stream *stream) { - void __iomem *base = stream->ispdev->base_addr; struct rkisp_device *dev = stream->ispdev; int ret; @@ -1226,7 +1225,7 @@ static int rkisp_start(struct rkisp_stream *stream) hdr_config_dmatx(dev); if (stream->ops->set_data_path) - stream->ops->set_data_path(base); + stream->ops->set_data_path(stream); ret = stream->ops->config_mi(stream); if (ret) return ret; diff --git a/drivers/media/platform/rockchip/isp/capture_v21.c b/drivers/media/platform/rockchip/isp/capture_v21.c index b17b1ef7d6a8..4bef12f6a9a4 100644 --- a/drivers/media/platform/rockchip/isp/capture_v21.c +++ b/drivers/media/platform/rockchip/isp/capture_v21.c @@ -733,7 +733,7 @@ static struct streams_ops rkisp_mp_streams_ops = { .enable_mi = mp_enable_mi, .disable_mi = mp_disable_mi, .stop_mi = mp_stop_mi, - .set_data_path = mp_set_data_path, + .set_data_path = stream_data_path, .is_stream_stopped = mp_is_stream_stopped, .update_mi = update_mi, .frame_end = mi_frame_end, @@ -744,7 +744,7 @@ static struct streams_ops rkisp_sp_streams_ops = { .enable_mi = sp_enable_mi, .disable_mi = sp_disable_mi, .stop_mi = sp_stop_mi, - .set_data_path = sp_set_data_path, + .set_data_path = stream_data_path, .is_stream_stopped = sp_is_stream_stopped, .update_mi = update_mi, .frame_end = mi_frame_end, @@ -1038,7 +1038,6 @@ static void rkisp_stream_stop(struct rkisp_stream *stream) */ static int rkisp_start(struct rkisp_stream *stream) { - void __iomem *base = stream->ispdev->base_addr; struct rkisp_device *dev = stream->ispdev; bool is_update = false; int ret; @@ -1050,7 +1049,7 @@ static int rkisp_start(struct rkisp_stream *stream) } if (stream->ops->set_data_path) - stream->ops->set_data_path(base); + stream->ops->set_data_path(stream); ret = stream->ops->config_mi(stream); if (ret) return ret; diff --git a/drivers/media/platform/rockchip/isp/capture_v30.c b/drivers/media/platform/rockchip/isp/capture_v30.c index 1032b6ff1332..6fcdeb72cb4b 100644 --- a/drivers/media/platform/rockchip/isp/capture_v30.c +++ b/drivers/media/platform/rockchip/isp/capture_v30.c @@ -134,7 +134,8 @@ static int rkisp_stream_config_dcrop(struct rkisp_stream *stream, bool async) if (dcrop->width == input_win->width && dcrop->height == input_win->height && - dcrop->left == 0 && dcrop->top == 0) { + dcrop->left == 0 && dcrop->top == 0 && + !dev->hw_dev->is_unite) { rkisp_disable_dcrop(stream, async); v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, "stream %d crop disabled\n", stream->id); @@ -274,6 +275,7 @@ static int mp_config_mi(struct rkisp_stream *stream) { struct rkisp_device *dev = stream->ispdev; struct v4l2_pix_format_mplane *out_fmt = &stream->out_fmt; + bool is_unite = dev->hw_dev->is_unite; u32 val, mask; /* @@ -281,26 +283,26 @@ static int mp_config_mi(struct rkisp_stream *stream) * memory plane formats, so calculate the size explicitly. */ val = out_fmt->plane_fmt[0].bytesperline * out_fmt->height; - rkisp_write(dev, stream->config->mi.y_size_init, val, false); + rkisp_unite_write(dev, stream->config->mi.y_size_init, val, false, is_unite); val = out_fmt->plane_fmt[1].sizeimage; - rkisp_write(dev, stream->config->mi.cb_size_init, val, false); + rkisp_unite_write(dev, stream->config->mi.cb_size_init, val, false, is_unite); val = out_fmt->plane_fmt[2].sizeimage; - rkisp_write(dev, stream->config->mi.cr_size_init, val, false); + rkisp_unite_write(dev, stream->config->mi.cr_size_init, val, false, is_unite); - val = out_fmt->width; - rkisp_write(dev, ISP3X_MI_MP_WR_Y_PIC_WIDTH, val, false); + val = is_unite ? out_fmt->width / 2 : out_fmt->width; + rkisp_unite_write(dev, ISP3X_MI_MP_WR_Y_PIC_WIDTH, val, false, is_unite); val = out_fmt->height; - rkisp_write(dev, ISP3X_MI_MP_WR_Y_PIC_HEIGHT, val, false); + rkisp_unite_write(dev, ISP3X_MI_MP_WR_Y_PIC_HEIGHT, val, false, is_unite); val = ALIGN(out_fmt->plane_fmt[0].bytesperline, 16); - rkisp_write(dev, ISP3X_MI_MP_WR_Y_LLENGTH, val, false); + rkisp_unite_write(dev, ISP3X_MI_MP_WR_Y_LLENGTH, val, false, is_unite); val = stream->out_isp_fmt.uv_swap ? ISP3X_MI_XTD_FORMAT_MP_UV_SWAP : 0; mask = ISP3X_MI_XTD_FORMAT_MP_UV_SWAP; - rkisp_set_bits(dev, ISP3X_MI_WR_XTD_FORMAT_CTRL, mask, val, false); + rkisp_unite_set_bits(dev, ISP3X_MI_WR_XTD_FORMAT_CTRL, mask, val, false, is_unite); if (stream->out_fmt.pixelformat == V4L2_PIX_FMT_NV21 || stream->out_fmt.pixelformat == V4L2_PIX_FMT_NV12 || @@ -311,13 +313,13 @@ static int mp_config_mi(struct rkisp_stream *stream) else val = ISP3X_SEPERATE_YUV_CFG | ISP3X_MP_YUV_MODE; mask = ISP3X_MPFBC_FORCE_UPD | ISP3X_MP_YUV_MODE; - rkisp_set_bits(dev, ISP3X_MPFBC_CTRL, mask, val, false); + rkisp_unite_set_bits(dev, ISP3X_MPFBC_CTRL, mask, val, false, is_unite); val = calc_burst_len(stream) | CIF_MI_CTRL_INIT_BASE_EN | CIF_MI_CTRL_INIT_OFFSET_EN | CIF_MI_MP_AUTOUPDATE_ENABLE | stream->out_isp_fmt.write_format; mask = GENMASK(19, 16) | MI_CTRL_MP_FMT_MASK; - rkisp_set_bits(dev, ISP3X_MI_WR_CTRL, mask, val, false); + rkisp_unite_set_bits(dev, ISP3X_MI_WR_CTRL, mask, val, false, is_unite); mi_frame_end_int_enable(stream); /* set up first buffer */ @@ -358,6 +360,7 @@ static int sp_config_mi(struct rkisp_stream *stream) struct v4l2_pix_format_mplane *out_fmt = &stream->out_fmt; struct ispsd_out_fmt *input_isp_fmt = rkisp_get_ispsd_out_fmt(&dev->isp_sdev); + bool is_unite = dev->hw_dev->is_unite; u32 sp_in_fmt, val, mask; if (mbus_code_sp_in_fmt(input_isp_fmt->mbus_code, @@ -371,26 +374,26 @@ static int sp_config_mi(struct rkisp_stream *stream) * memory plane formats, so calculate the size explicitly. */ val = out_fmt->plane_fmt[0].bytesperline * out_fmt->height; - rkisp_write(dev, stream->config->mi.y_size_init, val, false); + rkisp_unite_write(dev, stream->config->mi.y_size_init, val, false, is_unite); val = out_fmt->plane_fmt[1].sizeimage; - rkisp_write(dev, stream->config->mi.cb_size_init, val, false); + rkisp_unite_write(dev, stream->config->mi.cb_size_init, val, false, is_unite); val = out_fmt->plane_fmt[2].sizeimage; - rkisp_write(dev, stream->config->mi.cr_size_init, val, false); + rkisp_unite_write(dev, stream->config->mi.cr_size_init, val, false, is_unite); - val = out_fmt->width; - rkisp_write(dev, ISP3X_MI_SP_WR_Y_PIC_WIDTH, val, false); + val = is_unite ? out_fmt->width / 2 : out_fmt->width; + rkisp_unite_write(dev, ISP3X_MI_SP_WR_Y_PIC_WIDTH, val, false, is_unite); val = out_fmt->height; - rkisp_write(dev, ISP3X_MI_SP_WR_Y_PIC_HEIGHT, val, false); + rkisp_unite_write(dev, ISP3X_MI_SP_WR_Y_PIC_HEIGHT, val, false, is_unite); val = ALIGN(out_fmt->plane_fmt[0].bytesperline, 16); - rkisp_write(dev, ISP3X_MI_SP_WR_Y_LLENGTH, val, false); + rkisp_unite_write(dev, ISP3X_MI_SP_WR_Y_LLENGTH, val, false, is_unite); val = stream->out_isp_fmt.uv_swap ? ISP3X_MI_XTD_FORMAT_SP_UV_SWAP : 0; mask = ISP3X_MI_XTD_FORMAT_SP_UV_SWAP; - rkisp_set_bits(dev, ISP3X_MI_WR_XTD_FORMAT_CTRL, mask, val, false); + rkisp_unite_set_bits(dev, ISP3X_MI_WR_XTD_FORMAT_CTRL, mask, val, false, is_unite); if (stream->out_fmt.pixelformat == V4L2_PIX_FMT_NV21 || stream->out_fmt.pixelformat == V4L2_PIX_FMT_NV12 || @@ -401,14 +404,14 @@ static int sp_config_mi(struct rkisp_stream *stream) else val = ISP3X_SEPERATE_YUV_CFG | ISP3X_SP_YUV_MODE; mask = ISP3X_MPFBC_FORCE_UPD | ISP3X_SP_YUV_MODE; - rkisp_set_bits(dev, ISP3X_MPFBC_CTRL, mask, val, false); + rkisp_unite_set_bits(dev, ISP3X_MPFBC_CTRL, mask, val, false, is_unite); val = calc_burst_len(stream) | CIF_MI_CTRL_INIT_BASE_EN | CIF_MI_CTRL_INIT_OFFSET_EN | stream->out_isp_fmt.write_format | sp_in_fmt | stream->out_isp_fmt.output_format | CIF_MI_SP_AUTOUPDATE_ENABLE; mask = GENMASK(19, 16) | MI_CTRL_SP_FMT_MASK; - rkisp_set_bits(dev, ISP3X_MI_WR_CTRL, mask, val, false); + rkisp_unite_set_bits(dev, ISP3X_MI_WR_CTRL, mask, val, false, is_unite); mi_frame_end_int_enable(stream); /* set up first buffer */ @@ -418,10 +421,20 @@ static int sp_config_mi(struct rkisp_stream *stream) static int fbc_config_mi(struct rkisp_stream *stream) { - u32 h = stream->out_fmt.height; + u32 h = ALIGN(stream->out_fmt.height, 16); + u32 w = ALIGN(stream->out_fmt.width, 16); + u32 offs = w * h / 16; + bool is_unite = stream->ispdev->hw_dev->is_unite; - rkisp_write(stream->ispdev, ISP3X_MPFBC_VIR_WIDTH, 0, false); - rkisp_write(stream->ispdev, ISP3X_MPFBC_VIR_HEIGHT, ALIGN(h, 16), false); + rkisp_write(stream->ispdev, ISP3X_MPFBC_HEAD_OFFSET, offs, false); + rkisp_unite_write(stream->ispdev, ISP3X_MPFBC_VIR_WIDTH, w, false, is_unite); + rkisp_unite_write(stream->ispdev, ISP3X_MPFBC_VIR_HEIGHT, h, false, is_unite); + if (is_unite) { + u32 left_w = (stream->out_fmt.width / 2) & ~0xf; + + offs += left_w * 32; + rkisp_next_write(stream->ispdev, ISP3X_MPFBC_HEAD_OFFSET, offs, false); + } mi_frame_end_int_enable(stream); /* set up first buffer */ mi_frame_end(stream); @@ -432,6 +445,7 @@ static int bp_config_mi(struct rkisp_stream *stream) { struct v4l2_pix_format_mplane *out_fmt = &stream->out_fmt; struct rkisp_device *dev = stream->ispdev; + bool is_unite = dev->hw_dev->is_unite; u32 val, mask; /* @@ -439,19 +453,19 @@ static int bp_config_mi(struct rkisp_stream *stream) * memory plane formats, so calculate the size explicitly. */ val = out_fmt->plane_fmt[0].bytesperline * out_fmt->height; - rkisp_write(dev, stream->config->mi.y_size_init, val, false); + rkisp_unite_write(dev, stream->config->mi.y_size_init, val, false, is_unite); val = out_fmt->plane_fmt[1].sizeimage; - rkisp_write(dev, stream->config->mi.cb_size_init, val, false); + rkisp_unite_write(dev, stream->config->mi.cb_size_init, val, false, is_unite); - val = out_fmt->width; - rkisp_write(dev, ISP3X_MI_BP_WR_Y_PIC_WIDTH, val, false); + val = is_unite ? out_fmt->width / 2 : out_fmt->width; + rkisp_unite_write(dev, ISP3X_MI_BP_WR_Y_PIC_WIDTH, val, false, is_unite); val = out_fmt->height; - rkisp_write(dev, ISP3X_MI_BP_WR_Y_PIC_HEIGHT, val, false); + rkisp_unite_write(dev, ISP3X_MI_BP_WR_Y_PIC_HEIGHT, val, false, is_unite); val = ALIGN(out_fmt->plane_fmt[0].bytesperline, 16); - rkisp_write(dev, ISP3X_MI_BP_WR_Y_LLENGTH, val, false); + rkisp_unite_write(dev, ISP3X_MI_BP_WR_Y_LLENGTH, val, false, is_unite); if (out_fmt->pixelformat == V4L2_PIX_FMT_NV12 || out_fmt->pixelformat == V4L2_PIX_FMT_NV12M) @@ -459,7 +473,7 @@ static int bp_config_mi(struct rkisp_stream *stream) else val = ISP3X_SEPERATE_YUV_CFG | ISP3X_BP_YUV_MODE; mask = ISP3X_MPFBC_FORCE_UPD | ISP3X_BP_YUV_MODE; - rkisp_set_bits(dev, ISP3X_MPFBC_CTRL, mask, val, false); + rkisp_unite_set_bits(dev, ISP3X_MPFBC_CTRL, mask, val, false, is_unite); mi_frame_end_int_enable(stream); /* set up first buffer */ @@ -475,21 +489,25 @@ static void mp_enable_mi(struct rkisp_stream *stream) if (isp_fmt->fmt_type == FMT_BAYER) val = CIF_MI_CTRL_RAW_ENABLE; - rkisp_set_bits(stream->ispdev, ISP3X_MI_WR_CTRL, mask, val, false); + rkisp_unite_set_bits(stream->ispdev, ISP3X_MI_WR_CTRL, mask, val, + false, stream->ispdev->hw_dev->is_unite); } static void sp_enable_mi(struct rkisp_stream *stream) { - rkisp_set_bits(stream->ispdev, ISP3X_MI_WR_CTRL, - 0, CIF_MI_CTRL_SP_ENABLE, false); + rkisp_unite_set_bits(stream->ispdev, ISP3X_MI_WR_CTRL, 0, + CIF_MI_CTRL_SP_ENABLE, false, + stream->ispdev->hw_dev->is_unite); } static void fbc_enable_mi(struct rkisp_stream *stream) { u32 mask = ISP3X_MPFBC_FORCE_UPD | ISP3X_MPFBC_YUV_MASK; - u32 val = stream->out_isp_fmt.write_format | ISP3X_MPFBC_EN; + u32 val = stream->out_isp_fmt.write_format | + ISP3X_HEAD_OFFSET_EN | ISP3X_MPFBC_EN; + bool is_unite = stream->ispdev->hw_dev->is_unite; - rkisp_set_bits(stream->ispdev, ISP3X_MPFBC_CTRL, mask, val, false); + rkisp_unite_set_bits(stream->ispdev, ISP3X_MPFBC_CTRL, mask, val, false, is_unite); } static void bp_enable_mi(struct rkisp_stream *stream) @@ -497,48 +515,80 @@ static void bp_enable_mi(struct rkisp_stream *stream) u32 val = stream->out_isp_fmt.write_format | ISP3X_BP_ENABLE | ISP3X_BP_AUTO_UPD; - rkisp_write(stream->ispdev, ISP3X_MI_BP_WR_CTRL, val, false); + rkisp_unite_write(stream->ispdev, ISP3X_MI_BP_WR_CTRL, val, false, + stream->ispdev->hw_dev->is_unite); } static void mp_disable_mi(struct rkisp_stream *stream) { u32 mask = CIF_MI_CTRL_MP_ENABLE | CIF_MI_CTRL_RAW_ENABLE; - rkisp_clear_bits(stream->ispdev, ISP3X_MI_WR_CTRL, mask, false); + rkisp_unite_clear_bits(stream->ispdev, ISP3X_MI_WR_CTRL, mask, false, + stream->ispdev->hw_dev->is_unite); } static void sp_disable_mi(struct rkisp_stream *stream) { - rkisp_clear_bits(stream->ispdev, ISP3X_MI_WR_CTRL, CIF_MI_CTRL_SP_ENABLE, false); + rkisp_unite_clear_bits(stream->ispdev, ISP3X_MI_WR_CTRL, CIF_MI_CTRL_SP_ENABLE, + false, stream->ispdev->hw_dev->is_unite); } static void fbc_disable_mi(struct rkisp_stream *stream) { u32 mask = ISP3X_MPFBC_FORCE_UPD | ISP3X_MPFBC_EN; - rkisp_clear_bits(stream->ispdev, ISP3X_MPFBC_CTRL, mask, false); + rkisp_unite_clear_bits(stream->ispdev, ISP3X_MPFBC_CTRL, mask, + false, stream->ispdev->hw_dev->is_unite); } static void bp_disable_mi(struct rkisp_stream *stream) { - rkisp_clear_bits(stream->ispdev, ISP3X_MI_BP_WR_CTRL, ISP3X_BP_ENABLE, false); + rkisp_unite_clear_bits(stream->ispdev, ISP3X_MI_BP_WR_CTRL, ISP3X_BP_ENABLE, + false, stream->ispdev->hw_dev->is_unite); } static void update_mi(struct rkisp_stream *stream) { - struct rkisp_dummy_buffer *dummy_buf = &stream->ispdev->hw_dev->dummy_buf; struct rkisp_device *dev = stream->ispdev; - u32 val; + struct rkisp_dummy_buffer *dummy_buf = &dev->hw_dev->dummy_buf; + u32 val, reg; if (stream->next_buf) { + reg = stream->config->mi.y_base_ad_init; val = stream->next_buf->buff_addr[RKISP_PLANE_Y]; - rkisp_write(dev, stream->config->mi.y_base_ad_init, val, false); + rkisp_write(dev, reg, val, false); + + reg = stream->config->mi.cb_base_ad_init; val = stream->next_buf->buff_addr[RKISP_PLANE_CB]; - rkisp_write(dev, stream->config->mi.cb_base_ad_init, val, false); + rkisp_write(dev, reg, val, false); + if (stream->id != RKISP_STREAM_FBC && stream->id != RKISP_STREAM_BP) { + reg = stream->config->mi.cr_base_ad_init; val = stream->next_buf->buff_addr[RKISP_PLANE_CR]; - rkisp_write(dev, stream->config->mi.cr_base_ad_init, val, false); + rkisp_write(dev, reg, val, false); } + + if (dev->hw_dev->is_unite) { + u32 mult = stream->id != RKISP_STREAM_FBC ? 1 : 32; + + reg = stream->config->mi.y_base_ad_init; + val = stream->next_buf->buff_addr[RKISP_PLANE_Y]; + val += ((stream->out_fmt.width / 2) & ~0xf); + rkisp_next_write(dev, reg, val, false); + + reg = stream->config->mi.cb_base_ad_init; + val = stream->next_buf->buff_addr[RKISP_PLANE_CB]; + val += ((stream->out_fmt.width / 2) & ~0xf) * mult; + rkisp_next_write(dev, reg, val, false); + + if (stream->id != RKISP_STREAM_FBC && stream->id != RKISP_STREAM_BP) { + reg = stream->config->mi.cr_base_ad_init; + val = stream->next_buf->buff_addr[RKISP_PLANE_CR]; + val += ((stream->out_fmt.width / 2) & ~0xf); + rkisp_next_write(dev, reg, val, false); + } + } + /* single buf updated at readback for multidevice */ if (!dev->hw_dev->is_single) { stream->curr_buf = stream->next_buf; @@ -547,31 +597,45 @@ static void update_mi(struct rkisp_stream *stream) } else if (dummy_buf->mem_priv) { stream->dbg.frameloss++; val = dummy_buf->dma_addr; - rkisp_write(dev, stream->config->mi.y_base_ad_init, val, false); - rkisp_write(dev, stream->config->mi.cb_base_ad_init, val, false); + reg = stream->config->mi.y_base_ad_init; + rkisp_unite_write(dev, reg, val, false, dev->hw_dev->is_unite); + reg = stream->config->mi.cb_base_ad_init; + rkisp_unite_write(dev, reg, val, false, dev->hw_dev->is_unite); + reg = stream->config->mi.cr_base_ad_init; if (stream->id != RKISP_STREAM_FBC && stream->id != RKISP_STREAM_BP) - rkisp_write(dev, stream->config->mi.cr_base_ad_init, val, false); + rkisp_unite_write(dev, reg, val, false, dev->hw_dev->is_unite); } if (stream->id != RKISP_STREAM_FBC) { - mi_set_y_offset(stream, 0); - mi_set_cb_offset(stream, 0); + reg = stream->config->mi.y_offs_cnt_init; + rkisp_unite_write(dev, reg, 0, false, dev->hw_dev->is_unite); + reg = stream->config->mi.cb_offs_cnt_init; + rkisp_unite_write(dev, reg, 0, false, dev->hw_dev->is_unite); + reg = stream->config->mi.cr_offs_cnt_init; if (stream->id != RKISP_STREAM_BP) - mi_set_cr_offset(stream, 0); + rkisp_unite_write(dev, reg, 0, false, dev->hw_dev->is_unite); } + v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, "%s stream:%d Y:0x%x CB:0x%x | Y_SHD:0x%x\n", __func__, stream->id, rkisp_read(dev, stream->config->mi.y_base_ad_init, false), rkisp_read(dev, stream->config->mi.cb_base_ad_init, false), rkisp_read(dev, stream->config->mi.y_base_ad_shd, true)); + if (dev->hw_dev->is_unite) + v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, + "%s stream:%d Y:0x%x CB:0x%x | Y_SHD:0x%x, right\n", + __func__, stream->id, + rkisp_next_read(dev, stream->config->mi.y_base_ad_init, false), + rkisp_next_read(dev, stream->config->mi.cb_base_ad_init, false), + rkisp_next_read(dev, stream->config->mi.y_base_ad_shd, true)); } static struct streams_ops rkisp_mp_streams_ops = { .config_mi = mp_config_mi, .enable_mi = mp_enable_mi, .disable_mi = mp_disable_mi, - .set_data_path = mp_set_data_path, + .set_data_path = stream_data_path, .is_stream_stopped = mp_is_stream_stopped, .update_mi = update_mi, .frame_end = mi_frame_end, @@ -581,7 +645,7 @@ static struct streams_ops rkisp_sp_streams_ops = { .config_mi = sp_config_mi, .enable_mi = sp_enable_mi, .disable_mi = sp_disable_mi, - .set_data_path = sp_set_data_path, + .set_data_path = stream_data_path, .is_stream_stopped = sp_is_stream_stopped, .update_mi = update_mi, .frame_end = mi_frame_end, @@ -708,13 +772,12 @@ static void rkisp_stream_stop(struct rkisp_stream *stream) */ static int rkisp_start(struct rkisp_stream *stream) { - void __iomem *base = stream->ispdev->base_addr; struct rkisp_device *dev = stream->ispdev; bool is_update = atomic_read(&dev->cap_dev.refcnt) > 1 ? false : true; int ret; if (stream->ops->set_data_path) - stream->ops->set_data_path(base); + stream->ops->set_data_path(stream); ret = stream->ops->config_mi(stream); if (ret) return ret; @@ -907,12 +970,6 @@ static int rkisp_stream_start(struct rkisp_stream *stream) dev->cap_dev.stream[RKISP_STREAM_SP].streaming : dev->cap_dev.stream[RKISP_STREAM_MP].streaming; - ret = rkisp_stream_config_rsz(stream, async); - if (ret < 0) { - v4l2_err(v4l2_dev, "config rsz failed with error %d\n", ret); - return ret; - } - /* * can't be async now, otherwise the latter started stream fails to * produce mi interrupt. @@ -923,6 +980,11 @@ static int rkisp_stream_start(struct rkisp_stream *stream) return ret; } + ret = rkisp_stream_config_rsz(stream, async); + if (ret < 0) { + v4l2_err(v4l2_dev, "config rsz failed with error %d\n", ret); + return ret; + } end: return rkisp_start(stream); } @@ -1156,6 +1218,15 @@ void rkisp_mi_v30_isr(u32 mis_val, struct rkisp_device *dev) struct rkisp_stream *stream; unsigned int i; + if (dev->hw_dev->is_unite) { + u32 val = rkisp_read(dev, ISP3X_MI_RIS, true); + + if (val) { + rkisp_write(dev, ISP3X_MI_ICR, val, true); + v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, + "left mi isr:0x%x\n", val); + } + } v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, "mi isr:0x%x\n", mis_val); diff --git a/drivers/media/platform/rockchip/isp/common.c b/drivers/media/platform/rockchip/isp/common.c index 3f12b47d7567..30b69b204914 100644 --- a/drivers/media/platform/rockchip/isp/common.c +++ b/drivers/media/platform/rockchip/isp/common.c @@ -22,6 +22,20 @@ void rkisp_write(struct rkisp_device *dev, u32 reg, u32 val, bool is_direct) } } +void rkisp_next_write(struct rkisp_device *dev, u32 reg, u32 val, bool is_direct) +{ + u32 offset = RKISP_ISP_SW_MAX_SIZE + reg; + u32 *mem = dev->sw_base_addr + offset; + u32 *flag = dev->sw_base_addr + offset + RKISP_ISP_SW_REG_SIZE; + + *mem = val; + *flag = SW_REG_CACHE; + if (dev->hw_dev->is_single || is_direct) { + *flag = SW_REG_CACHE_SYNC; + writel(val, dev->hw_dev->base_next_addr + reg); + } +} + u32 rkisp_read(struct rkisp_device *dev, u32 reg, bool is_direct) { u32 val; @@ -33,11 +47,27 @@ u32 rkisp_read(struct rkisp_device *dev, u32 reg, bool is_direct) return val; } +u32 rkisp_next_read(struct rkisp_device *dev, u32 reg, bool is_direct) +{ + u32 val; + + if (dev->hw_dev->is_single || is_direct) + val = readl(dev->hw_dev->base_next_addr + reg); + else + val = *(u32 *)(dev->sw_base_addr + RKISP_ISP_SW_MAX_SIZE + reg); + return val; +} + u32 rkisp_read_reg_cache(struct rkisp_device *dev, u32 reg) { return *(u32 *)(dev->sw_base_addr + reg); } +u32 rkisp_next_read_reg_cache(struct rkisp_device *dev, u32 reg) +{ + return *(u32 *)(dev->sw_base_addr + RKISP_ISP_SW_MAX_SIZE + reg); +} + void rkisp_set_bits(struct rkisp_device *dev, u32 reg, u32 mask, u32 val, bool is_direct) { u32 tmp = rkisp_read(dev, reg, is_direct) & ~mask; @@ -45,6 +75,13 @@ void rkisp_set_bits(struct rkisp_device *dev, u32 reg, u32 mask, u32 val, bool i rkisp_write(dev, reg, val | tmp, is_direct); } +void rkisp_next_set_bits(struct rkisp_device *dev, u32 reg, u32 mask, u32 val, bool is_direct) +{ + u32 tmp = rkisp_next_read(dev, reg, is_direct) & ~mask; + + rkisp_next_write(dev, reg, val | tmp, is_direct); +} + void rkisp_clear_bits(struct rkisp_device *dev, u32 reg, u32 mask, bool is_direct) { u32 tmp = rkisp_read(dev, reg, is_direct); @@ -52,6 +89,13 @@ void rkisp_clear_bits(struct rkisp_device *dev, u32 reg, u32 mask, bool is_direc rkisp_write(dev, reg, tmp & ~mask, is_direct); } +void rkisp_next_clear_bits(struct rkisp_device *dev, u32 reg, u32 mask, bool is_direct) +{ + u32 tmp = rkisp_next_read(dev, reg, is_direct); + + rkisp_next_write(dev, reg, tmp & ~mask, is_direct); +} + void rkisp_update_regs(struct rkisp_device *dev, u32 start, u32 end) { void __iomem *base = dev->hw_dev->base_addr; diff --git a/drivers/media/platform/rockchip/isp/common.h b/drivers/media/platform/rockchip/isp/common.h index 589099c4fff3..6ff84a21b216 100644 --- a/drivers/media/platform/rockchip/isp/common.h +++ b/drivers/media/platform/rockchip/isp/common.h @@ -164,6 +164,39 @@ u32 rkisp_read(struct rkisp_device *dev, u32 reg, bool is_direct); u32 rkisp_read_reg_cache(struct rkisp_device *dev, u32 reg); void rkisp_set_bits(struct rkisp_device *dev, u32 reg, u32 mask, u32 val, bool is_direct); void rkisp_clear_bits(struct rkisp_device *dev, u32 reg, u32 mask, bool is_direct); +/* for dual isp, config for next isp reg */ +void rkisp_next_write(struct rkisp_device *dev, u32 reg, u32 val, bool is_direct); +u32 rkisp_next_read(struct rkisp_device *dev, u32 reg, bool is_direct); +u32 rkisp_next_read_reg_cache(struct rkisp_device *dev, u32 reg); +void rkisp_next_set_bits(struct rkisp_device *dev, u32 reg, u32 mask, u32 val, bool is_direct); +void rkisp_next_clear_bits(struct rkisp_device *dev, u32 reg, u32 mask, bool is_direct); + +static inline void +rkisp_unite_write(struct rkisp_device *dev, u32 reg, u32 val, bool is_direct, bool is_unite) +{ + rkisp_write(dev, reg, val, is_direct); + if (is_unite) + rkisp_next_write(dev, reg, val, is_direct); +} + +static inline void +rkisp_unite_set_bits(struct rkisp_device *dev, u32 reg, u32 mask, + u32 val, bool is_direct, bool is_unite) +{ + rkisp_set_bits(dev, reg, mask, val, is_direct); + if (is_unite) + rkisp_next_set_bits(dev, reg, mask, val, is_direct); +} + +static inline void +rkisp_unite_clear_bits(struct rkisp_device *dev, u32 reg, u32 mask, + bool is_direct, bool is_unite) +{ + rkisp_clear_bits(dev, reg, mask, is_direct); + if (is_unite) + rkisp_next_clear_bits(dev, reg, mask, is_direct); +} + void rkisp_update_regs(struct rkisp_device *dev, u32 start, u32 end); int rkisp_alloc_buffer(struct rkisp_device *dev, struct rkisp_dummy_buffer *buf); diff --git a/drivers/media/platform/rockchip/isp/csi.c b/drivers/media/platform/rockchip/isp/csi.c index 319188ea490b..53eb1ab3d2cf 100644 --- a/drivers/media/platform/rockchip/isp/csi.c +++ b/drivers/media/platform/rockchip/isp/csi.c @@ -497,8 +497,9 @@ int rkisp_csi_config_patch(struct rkisp_device *dev) } if (!dev->hw_dev->is_mi_update) - rkisp_write(dev, CSI2RX_CTRL0, - SW_IBUF_OP_MODE(dev->hdr.op_mode), true); + rkisp_unite_write(dev, CSI2RX_CTRL0, + SW_IBUF_OP_MODE(dev->hdr.op_mode), + true, dev->hw_dev->is_unite); /* hdr merge */ switch (dev->hdr.op_mode) { @@ -522,16 +523,19 @@ int rkisp_csi_config_patch(struct rkisp_device *dev) return -EINVAL; } } - rkisp_write(dev, ISP_HDRMGE_BASE, val, false); + rkisp_unite_write(dev, ISP_HDRMGE_BASE, val, false, dev->hw_dev->is_unite); - rkisp_set_bits(dev, CSI2RX_MASK_STAT, 0, RAW_RD_SIZE_ERR, true); + rkisp_unite_set_bits(dev, CSI2RX_MASK_STAT, 0, RAW_RD_SIZE_ERR, + true, dev->hw_dev->is_unite); } if (IS_HDR_RDBK(dev->hdr.op_mode)) - rkisp_set_bits(dev, CTRL_SWS_CFG, 0, SW_MPIP_DROP_FRM_DIS, true); + rkisp_unite_set_bits(dev, CTRL_SWS_CFG, 0, SW_MPIP_DROP_FRM_DIS, + true, dev->hw_dev->is_unite); if (dev->isp_ver == ISP_V30) - rkisp_set_bits(dev, CTRL_SWS_CFG, 0, ISP3X_SW_ACK_FRM_PRO_DIS, true); + rkisp_unite_set_bits(dev, CTRL_SWS_CFG, 0, ISP3X_SW_ACK_FRM_PRO_DIS, + true, dev->hw_dev->is_unite); memset(dev->filt_state, 0, sizeof(dev->filt_state)); dev->rdbk_cnt = -1; diff --git a/drivers/media/platform/rockchip/isp/dev.c b/drivers/media/platform/rockchip/isp/dev.c index 101a1b662289..e8628681d570 100644 --- a/drivers/media/platform/rockchip/isp/dev.c +++ b/drivers/media/platform/rockchip/isp/dev.c @@ -224,6 +224,8 @@ static int __isp_pipeline_s_isp_clk(struct rkisp_pipeline *p) end: /* set isp clock rate */ rkisp_set_clk_rate(hw_dev->clks[0], hw_dev->clk_rate_tbl[i].clk_rate * 1000000UL); + if (hw_dev->is_unite) + rkisp_set_clk_rate(hw_dev->clks[5], hw_dev->clk_rate_tbl[i].clk_rate * 1000000UL); dev_dbg(hw_dev->dev, "set isp clk = %luHz\n", clk_get_rate(hw_dev->clks[0])); return 0; @@ -722,7 +724,7 @@ static int rkisp_plat_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct v4l2_device *v4l2_dev; struct rkisp_device *isp_dev; - int i, ret; + int i, ret, mult = 1; sprintf(rkisp_version, "v%02x.%02x.%02x", RKISP_DRIVER_VERSION >> 16, @@ -734,24 +736,29 @@ static int rkisp_plat_probe(struct platform_device *pdev) isp_dev = devm_kzalloc(dev, sizeof(*isp_dev), GFP_KERNEL); if (!isp_dev) return -ENOMEM; - isp_dev->sw_base_addr = devm_kzalloc(dev, RKISP_ISP_SW_MAX_SIZE, GFP_KERNEL); - if (!isp_dev->sw_base_addr) - return -ENOMEM; dev_set_drvdata(dev, isp_dev); isp_dev->dev = dev; + ret = rkisp_attach_hw(isp_dev); + if (ret) + return ret; + + if (isp_dev->hw_dev->is_unite) + mult = 2; + isp_dev->sw_base_addr = devm_kzalloc(dev, RKISP_ISP_SW_MAX_SIZE * mult, GFP_KERNEL); + if (!isp_dev->sw_base_addr) + return -ENOMEM; ret = rkisp_vs_irq_parse(dev); if (ret) return ret; - ret = rkisp_attach_hw(isp_dev); - if (ret) - return ret; - sprintf(isp_dev->media_dev.model, "%s%d", DRIVER_NAME, isp_dev->dev_id); - strscpy(isp_dev->name, dev_name(dev), sizeof(isp_dev->name)); + if (!isp_dev->hw_dev->is_unite) + strscpy(isp_dev->name, dev_name(dev), sizeof(isp_dev->name)); + else + strscpy(isp_dev->name, "rkisp-unite", sizeof(isp_dev->name)); strscpy(isp_dev->media_dev.driver_name, isp_dev->name, sizeof(isp_dev->media_dev.driver_name)); diff --git a/drivers/media/platform/rockchip/isp/dmarx.c b/drivers/media/platform/rockchip/isp/dmarx.c index e4f2b70cff5a..0dcc080d7cdc 100644 --- a/drivers/media/platform/rockchip/isp/dmarx.c +++ b/drivers/media/platform/rockchip/isp/dmarx.c @@ -318,6 +318,7 @@ static struct streams_ops rkisp_dmarx_streams_ops = { static int rawrd_config_mi(struct rkisp_stream *stream) { struct rkisp_device *dev = stream->ispdev; + bool is_unite = dev->hw_dev->is_unite; u32 val; val = rkisp_read(dev, CSI2RX_DATA_IDS_1, true); @@ -346,9 +347,9 @@ static int rawrd_config_mi(struct rkisp_stream *stream) default: val |= CIF_CSI2_DT_RAW12; } - rkisp_write(dev, CSI2RX_RAW_RD_CTRL, - stream->memory << 2, false); - rkisp_write(dev, CSI2RX_DATA_IDS_1, val, false); + rkisp_unite_write(dev, CSI2RX_RAW_RD_CTRL, + stream->memory << 2, false, is_unite); + rkisp_unite_write(dev, CSI2RX_DATA_IDS_1, val, false, is_unite); rkisp_rawrd_set_pic_size(dev, stream->out_fmt.width, stream->out_fmt.height); mi_raw_length(stream); @@ -364,11 +365,17 @@ static void update_rawrd(struct rkisp_stream *stream) { struct rkisp_device *dev = stream->ispdev; void __iomem *base = dev->base_addr; + struct capture_fmt *fmt = &stream->out_isp_fmt; + u32 val; if (stream->curr_buf) { - rkisp_write(dev, stream->config->mi.y_base_ad_init, - stream->curr_buf->buff_addr[RKISP_PLANE_Y], - false); + val = stream->curr_buf->buff_addr[RKISP_PLANE_Y]; + rkisp_write(dev, stream->config->mi.y_base_ad_init, val, false); + if (dev->hw_dev->is_unite) { + val += (stream->out_fmt.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL) * + fmt->bpp[0] / 8; + rkisp_next_write(dev, stream->config->mi.y_base_ad_init, val, false); + } stream->frame_end = false; if (stream->id == RKISP_STREAM_RAWRD2 && stream->out_isp_fmt.fmt_type == FMT_YUV) { @@ -1059,6 +1066,8 @@ void rkisp_rawrd_set_pic_size(struct rkisp_device *dev, { struct rkisp_isp_subdev *sdev = &dev->isp_sdev; u8 mult = sdev->in_fmt.fmt_type == FMT_YUV ? 2 : 1; + bool is_unite = dev->hw_dev->is_unite; + u32 w = !is_unite ? width : width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; /* rx height should equal to isp height + offset for read back mode */ height = sdev->in_crop.top + sdev->in_crop.height; @@ -1070,7 +1079,8 @@ void rkisp_rawrd_set_pic_size(struct rkisp_device *dev, dev->rd_mode == HDR_RDBK_FRAME1) height += RKMODULE_EXTEND_LINE; - rkisp_write(dev, CSI2RX_RAW_RD_PIC_SIZE, height << 16 | width * mult, false); + w *= mult; + rkisp_unite_write(dev, CSI2RX_RAW_RD_PIC_SIZE, height << 16 | w, false, is_unite); } void rkisp_dmarx_get_frame(struct rkisp_device *dev, u32 *id, diff --git a/drivers/media/platform/rockchip/isp/hw.c b/drivers/media/platform/rockchip/isp/hw.c index bec77d87cdb9..3dea097c527e 100644 --- a/drivers/media/platform/rockchip/isp/hw.c +++ b/drivers/media/platform/rockchip/isp/hw.c @@ -109,6 +109,10 @@ static void default_sw_reg_flag(struct rkisp_device *dev) for (i = 0; i < size; i++) { flag = dev->sw_base_addr + reg[i] + RKISP_ISP_SW_REG_SIZE; *flag = SW_REG_CACHE; + if (dev->hw_dev->is_unite) { + flag += RKISP_ISP_SW_MAX_SIZE / 4; + *flag = SW_REG_CACHE; + } } } @@ -117,6 +121,8 @@ static irqreturn_t mipi_irq_hdl(int irq, void *ctx) struct device *dev = ctx; struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev); struct rkisp_device *isp = hw_dev->isp[hw_dev->mipi_dev_id]; + void __iomem *base = !hw_dev->is_unite ? + hw_dev->base_addr : hw_dev->base_next_addr; if (hw_dev->is_thunderboot) return IRQ_HANDLED; @@ -124,9 +130,9 @@ static irqreturn_t mipi_irq_hdl(int irq, void *ctx) if (hw_dev->isp_ver == ISP_V13 || hw_dev->isp_ver == ISP_V12) { u32 err1, err2, err3; - err1 = readl(hw_dev->base_addr + CIF_ISP_CSI0_ERR1); - err2 = readl(hw_dev->base_addr + CIF_ISP_CSI0_ERR2); - err3 = readl(hw_dev->base_addr + CIF_ISP_CSI0_ERR3); + err1 = readl(base + CIF_ISP_CSI0_ERR1); + err2 = readl(base + CIF_ISP_CSI0_ERR2); + err3 = readl(base + CIF_ISP_CSI0_ERR3); if (err1 || err2 || err3) rkisp_mipi_v13_isr(err1, err2, err3, isp); @@ -135,10 +141,10 @@ static irqreturn_t mipi_irq_hdl(int irq, void *ctx) hw_dev->isp_ver == ISP_V30) { u32 phy, packet, overflow, state; - state = readl(hw_dev->base_addr + CSI2RX_ERR_STAT); - phy = readl(hw_dev->base_addr + CSI2RX_ERR_PHY); - packet = readl(hw_dev->base_addr + CSI2RX_ERR_PACKET); - overflow = readl(hw_dev->base_addr + CSI2RX_ERR_OVERFLOW); + state = readl(base + CSI2RX_ERR_STAT); + phy = readl(base + CSI2RX_ERR_PHY); + packet = readl(base + CSI2RX_ERR_PACKET); + overflow = readl(base + CSI2RX_ERR_OVERFLOW); if (phy | packet | overflow | state) { if (hw_dev->isp_ver == ISP_V20) rkisp_mipi_v20_isr(phy, packet, overflow, state, isp); @@ -148,7 +154,7 @@ static irqreturn_t mipi_irq_hdl(int irq, void *ctx) rkisp_mipi_v30_isr(phy, packet, overflow, state, isp); } } else { - u32 mis_val = readl(hw_dev->base_addr + CIF_MIPI_MIS); + u32 mis_val = readl(base + CIF_MIPI_MIS); if (mis_val) rkisp_mipi_isr(mis_val, isp); @@ -162,13 +168,15 @@ static irqreturn_t mi_irq_hdl(int irq, void *ctx) struct device *dev = ctx; struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev); struct rkisp_device *isp = hw_dev->isp[hw_dev->cur_dev_id]; + void __iomem *base = !hw_dev->is_unite ? + hw_dev->base_addr : hw_dev->base_next_addr; u32 mis_val, tx_isr = MI_RAW0_WR_FRAME | MI_RAW1_WR_FRAME | MI_RAW2_WR_FRAME | MI_RAW3_WR_FRAME; if (hw_dev->is_thunderboot) return IRQ_HANDLED; - mis_val = readl(hw_dev->base_addr + CIF_MI_MIS); + mis_val = readl(base + CIF_MI_MIS); if (mis_val) { if (mis_val & ~tx_isr) rkisp_mi_isr(mis_val & ~tx_isr, isp); @@ -185,16 +193,18 @@ static irqreturn_t isp_irq_hdl(int irq, void *ctx) struct device *dev = ctx; struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev); struct rkisp_device *isp = hw_dev->isp[hw_dev->cur_dev_id]; + void __iomem *base = !hw_dev->is_unite ? + hw_dev->base_addr : hw_dev->base_next_addr; unsigned int mis_val, mis_3a = 0; if (hw_dev->is_thunderboot) return IRQ_HANDLED; - mis_val = readl(hw_dev->base_addr + CIF_ISP_MIS); + mis_val = readl(base + CIF_ISP_MIS); if (hw_dev->isp_ver == ISP_V20 || hw_dev->isp_ver == ISP_V21 || hw_dev->isp_ver == ISP_V30) - mis_3a = readl(hw_dev->base_addr + ISP_ISP3A_MIS); + mis_3a = readl(base + ISP_ISP3A_MIS); if (mis_val || mis_3a) rkisp_isp_isr(mis_val, mis_3a, isp); @@ -474,7 +484,8 @@ static const struct isp_match_data rv1126_isp_match_data = { .clk_rate_tbl = rv1126_isp_clk_rate, .num_clk_rate_tbl = ARRAY_SIZE(rv1126_isp_clk_rate), .irqs = rv1126_isp_irqs, - .num_irqs = ARRAY_SIZE(rv1126_isp_irqs) + .num_irqs = ARRAY_SIZE(rv1126_isp_irqs), + .unite = false, }; static const struct isp_match_data rk1808_isp_match_data = { @@ -484,7 +495,8 @@ static const struct isp_match_data rk1808_isp_match_data = { .clk_rate_tbl = rk1808_isp_clk_rate, .num_clk_rate_tbl = ARRAY_SIZE(rk1808_isp_clk_rate), .irqs = rk1808_isp_irqs, - .num_irqs = ARRAY_SIZE(rk1808_isp_irqs) + .num_irqs = ARRAY_SIZE(rk1808_isp_irqs), + .unite = false, }; static const struct isp_match_data rk3288_isp_match_data = { @@ -494,7 +506,8 @@ static const struct isp_match_data rk3288_isp_match_data = { .clk_rate_tbl = rk3288_isp_clk_rate, .num_clk_rate_tbl = ARRAY_SIZE(rk3288_isp_clk_rate), .irqs = rk3288_isp_irqs, - .num_irqs = ARRAY_SIZE(rk3288_isp_irqs) + .num_irqs = ARRAY_SIZE(rk3288_isp_irqs), + .unite = false, }; static const struct isp_match_data rk3326_isp_match_data = { @@ -504,7 +517,8 @@ static const struct isp_match_data rk3326_isp_match_data = { .clk_rate_tbl = rk3326_isp_clk_rate, .num_clk_rate_tbl = ARRAY_SIZE(rk3326_isp_clk_rate), .irqs = rk3326_isp_irqs, - .num_irqs = ARRAY_SIZE(rk3326_isp_irqs) + .num_irqs = ARRAY_SIZE(rk3326_isp_irqs), + .unite = false, }; static const struct isp_match_data rk3368_isp_match_data = { @@ -514,7 +528,8 @@ static const struct isp_match_data rk3368_isp_match_data = { .clk_rate_tbl = rk3368_isp_clk_rate, .num_clk_rate_tbl = ARRAY_SIZE(rk3368_isp_clk_rate), .irqs = rk3368_isp_irqs, - .num_irqs = ARRAY_SIZE(rk3368_isp_irqs) + .num_irqs = ARRAY_SIZE(rk3368_isp_irqs), + .unite = false, }; static const struct isp_match_data rk3399_isp_match_data = { @@ -524,7 +539,8 @@ static const struct isp_match_data rk3399_isp_match_data = { .clk_rate_tbl = rk3399_isp_clk_rate, .num_clk_rate_tbl = ARRAY_SIZE(rk3399_isp_clk_rate), .irqs = rk3399_isp_irqs, - .num_irqs = ARRAY_SIZE(rk3399_isp_irqs) + .num_irqs = ARRAY_SIZE(rk3399_isp_irqs), + .unite = false, }; static const struct isp_match_data rk3568_isp_match_data = { @@ -534,7 +550,8 @@ static const struct isp_match_data rk3568_isp_match_data = { .clk_rate_tbl = rk3568_isp_clk_rate, .num_clk_rate_tbl = ARRAY_SIZE(rk3568_isp_clk_rate), .irqs = rk3568_isp_irqs, - .num_irqs = ARRAY_SIZE(rk3568_isp_irqs) + .num_irqs = ARRAY_SIZE(rk3568_isp_irqs), + .unite = false, }; static const struct isp_match_data rk3588_isp_match_data = { @@ -545,6 +562,7 @@ static const struct isp_match_data rk3588_isp_match_data = { .num_clk_rate_tbl = ARRAY_SIZE(rk3588_isp_clk_rate), .irqs = rk3588_isp_irqs, .num_irqs = ARRAY_SIZE(rk3588_isp_irqs), + .unite = false, }; static const struct of_device_id rkisp_hw_of_match[] = { @@ -603,6 +621,8 @@ void rkisp_soft_reset(struct rkisp_hw_dev *dev, bool is_secure) * isp soft reset first to protect isp reset. */ writel(0xffff, base + CIF_IRCL); + if (dev->is_unite) + writel(0xffff, dev->base_next_addr + CIF_IRCL); udelay(10); } @@ -617,6 +637,8 @@ void rkisp_soft_reset(struct rkisp_hw_dev *dev, bool is_secure) if (dev->isp_ver == ISP_V20) writel(CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601, base + CIF_ISP_CTRL); writel(0xffff, base + CIF_IRCL); + if (dev->is_unite) + writel(0xffff, dev->base_next_addr + CIF_IRCL); udelay(10); /* refresh iommu after reset */ @@ -637,6 +659,8 @@ static void isp_config_clk(struct rkisp_hw_dev *dev, int on) val |= ICCL_MPFBC_CLK; writel(val, dev->base_addr + CIF_ICCL); + if (dev->is_unite) + writel(val, dev->base_next_addr + CIF_ICCL); if (dev->isp_ver == ISP_V12 || dev->isp_ver == ISP_V13) { val = !on ? 0 : @@ -660,6 +684,8 @@ static void isp_config_clk(struct rkisp_hw_dev *dev, int on) if (dev->isp_ver == ISP_V20 && on) val |= CLK_CTRL_ISP_3A; writel(val, dev->base_addr + CTRL_VI_ISP_CLK_CTRL); + if (dev->is_unite) + writel(val, dev->base_next_addr + CTRL_VI_ISP_CLK_CTRL); } } @@ -682,6 +708,7 @@ static void disable_sys_clk(struct rkisp_hw_dev *dev) static int enable_sys_clk(struct rkisp_hw_dev *dev) { int i, ret = -EINVAL; + unsigned long rate; for (i = 0; i < dev->num_clks; i++) { if (!IS_ERR(dev->clks[i])) { @@ -691,8 +718,10 @@ static int enable_sys_clk(struct rkisp_hw_dev *dev) } } - rkisp_set_clk_rate(dev->clks[0], - dev->clk_rate_tbl[0].clk_rate * 1000000UL); + rate = dev->clk_rate_tbl[0].clk_rate * 1000000UL; + rkisp_set_clk_rate(dev->clks[0], rate); + if (dev->is_unite) + rkisp_set_clk_rate(dev->clks[5], rate); rkisp_soft_reset(dev, false); isp_config_clk(dev, true); @@ -764,9 +793,31 @@ static int rkisp_hw_probe(struct platform_device *pdev) goto err; } - rkisp_monitor = device_property_read_bool(dev, "rockchip,restart-monitor-en"); - match_data = match->data; + hw_dev->base_next_addr = NULL; + if (match_data->unite) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(dev, "get next resource failed\n"); + ret = -EINVAL; + goto err; + } + hw_dev->base_next_addr = devm_ioremap_resource(dev, res); + if (PTR_ERR(hw_dev->base_next_addr) == -EBUSY) { + resource_size_t offset = res->start; + resource_size_t size = resource_size(res); + + hw_dev->base_next_addr = devm_ioremap(dev, offset, size); + } + + if (IS_ERR(hw_dev->base_next_addr)) { + dev_err(dev, "ioremap next failed\n"); + ret = PTR_ERR(hw_dev->base_next_addr); + goto err; + } + } + + rkisp_monitor = device_property_read_bool(dev, "rockchip,restart-monitor-en"); hw_dev->mipi_irq = -1; hw_dev->pdev = pdev; @@ -804,6 +855,7 @@ static int rkisp_hw_probe(struct platform_device *pdev) hw_dev->cur_dev_id = 0; hw_dev->mipi_dev_id = 0; hw_dev->isp_ver = match_data->isp_ver; + hw_dev->is_unite = match_data->unite; mutex_init(&hw_dev->dev_lock); spin_lock_init(&hw_dev->rdbk_lock); atomic_set(&hw_dev->refcnt, 0); @@ -860,8 +912,11 @@ static void rkisp_hw_shutdown(struct platform_device *pdev) struct rkisp_hw_dev *hw_dev = platform_get_drvdata(pdev); hw_dev->is_shutdown = true; - if (pm_runtime_active(&pdev->dev)) + if (pm_runtime_active(&pdev->dev)) { writel(0xffff, hw_dev->base_addr + CIF_IRCL); + if (hw_dev->is_unite) + writel(0xffff, hw_dev->base_next_addr + CIF_IRCL); + } dev_info(&pdev->dev, "%s\n", __func__); } @@ -877,6 +932,7 @@ static int __maybe_unused rkisp_runtime_resume(struct device *dev) { struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev); void __iomem *base = hw_dev->base_addr; + int mult = hw_dev->is_unite ? 2 : 1; int ret, i; ret = pinctrl_pm_select_default_state(dev); @@ -888,8 +944,13 @@ static int __maybe_unused rkisp_runtime_resume(struct device *dev) for (i = 0; i < hw_dev->dev_num; i++) { void *buf = hw_dev->isp[i]->sw_base_addr; - memset(buf, 0, RKISP_ISP_SW_MAX_SIZE); + memset(buf, 0, RKISP_ISP_SW_MAX_SIZE * mult); memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE); + if (hw_dev->is_unite) { + buf += RKISP_ISP_SW_MAX_SIZE; + base = hw_dev->base_next_addr; + memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE); + } default_sw_reg_flag(hw_dev->isp[i]); } hw_dev->monitor.is_en = rkisp_monitor; diff --git a/drivers/media/platform/rockchip/isp/hw.h b/drivers/media/platform/rockchip/isp/hw.h index d07b645f6733..dce2f0a715ee 100644 --- a/drivers/media/platform/rockchip/isp/hw.h +++ b/drivers/media/platform/rockchip/isp/hw.h @@ -22,6 +22,7 @@ struct isp_match_data { int num_clk_rate_tbl; struct isp_irqs_data *irqs; int num_irqs; + bool unite; }; struct rkisp_monitor { @@ -40,6 +41,7 @@ struct rkisp_hw_dev { struct device *dev; struct regmap *grf; void __iomem *base_addr; + void __iomem *base_next_addr; struct clk *clks[RKISP_MAX_BUS_CLK]; int num_clks; const struct isp_clk_info *clk_rate_tbl; @@ -79,6 +81,7 @@ struct rkisp_hw_dev { bool is_thunderboot; bool is_buf_init; bool is_shutdown; + bool is_unite; }; int rkisp_register_irq(struct rkisp_hw_dev *dev); diff --git a/drivers/media/platform/rockchip/isp/regs.c b/drivers/media/platform/rockchip/isp/regs.c index 766bcbe36839..753247f4dc7c 100644 --- a/drivers/media/platform/rockchip/isp/regs.c +++ b/drivers/media/platform/rockchip/isp/regs.c @@ -33,6 +33,7 @@ */ #include +#include #include "regs.h" void rkisp_disable_dcrop(struct rkisp_stream *stream, bool async) @@ -44,7 +45,8 @@ void rkisp_disable_dcrop(struct rkisp_stream *stream, bool async) if (async && dev->hw_dev->is_single) val = CIF_DUAL_CROP_GEN_CFG_UPD; - rkisp_set_bits(dev, stream->config->dual_crop.ctrl, mask, val, false); + rkisp_unite_set_bits(dev, stream->config->dual_crop.ctrl, + mask, val, false, dev->hw_dev->is_unite); } void rkisp_config_dcrop(struct rkisp_stream *stream, @@ -52,16 +54,49 @@ void rkisp_config_dcrop(struct rkisp_stream *stream, { struct rkisp_device *dev = stream->ispdev; u32 val = stream->config->dual_crop.yuvmode_mask; + bool is_unite = dev->hw_dev->is_unite; + struct v4l2_rect tmp = *rect; + u32 reg; + + if (is_unite) + tmp.width /= 2; + reg = stream->config->dual_crop.h_offset; + rkisp_write(dev, reg, tmp.left, false); + reg = stream->config->dual_crop.h_size; + rkisp_write(dev, reg, tmp.width, false); + + reg = stream->config->dual_crop.v_offset; + rkisp_unite_write(dev, reg, tmp.top, false, is_unite); + reg = stream->config->dual_crop.v_size; + rkisp_unite_write(dev, reg, tmp.height, false, is_unite); - rkisp_write(dev, stream->config->dual_crop.h_offset, rect->left, false); - rkisp_write(dev, stream->config->dual_crop.v_offset, rect->top, false); - rkisp_write(dev, stream->config->dual_crop.h_size, rect->width, false); - rkisp_write(dev, stream->config->dual_crop.v_size, rect->height, false); if (async && dev->hw_dev->is_single) val |= CIF_DUAL_CROP_GEN_CFG_UPD; else val |= CIF_DUAL_CROP_CFG_UPD; - rkisp_set_bits(dev, stream->config->dual_crop.ctrl, 0, val, false); + if (is_unite) { + reg = stream->config->dual_crop.h_offset; + rkisp_next_write(dev, reg, RKMOUDLE_UNITE_EXTEND_PIXEL, false); + reg = stream->config->dual_crop.h_size; + rkisp_next_write(dev, reg, tmp.width, false); + + reg = stream->config->dual_crop.ctrl; + rkisp_next_set_bits(dev, reg, 0, val, false); + /* output with scale, crop by scl output */ + if (stream->out_fmt.width < rect->width) + val = 0; + else + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "left dcrop (%d, %d) %dx%d\n", + tmp.top, tmp.left, tmp.width, tmp.height); + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "right dcrop (%d, %d) %dx%d\n", + RKMOUDLE_UNITE_EXTEND_PIXEL, tmp.top, tmp.width, tmp.height); + } + if (val) { + reg = stream->config->dual_crop.ctrl; + rkisp_set_bits(dev, reg, 0, val, false); + } } void rkisp_dump_rsz_regs(struct rkisp_stream *stream) @@ -107,7 +142,8 @@ static void update_rsz_shadow(struct rkisp_stream *stream, bool async) if (async && dev->hw_dev->is_single) val = CIF_RSZ_CTRL_CFG_UPD_AUTO; - rkisp_set_bits(dev, stream->config->rsz.ctrl, 0, val, false); + rkisp_unite_set_bits(dev, stream->config->rsz.ctrl, 0, + val, false, dev->hw_dev->is_unite); } static void set_scale(struct rkisp_stream *stream, struct v4l2_rect *in_y, @@ -121,7 +157,8 @@ static void set_scale(struct rkisp_stream *stream, struct v4l2_rect *in_y, u32 scale_vy_addr = stream->config->rsz.scale_vy; u32 scale_vc_addr = stream->config->rsz.scale_vc; u32 rsz_ctrl_addr = stream->config->rsz.ctrl; - u32 scale_hy, scale_hc, scale_vy, scale_vc, rsz_ctrl = 0; + u32 scale_hy = 1, scale_hc = 1, scale_vy = 1, scale_vc = 1; + u32 rsz_ctrl = 0; if (in_y->width < out_y->width) { rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE | @@ -176,6 +213,75 @@ static void set_scale(struct rkisp_stream *stream, struct v4l2_rect *in_y, rkisp_write(dev, scale_vc_addr, scale_vc, false); } + if (dev->hw_dev->is_unite) { + u32 hy_size_reg = stream->id == RKISP_STREAM_MP ? + ISP3X_MAIN_RESIZE_HY_SIZE : ISP3X_SELF_RESIZE_HY_SIZE; + u32 hc_size_reg = stream->id == RKISP_STREAM_MP ? + ISP3X_MAIN_RESIZE_HC_SIZE : ISP3X_SELF_RESIZE_HC_SIZE; + u32 hy_offs_mi_reg = stream->id == RKISP_STREAM_MP ? + ISP3X_MAIN_RESIZE_HY_OFFS_MI : ISP3X_SELF_RESIZE_HY_OFFS_MI; + u32 hc_offs_mi_reg = stream->id == RKISP_STREAM_MP ? + ISP3X_MAIN_RESIZE_HC_OFFS_MI : ISP3X_SELF_RESIZE_HC_OFFS_MI; + u32 in_crop_offs_reg = stream->id == RKISP_STREAM_MP ? + ISP3X_MAIN_RESIZE_IN_CROP_OFFSET : ISP3X_SELF_RESIZE_IN_CROP_OFFSET; + u32 isp_in_w = in_y->width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + u32 scl_w = out_y->width / 2; + u32 left_y = DIV_ROUND_UP(scl_w * 65536, scale_hy); + u32 left_c = DIV_ROUND_UP(scl_w * 65536 / 2, scale_hc); + u32 phase_src_y = left_y * scale_hy; + u32 phase_dst_y = scl_w * 65536; + u32 phase_left_y = scale_hy - (phase_src_y - phase_dst_y); + u32 phase_src_c = left_c * scale_hc; + u32 phase_dst_c = scl_w * 65536 / 2; + u32 phase_left_c = scale_hc - (phase_src_c - phase_dst_c); + u32 right_y = phase_left_y ? + in_y->width - (left_y - 1) : + in_y->width - left_y; + u32 right_c = phase_left_c ? + in_y->width - (left_c - 1) * 2 : + in_y->width - left_c * 2; + u32 right_crop_y = isp_in_w - right_y; + u32 right_crop_c = isp_in_w - right_c; + u32 right_scl_in_y = right_crop_y - RKMOUDLE_UNITE_EXTEND_PIXEL; + u32 right_scl_in_c = right_crop_c - RKMOUDLE_UNITE_EXTEND_PIXEL; + + /* left isp */ + rkisp_write(dev, hy_size_reg, scl_w, false); + rkisp_write(dev, hc_size_reg, scl_w, false); + rkisp_write(dev, hy_offs_mi_reg, 0, false); + rkisp_write(dev, hc_offs_mi_reg, 0, false); + rkisp_write(dev, in_crop_offs_reg, 0, false); + + /* right isp */ + rkisp_next_write(dev, hy_size_reg, scl_w, false); + rkisp_next_write(dev, hc_size_reg, scl_w, false); + rkisp_next_write(dev, scale_hy_addr, scale_hy, false); + rkisp_next_write(dev, scale_hcb_addr, scale_hc, false); + rkisp_next_write(dev, scale_hcr_addr, scale_hc, false); + rkisp_next_write(dev, scale_vy_addr, scale_vy, false); + rkisp_next_write(dev, scale_vc_addr, scale_vc, false); + rkisp_next_write(dev, stream->config->rsz.phase_hy, phase_left_y, false); + rkisp_next_write(dev, stream->config->rsz.phase_hc, phase_left_c, false); + rkisp_next_write(dev, stream->config->rsz.phase_vy, 0, false); + rkisp_next_write(dev, stream->config->rsz.phase_vc, 0, false); + rkisp_next_write(dev, hy_offs_mi_reg, scl_w & 15, false); + rkisp_next_write(dev, hc_offs_mi_reg, scl_w & 15, false); + rkisp_next_write(dev, in_crop_offs_reg, + right_scl_in_c << 4 | right_scl_in_y, false); + + rsz_ctrl |= ISP3X_SCL_CLIP_EN; + rkisp_next_write(dev, rsz_ctrl_addr, + rsz_ctrl | ISP3X_SCL_HPHASE_EN | ISP3X_SCL_IN_CLIP_EN, false); + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "scl:%dx%d, scl factor[hy:%d hc:%d vy:%d vc:%d]\n", + scl_w, out_y->height, scale_hy, scale_hc, scale_vy, scale_vc); + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "scl_left size[y:%d c:%d] phase[y:%d c:%d]\n", + left_y, left_c, phase_left_y, phase_left_c); + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "scl_right size[y:%d c:%d] offs_mi[y:%d c:%d] in_crop[y:%d c:%d]\n", + right_y, right_c, scl_w & 15, scl_w & 15, right_scl_in_y, right_scl_in_c); + } rkisp_write(dev, rsz_ctrl_addr, rsz_ctrl, false); } @@ -185,6 +291,7 @@ void rkisp_config_rsz(struct rkisp_stream *stream, struct v4l2_rect *in_y, { struct rkisp_device *dev = stream->ispdev; int i = 0; + bool is_unite = dev->hw_dev->is_unite; /* No phase offset */ rkisp_write(dev, stream->config->rsz.phase_hy, 0, true); @@ -194,8 +301,8 @@ void rkisp_config_rsz(struct rkisp_stream *stream, struct v4l2_rect *in_y, /* Linear interpolation */ for (i = 0; i < 64; i++) { - rkisp_write(dev, stream->config->rsz.scale_lut_addr, i, true); - rkisp_write(dev, stream->config->rsz.scale_lut, i, true); + rkisp_unite_write(dev, stream->config->rsz.scale_lut_addr, i, true, is_unite); + rkisp_unite_write(dev, stream->config->rsz.scale_lut, i, true, is_unite); } set_scale(stream, in_y, in_c, out_y, out_c); @@ -205,7 +312,9 @@ void rkisp_config_rsz(struct rkisp_stream *stream, struct v4l2_rect *in_y, void rkisp_disable_rsz(struct rkisp_stream *stream, bool async) { - rkisp_write(stream->ispdev, stream->config->rsz.ctrl, 0, false); + bool is_unite = stream->ispdev->hw_dev->is_unite; + + rkisp_unite_write(stream->ispdev, stream->config->rsz.ctrl, 0, false, is_unite); if (!async) update_rsz_shadow(stream, async); diff --git a/drivers/media/platform/rockchip/isp/regs.h b/drivers/media/platform/rockchip/isp/regs.h index fe9cf22c1d6d..5e66af96df00 100644 --- a/drivers/media/platform/rockchip/isp/regs.h +++ b/drivers/media/platform/rockchip/isp/regs.h @@ -1735,7 +1735,9 @@ static inline void mi_set_cr_offset(struct rkisp_stream *stream, int val) static inline void mi_frame_end_int_enable(struct rkisp_stream *stream) { - void __iomem *base = stream->ispdev->base_addr; + struct rkisp_hw_dev *hw = stream->ispdev->hw_dev; + void __iomem *base = !hw->is_unite ? + hw->base_addr : hw->base_next_addr; void __iomem *addr = base + CIF_MI_IMSC; writel(CIF_MI_FRAME(stream) | readl(addr), addr); @@ -1743,7 +1745,9 @@ static inline void mi_frame_end_int_enable(struct rkisp_stream *stream) static inline void mi_frame_end_int_disable(struct rkisp_stream *stream) { - void __iomem *base = stream->ispdev->base_addr; + struct rkisp_hw_dev *hw = stream->ispdev->hw_dev; + void __iomem *base = !hw->is_unite ? + hw->base_addr : hw->base_next_addr; void __iomem *addr = base + CIF_MI_IMSC; writel(~CIF_MI_FRAME(stream) & readl(addr), addr); @@ -1751,42 +1755,27 @@ static inline void mi_frame_end_int_disable(struct rkisp_stream *stream) static inline void mi_frame_end_int_clear(struct rkisp_stream *stream) { - void __iomem *base = stream->ispdev->base_addr; + struct rkisp_hw_dev *hw = stream->ispdev->hw_dev; + void __iomem *base = !hw->is_unite ? + hw->base_addr : hw->base_next_addr; void __iomem *addr = base + CIF_MI_ICR; writel(CIF_MI_FRAME(stream), addr); } -static inline void mp_set_chain_mode(void __iomem *base) +static inline void stream_data_path(struct rkisp_stream *stream) { - u32 dpcl = readl(base + CIF_VI_DPCL); + struct rkisp_device *dev = stream->ispdev; + bool is_unite = dev->hw_dev->is_unite; + u32 dpcl = 0; - dpcl |= CIF_VI_DPCL_CHAN_MODE_MP; - writel(dpcl, base + CIF_VI_DPCL); -} + if (stream->id == RKISP_STREAM_MP) + dpcl |= CIF_VI_DPCL_CHAN_MODE_MP | CIF_VI_DPCL_MP_MUX_MRSZ_MI; + else if (stream->id == RKISP_STREAM_SP) + dpcl |= CIF_VI_DPCL_CHAN_MODE_SP; -static inline void sp_set_chain_mode(void __iomem *base) -{ - u32 dpcl = readl(base + CIF_VI_DPCL); - - dpcl |= CIF_VI_DPCL_CHAN_MODE_SP; - writel(dpcl, base + CIF_VI_DPCL); -} - -static inline void mp_set_data_path(void __iomem *base) -{ - u32 dpcl = readl(base + CIF_VI_DPCL); - - dpcl = dpcl | CIF_VI_DPCL_CHAN_MODE_MP | CIF_VI_DPCL_MP_MUX_MRSZ_MI; - writel(dpcl, base + CIF_VI_DPCL); -} - -static inline void sp_set_data_path(void __iomem *base) -{ - u32 dpcl = readl(base + CIF_VI_DPCL); - - dpcl |= CIF_VI_DPCL_CHAN_MODE_SP; - writel(dpcl, base + CIF_VI_DPCL); + if (dpcl) + rkisp_unite_set_bits(dev, CIF_VI_DPCL, 0, dpcl, true, is_unite); } static inline void mp_set_uv_swap(void __iomem *base) @@ -1907,13 +1896,13 @@ static inline void sp_mi_ctrl_autoupdate_en(void __iomem *base) static inline void force_cfg_update(struct rkisp_device *dev) { - void __iomem *base = dev->base_addr; - u32 val = readl(base + CIF_MI_CTRL); + u32 val = CIF_MI_CTRL_INIT_OFFSET_EN | CIF_MI_CTRL_INIT_BASE_EN; + bool is_unite = dev->hw_dev->is_unite; dev->hw_dev->is_mi_update = true; - val |= CIF_MI_CTRL_INIT_OFFSET_EN | CIF_MI_CTRL_INIT_BASE_EN; - writel(val, base + CIF_MI_CTRL); - writel(CIF_MI_INIT_SOFT_UPD, base + CIF_MI_INIT); + rkisp_unite_set_bits(dev, CIF_MI_CTRL, 0, val, true, is_unite); + val = CIF_MI_INIT_SOFT_UPD; + rkisp_unite_write(dev, CIF_MI_INIT, val, true, is_unite); } static inline void dmatx0_ctrl(void __iomem *base, u32 val) diff --git a/drivers/media/platform/rockchip/isp/regs_v2x.h b/drivers/media/platform/rockchip/isp/regs_v2x.h index a59000c5186d..34f7a9fc3a7b 100644 --- a/drivers/media/platform/rockchip/isp/regs_v2x.h +++ b/drivers/media/platform/rockchip/isp/regs_v2x.h @@ -2699,6 +2699,11 @@ static inline void mi_raw_length(struct rkisp_stream *stream) stream->out_fmt.plane_fmt[0].bytesperline, is_direct); if (stream->ispdev->isp_ver == ISP_V21 || stream->ispdev->isp_ver == ISP_V30) rkisp_set_bits(stream->ispdev, MI_RD_CTRL2, 0, BIT(30), false); + if (stream->ispdev->hw_dev->is_unite) { + rkisp_next_write(stream->ispdev, stream->config->mi.length, + stream->out_fmt.plane_fmt[0].bytesperline, is_direct); + rkisp_next_set_bits(stream->ispdev, MI_RD_CTRL2, 0, BIT(30), false); + } } static inline void rx_force_upd(void __iomem *base) diff --git a/drivers/media/platform/rockchip/isp/regs_v3x.h b/drivers/media/platform/rockchip/isp/regs_v3x.h index 60b63a872209..8423936620e0 100644 --- a/drivers/media/platform/rockchip/isp/regs_v3x.h +++ b/drivers/media/platform/rockchip/isp/regs_v3x.h @@ -1625,6 +1625,11 @@ #define ISP3X_GAMMA_OUT_EQU_SEGM BIT(1) #define ISP3X_GAMMA_OUT_FINALX4_DENSE BIT(2) +/* RESIZE */ +#define ISP3X_SCL_HPHASE_EN BIT(10) +#define ISP3X_SCL_CLIP_EN BIT(11) +#define ISP3X_SCL_IN_CLIP_EN BIT(12) + /* mi interrupt */ #define ISP3X_MI_MP_FRAME BIT(0) #define ISP3X_MI_SP_FRAME BIT(1) diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index d9e89fb4edaf..c1753777b79d 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -222,12 +222,12 @@ int rkisp_align_sensor_resolution(struct rkisp_device *dev, CIF_ISP_INPUT_H_MAX_V21); break; case ISP_V30: - w = clamp_t(u32, src_w, - CIF_ISP_INPUT_W_MIN, - CIF_ISP_INPUT_W_MAX_V30); - h = clamp_t(u32, src_h, - CIF_ISP_INPUT_H_MIN, - CIF_ISP_INPUT_H_MAX_V30); + w = dev->hw_dev->is_unite ? + CIF_ISP_INPUT_W_MAX_V30_UNITE : CIF_ISP_INPUT_W_MAX_V30; + w = clamp_t(u32, src_w, CIF_ISP_INPUT_W_MIN, w); + h = dev->hw_dev->is_unite ? + CIF_ISP_INPUT_H_MAX_V30_UNITE : CIF_ISP_INPUT_H_MAX_V30; + h = clamp_t(u32, src_h, CIF_ISP_INPUT_H_MIN, h); break; default: w = clamp_t(u32, src_w, @@ -529,7 +529,7 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo tmp = rkisp_read(dev, ISP_HDRMGE_BASE, false) & 0xf; if (val != tmp) { - rkisp_write(dev, ISP_HDRMGE_BASE, val, false); + rkisp_unite_write(dev, ISP_HDRMGE_BASE, val, false, hw->is_unite); dev->skip_frame = 2; is_upd = true; } @@ -645,7 +645,7 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo if (!dma2frm) rkisp_bridge_update_mi(dev, 0); if (!hw->is_shutdown) - rkisp_write(dev, CSI2RX_CTRL0, val, true); + rkisp_unite_write(dev, CSI2RX_CTRL0, val, true, hw->is_unite); } static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd) @@ -806,22 +806,26 @@ static void rkisp_set_state(u32 *state, u32 val) static void rkisp_config_ism(struct rkisp_device *dev) { struct v4l2_rect *out_crop = &dev->isp_sdev.out_crop; + u32 width = out_crop->width, mult = 1; + bool is_unite = dev->hw_dev->is_unite; /* isp2.0 no ism */ if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21) return; - rkisp_write(dev, CIF_ISP_IS_RECENTER, 0, false); - rkisp_write(dev, CIF_ISP_IS_MAX_DX, 0, false); - rkisp_write(dev, CIF_ISP_IS_MAX_DY, 0, false); - rkisp_write(dev, CIF_ISP_IS_DISPLACE, 0, false); - rkisp_write(dev, CIF_ISP_IS_H_OFFS, out_crop->left, false); - rkisp_write(dev, CIF_ISP_IS_V_OFFS, out_crop->top, false); - rkisp_write(dev, CIF_ISP_IS_H_SIZE, out_crop->width, false); + if (is_unite) + width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + rkisp_unite_write(dev, CIF_ISP_IS_RECENTER, 0, false, is_unite); + rkisp_unite_write(dev, CIF_ISP_IS_MAX_DX, 0, false, is_unite); + rkisp_unite_write(dev, CIF_ISP_IS_MAX_DY, 0, false, is_unite); + rkisp_unite_write(dev, CIF_ISP_IS_DISPLACE, 0, false, is_unite); + rkisp_unite_write(dev, CIF_ISP_IS_H_OFFS, out_crop->left, false, is_unite); + rkisp_unite_write(dev, CIF_ISP_IS_V_OFFS, out_crop->top, false, is_unite); + rkisp_unite_write(dev, CIF_ISP_IS_H_SIZE, width, false, is_unite); if (dev->cap_dev.stream[RKISP_STREAM_SP].interlaced) - rkisp_write(dev, CIF_ISP_IS_V_SIZE, out_crop->height / 2, false); - else - rkisp_write(dev, CIF_ISP_IS_V_SIZE, out_crop->height, false); + mult = 2; + rkisp_unite_write(dev, CIF_ISP_IS_V_SIZE, out_crop->height / mult, + false, is_unite); if (dev->isp_ver == ISP_V30) return; @@ -1116,22 +1120,188 @@ static void rkisp_config_color_space(struct rkisp_device *dev) } for (i = 0; i < 9; i++) - rkisp_write(dev, CIF_ISP_CC_COEFF_0 + i * 4, *(coeff + i), false); + rkisp_unite_write(dev, CIF_ISP_CC_COEFF_0 + i * 4, + *(coeff + i), false, dev->hw_dev->is_unite); if (dev->isp_sdev.quantization == V4L2_QUANTIZATION_FULL_RANGE) - rkisp_set_bits(dev, CIF_ISP_CTRL, 0, - CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | - CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA, false); + rkisp_unite_set_bits(dev, CIF_ISP_CTRL, 0, + CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | + CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA, + false, dev->hw_dev->is_unite); else - rkisp_clear_bits(dev, CIF_ISP_CTRL, - CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | - CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA, false); + rkisp_unite_clear_bits(dev, CIF_ISP_CTRL, + CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | + CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA, + false, dev->hw_dev->is_unite); +} + +static void rkisp_config_cmsk_single(struct rkisp_device *dev, + struct rkisp_cmsk_cfg *cfg) +{ + u32 i, val, ctrl = 0; + u32 mp_en = cfg->win[0].win_en; + u32 sp_en = cfg->win[1].win_en; + u32 bp_en = cfg->win[2].win_en; + + if (mp_en) { + ctrl |= ISP3X_SW_CMSK_EN_MP; + rkisp_write(dev, ISP3X_CMSK_CTRL1, mp_en, false); + val = cfg->win[0].mode; + rkisp_write(dev, ISP3X_CMSK_CTRL4, val, false); + } + + if (sp_en) { + ctrl |= ISP3X_SW_CMSK_EN_SP; + rkisp_write(dev, ISP3X_CMSK_CTRL2, sp_en, false); + val = cfg->win[1].mode; + rkisp_write(dev, ISP3X_CMSK_CTRL5, val, false); + } + + if (bp_en) { + ctrl |= ISP3X_SW_CMSK_EN_BP; + rkisp_write(dev, ISP3X_CMSK_CTRL3, bp_en, false); + val = cfg->win[2].mode; + rkisp_write(dev, ISP3X_CMSK_CTRL6, val, false); + } + + for (i = 0; i < RKISP_CMSK_WIN_MAX; i++) { + if (!(mp_en & BIT(i)) && !(sp_en & BIT(i)) && !(bp_en & BIT(i))) + continue; + + val = ISP3X_SW_CMSK_YUV(cfg->win[i].cover_color_y, + cfg->win[i].cover_color_u, + cfg->win[i].cover_color_v); + rkisp_write(dev, ISP3X_CMSK_YUV0 + i * 4, val, false); + + val = ISP_PACK_2SHORT(cfg->win[i].h_offs, cfg->win[i].v_offs); + rkisp_write(dev, ISP3X_CMSK_OFFS0 + i * 8, val, false); + + val = ISP_PACK_2SHORT(cfg->win[i].h_size, cfg->win[i].v_size); + rkisp_write(dev, ISP3X_CMSK_SIZE0 + i * 8, val, false); + } + + if (ctrl) { + val = ISP_PACK_2SHORT(dev->isp_sdev.out_crop.width, + dev->isp_sdev.out_crop.height); + rkisp_write(dev, ISP3X_CMSK_PIC_SIZE, val, false); + ctrl |= ISP3X_SW_CMSK_EN | ISP3X_SW_CMSK_ORDER_MODE; + } + rkisp_write(dev, ISP3X_CMSK_CTRL0, ctrl, false); +} + +static void rkisp_config_cmsk_dual(struct rkisp_device *dev, + struct rkisp_cmsk_cfg *cfg) +{ + struct rkisp_cmsk_cfg left = *cfg; + struct rkisp_cmsk_cfg right = *cfg; + u32 width = dev->isp_sdev.out_crop.width; + u32 height = dev->isp_sdev.out_crop.height; + u32 w = width / 2; + u32 i, val, h_offs, h_size, ctrl; + u8 mp_en = cfg->win[0].win_en; + u8 sp_en = cfg->win[1].win_en; + u8 bp_en = cfg->win[2].win_en; + + for (i = 0; i < RKISP_CMSK_WIN_MAX; i++) { + if (!(mp_en & BIT(i)) && !(sp_en & BIT(i)) && !(bp_en & BIT(i))) + continue; + + h_offs = cfg->win[i].h_offs; + h_size = cfg->win[i].h_size; + if (h_offs + h_size <= w) { + /* cmsk window at left isp */ + right.win[0].win_en &= ~BIT(i); + right.win[1].win_en &= ~BIT(i); + right.win[2].win_en &= ~BIT(i); + } else if (h_offs >= w) { + /* cmsk window at right isp */ + left.win[0].win_en &= ~BIT(i); + left.win[1].win_en &= ~BIT(i); + left.win[2].win_en &= ~BIT(i); + } else { + /* cmsk window at dual isp */ + left.win[i].h_size = ALIGN(w - h_offs, 8); + + right.win[i].h_offs = RKMOUDLE_UNITE_EXTEND_PIXEL; + val = h_offs + h_size - w; + right.win[i].h_size = ALIGN(val, 8); + right.win[i].h_offs -= right.win[i].h_size - val; + } + + val = ISP3X_SW_CMSK_YUV(left.win[i].cover_color_y, + left.win[i].cover_color_u, + left.win[i].cover_color_v); + rkisp_write(dev, ISP3X_CMSK_YUV0 + i * 4, val, false); + rkisp_next_write(dev, ISP3X_CMSK_YUV0 + i * 4, val, false); + + val = ISP_PACK_2SHORT(left.win[i].h_offs, left.win[i].v_offs); + rkisp_write(dev, ISP3X_CMSK_OFFS0 + i * 8, val, false); + val = ISP_PACK_2SHORT(left.win[i].h_size, left.win[i].v_size); + rkisp_write(dev, ISP3X_CMSK_SIZE0 + i * 8, val, false); + + val = ISP_PACK_2SHORT(right.win[i].h_offs, right.win[i].v_offs); + rkisp_next_write(dev, ISP3X_CMSK_OFFS0 + i * 8, val, false); + val = ISP_PACK_2SHORT(right.win[i].h_size, right.win[i].v_size); + rkisp_next_write(dev, ISP3X_CMSK_SIZE0 + i * 8, val, false); + } + + w += RKMOUDLE_UNITE_EXTEND_PIXEL; + ctrl = 0; + if (left.win[0].win_en) { + ctrl |= ISP3X_SW_CMSK_EN_MP; + rkisp_write(dev, ISP3X_CMSK_CTRL1, left.win[0].win_en, false); + val = left.win[0].mode; + rkisp_write(dev, ISP3X_CMSK_CTRL4, val, false); + } + if (left.win[1].win_en) { + ctrl |= ISP3X_SW_CMSK_EN_SP; + rkisp_write(dev, ISP3X_CMSK_CTRL2, left.win[1].win_en, false); + val = left.win[1].mode; + rkisp_write(dev, ISP3X_CMSK_CTRL5, val, false); + } + if (left.win[2].win_en) { + ctrl |= ISP3X_SW_CMSK_EN_BP; + rkisp_write(dev, ISP3X_CMSK_CTRL3, left.win[2].win_en, false); + val = left.win[2].mode; + rkisp_write(dev, ISP3X_CMSK_CTRL6, val, false); + } + if (ctrl) { + val = ISP_PACK_2SHORT(w, height); + rkisp_write(dev, ISP3X_CMSK_PIC_SIZE, val, false); + ctrl |= ISP3X_SW_CMSK_EN | ISP3X_SW_CMSK_ORDER_MODE; + } + rkisp_write(dev, ISP3X_CMSK_CTRL0, ctrl, false); + + ctrl = 0; + if (right.win[0].win_en) { + ctrl |= ISP3X_SW_CMSK_EN_MP; + rkisp_next_write(dev, ISP3X_CMSK_CTRL1, right.win[0].win_en, false); + val = right.win[0].mode; + rkisp_next_write(dev, ISP3X_CMSK_CTRL4, val, false); + } + if (right.win[1].win_en) { + ctrl |= ISP3X_SW_CMSK_EN_SP; + rkisp_next_write(dev, ISP3X_CMSK_CTRL2, right.win[1].win_en, false); + val = right.win[1].mode; + rkisp_next_write(dev, ISP3X_CMSK_CTRL5, val, false); + } + if (right.win[2].win_en) { + ctrl |= ISP3X_SW_CMSK_EN_BP; + rkisp_next_write(dev, ISP3X_CMSK_CTRL3, right.win[2].win_en, false); + val = right.win[2].mode; + rkisp_next_write(dev, ISP3X_CMSK_CTRL6, val, false); + } + if (ctrl) { + val = ISP_PACK_2SHORT(w, height); + rkisp_next_write(dev, ISP3X_CMSK_PIC_SIZE, val, false); + ctrl |= ISP3X_SW_CMSK_EN | ISP3X_SW_CMSK_ORDER_MODE; + } + rkisp_next_write(dev, ISP3X_CMSK_CTRL0, ctrl, false); } static void rkisp_config_cmsk(struct rkisp_device *dev) { unsigned long lock_flags = 0; - u32 i, val, mp_en, sp_en, bp_en, ctrl = 0; struct rkisp_cmsk_cfg cfg; if (dev->isp_ver != ISP_V30) @@ -1146,53 +1316,10 @@ static void rkisp_config_cmsk(struct rkisp_device *dev) cfg = dev->cmsk_cfg; spin_unlock_irqrestore(&dev->cmsk_lock, lock_flags); - mp_en = cfg.win[0].win_en; - if (mp_en) { - ctrl |= ISP3X_SW_CMSK_EN_MP; - rkisp_write(dev, ISP3X_CMSK_CTRL1, mp_en, false); - val = cfg.win[0].mode; - rkisp_write(dev, ISP3X_CMSK_CTRL4, val, false); - } - - sp_en = cfg.win[1].win_en; - if (sp_en) { - ctrl |= ISP3X_SW_CMSK_EN_SP; - rkisp_write(dev, ISP3X_CMSK_CTRL2, sp_en, false); - val = cfg.win[1].mode; - rkisp_write(dev, ISP3X_CMSK_CTRL5, val, false); - } - - bp_en = cfg.win[2].win_en; - if (bp_en) { - ctrl |= ISP3X_SW_CMSK_EN_BP; - rkisp_write(dev, ISP3X_CMSK_CTRL3, bp_en, false); - val = cfg.win[2].mode; - rkisp_write(dev, ISP3X_CMSK_CTRL6, val, false); - } - - for (i = 0; i < RKISP_CMSK_WIN_MAX; i++) { - if (!(mp_en & BIT(i)) && !(sp_en & BIT(i)) && !(bp_en & BIT(i))) - continue; - - val = ISP3X_SW_CMSK_YUV(cfg.win[i].cover_color_y, - cfg.win[i].cover_color_u, - cfg.win[i].cover_color_v); - rkisp_write(dev, ISP3X_CMSK_YUV0 + i * 4, val, false); - - val = ISP_PACK_2SHORT(cfg.win[i].h_offs, cfg.win[i].v_offs); - rkisp_write(dev, ISP3X_CMSK_OFFS0 + i * 8, val, false); - - val = ISP_PACK_2SHORT(cfg.win[i].h_size, cfg.win[i].v_size); - rkisp_write(dev, ISP3X_CMSK_SIZE0 + i * 8, val, false); - } - - if (ctrl) { - val = ISP_PACK_2SHORT(dev->isp_sdev.out_crop.width, - dev->isp_sdev.out_crop.height); - rkisp_write(dev, ISP3X_CMSK_PIC_SIZE, val, false); - ctrl |= ISP3X_SW_CMSK_EN | ISP3X_SW_CMSK_ORDER_MODE; - } - rkisp_write(dev, ISP3X_CMSK_CTRL0, ctrl, false); + if (!dev->hw_dev->is_unite) + rkisp_config_cmsk_single(dev, &cfg); + else + rkisp_config_cmsk_dual(dev, &cfg); } /* @@ -1204,17 +1331,20 @@ static int rkisp_config_isp(struct rkisp_device *dev) struct ispsd_out_fmt *out_fmt; struct v4l2_rect *in_crop; struct rkisp_sensor_info *sensor; + bool is_unite = dev->hw_dev->is_unite; u32 isp_ctrl = 0; u32 irq_mask = 0; u32 signal = 0; u32 acq_mult = 0; u32 acq_prop = 0; u32 extend_line = 0; + u32 width; sensor = dev->active_sensor; in_fmt = &dev->isp_sdev.in_fmt; out_fmt = &dev->isp_sdev.out_fmt; in_crop = &dev->isp_sdev.in_crop; + width = in_crop->width; if (in_fmt->fmt_type == FMT_BAYER) { acq_mult = 1; @@ -1233,7 +1363,8 @@ static int rkisp_config_isp(struct rkisp_device *dev) if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21 || dev->isp_ver == ISP_V30) - rkisp_write(dev, ISP_DEBAYER_CONTROL, 0, false); + rkisp_unite_write(dev, ISP_DEBAYER_CONTROL, + 0, false, is_unite); else rkisp_write(dev, CIF_ISP_DEMOSAIC, CIF_ISP_DEMOSAIC_BYPASS | @@ -1242,10 +1373,11 @@ static int rkisp_config_isp(struct rkisp_device *dev) if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21 || dev->isp_ver == ISP_V30) - rkisp_write(dev, ISP_DEBAYER_CONTROL, - SW_DEBAYER_EN | - SW_DEBAYER_FILTER_G_EN | - SW_DEBAYER_FILTER_C_EN, false); + rkisp_unite_write(dev, ISP_DEBAYER_CONTROL, + SW_DEBAYER_EN | + SW_DEBAYER_FILTER_G_EN | + SW_DEBAYER_FILTER_C_EN, + false, is_unite); else rkisp_write(dev, CIF_ISP_DEMOSAIC, CIF_ISP_DEMOSAIC_TH(0xc), false); @@ -1298,29 +1430,38 @@ static int rkisp_config_isp(struct rkisp_device *dev) signal |= CIF_ISP_ACQ_PROP_HSYNC_LOW; } - rkisp_write(dev, CIF_ISP_CTRL, isp_ctrl, false); + rkisp_unite_write(dev, CIF_ISP_CTRL, isp_ctrl, false, is_unite); acq_prop |= signal | in_fmt->yuv_seq | CIF_ISP_ACQ_PROP_BAYER_PAT(in_fmt->bayer_pat) | CIF_ISP_ACQ_PROP_FIELD_SEL_ALL; - rkisp_write(dev, CIF_ISP_ACQ_PROP, acq_prop, false); - rkisp_write(dev, CIF_ISP_ACQ_NR_FRAMES, 0, true); + rkisp_unite_write(dev, CIF_ISP_ACQ_PROP, acq_prop, false, is_unite); + rkisp_unite_write(dev, CIF_ISP_ACQ_NR_FRAMES, 0, true, is_unite); + if (is_unite) + width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; /* Acquisition Size */ - rkisp_write(dev, CIF_ISP_ACQ_H_OFFS, acq_mult * in_crop->left, false); - rkisp_write(dev, CIF_ISP_ACQ_V_OFFS, in_crop->top, false); - rkisp_write(dev, CIF_ISP_ACQ_H_SIZE, acq_mult * in_crop->width, false); + rkisp_unite_write(dev, CIF_ISP_ACQ_H_OFFS, acq_mult * in_crop->left, + false, is_unite); + rkisp_unite_write(dev, CIF_ISP_ACQ_V_OFFS, in_crop->top, + false, is_unite); + rkisp_unite_write(dev, CIF_ISP_ACQ_H_SIZE, acq_mult * width, + false, is_unite); /* ISP Out Area differ with ACQ is only FIFO, so don't crop in this */ - rkisp_write(dev, CIF_ISP_OUT_H_OFFS, 0, true); - rkisp_write(dev, CIF_ISP_OUT_V_OFFS, 0, true); - rkisp_write(dev, CIF_ISP_OUT_H_SIZE, in_crop->width, false); + rkisp_unite_write(dev, CIF_ISP_OUT_H_OFFS, 0, true, is_unite); + rkisp_unite_write(dev, CIF_ISP_OUT_V_OFFS, 0, true, is_unite); + rkisp_unite_write(dev, CIF_ISP_OUT_H_SIZE, width, false, is_unite); if (dev->cap_dev.stream[RKISP_STREAM_SP].interlaced) { - rkisp_write(dev, CIF_ISP_ACQ_V_SIZE, in_crop->height / 2, false); - rkisp_write(dev, CIF_ISP_OUT_V_SIZE, in_crop->height / 2, false); + rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, in_crop->height / 2, + false, is_unite); + rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, in_crop->height / 2, + false, is_unite); } else { - rkisp_write(dev, CIF_ISP_ACQ_V_SIZE, in_crop->height + extend_line, false); - rkisp_write(dev, CIF_ISP_OUT_V_SIZE, in_crop->height + extend_line, false); + rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, in_crop->height + extend_line, + false, is_unite); + rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, in_crop->height + extend_line, + false, is_unite); } /* interrupt mask */ @@ -1330,7 +1471,10 @@ static int rkisp_config_isp(struct rkisp_device *dev) dev->isp_ver == ISP_V21 || dev->isp_ver == ISP_V30) irq_mask |= ISP2X_LSC_LUT_ERR; - rkisp_write(dev, CIF_ISP_IMSC, irq_mask, true); + if (is_unite) + rkisp_next_write(dev, CIF_ISP_IMSC, irq_mask, true); + else + rkisp_write(dev, CIF_ISP_IMSC, irq_mask, true); if ((dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21) && @@ -1455,9 +1599,9 @@ err: /* Configure MUX */ static int rkisp_config_path(struct rkisp_device *dev) { - int ret = 0; struct rkisp_sensor_info *sensor = dev->active_sensor; - u32 dpcl = readl(dev->base_addr + CIF_VI_DPCL); + int ret = 0; + u32 dpcl = 0; /* isp input interface selects */ if ((sensor && sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) || @@ -1482,8 +1626,8 @@ static int rkisp_config_path(struct rkisp_device *dev) ret = -EINVAL; } - writel(dpcl, dev->base_addr + CIF_VI_DPCL); - + rkisp_unite_set_bits(dev, CIF_VI_DPCL, 0, dpcl, true, + dev->hw_dev->is_unite); return ret; } @@ -1572,6 +1716,7 @@ static void rkisp_stop_3a_run(struct rkisp_device *dev) /* Mess register operations to stop isp */ static int rkisp_isp_stop(struct rkisp_device *dev) { + struct rkisp_hw_dev *hw = dev->hw_dev; void __iomem *base = dev->base_addr; unsigned long old_rate, safe_rate; u32 val; @@ -1650,6 +1795,9 @@ static int rkisp_isp_stop(struct rkisp_device *dev) val = readl(base + CIF_ISP_CTRL); writel(val | CIF_ISP_CTRL_ISP_CFG_UPD, base + CIF_ISP_CTRL); + if (hw->is_unite) + rkisp_next_write(dev, CIF_ISP_CTRL, + val | CIF_ISP_CTRL_ISP_CFG_UPD, true); readx_poll_timeout_atomic(readl, base + CIF_ISP_RIS, val, val & CIF_ISP_OFF, 20, 100); @@ -1661,10 +1809,12 @@ static int rkisp_isp_stop(struct rkisp_device *dev) if (!in_interrupt()) { /* normal case */ /* check the isp_clk before isp reset operation */ - old_rate = clk_get_rate(dev->hw_dev->clks[0]); - safe_rate = dev->hw_dev->clk_rate_tbl[0].clk_rate * 1000000UL; + old_rate = clk_get_rate(hw->clks[0]); + safe_rate = hw->clk_rate_tbl[0].clk_rate * 1000000UL; if (old_rate > safe_rate) { - rkisp_set_clk_rate(dev->hw_dev->clks[0], safe_rate); + rkisp_set_clk_rate(hw->clks[0], safe_rate); + if (hw->is_unite) + rkisp_set_clk_rate(hw->clks[5], safe_rate); udelay(100); } rkisp_soft_reset(dev->hw_dev, false); @@ -1681,6 +1831,8 @@ static int rkisp_isp_stop(struct rkisp_device *dev) dev->isp_ver == ISP_V21 || dev->isp_ver == ISP_V30) { writel(0, base + CSI2RX_CSI2_RESETN); + if (hw->is_unite) + rkisp_next_write(dev, CSI2RX_CSI2_RESETN, 0, true); } dev->hw_dev->is_idle = true; @@ -1713,8 +1865,8 @@ static int rkisp_isp_start(struct rkisp_device *dev) { struct rkisp_sensor_info *sensor = dev->active_sensor; void __iomem *base = dev->base_addr; - u32 val; bool is_direct = true; + u32 val; v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, "%s refcnt:%d\n", __func__, @@ -1743,7 +1895,7 @@ static int rkisp_isp_start(struct rkisp_device *dev) val |= NOC_HURRY_PRIORITY(2) | NOC_HURRY_W_MODE(2) | NOC_HURRY_R_MODE(1); if (atomic_read(&dev->hw_dev->refcnt) > 1) is_direct = false; - rkisp_write(dev, CIF_ISP_CTRL, val, is_direct); + rkisp_unite_write(dev, CIF_ISP_CTRL, val, is_direct, dev->hw_dev->is_unite); dev->isp_err_cnt = 0; dev->isp_isr_cnt = 0; @@ -2223,8 +2375,10 @@ static int rkisp_isp_sd_get_selection(struct v4l2_subdev *sd, max_h = CIF_ISP_INPUT_H_MAX_V21; break; case ISP_V30: - max_w = CIF_ISP_INPUT_W_MAX_V30; - max_h = CIF_ISP_INPUT_H_MAX_V30; + max_w = dev->hw_dev->is_unite ? + CIF_ISP_INPUT_W_MAX_V30_UNITE : CIF_ISP_INPUT_W_MAX_V30; + max_h = dev->hw_dev->is_unite ? + CIF_ISP_INPUT_H_MAX_V30_UNITE : CIF_ISP_INPUT_H_MAX_V30; break; default: max_w = CIF_ISP_INPUT_W_MAX; @@ -2427,6 +2581,7 @@ static int rkisp_rx_buf_pool_init(struct rkisp_device *dev, struct sg_table *sg_tbl; int i, ret; void *mem; + u32 val; for (i = 0; i < RKISP_RX_BUF_POOL_MAX; i++) { pool = &dev->pv_pool[i]; @@ -2471,7 +2626,13 @@ static int rkisp_rx_buf_pool_init(struct rkisp_device *dev, } stream->ops->config_mi(stream); - rkisp_write(dev, stream->config->mi.y_base_ad_init, pool->dma, false); + val = pool->dma; + rkisp_write(dev, stream->config->mi.y_base_ad_init, val, false); + if (dev->hw_dev->is_unite) { + val += (stream->out_fmt.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL) * + stream->out_isp_fmt.bpp[0] / 8; + rkisp_next_write(dev, stream->config->mi.y_base_ad_init, val, false); + } v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, "%s dma:0x%x vaddr:%p", __func__, (u32)pool->dma, pool->vaddr); return 0; @@ -3198,7 +3359,9 @@ void rkisp_isp_isr(unsigned int isp_mis, unsigned int isp3a_mis, struct rkisp_device *dev) { - void __iomem *base = dev->base_addr; + struct rkisp_hw_dev *hw = dev->hw_dev; + void __iomem *base = !hw->is_unite ? + hw->base_addr : hw->base_next_addr; unsigned int isp_mis_tmp = 0; unsigned int isp_err = 0; u32 si3a_isr_mask = ISP2X_SIAWB_DONE | ISP2X_SIAF_FIN | @@ -3218,6 +3381,15 @@ void rkisp_isp_isr(unsigned int isp_mis, if (isp3a_mis & ISP2X_3A_RAWAE_BIG && dev->params_vdev.rdbk_times > 0) writel(BIT(31), base + RAWAE_BIG1_BASE + RAWAE_BIG_CTRL); + if (hw->is_unite) { + u32 val = rkisp_read(dev, ISP3X_ISP_RIS, true); + + if (val) { + rkisp_write(dev, ISP3X_ISP_ICR, val, true); + v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, + "left isp isr:0x%x\n", val); + } + } v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, "isp isr:0x%x, 0x%x\n", isp_mis, isp3a_mis); dev->isp_isr_cnt++; diff --git a/drivers/media/platform/rockchip/isp/rkisp.h b/drivers/media/platform/rockchip/isp/rkisp.h index db1a8167df15..bb19692e8a87 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.h +++ b/drivers/media/platform/rockchip/isp/rkisp.h @@ -53,6 +53,8 @@ #define CIF_ISP_INPUT_H_MAX_V21 3072 #define CIF_ISP_INPUT_W_MAX_V30 4672 #define CIF_ISP_INPUT_H_MAX_V30 3504 +#define CIF_ISP_INPUT_W_MAX_V30_UNITE 8192 +#define CIF_ISP_INPUT_H_MAX_V30_UNITE 6144 #define CIF_ISP_INPUT_W_MIN 208 #define CIF_ISP_INPUT_H_MIN 128 #define CIF_ISP_OUTPUT_W_MAX CIF_ISP_INPUT_W_MAX diff --git a/include/uapi/linux/rk-camera-module.h b/include/uapi/linux/rk-camera-module.h index 1ea1421640ff..d32d71af8f53 100644 --- a/include/uapi/linux/rk-camera-module.h +++ b/include/uapi/linux/rk-camera-module.h @@ -12,6 +12,8 @@ #define RKMODULE_API_VERSION KERNEL_VERSION(0, 1, 0x2) +/* using for rk3588 dual isp unite */ +#define RKMOUDLE_UNITE_EXTEND_PIXEL 128 /* using for rv1109 and rv1126 */ #define RKMODULE_EXTEND_LINE 24