From c76be98cdc01f2d56fda446d582d6c49b0fdbe17 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Mon, 14 Feb 2022 17:41:10 +0800 Subject: [PATCH] media: rockchip: isp: isp32 support mirror and flip Change-Id: I8e067cddee9bb314d97e2fd09b62886e8f9b222d Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/capture.c | 58 +++++++++++++ drivers/media/platform/rockchip/isp/capture.h | 4 + .../media/platform/rockchip/isp/capture_v32.c | 84 ++++++++++++++++--- .../media/platform/rockchip/isp/regs_v3x.h | 8 +- include/uapi/linux/rkisp2-config.h | 15 ++++ 5 files changed, 156 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/capture.c b/drivers/media/platform/rockchip/isp/capture.c index 0639b928e0d9..b0c16e098a4c 100644 --- a/drivers/media/platform/rockchip/isp/capture.c +++ b/drivers/media/platform/rockchip/isp/capture.c @@ -443,6 +443,7 @@ static const struct capture_fmt mp_fmts[] = { .mplanes = 1, .uv_swap = 0, .write_format = MI_CTRL_MP_WRITE_YUVINT, + .output_format = ISP32_MI_OUTPUT_YUV422, }, { .fourcc = V4L2_PIX_FMT_YUV422P, .fmt_type = FMT_YUV, @@ -451,6 +452,7 @@ static const struct capture_fmt mp_fmts[] = { .mplanes = 1, .uv_swap = 0, .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .output_format = ISP32_MI_OUTPUT_YUV422, }, { .fourcc = V4L2_PIX_FMT_NV16, .fmt_type = FMT_YUV, @@ -459,6 +461,7 @@ static const struct capture_fmt mp_fmts[] = { .mplanes = 1, .uv_swap = 0, .write_format = MI_CTRL_MP_WRITE_YUV_SPLA, + .output_format = ISP32_MI_OUTPUT_YUV422, }, { .fourcc = V4L2_PIX_FMT_NV61, .fmt_type = FMT_YUV, @@ -467,6 +470,7 @@ static const struct capture_fmt mp_fmts[] = { .mplanes = 1, .uv_swap = 1, .write_format = MI_CTRL_MP_WRITE_YUV_SPLA, + .output_format = ISP32_MI_OUTPUT_YUV422, }, { .fourcc = V4L2_PIX_FMT_YUV422M, .fmt_type = FMT_YUV, @@ -475,6 +479,7 @@ static const struct capture_fmt mp_fmts[] = { .mplanes = 3, .uv_swap = 0, .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .output_format = ISP32_MI_OUTPUT_YUV422, }, /* yuv420 */ { @@ -485,6 +490,7 @@ static const struct capture_fmt mp_fmts[] = { .mplanes = 1, .uv_swap = 1, .write_format = MI_CTRL_MP_WRITE_YUV_SPLA, + .output_format = ISP32_MI_OUTPUT_YUV420, }, { .fourcc = V4L2_PIX_FMT_NV12, .fmt_type = FMT_YUV, @@ -493,6 +499,7 @@ static const struct capture_fmt mp_fmts[] = { .mplanes = 1, .uv_swap = 0, .write_format = MI_CTRL_MP_WRITE_YUV_SPLA, + .output_format = ISP32_MI_OUTPUT_YUV420, }, { .fourcc = V4L2_PIX_FMT_NV21M, .fmt_type = FMT_YUV, @@ -501,6 +508,7 @@ static const struct capture_fmt mp_fmts[] = { .mplanes = 2, .uv_swap = 1, .write_format = MI_CTRL_MP_WRITE_YUV_SPLA, + .output_format = ISP32_MI_OUTPUT_YUV420, }, { .fourcc = V4L2_PIX_FMT_NV12M, .fmt_type = FMT_YUV, @@ -509,6 +517,7 @@ static const struct capture_fmt mp_fmts[] = { .mplanes = 2, .uv_swap = 0, .write_format = MI_CTRL_MP_WRITE_YUV_SPLA, + .output_format = ISP32_MI_OUTPUT_YUV420, }, { .fourcc = V4L2_PIX_FMT_YUV420, .fmt_type = FMT_YUV, @@ -517,6 +526,7 @@ static const struct capture_fmt mp_fmts[] = { .mplanes = 1, .uv_swap = 0, .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .output_format = ISP32_MI_OUTPUT_YUV420, }, /* yuv444 */ { @@ -527,6 +537,7 @@ static const struct capture_fmt mp_fmts[] = { .mplanes = 3, .uv_swap = 0, .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .output_format = 0, }, /* raw */ { @@ -535,72 +546,84 @@ static const struct capture_fmt mp_fmts[] = { .bpp = { 8 }, .mplanes = 1, .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .output_format = 0, }, { .fourcc = V4L2_PIX_FMT_SGRBG8, .fmt_type = FMT_BAYER, .bpp = { 8 }, .mplanes = 1, .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .output_format = 0, }, { .fourcc = V4L2_PIX_FMT_SGBRG8, .fmt_type = FMT_BAYER, .bpp = { 8 }, .mplanes = 1, .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .output_format = 0, }, { .fourcc = V4L2_PIX_FMT_SBGGR8, .fmt_type = FMT_BAYER, .bpp = { 8 }, .mplanes = 1, .write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .output_format = 0, }, { .fourcc = V4L2_PIX_FMT_SRGGB10, .fmt_type = FMT_BAYER, .bpp = { 10 }, .mplanes = 1, .write_format = MI_CTRL_MP_WRITE_RAW12, + .output_format = 0, }, { .fourcc = V4L2_PIX_FMT_SGRBG10, .fmt_type = FMT_BAYER, .bpp = { 10 }, .mplanes = 1, .write_format = MI_CTRL_MP_WRITE_RAW12, + .output_format = 0, }, { .fourcc = V4L2_PIX_FMT_SGBRG10, .fmt_type = FMT_BAYER, .bpp = { 10 }, .mplanes = 1, .write_format = MI_CTRL_MP_WRITE_RAW12, + .output_format = 0, }, { .fourcc = V4L2_PIX_FMT_SBGGR10, .fmt_type = FMT_BAYER, .bpp = { 10 }, .mplanes = 1, .write_format = MI_CTRL_MP_WRITE_RAW12, + .output_format = 0, }, { .fourcc = V4L2_PIX_FMT_SRGGB12, .fmt_type = FMT_BAYER, .bpp = { 12 }, .mplanes = 1, .write_format = MI_CTRL_MP_WRITE_RAW12, + .output_format = 0, }, { .fourcc = V4L2_PIX_FMT_SGRBG12, .fmt_type = FMT_BAYER, .bpp = { 12 }, .mplanes = 1, .write_format = MI_CTRL_MP_WRITE_RAW12, + .output_format = 0, }, { .fourcc = V4L2_PIX_FMT_SGBRG12, .fmt_type = FMT_BAYER, .bpp = { 12 }, .mplanes = 1, .write_format = MI_CTRL_MP_WRITE_RAW12, + .output_format = 0, }, { .fourcc = V4L2_PIX_FMT_SBGGR12, .fmt_type = FMT_BAYER, .bpp = { 12 }, .mplanes = 1, .write_format = MI_CTRL_MP_WRITE_RAW12, + .output_format = 0, }, }; @@ -804,6 +827,7 @@ struct stream_config rkisp_mp_stream_config = { .cb_offs_cnt_init = CIF_MI_MP_CB_OFFS_CNT_INIT, .cr_offs_cnt_init = CIF_MI_MP_CR_OFFS_CNT_INIT, .y_base_ad_shd = CIF_MI_MP_Y_BASE_AD_SHD, + .y_pic_size = ISP3X_MI_MP_WR_Y_PIC_SIZE, }, }; @@ -861,6 +885,7 @@ struct stream_config rkisp_sp_stream_config = { .cb_offs_cnt_init = CIF_MI_SP_CB_OFFS_CNT_INIT, .cr_offs_cnt_init = CIF_MI_SP_CR_OFFS_CNT_INIT, .y_base_ad_shd = CIF_MI_SP_Y_BASE_AD_SHD, + .y_pic_size = ISP3X_MI_SP_WR_Y_PIC_SIZE, }, }; @@ -1339,6 +1364,33 @@ static int rkisp_get_stream_info(struct rkisp_stream *stream, return 0; } +static int rkisp_get_mirror_flip(struct rkisp_stream *stream, + struct rkisp_mirror_flip *cfg) +{ + struct rkisp_device *dev = stream->ispdev; + + if (dev->isp_ver != ISP_V32) + return -EINVAL; + + cfg->mirror = dev->cap_dev.is_mirror; + cfg->flip = stream->is_flip; + return 0; +} + +static int rkisp_set_mirror_flip(struct rkisp_stream *stream, + struct rkisp_mirror_flip *cfg) +{ + struct rkisp_device *dev = stream->ispdev; + + if (dev->isp_ver != ISP_V32) + return -EINVAL; + + dev->cap_dev.is_mirror = cfg->mirror; + stream->is_flip = cfg->flip; + stream->is_mf_upd = true; + return 0; +} + static long rkisp_ioctl_default(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg) { @@ -1385,6 +1437,12 @@ static long rkisp_ioctl_default(struct file *file, void *fh, case RKISP_CMD_GET_STREAM_INFO: ret = rkisp_get_stream_info(stream, arg); break; + case RKISP_CMD_GET_MIRROR_FLIP: + ret = rkisp_get_mirror_flip(stream, arg); + break; + case RKISP_CMD_SET_MIRROR_FLIP: + ret = rkisp_set_mirror_flip(stream, arg); + break; default: ret = -EINVAL; } diff --git a/drivers/media/platform/rockchip/isp/capture.h b/drivers/media/platform/rockchip/isp/capture.h index 418fbaabbe32..4fdf9789c85c 100644 --- a/drivers/media/platform/rockchip/isp/capture.h +++ b/drivers/media/platform/rockchip/isp/capture.h @@ -192,6 +192,7 @@ struct stream_config { u32 y_base_ad_shd; u32 length; u32 ctrl; + u32 y_pic_size; } mi; struct { u32 ctrl; @@ -253,6 +254,8 @@ struct rkisp_stream { bool frame_end; bool linked; bool start_stream; + bool is_mf_upd; + bool is_flip; wait_queue_head_t done; unsigned int burst; atomic_t sequence; @@ -283,6 +286,7 @@ struct rkisp_capture_device { u32 wait_line; u32 wrap_line; bool is_done_early; + bool is_mirror; }; extern struct stream_config rkisp_mp_stream_config; diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index bec6d6a89c50..79fcee25c845 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -109,6 +109,7 @@ static struct stream_config rkisp_bp_stream_config = { .y_offs_cnt_init = ISP3X_MI_BP_WR_Y_OFFS_CNT, .cb_offs_cnt_init = ISP3X_MI_BP_WR_CB_OFFS_CNT, .y_base_ad_shd = ISP3X_MI_BP_WR_Y_BASE_SHD, + .y_pic_size = ISP3X_MI_BP_WR_Y_PIC_SIZE, }, }; @@ -126,6 +127,7 @@ static struct stream_config rkisp_bpds_stream_config = { .y_offs_cnt_init = ISP32_MI_BPDS_WR_Y_OFFS_CNT, .cb_offs_cnt_init = ISP32_MI_BPDS_WR_CB_OFFS_CNT, .y_base_ad_shd = ISP32_MI_BPDS_WR_Y_BASE_SHD, + .y_pic_size = ISP32_MI_BPDS_WR_Y_PIC_SIZE, }, }; @@ -143,6 +145,7 @@ static struct stream_config rkisp_mpds_stream_config = { .y_offs_cnt_init = ISP32_MI_MPDS_WR_Y_OFFS_CNT, .cb_offs_cnt_init = ISP32_MI_MPDS_WR_CB_OFFS_CNT, .y_base_ad_shd = ISP32_MI_MPDS_WR_Y_BASE_SHD, + .y_pic_size = ISP32_MI_MPDS_WR_Y_PIC_SIZE, }, }; @@ -336,6 +339,7 @@ static u32 calc_burst_len(struct rkisp_stream *stream) static int mp_config_mi(struct rkisp_stream *stream) { struct rkisp_device *dev = stream->ispdev; + struct capture_fmt *fmt = &stream->out_isp_fmt; struct v4l2_pix_format_mplane *out_fmt = &stream->out_fmt; u32 val, mask, height = out_fmt->height; @@ -347,6 +351,11 @@ static int mp_config_mi(struct rkisp_stream *stream) height = dev->cap_dev.wrap_line; rkisp_clear_bits(dev, 0x1814, BIT(0), false); } + val = out_fmt->plane_fmt[0].bytesperline; + rkisp_write(dev, ISP3X_MI_MP_WR_Y_LLENGTH, val, false); + val /= DIV_ROUND_UP(fmt->bpp[0], 8); + val *= height; + rkisp_write(dev, stream->config->mi.y_pic_size, val, false); val = out_fmt->plane_fmt[0].bytesperline * height; rkisp_write(dev, stream->config->mi.y_size_init, val, false); @@ -356,9 +365,6 @@ static int mp_config_mi(struct rkisp_stream *stream) val = out_fmt->plane_fmt[2].sizeimage; rkisp_write(dev, stream->config->mi.cr_size_init, val, false); - val = ALIGN(out_fmt->plane_fmt[0].bytesperline, 16); - rkisp_write(dev, ISP3X_MI_MP_WR_Y_LLENGTH, val, false); - 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); @@ -375,6 +381,9 @@ static int mp_config_mi(struct rkisp_stream *stream) val |= ISP3X_SEPERATE_YUV_CFG | ISP3X_MP_YUV_MODE; rkisp_write(dev, ISP3X_MPFBC_CTRL, val, false); + val = stream->out_isp_fmt.output_format; + rkisp_write(dev, ISP32_MI_MP_WR_CTRL, val, false); + 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; @@ -432,6 +441,10 @@ static int sp_config_mi(struct rkisp_stream *stream) * NOTE: plane_fmt[0].sizeimage is total size of all planes for single * memory plane formats, so calculate the size explicitly. */ + val = stream->u.sp.y_stride; + rkisp_write(dev, ISP3X_MI_SP_WR_Y_LLENGTH, val, false); + val *= out_fmt->height; + rkisp_write(dev, stream->config->mi.y_pic_size, val, false); val = out_fmt->plane_fmt[0].bytesperline * out_fmt->height; rkisp_write(dev, stream->config->mi.y_size_init, val, false); @@ -441,9 +454,6 @@ static int sp_config_mi(struct rkisp_stream *stream) val = out_fmt->plane_fmt[2].sizeimage; rkisp_write(dev, stream->config->mi.cr_size_init, val, false); - val = ALIGN(out_fmt->plane_fmt[0].bytesperline, 16); - rkisp_write(dev, ISP3X_MI_SP_WR_Y_LLENGTH, val, false); - 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); @@ -476,6 +486,7 @@ static int sp_config_mi(struct rkisp_stream *stream) static int bp_config_mi(struct rkisp_stream *stream) { struct v4l2_pix_format_mplane *out_fmt = &stream->out_fmt; + struct capture_fmt *fmt = &stream->out_isp_fmt; struct rkisp_device *dev = stream->ispdev; u32 val, mask; @@ -483,15 +494,17 @@ static int bp_config_mi(struct rkisp_stream *stream) * NOTE: plane_fmt[0].sizeimage is total size of all planes for single * memory plane formats, so calculate the size explicitly. */ + val = out_fmt->plane_fmt[0].bytesperline; + rkisp_write(dev, ISP3X_MI_BP_WR_Y_LLENGTH, val, false); + val /= DIV_ROUND_UP(fmt->bpp[0], 8); + val *= out_fmt->height; + rkisp_write(dev, stream->config->mi.y_pic_size, val, false); val = out_fmt->plane_fmt[0].bytesperline * out_fmt->height; rkisp_write(dev, stream->config->mi.y_size_init, val, false); val = out_fmt->plane_fmt[1].sizeimage; rkisp_write(dev, stream->config->mi.cb_size_init, val, false); - val = ALIGN(out_fmt->plane_fmt[0].bytesperline, 16); - rkisp_write(dev, ISP3X_MI_BP_WR_Y_LLENGTH, val, false); - mask = ISP3X_MPFBC_FORCE_UPD | ISP3X_BP_YUV_MODE; val = rkisp_read_reg_cache(dev, ISP3X_MPFBC_CTRL) & ~mask; @@ -511,19 +524,22 @@ static int bp_config_mi(struct rkisp_stream *stream) static int ds_config_mi(struct rkisp_stream *stream) { + struct capture_fmt *fmt = &stream->out_isp_fmt; struct v4l2_pix_format_mplane *out_fmt = &stream->out_fmt; struct rkisp_device *dev = stream->ispdev; u32 val; + val = out_fmt->plane_fmt[0].bytesperline; + rkisp_write(dev, stream->config->mi.length, val, false); + val /= DIV_ROUND_UP(fmt->bpp[0], 8); + val *= out_fmt->height; + rkisp_write(dev, stream->config->mi.y_pic_size, val, false); val = out_fmt->plane_fmt[0].bytesperline * out_fmt->height; rkisp_write(dev, stream->config->mi.y_size_init, val, false); val = out_fmt->plane_fmt[1].sizeimage; rkisp_write(dev, stream->config->mi.cb_size_init, val, false); - val = ALIGN(out_fmt->plane_fmt[0].bytesperline, 16); - rkisp_write(dev, stream->config->mi.length, val, false); - val = CIF_MI_CTRL_INIT_BASE_EN | CIF_MI_CTRL_INIT_OFFSET_EN; rkisp_set_bits(dev, ISP3X_MI_WR_CTRL, 0, val, false); @@ -684,6 +700,49 @@ static void update_mi(struct rkisp_stream *stream) rkisp_read(dev, stream->config->mi.y_base_ad_shd, true)); } +static int set_mirror_flip(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + u32 val = 0; + + if (!stream->is_mf_upd) + return 0; + + stream->is_mf_upd = false; + if (dev->cap_dev.is_mirror) + rkisp_set_bits(dev, ISP3X_ISP_CTRL0, 0, ISP32_MIR_ENABLE, false); + else + rkisp_clear_bits(dev, ISP3X_ISP_CTRL0, ISP32_MIR_ENABLE, false); + + switch (stream->id) { + case RKISP_STREAM_SP: + val = ISP32_SP_WR_V_FLIP; + break; + case RKISP_STREAM_BP: + val = ISP32_BP_WR_V_FLIP; + break; + case RKISP_STREAM_MPDS: + val = ISP32_MPDS_WR_V_FLIP; + break; + case RKISP_STREAM_BPDS: + val = ISP32_BPDS_WR_V_FIIP; + break; + default: + val = ISP32_MP_WR_V_FLIP; + if (dev->cap_dev.wrap_line) { + stream->is_flip = false; + v4l2_warn(&dev->v4l2_dev, "flip not support width wrap function\n"); + return -EINVAL; + } + } + + if (stream->is_flip) + rkisp_set_bits(dev, ISP32_MI_WR_VFLIP_CTRL, 0, val, false); + else + rkisp_clear_bits(dev, ISP32_MI_WR_VFLIP_CTRL, val, false); + return 0; +} + static struct streams_ops rkisp_mp_streams_ops = { .config_mi = mp_config_mi, .enable_mi = mp_enable_mi, @@ -743,6 +802,7 @@ static int mi_frame_end(struct rkisp_stream *stream) u64 ns = 0; u32 i, seq; + set_mirror_flip(stream); rkisp_dmarx_get_frame(dev, &seq, NULL, &ns, true); /* hold one buf for hw dma write */ diff --git a/drivers/media/platform/rockchip/isp/regs_v3x.h b/drivers/media/platform/rockchip/isp/regs_v3x.h index f2c88e825008..5a1fb5ec0227 100644 --- a/drivers/media/platform/rockchip/isp/regs_v3x.h +++ b/drivers/media/platform/rockchip/isp/regs_v3x.h @@ -1904,6 +1904,12 @@ #define ISP3X_DBR_ST_MODE BIT(30) #define ISP3X_DBR_ST BIT(31) +/* WR_OUTPUT_FORMAT */ +#define ISP32_MI_OUTPUT_MASK GENMASK(10, 8) +#define ISP32_MI_OUTPUT_YUV400 0 +#define ISP32_MI_OUTPUT_YUV420 BIT(8) +#define ISP32_MI_OUTPUT_YUV422 BIT(9) + /* MI_WR_CTRL2_SHD */ #define ISP32_BP_EN_IN_SHD BIT(4) #define ISP32_DBR_WR_EN_IN_SHD BIT(5) @@ -1966,7 +1972,7 @@ #define ISP32_MPDS_WR_FRMEND_UPD_DIS BIT(27) #define ISP32_BPDS_WR_FRMEND_UPD_DIS BIT(28) -/* WRAP_CTRL */ +/* VFLIP_CTRL */ #define ISP32_MP_WR_V_FLIP BIT(0) #define ISP32_SP_WR_V_FLIP BIT(1) #define ISP32_BP_WR_V_FLIP BIT(2) diff --git a/include/uapi/linux/rkisp2-config.h b/include/uapi/linux/rkisp2-config.h index bed3e199170a..c7b28cf75c33 100644 --- a/include/uapi/linux/rkisp2-config.h +++ b/include/uapi/linux/rkisp2-config.h @@ -58,6 +58,12 @@ #define RKISP_CMD_GET_STREAM_INFO \ _IOR('V', BASE_VIDIOC_PRIVATE + 104, struct rkisp_stream_info) +#define RKISP_CMD_GET_MIRROR_FLIP \ + _IOR('V', BASE_VIDIOC_PRIVATE + 105, struct rkisp_mirror_flip) + +#define RKISP_CMD_SET_MIRROR_FLIP \ + _IOW('V', BASE_VIDIOC_PRIVATE + 106, struct rkisp_mirror_flip) + /*************************************************************/ #define ISP2X_ID_DPCC (0) @@ -311,6 +317,15 @@ struct rkisp_stream_info { unsigned char stream_on; } __attribute__ ((packed)); +/* struct rkisp_mirror_flip + * mirror: global for all output stream + * flip: independent for all output stream + */ +struct rkisp_mirror_flip { + unsigned char mirror; + unsigned char flip; +} __attribute__ ((packed)); + /* trigger event mode * T_TRY: trigger maybe with retry * T_TRY_YES: trigger to retry