From 46b9b70ded96429fd63a91d256bb3766060ceed7 Mon Sep 17 00:00:00 2001 From: Mingwei Yan Date: Tue, 22 Oct 2024 17:39:59 +0800 Subject: [PATCH] media: rockchip: vpss: online support tile write Signed-off-by: Mingwei Yan Change-Id: Iab4ca3d82315222543c5f98b5adb8847ed872b3b --- drivers/media/platform/rockchip/vpss/stream.c | 182 +++++++++++++++++- 1 file changed, 173 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/rockchip/vpss/stream.c b/drivers/media/platform/rockchip/vpss/stream.c index 2ebdbf3c7d09..1e6552889b96 100644 --- a/drivers/media/platform/rockchip/vpss/stream.c +++ b/drivers/media/platform/rockchip/vpss/stream.c @@ -25,7 +25,7 @@ static int rkvpss_stream_crop(struct rkvpss_stream *stream, bool on, bool sync); static int rkvpss_stream_scale(struct rkvpss_stream *stream, bool on, bool sync); static void rkvpss_stream_mf(struct rkvpss_stream *stream); -static const struct capture_fmt scl_fmts[] = { +static const struct capture_fmt scl0_fmts[] = { { .fourcc = V4L2_PIX_FMT_NV16, .fmt_type = FMT_YUV, @@ -89,6 +89,24 @@ static const struct capture_fmt scl_fmts[] = { .swap = 0, .wr_fmt = RKVPSS_MI_CHN_WR_422P, .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV422, + }, { + .fourcc = V4L2_PIX_FMT_TILE420, + .fmt_type = FMT_YUV, + .bpp = { 24 }, + .cplanes = 1, + .mplanes = 1, + .swap = 0, + .wr_fmt = 0, + .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV420, + }, { + .fourcc = V4L2_PIX_FMT_TILE422, + .fmt_type = FMT_YUV, + .bpp = { 32 }, + .cplanes = 1, + .mplanes = 1, + .swap = 0, + .wr_fmt = 0, + .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV422, } }; @@ -210,12 +228,98 @@ static const struct capture_fmt scl1_fmts[] = { .swap = 0, .wr_fmt = RKVPSS_MI_CHN_WR_422P, .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV422, + }, { + .fourcc = V4L2_PIX_FMT_TILE420, + .fmt_type = FMT_YUV, + .bpp = { 24 }, + .cplanes = 1, + .mplanes = 1, + .swap = 0, + .wr_fmt = 0, + .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV420, + }, { + .fourcc = V4L2_PIX_FMT_TILE422, + .fmt_type = FMT_YUV, + .bpp = { 32 }, + .cplanes = 1, + .mplanes = 1, + .swap = 0, + .wr_fmt = 0, + .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV422, } }; +static const struct capture_fmt scl2_3_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_NV16, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .swap = 0, + .wr_fmt = RKVPSS_MI_CHN_WR_42XSP, + .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV422, + }, { + .fourcc = V4L2_PIX_FMT_NV12, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .swap = 0, + .wr_fmt = RKVPSS_MI_CHN_WR_42XSP, + .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV420, + }, { + .fourcc = V4L2_PIX_FMT_GREY, + .fmt_type = FMT_YUV, + .bpp = { 8 }, + .cplanes = 1, + .mplanes = 1, + .swap = 0, + .wr_fmt = RKVPSS_MI_CHN_WR_42XSP, + .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV400, + }, { + .fourcc = V4L2_PIX_FMT_UYVY, + .fmt_type = FMT_YUV, + .bpp = { 16 }, + .cplanes = 1, + .mplanes = 1, + .swap = 0, + .wr_fmt = RKVPSS_MI_CHN_WR_422P, + .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV422, + }, { + .fourcc = V4L2_PIX_FMT_NV61, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .swap = 0, + .wr_fmt = RKVPSS_MI_CHN_WR_42XSP, + .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV422, + }, { + .fourcc = V4L2_PIX_FMT_NV21, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .swap = 0, + .wr_fmt = RKVPSS_MI_CHN_WR_42XSP, + .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV420, + }, { + .fourcc = V4L2_PIX_FMT_VYUY, + .fmt_type = FMT_YUV, + .bpp = { 16 }, + .cplanes = 1, + .mplanes = 1, + .swap = 0, + .wr_fmt = RKVPSS_MI_CHN_WR_422P, + .output_fmt = RKVPSS_MI_CHN_WR_OUTPUT_YUV422, + } +}; + + static struct stream_config scl0_config = { - .fmts = scl_fmts, - .fmt_size = ARRAY_SIZE(scl_fmts), + .fmts = scl0_fmts, + .fmt_size = ARRAY_SIZE(scl0_fmts), .frame_end_id = RKVPSS_MI_CHN0_FRM_END, .crop = { .ctrl = RKVPSS_CROP1_CTRL, @@ -319,8 +423,8 @@ static struct stream_config scl1_config = { }; static struct stream_config scl2_config = { - .fmts = scl_fmts, - .fmt_size = ARRAY_SIZE(scl_fmts), + .fmts = scl2_3_fmts, + .fmt_size = ARRAY_SIZE(scl2_3_fmts), .frame_end_id = RKVPSS_MI_CHN2_FRM_END, .crop = { .ctrl = RKVPSS_CROP1_CTRL, @@ -389,8 +493,8 @@ static struct stream_config scl2_config = { }; static struct stream_config scl3_config = { - .fmts = scl_fmts, - .fmt_size = ARRAY_SIZE(scl_fmts), + .fmts = scl2_3_fmts, + .fmt_size = ARRAY_SIZE(scl2_3_fmts), .frame_end_id = RKVPSS_MI_CHN3_FRM_END, .crop = { .ctrl = RKVPSS_CROP1_CTRL, @@ -689,6 +793,15 @@ static void scl_config_mi(struct rkvpss_stream *stream) mask = RKVPSS_MI_WR_UV_SWAP; val = RKVPSS_MI_WR_UV_SWAP; rkvpss_hw_set_bits(dev->hw_dev, RKVPSS_MI_WR_CTRL, mask, val); + break; + case V4L2_PIX_FMT_TILE420: + case V4L2_PIX_FMT_TILE422: + mask = RKVPSS_MI_WR_TILE_SEL(3); + val = RKVPSS_MI_WR_TILE_SEL(stream->id + 1); + rkvpss_hw_set_bits(dev->hw_dev, RKVPSS_MI_WR_CTRL, mask, val); + break; + default: + break; } stream->is_mf_upd = true; @@ -1775,6 +1888,28 @@ static int rkvpss_set_fmt(struct rkvpss_stream *stream, return -EINVAL; } + /* Tile4x4 writing of Channel0 and Channel1 only supports either one.*/ + if (fmt->fourcc == V4L2_PIX_FMT_TILE420 || fmt->fourcc == V4L2_PIX_FMT_TILE422) { + if (stream->id == 0) { + if (dev->stream_vdev.stream[1].streaming && + (dev->stream_vdev.stream[1].out_cap_fmt.fourcc == V4L2_PIX_FMT_TILE420 || + dev->stream_vdev.stream[1].out_cap_fmt.fourcc == V4L2_PIX_FMT_TILE422)) { + v4l2_err(&dev->v4l2_dev, + "Tile4x4 writing of Ch0 and Cl1 only supports either one\n"); + return -EINVAL; + } + } + if (stream->id == 1) { + if (dev->stream_vdev.stream[0].streaming && + (dev->stream_vdev.stream[0].out_cap_fmt.fourcc == V4L2_PIX_FMT_TILE420 || + dev->stream_vdev.stream[0].out_cap_fmt.fourcc == V4L2_PIX_FMT_TILE422)) { + v4l2_err(&dev->v4l2_dev, + "Tile4x4 writing of Ch0 and Cl1 only supports either one\n"); + return -EINVAL; + } + } + } + pixm->num_planes = fmt->mplanes; pixm->field = V4L2_FIELD_NONE; if (!pixm->quantization) @@ -1790,10 +1925,20 @@ static int rkvpss_set_fmt(struct rkvpss_stream *stream, h = pixm->height; width = i ? w / xsubs : w; height = i ? h / ysubs : h; - bytesperline = width * DIV_ROUND_UP(fmt->bpp[i], 8); + + if (fmt->fourcc == V4L2_PIX_FMT_TILE420 || fmt->fourcc == V4L2_PIX_FMT_TILE422) + bytesperline = ALIGN(((width / 4) * fmt->bpp[i]), 16); + else + bytesperline = width * DIV_ROUND_UP(fmt->bpp[i], 8); + if (i != 0 || plane_fmt->bytesperline < bytesperline) plane_fmt->bytesperline = bytesperline; - plane_fmt->sizeimage = plane_fmt->bytesperline * height; + + if (fmt->fourcc == V4L2_PIX_FMT_TILE420 || fmt->fourcc == V4L2_PIX_FMT_TILE422) + plane_fmt->sizeimage = plane_fmt->bytesperline * (height / 4); + else + plane_fmt->sizeimage = plane_fmt->bytesperline * height; + imagsize += plane_fmt->sizeimage; } if (fmt->mplanes == 1) @@ -1886,6 +2031,21 @@ static int rkvpss_enum_fmt_vid_mplane(struct file *file, void *priv, fmt = &stream->config->fmts[f->index]; f->pixelformat = fmt->fourcc; + switch (f->pixelformat) { + case V4L2_PIX_FMT_TILE420: + strscpy(f->description, + "Rockchip yuv420 tile", + sizeof(f->description)); + break; + case V4L2_PIX_FMT_TILE422: + strscpy(f->description, + "Rockchip yuv422 tile", + sizeof(f->description)); + break; + default: + break; + } + return 0; } @@ -1998,6 +2158,10 @@ static void rkvpss_stream_mf(struct rkvpss_stream *stream) rkvpss_unite_set_bits(dev, RKVPSS_VPSS_CTRL, mask, val); } mask = RKVPSS_MI_CHN_V_FLIP(stream->id); + /* Tile4x4 writing can't flip*/ + if (stream->out_cap_fmt.fourcc == V4L2_PIX_FMT_TILE420 || + stream->out_cap_fmt.fourcc == V4L2_PIX_FMT_TILE422) + stream->flip_en = false; val = stream->flip_en ? mask : 0; rkvpss_unite_set_bits(dev, RKVPSS_MI_WR_VFLIP_CTRL, mask, val); }