Message ID | 20240510112252.800-5-jackson.lee@chipsnmedia.com |
---|---|
State | Superseded |
Headers | show |
Series | Add features to an existing driver | expand |
Le vendredi 10 mai 2024 à 20:22 +0900, Jackson Lee a écrit : > From: "Jackson.lee" <jackson.lee@chipsnmedia.com> > > Add support for the YUV422P, NV16, NV61, YUV422M, NV16M, > NV61M raw pixel-formats to the Wave5 encoder. > > All these formats have a chroma subsampling ratio of 4:2:2 and > therefore require a new image size calculation as the driver > previously only handled a ratio of 4:2:0. > > Signed-off-by: Jackson.lee <jackson.lee@chipsnmedia.com> > Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> > --- > .../chips-media/wave5/wave5-vpu-enc.c | 81 +++++++++++++++---- > 1 file changed, 67 insertions(+), 14 deletions(-) > > diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c > index 75d230df45f6..3f148e1b0513 100644 > --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c > +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c > @@ -66,6 +66,24 @@ static const struct vpu_format enc_fmt_list[FMT_TYPES][MAX_FMTS] = { > .v4l2_pix_fmt = V4L2_PIX_FMT_NV21M, > .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW], > }, > + { > + .v4l2_pix_fmt = V4L2_PIX_FMT_YUV422P, > + }, > + { > + .v4l2_pix_fmt = V4L2_PIX_FMT_NV16, > + }, > + { > + .v4l2_pix_fmt = V4L2_PIX_FMT_NV61, > + }, > + { > + .v4l2_pix_fmt = V4L2_PIX_FMT_YUV422M, > + }, > + { > + .v4l2_pix_fmt = V4L2_PIX_FMT_NV16M, > + }, > + { > + .v4l2_pix_fmt = V4L2_PIX_FMT_NV61M, > + }, > } > }; > > @@ -109,13 +127,26 @@ static int start_encode(struct vpu_instance *inst, u32 *fail_res) > struct vb2_v4l2_buffer *dst_buf; > struct frame_buffer frame_buf; > struct enc_param pic_param; > - u32 stride = ALIGN(inst->dst_fmt.width, 32); > - u32 luma_size = (stride * inst->dst_fmt.height); > - u32 chroma_size = ((stride / 2) * (inst->dst_fmt.height / 2)); > + const struct v4l2_format_info *info; > + u32 stride = inst->src_fmt.plane_fmt[0].bytesperline; > + u32 luma_size = 0; > + u32 chroma_size = 0; > > memset(&pic_param, 0, sizeof(struct enc_param)); > memset(&frame_buf, 0, sizeof(struct frame_buffer)); > > + info = v4l2_format_info(inst->src_fmt.pixelformat); > + if (!info) > + return -EINVAL; > + > + if (info->mem_planes == 1) { > + luma_size = stride * inst->dst_fmt.height; > + chroma_size = luma_size / (info->hdiv * info->vdiv); > + } else { > + luma_size = inst->src_fmt.plane_fmt[0].sizeimage; > + chroma_size = inst->src_fmt.plane_fmt[1].sizeimage; > + } > + > dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx); > if (!dst_buf) { > dev_dbg(inst->dev->dev, "%s: No destination buffer found\n", __func__); > @@ -479,6 +510,7 @@ static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_form > { > struct vpu_instance *inst = wave5_to_vpu_inst(fh); > const struct vpu_format *vpu_fmt; > + const struct v4l2_format_info *info; > int i, ret; > > dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n", > @@ -500,16 +532,20 @@ static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_form > inst->src_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage; > } > > - if (inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV12 || > - inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV12M) { > - inst->cbcr_interleave = true; > - inst->nv21 = false; > - } else if (inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV21 || > - inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV21M) { > - inst->cbcr_interleave = true; > + info = v4l2_format_info(inst->src_fmt.pixelformat); > + if (!info) > + return -EINVAL; > + > + inst->cbcr_interleave = (info->comp_planes == 2) ? true : false; > + > + switch (inst->src_fmt.pixelformat) { > + case V4L2_PIX_FMT_NV21: > + case V4L2_PIX_FMT_NV21M: > + case V4L2_PIX_FMT_NV61: > + case V4L2_PIX_FMT_NV61M: > inst->nv21 = true; > - } else { > - inst->cbcr_interleave = false; > + break; > + default: > inst->nv21 = false; > } > > @@ -1095,13 +1131,23 @@ static void wave5_vpu_enc_buf_queue(struct vb2_buffer *vb) > v4l2_m2m_buf_queue(m2m_ctx, vbuf); > } > > -static void wave5_set_enc_openparam(struct enc_open_param *open_param, > +static int wave5_set_enc_openparam(struct enc_open_param *open_param, > struct vpu_instance *inst) > { > struct enc_wave_param input = inst->enc_param; > + const struct v4l2_format_info *info; > u32 num_ctu_row = ALIGN(inst->dst_fmt.height, 64) / 64; > u32 num_mb_row = ALIGN(inst->dst_fmt.height, 16) / 16; > > + info = v4l2_format_info(inst->src_fmt.pixelformat); > + if (!info) > + return -EINVAL; > + > + if (info->hdiv == 2 && info->vdiv == 1) > + open_param->src_format = FORMAT_422; > + else > + open_param->src_format = FORMAT_420; > + > open_param->wave_param.gop_preset_idx = PRESET_IDX_IPP_SINGLE; > open_param->wave_param.hvs_qp_scale = 2; > open_param->wave_param.hvs_max_delta_qp = 10; > @@ -1190,6 +1236,8 @@ static void wave5_set_enc_openparam(struct enc_open_param *open_param, > open_param->wave_param.intra_refresh_arg = num_ctu_row; > } > open_param->wave_param.forced_idr_header_enable = input.forced_idr_header_enable; > + > + return 0; > } > > static int initialize_sequence(struct vpu_instance *inst) > @@ -1285,7 +1333,12 @@ static int wave5_vpu_enc_start_streaming(struct vb2_queue *q, unsigned int count > > memset(&open_param, 0, sizeof(struct enc_open_param)); > > - wave5_set_enc_openparam(&open_param, inst); > + ret = wave5_set_enc_openparam(&open_param, inst); > + if (ret) { > + dev_dbg(inst->dev->dev, "%s: wave5_set_enc_openparam, fail: %d\n", > + __func__, ret); > + goto return_buffers; > + } > > ret = wave5_vpu_enc_open(inst, &open_param); > if (ret) {
diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c index 75d230df45f6..3f148e1b0513 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c @@ -66,6 +66,24 @@ static const struct vpu_format enc_fmt_list[FMT_TYPES][MAX_FMTS] = { .v4l2_pix_fmt = V4L2_PIX_FMT_NV21M, .v4l2_frmsize = &enc_frmsize[VPU_FMT_TYPE_RAW], }, + { + .v4l2_pix_fmt = V4L2_PIX_FMT_YUV422P, + }, + { + .v4l2_pix_fmt = V4L2_PIX_FMT_NV16, + }, + { + .v4l2_pix_fmt = V4L2_PIX_FMT_NV61, + }, + { + .v4l2_pix_fmt = V4L2_PIX_FMT_YUV422M, + }, + { + .v4l2_pix_fmt = V4L2_PIX_FMT_NV16M, + }, + { + .v4l2_pix_fmt = V4L2_PIX_FMT_NV61M, + }, } }; @@ -109,13 +127,26 @@ static int start_encode(struct vpu_instance *inst, u32 *fail_res) struct vb2_v4l2_buffer *dst_buf; struct frame_buffer frame_buf; struct enc_param pic_param; - u32 stride = ALIGN(inst->dst_fmt.width, 32); - u32 luma_size = (stride * inst->dst_fmt.height); - u32 chroma_size = ((stride / 2) * (inst->dst_fmt.height / 2)); + const struct v4l2_format_info *info; + u32 stride = inst->src_fmt.plane_fmt[0].bytesperline; + u32 luma_size = 0; + u32 chroma_size = 0; memset(&pic_param, 0, sizeof(struct enc_param)); memset(&frame_buf, 0, sizeof(struct frame_buffer)); + info = v4l2_format_info(inst->src_fmt.pixelformat); + if (!info) + return -EINVAL; + + if (info->mem_planes == 1) { + luma_size = stride * inst->dst_fmt.height; + chroma_size = luma_size / (info->hdiv * info->vdiv); + } else { + luma_size = inst->src_fmt.plane_fmt[0].sizeimage; + chroma_size = inst->src_fmt.plane_fmt[1].sizeimage; + } + dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx); if (!dst_buf) { dev_dbg(inst->dev->dev, "%s: No destination buffer found\n", __func__); @@ -479,6 +510,7 @@ static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_form { struct vpu_instance *inst = wave5_to_vpu_inst(fh); const struct vpu_format *vpu_fmt; + const struct v4l2_format_info *info; int i, ret; dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n", @@ -500,16 +532,20 @@ static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_form inst->src_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage; } - if (inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV12 || - inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV12M) { - inst->cbcr_interleave = true; - inst->nv21 = false; - } else if (inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV21 || - inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV21M) { - inst->cbcr_interleave = true; + info = v4l2_format_info(inst->src_fmt.pixelformat); + if (!info) + return -EINVAL; + + inst->cbcr_interleave = (info->comp_planes == 2) ? true : false; + + switch (inst->src_fmt.pixelformat) { + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV21M: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_NV61M: inst->nv21 = true; - } else { - inst->cbcr_interleave = false; + break; + default: inst->nv21 = false; } @@ -1095,13 +1131,23 @@ static void wave5_vpu_enc_buf_queue(struct vb2_buffer *vb) v4l2_m2m_buf_queue(m2m_ctx, vbuf); } -static void wave5_set_enc_openparam(struct enc_open_param *open_param, +static int wave5_set_enc_openparam(struct enc_open_param *open_param, struct vpu_instance *inst) { struct enc_wave_param input = inst->enc_param; + const struct v4l2_format_info *info; u32 num_ctu_row = ALIGN(inst->dst_fmt.height, 64) / 64; u32 num_mb_row = ALIGN(inst->dst_fmt.height, 16) / 16; + info = v4l2_format_info(inst->src_fmt.pixelformat); + if (!info) + return -EINVAL; + + if (info->hdiv == 2 && info->vdiv == 1) + open_param->src_format = FORMAT_422; + else + open_param->src_format = FORMAT_420; + open_param->wave_param.gop_preset_idx = PRESET_IDX_IPP_SINGLE; open_param->wave_param.hvs_qp_scale = 2; open_param->wave_param.hvs_max_delta_qp = 10; @@ -1190,6 +1236,8 @@ static void wave5_set_enc_openparam(struct enc_open_param *open_param, open_param->wave_param.intra_refresh_arg = num_ctu_row; } open_param->wave_param.forced_idr_header_enable = input.forced_idr_header_enable; + + return 0; } static int initialize_sequence(struct vpu_instance *inst) @@ -1285,7 +1333,12 @@ static int wave5_vpu_enc_start_streaming(struct vb2_queue *q, unsigned int count memset(&open_param, 0, sizeof(struct enc_open_param)); - wave5_set_enc_openparam(&open_param, inst); + ret = wave5_set_enc_openparam(&open_param, inst); + if (ret) { + dev_dbg(inst->dev->dev, "%s: wave5_set_enc_openparam, fail: %d\n", + __func__, ret); + goto return_buffers; + } ret = wave5_vpu_enc_open(inst, &open_param); if (ret) {