[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <eb27753cd92fea1f12663336ab0d824977ae5887.camel@mediatek.com>
Date: Mon, 6 Jan 2025 06:58:01 +0000
From: Yunfei Dong (董云飞) <Yunfei.Dong@...iatek.com>
To: "sebastian.fricke@...labora.com" <sebastian.fricke@...labora.com>
CC: "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"linux-mediatek@...ts.infradead.org" <linux-mediatek@...ts.infradead.org>,
"frkoenig@...omium.org" <frkoenig@...omium.org>, "stevecho@...omium.org"
<stevecho@...omium.org>, "nhebert@...omium.org" <nhebert@...omium.org>,
"linux-media@...r.kernel.org" <linux-media@...r.kernel.org>,
"devicetree@...r.kernel.org" <devicetree@...r.kernel.org>,
"nicolas.dufresne@...labora.com" <nicolas.dufresne@...labora.com>,
"daniel.almeida@...labora.com" <daniel.almeida@...labora.com>,
"daniel@...ll.ch" <daniel@...ll.ch>, Project_Global_Chrome_Upstream_Group
<Project_Global_Chrome_Upstream_Group@...iatek.com>,
"benjamin.gaignard@...labora.com" <benjamin.gaignard@...labora.com>,
"hverkuil-cisco@...all.nl" <hverkuil-cisco@...all.nl>,
"linux-arm-kernel@...ts.infradead.org"
<linux-arm-kernel@...ts.infradead.org>, "hsinyi@...omium.org"
<hsinyi@...omium.org>, AngeloGioacchino Del Regno
<angelogioacchino.delregno@...labora.com>, Nicolas Prado
<nfraprado@...labora.com>
Subject: Re: [PATCH v6 2/3] media: mediatek: vcodec: support extended h264
decode
Hi Sebastian,
Thanks for your advice.
On Wed, 2024-12-11 at 14:17 +0100, Sebastian Fricke wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> Hey Yunfei,
>
> On 16.11.2024 11:16, Yunfei Dong wrote:
> > The address end of working buffer can't be calculated directly with
> > buffer
> > size in kernel for some special architecture. Adding new extend
> > vsi_ex to
> > calculate the address end in firmware.
> > Adding capability to separate extend and non extend driver for
> > different
> > platform.
> > At last, hardware can parse the syntax to get nal information in
> > firmware
> > for extend architecture, needn't to parse it again in kernel.
>
> I'd recommend changing this to:
>
> Add a new extended vsi_ext struct besides the existing vsi struct, to
> enable calculating the end of the adress range of the current working
> buffer for architectures, where simply adding the buffer size to the
> start of the address range isn't sufficient.
> Additionally, on extended architectures, the NAL information can be
> fetched directly from the firmware, which allows skipping the parsing
> step within the kernel.
>
> Also, this sentence:
> > Adding capability to separate extend and non extend driver for
> > different
> > platform.
>
> Is a bit ambigious for me and doesn't seem to be something worth
> mentioning. But maybe I misunderstand your point here.
>
> >
> > Signed-off-by: Yunfei Dong <yunfei.dong@...iatek.com>
> > Reviewed-by: AngeloGioacchino Del Regno <
> > angelogioacchino.delregno@...labora.com>
> > ---
> > .../vcodec/decoder/mtk_vcodec_dec_drv.h | 2 +
> > .../decoder/vdec/vdec_h264_req_multi_if.c | 575
> > ++++++++++++++++--
> > 2 files changed, 518 insertions(+), 59 deletions(-)
> >
> > diff --git
> > a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv
> > .h
> > b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv
> > .h
> > index ac568ed14fa2..a0bb23962209 100644
> > ---
> > a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv
> > .h
> > +++
> > b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv
> > .h
> > @@ -17,6 +17,7 @@
> >
> > #define IS_VDEC_LAT_ARCH(hw_arch) ((hw_arch) >=
> > MTK_VDEC_LAT_SINGLE_CORE)
> > #define IS_VDEC_INNER_RACING(capability) ((capability) &
> > MTK_VCODEC_INNER_RACING)
> > +#define IS_VDEC_SUPPORT_EX(capability) ((capability) &
> > MTK_VDEC_IS_SUPPORT_EX)
>
> I'd recommend changing this to: IS_VDEC_SUPPORT_EXT as EXT is way
> less
> ambigious acronym for extension, EX could mean way more.
> You'll see me mentioning that below a couple of times.
>
> >
> > enum mtk_vcodec_dec_chip_name {
> > MTK_VDEC_INVAL = 0,
> > @@ -42,6 +43,7 @@ enum mtk_vdec_format_types {
> > MTK_VDEC_FORMAT_HEVC_FRAME = 0x1000,
> > MTK_VCODEC_INNER_RACING = 0x20000,
> > MTK_VDEC_IS_SUPPORT_10BIT = 0x40000,
> > + MTK_VDEC_IS_SUPPORT_EX = 0x80000,
> > };
> >
> > /*
> > diff --git
> > a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req
> > _multi_if.c
> > b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req
> > _multi_if.c
> > index ab192ce0b851..a7de95b9a7c0 100644
> > ---
> > a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req
> > _multi_if.c
> > +++
> > b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req
> > _multi_if.c
> > @@ -128,6 +128,83 @@ struct vdec_h264_slice_share_info {
> > u16 nal_info;
> > };
> >
> > +/*
> > + * struct vdec_h264_slice_mem - memory address and size (shared
> > interface with firmware)
> > + */
> > +struct vdec_h264_slice_mem {
> > + union {
> > + u64 buf;
> > + u64 dma_addr;
> > + };
> > + union {
> > + size_t size;
> > + u64 dma_addr_end;
> > + };
> > +};
> > +
> > +/**
> > + * struct vdec_h264_slice_fb - frame buffer for decoding (shared
> > interface with firmware)
> > + *
> > + * @y: current y buffer address info
>
> As this is a description I'd say lets describe a bit more detailed
> and
> rewrite this to: "@y: current luma buffer address info"
>
>
> > + * @c: current c buffer address info
>
> ... and "@c: current chroma buffer address info"
>
> > + */
> > +struct vdec_h264_slice_fb {
> > + struct vdec_h264_slice_mem y;
> > + struct vdec_h264_slice_mem c;
> > +};
> > +
> > +/**
> > + * struct vdec_h264_slice_info_ex - extend decode information
> > (shared interface with firmware)
>
> Can we call this also ..info_ext please?
>
> > + *
> > + * @wdma_end_addr_offset: offset from buffer start
> > + * @nal_info: nal info of current picture
> > + * @timeout: Decode timeout: 1 timeout, 0 no
> > timeout
>
> I'd rename the description to: "Toggles whether a decode operation
> can timeout"
> Then the effect of 1 and 0 becomes obvious.
>
> > + * @reserved: reserved
> > + * @vdec_fb_va: VDEC frame buffer struct virtual
> > address
> > + * @crc: Used to check whether hardware's
> > status is right
>
> I'd rename this to: "Displays the hardware status"
> Saying whether a status is "right" is rather ambigious.
>
> > + */
> > +struct vdec_h264_slice_info_ex {
>
> ... and this ... info_ext
>
> > + u64 wdma_end_addr_offset;
> > + u16 nal_info;
> > + u16 timeout;
> > + u32 reserved;
> > + u64 vdec_fb_va;
> > + u32 crc[8];
> > +};
> > +
> > +/**
> > + * struct vdec_h264_slice_vsi_ex - extend shared memory for decode
> > information exchange
>
> s/vsi_ex/vsi_ext/
>
> > + * between SCP and Host (shared interface with firmware).
> > + *
> > + * @bs: input buffer info
> > + * @fb: current y/c buffer
> > + *
> > + * @ube: ube buffer
>
> While we are at it and this acronym isn't terrible self-descriptive
> could you write in the description what ube stands for?
I can rewrite the description to: ube is a buffer used to share date
between two hardware.
>
> > + * @trans: transcoded buffer
> > + * @row_info: row info buffer
> > + * @err_map: err map buffer
> > + * @slice_bc: slice buffer
> > + *
> > + * @mv_buf_dma: HW working motion vector buffer
>
> HW working sounds weird, do you want to say the current?
>
> > + * @dec: decode information (AP-R, VPU-W)
> > + * @h264_slice_params: decode parameters for hw used
>
> s/for hw used/used for the hw/
>
> > + */
> > +struct vdec_h264_slice_vsi_ex {
>
> s/vsi_ex/vsi_ext/
>
> > + /* LAT dec addr */
> > + struct vdec_h264_slice_mem bs;
> > + struct vdec_h264_slice_fb fb;
> > +
> > + struct vdec_h264_slice_mem ube;
> > + struct vdec_h264_slice_mem trans;
> > + struct vdec_h264_slice_mem row_info;
> > + struct vdec_h264_slice_mem err_map;
> > + struct vdec_h264_slice_mem slice_bc;
> > +
> > + struct vdec_h264_slice_mem mv_buf_dma[H264_MAX_MV_NUM];
> > + struct vdec_h264_slice_info_ex dec;
>
> s/info_ex/info_ext/
>
> > + struct vdec_h264_slice_lat_dec_param h264_slice_params;
> > +};
> > +
> > /**
> > * struct vdec_h264_slice_inst - h264 decoder instance
> > *
> > @@ -138,8 +215,10 @@ struct vdec_h264_slice_share_info {
> > * @vpu: VPU instance
> > * @vsi: vsi used for lat
> > * @vsi_core: vsi used for core
> > - *
> > - * @vsi_ctx: Local VSI data for this decoding context
> > + * @vsi_ctx: Local vsi data for this decoding context
> > + * @vsi_ex: extend vsi used for lat
>
> s/vsi_ex/vsi_ext/
> s/extend/extended/
>
> > + * @vsi_core_ex: extend vsi used for core
>
> s/vsi_core_ex/vsi_core_ext/
> s/extend/extended/
>
> > + * @vsi_ctx_ex: Local extend vsi data for this decoding
> > context
>
> s/vsi_ctx_ex/vsi_ctx_ext/
> s/extend/extended/
>
> Also you can drop the word Local as that is clear already with:
> "for this decoding context"
>
> > * @h264_slice_param: the parameters that hardware use to decode
> > *
> > * @resolution_changed:resolution changed
> > @@ -148,7 +227,9 @@ struct vdec_h264_slice_share_info {
> > *
> > * @dpb: decoded picture buffer used to store
> > reference
> > * buffer information
> > - *@...field_bitstream: is field bitstream
> > + * @is_field_bitstream: is field bitstream
>
> That is not a description, that is a repetition :)
> Please make this a bit more descriptive. Like do you describe
> anywhere
> else already what a field bitstream is and how it differentiates from
> the alternative?
>
bitstream can be field / frame or adapt field frame. The driver only
support frame decode.
> > + *
> > + * @decode: lat decoder pointer for different
> > architecture
>
> s/architecture/architectures/
>
> > */
> > struct vdec_h264_slice_inst {
> > unsigned int slice_dec_num;
> > @@ -156,10 +237,18 @@ struct vdec_h264_slice_inst {
> > struct mtk_vcodec_mem pred_buf;
> > struct mtk_vcodec_mem mv_buf[H264_MAX_MV_NUM];
> > struct vdec_vpu_inst vpu;
> > - struct vdec_h264_slice_vsi *vsi;
> > - struct vdec_h264_slice_vsi *vsi_core;
> > -
> > - struct vdec_h264_slice_vsi vsi_ctx;
> > + union {
> > + struct {
> > + struct vdec_h264_slice_vsi *vsi;
> > + struct vdec_h264_slice_vsi *vsi_core;
> > + struct vdec_h264_slice_vsi vsi_ctx;
> > + };
> > + struct {
> > + struct vdec_h264_slice_vsi_ex *vsi_ex;
> > + struct vdec_h264_slice_vsi_ex *vsi_core_ex;
> > + struct vdec_h264_slice_vsi_ex vsi_ctx_ex;
>
> s/vsi_ex/vsi_ext/
> s/vsi_core_ex/vsi_core_ext/
> s/vsi_ctx_ex/vsi_ctx_ext/
>
> > + };
> > + };
> > struct vdec_h264_slice_lat_dec_param h264_slice_param;
> >
> > unsigned int resolution_changed;
> > @@ -168,6 +257,9 @@ struct vdec_h264_slice_inst {
> >
> > struct v4l2_h264_dpb_entry dpb[16];
> > bool is_field_bitstream;
> > +
> > + int (*decode)(void *h_vdec, struct mtk_vcodec_mem *bs,
> > + struct vdec_fb *unused, bool *res_chg);
> > };
> >
> > static int vdec_h264_slice_fill_decode_parameters(struct
> > vdec_h264_slice_inst *inst,
> > @@ -389,62 +481,143 @@ static void
> > vdec_h264_slice_get_crop_info(struct vdec_h264_slice_inst *inst,
> > cr->left, cr->top, cr->width, cr->height);
> > }
> >
> > -static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx *ctx)
> > +static void vdec_h264_slice_setup_lat_buffer_ex(struct
> > vdec_h264_slice_inst *inst,
>
> s/buffer_ex/buffer_ext/
>
> > + struct
> > mtk_vcodec_mem *bs,
> > + struct vdec_lat_buf
> > *lat_buf)
> > {
> > - struct vdec_h264_slice_inst *inst;
> > - int err, vsi_size;
> > + struct mtk_vcodec_mem *mem;
> > + int i;
> >
> > - inst = kzalloc(sizeof(*inst), GFP_KERNEL);
> > - if (!inst)
> > - return -ENOMEM;
> > + inst->vsi_ex->bs.dma_addr = (u64)bs->dma_addr;
> > + inst->vsi_ex->bs.size = bs->size;
> >
> > - inst->ctx = ctx;
> > + for (i = 0; i < H264_MAX_MV_NUM; i++) {
> > + mem = &inst->mv_buf[i];
> > + inst->vsi_ex->mv_buf_dma[i].dma_addr = mem-
> > >dma_addr;
>
> s/vsi_ex/vsi_ext/
> and in all other cases below ...
>
> > + inst->vsi_ex->mv_buf_dma[i].size = mem->size;
> > + }
> > + inst->vsi_ex->ube.dma_addr = lat_buf->ctx-
> > >msg_queue.wdma_addr.dma_addr;
> > + inst->vsi_ex->ube.size = lat_buf->ctx-
> > >msg_queue.wdma_addr.size;
> >
> > - inst->vpu.id = SCP_IPI_VDEC_LAT;
> > - inst->vpu.core_id = SCP_IPI_VDEC_CORE;
> > - inst->vpu.ctx = ctx;
> > - inst->vpu.codec_type = ctx->current_codec;
> > - inst->vpu.capture_type = ctx->capture_fourcc;
> > + inst->vsi_ex->row_info.dma_addr = 0;
> > + inst->vsi_ex->row_info.size = 0;
> >
> > - err = vpu_dec_init(&inst->vpu);
> > - if (err) {
> > - mtk_vdec_err(ctx, "vdec_h264 init err=%d", err);
> > - goto error_free_inst;
> > + inst->vsi_ex->err_map.dma_addr = lat_buf-
> > >wdma_err_addr.dma_addr;
> > + inst->vsi_ex->err_map.size = lat_buf->wdma_err_addr.size;
> > +
> > + inst->vsi_ex->slice_bc.dma_addr = lat_buf-
> > >slice_bc_addr.dma_addr;
> > + inst->vsi_ex->slice_bc.size = lat_buf->slice_bc_addr.size;
> > +
> > + inst->vsi_ex->trans.dma_addr_end = inst->ctx-
> > >msg_queue.wdma_rptr_addr;
> > + inst->vsi_ex->trans.dma_addr = inst->ctx-
> > >msg_queue.wdma_wptr_addr;
> > +}
> > +
> > +static int vdec_h264_slice_setup_core_buffer_ex(struct
> > vdec_h264_slice_inst *inst,
>
> s/buffer_ex/buffer_ext/
Will fix all.
>
> > + struct
> > vdec_h264_slice_share_info *share_info,
> > + struct vdec_lat_buf
> > *lat_buf)
> > +{
> > + struct mtk_vcodec_mem *mem;
> > + struct mtk_vcodec_dec_ctx *ctx = inst->ctx;
> > + struct vb2_v4l2_buffer *vb2_v4l2;
> > + struct vdec_fb *fb;
> > + u64 y_fb_dma, c_fb_dma = 0;
> > + int i;
> > +
> > + fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx);
> > + if (!fb) {
> > + mtk_vdec_err(ctx, "fb buffer is NULL");
>
> A frame buffer buffer sounds a bit repetitive, lets just call it
> frame
> buffer. Also this error message tells the user nothing. When I look
> at
> the function within `mtk_vcodec_dec_stateless` it looks like the only
> way we get a NULL here is if `v4l2_m2m_next_dst_buf` returns nothing,
> e.g. if we don't have a next destination buffer. Can you confirm
> this?
> If that is the case a better error message would be:
> "Unable to get a CAPTURE buffer, because the CAPTURE queue is empty"
> Or something along those lines.
>
I will change the error message.
> > + return -EBUSY;
> > }
> >
> > - vsi_size = round_up(sizeof(struct vdec_h264_slice_vsi),
> > VCODEC_DEC_ALIGNED_64);
> > - inst->vsi = inst->vpu.vsi;
> > - inst->vsi_core =
> > - (struct vdec_h264_slice_vsi *)(((char *)inst-
> > >vpu.vsi) + vsi_size);
> > - inst->resolution_changed = true;
> > - inst->realloc_mv_buf = true;
> > + y_fb_dma = (u64)fb->base_y.dma_addr;
> > + if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1)
> > + c_fb_dma =
> > + y_fb_dma + inst->ctx->picinfo.buf_w * inst-
> > >ctx->picinfo.buf_h;
>
> Looks like it is worth it to create a separate variable for picinfo
> as
> you use it here and below, so that you can do a bit less copy-paste.
>
Will fix.
> > + else
> > + c_fb_dma = (u64)fb->base_c.dma_addr;
> >
> > - mtk_vdec_debug(ctx, "lat struct size = %d,%d,%d,%d vsi:
> > %d\n",
> > - (int)sizeof(struct mtk_h264_sps_param),
> > - (int)sizeof(struct mtk_h264_pps_param),
> > - (int)sizeof(struct
> > vdec_h264_slice_lat_dec_param),
> > - (int)sizeof(struct mtk_h264_dpb_info),
> > - vsi_size);
> > - mtk_vdec_debug(ctx, "lat H264 instance >> %p, codec_type =
> > 0x%x",
> > - inst, inst->vpu.codec_type);
> > + mtk_vdec_debug(ctx, "[h264-core] y/c addr = 0x%llx 0x%llx",
> > y_fb_dma, c_fb_dma);
> >
> > - ctx->drv_handle = inst;
> > - return 0;
> > + inst->vsi_core_ex->fb.y.dma_addr = y_fb_dma;
>
> s/vsi_core_ex/vsi_core_ext/
> and everywhere below ...
>
> > + inst->vsi_core_ex->fb.y.size = ctx->picinfo.fb_sz[0];
> > + inst->vsi_core_ex->fb.c.dma_addr = c_fb_dma;
> > + inst->vsi_core_ex->fb.c.size = ctx->picinfo.fb_sz[1];
> >
> > -error_free_inst:
> > - kfree(inst);
> > - return err;
> > + inst->vsi_core_ex->dec.vdec_fb_va = (unsigned long)fb;
> > + inst->vsi_core_ex->dec.nal_info = share_info->nal_info;
> > +
> > + inst->vsi_core_ex->ube.dma_addr = lat_buf->ctx-
> > >msg_queue.wdma_addr.dma_addr;
> > + inst->vsi_core_ex->ube.size = lat_buf->ctx-
> > >msg_queue.wdma_addr.size;
> > +
> > + inst->vsi_core_ex->err_map.dma_addr = lat_buf-
> > >wdma_err_addr.dma_addr;
> > + inst->vsi_core_ex->err_map.size = lat_buf-
> > >wdma_err_addr.size;
> > +
> > + inst->vsi_core_ex->slice_bc.dma_addr = lat_buf-
> > >slice_bc_addr.dma_addr;
> > + inst->vsi_core_ex->slice_bc.size = lat_buf-
> > >slice_bc_addr.size;
> > +
> > + inst->vsi_core_ex->row_info.dma_addr = 0;
> > + inst->vsi_core_ex->row_info.size = 0;
> > +
> > + inst->vsi_core_ex->trans.dma_addr = share_info->trans_start;
> > + inst->vsi_core_ex->trans.dma_addr_end = share_info-
> > >trans_end;
> > +
> > + for (i = 0; i < H264_MAX_MV_NUM; i++) {
> > + mem = &inst->mv_buf[i];
> > + inst->vsi_core_ex->mv_buf_dma[i].dma_addr = mem-
> > >dma_addr;
> > + inst->vsi_core_ex->mv_buf_dma[i].size = mem->size;
> > + }
> > +
> > + vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
> > + v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, vb2_v4l2,
> > true);
> > +
> > + return 0;
> > }
> >
> > -static void vdec_h264_slice_deinit(void *h_vdec)
> > +static int vdec_h264_slice_core_decode_ex(struct vdec_lat_buf
> > *lat_buf)
>
> s/decode_ex/decode_ext/
>
> No no no, I don't like this or vdec_h264_slice_lat_decode_ex you
> basically just duplicated the whole decode function in both cases and
> added a few extended bits to them. Unless the two routines are
> substantially different (which from my point of view they are not)
> you
> should be able to create conditional branches for the extended bits
> into
> the decode functions.
>
> But please also look at my general comments in the functions, I'd
> still
> like to know why timeouts are handled the way they are and whether
> the
> status of a device can be made a bit more obvious to the user.
>
1: single decode and lat single decode (lat + core) are different
architectures.
2: The vsi is different for extend and non extend, need to fill
different parameters for vsi and vsi_ext. There are many if...else..
to separate vsi ane vsi_ext if the driver only use one function core
decoder and one function lat decode.
> > {
> > - struct vdec_h264_slice_inst *inst = h_vdec;
> > + int err, timeout;
> > + struct mtk_vcodec_dec_ctx *ctx = lat_buf->ctx;
> > + struct vdec_h264_slice_inst *inst = ctx->drv_handle;
> > + struct vdec_h264_slice_share_info *share_info = lat_buf-
> > >private_data;
> > + struct vdec_vpu_inst *vpu = &inst->vpu;
> >
> > - vpu_dec_deinit(&inst->vpu);
> > - vdec_h264_slice_free_mv_buf(inst);
> > - vdec_msg_queue_deinit(&inst->ctx->msg_queue, inst->ctx);
> > + mtk_vdec_debug(ctx, "[h264-core] vdec_h264 core decode");
>
> This looks like a left over development comment, this is not useful
> for
> general debugging and shouldn't be upstreamed.
>
> > + memcpy(&inst->vsi_core_ex->h264_slice_params, &share_info-
> > >h264_slice_params,
> > + sizeof(share_info->h264_slice_params));
> >
> > - kfree(inst);
> > + err = vdec_h264_slice_setup_core_buffer_ex(inst, share_info,
> > lat_buf);
>
> s/buffer_ex/buffer_ext/
>
> > + if (err)
> > + goto vdec_dec_end;
> > +
> > + vdec_h264_slice_fill_decode_reflist(inst, &inst-
> > >vsi_core_ex->h264_slice_params,
> > + share_info);
> > + err = vpu_dec_core(vpu);
> > + if (err) {
> > + mtk_vdec_err(ctx, "core decode err=%d", err);
> > + goto vdec_dec_end;
> > + }
> > +
> > + /* wait decoder done interrupt */
> > + timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx,
> > MTK_INST_IRQ_RECEIVED,
> > + WAIT_INTR_TIMEOUT_MS,
> > MTK_VDEC_CORE);
> > + if (timeout)
> > + mtk_vdec_err(ctx, "core decode timeout: pic_%d",
> > ctx->decoded_frame_cnt);
>
> So as you don't bail out here, it looks like this conditional branch
> will end up returning 0. Why do you return 0 on a timeout? Isn't a
> timeout a failed decode?
If core decode timeout, the core can re-decode next frame, may show
garbage or green picture, if lat decode timeout. It's mean the input
data must be not correctly.
>
> > + inst->vsi_core_ex->dec.timeout = !!timeout;
> > +
> > + vpu_dec_core_end(vpu);
> > + mtk_vdec_debug(ctx, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x 0x%x
> > 0x%x 0x%x 0x%x",
> > + ctx->decoded_frame_cnt,
> > + inst->vsi_core_ex->dec.crc[0], inst-
> > >vsi_core_ex->dec.crc[1],
> > + inst->vsi_core_ex->dec.crc[2], inst-
> > >vsi_core_ex->dec.crc[3],
> > + inst->vsi_core_ex->dec.crc[4], inst-
> > >vsi_core_ex->dec.crc[5],
> > + inst->vsi_core_ex->dec.crc[6], inst-
> > >vsi_core_ex->dec.crc[7]);
>
> Can you add a small comment above this that explains to the user what
> these CRCs are supposed to mean?
crc is just hardware checksume used for debug, I can add.
>
> > +
> > +vdec_dec_end:
> > + vdec_msg_queue_update_ube_rptr(&lat_buf->ctx->msg_queue,
> > share_info->trans_end);
> > + ctx->dev->vdec_pdata->cap_to_disp(ctx, !!err, lat_buf-
> > >src_buf_req);
> > + mtk_vdec_debug(ctx, "core decode done err=%d", err);
> > + ctx->decoded_frame_cnt++;
> > + return 0;
> > }
> >
> > static int vdec_h264_slice_core_decode(struct vdec_lat_buf
> > *lat_buf)
> > @@ -559,6 +732,127 @@ static void vdec_h264_insert_startcode(struct
> > mtk_vcodec_dec_dev *vcodec_dev, un
> > (*bs_size) += 4;
> > }
> >
> > +static int vdec_h264_slice_lat_decode_ex(void *h_vdec, struct
> > mtk_vcodec_mem *bs,
> > + struct vdec_fb *fb, bool
> > *res_chg)
> > +{
> > + struct vdec_h264_slice_inst *inst = h_vdec;
> > + struct vdec_vpu_inst *vpu = &inst->vpu;
> > + struct mtk_video_dec_buf *src_buf_info;
> > + int err, timeout = 0;
> > + unsigned int data[2];
> > + struct vdec_lat_buf *lat_buf;
> > + struct vdec_h264_slice_share_info *share_info;
> > +
> > + if (vdec_msg_queue_init(&inst->ctx->msg_queue, inst->ctx,
> > + vdec_h264_slice_core_decode_ex,
> > + sizeof(*share_info)))
> > + return -ENOMEM;
> > +
> > + /* bs NULL means flush decoder */
> > + if (!bs) {
> > + vdec_msg_queue_wait_lat_buf_full(&inst->ctx-
> > >msg_queue);
> > + return vpu_dec_reset(vpu);
> > + }
> > +
> > + if (inst->is_field_bitstream)
> > + return -EINVAL;
> > +
> > + lat_buf = vdec_msg_queue_dqbuf(&inst->ctx-
> > >msg_queue.lat_ctx);
> > + if (!lat_buf) {
> > + mtk_vdec_debug(inst->ctx, "failed to get lat
> > buffer");
> > + return -EAGAIN;
> > + }
> > + share_info = lat_buf->private_data;
> > + src_buf_info = container_of(bs, struct mtk_video_dec_buf,
> > bs_buffer);
> > +
> > + lat_buf->src_buf_req = src_buf_info-
> > >m2m_buf.vb.vb2_buf.req_obj.req;
> > + v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb,
> > &lat_buf->ts_info, true);
> > +
> > + err = vdec_h264_slice_fill_decode_parameters(inst,
> > share_info,
> > + &inst->vsi_ex-
> > >h264_slice_params);
> > + if (err)
> > + goto err_free_fb_out;
> > +
> > + vdec_h264_insert_startcode(inst->ctx->dev, bs->va, &bs-
> > >size,
> > + &share_info-
> > >h264_slice_params.pps);
> > +
> > + *res_chg = inst->resolution_changed;
> > + if (inst->resolution_changed) {
> > + mtk_vdec_debug(inst->ctx, "- resolution changed -");
> > + if (inst->realloc_mv_buf) {
> > + err = vdec_h264_slice_alloc_mv_buf(inst,
> > &inst->ctx->picinfo);
> > + inst->realloc_mv_buf = false;
> > + if (err)
> > + goto err_free_fb_out;
> > + }
> > + inst->resolution_changed = false;
> > + }
> > +
> > + vdec_h264_slice_setup_lat_buffer_ex(inst, bs, lat_buf);
> > + mtk_vdec_debug(inst->ctx, "lat:trans(0x%llx 0x%lx)
> > err:0x%llx",
> > + inst->vsi_ex->ube.dma_addr, (unsigned
> > long)inst->vsi_ex->ube.size,
> > + inst->vsi_ex->err_map.dma_addr);
> > +
> > + mtk_vdec_debug(inst->ctx, "slice(0x%llx 0x%lx) rprt((0x%llx
> > 0x%llx))",
> > + inst->vsi_ex->slice_bc.dma_addr, (unsigned
> > long)inst->vsi_ex->slice_bc.size,
> > + inst->vsi_ex->trans.dma_addr, inst->vsi_ex-
> > >trans.dma_addr_end);
> > +
> > + err = vpu_dec_start(vpu, data, 2);
> > + if (err) {
> > + mtk_vdec_debug(inst->ctx, "lat decode err: %d",
> > err);
> > + goto err_free_fb_out;
> > + }
> > +
> > + share_info->trans_end = inst->ctx-
> > >msg_queue.wdma_addr.dma_addr +
> > + inst->vsi_ex->dec.wdma_end_addr_offset;
> > +
> > + share_info->trans_start = inst->ctx-
> > >msg_queue.wdma_wptr_addr;
> > + share_info->nal_info = inst->vsi_ex->dec.nal_info;
> > +
> > + if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
> > + memcpy(&share_info->h264_slice_params, &inst-
> > >vsi_ex->h264_slice_params,
> > + sizeof(share_info->h264_slice_params));
> > + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx,
> > lat_buf);
> > + }
> > +
> > + /* wait decoder done interrupt */
> > + timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx,
> > MTK_INST_IRQ_RECEIVED,
> > + WAIT_INTR_TIMEOUT_MS,
> > MTK_VDEC_LAT0);
> > + if (timeout)
> > + mtk_vdec_err(inst->ctx, "lat decode timeout:
> > pic_%d", inst->slice_dec_num);
> > + inst->vsi_ex->dec.timeout = !!timeout;
> > +
> > + err = vpu_dec_end(vpu);
> > + if (err == SLICE_HEADER_FULL || err == TRANS_BUFFER_FULL) {
> > + if (!IS_VDEC_INNER_RACING(inst->ctx->dev-
> > >dec_capability))
> > + vdec_msg_queue_qbuf(&inst->ctx-
> > >msg_queue.lat_ctx, lat_buf);
> > + inst->slice_dec_num++;
> > + mtk_vdec_err(inst->ctx, "lat dec fail: pic_%d
> > err:%d", inst->slice_dec_num, err);
> > + return -EINVAL;
> > + }
> > +
> > + share_info->trans_end = inst->ctx-
> > >msg_queue.wdma_addr.dma_addr +
> > + inst->vsi_ex->dec.wdma_end_addr_offset;
> > +
> > + vdec_msg_queue_update_ube_wptr(&lat_buf->ctx->msg_queue,
> > share_info->trans_end);
> > +
> > + if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
> > + memcpy(&share_info->h264_slice_params, &inst-
> > >vsi_ex->h264_slice_params,
> > + sizeof(share_info->h264_slice_params));
> > + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx,
> > lat_buf);
> > + }
> > + mtk_vdec_debug(inst->ctx, "dec num: %d lat crc: 0x%x 0x%x
> > 0x%x", inst->slice_dec_num,
> > + inst->vsi_ex->dec.crc[0], inst->vsi_ex-
> > >dec.crc[1],
> > + inst->vsi_ex->dec.crc[2]);
> > +
> > + inst->slice_dec_num++;
> > + return 0;
> > +err_free_fb_out:
> > + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf);
> > + mtk_vdec_err(inst->ctx, "slice dec number: %d err: %d",
> > inst->slice_dec_num, err);
> > + return err;
> > +}
> > +
> > static int vdec_h264_slice_lat_decode(void *h_vdec, struct
> > mtk_vcodec_mem *bs,
> > struct vdec_fb *fb, bool
> > *res_chg)
> > {
> > @@ -704,18 +998,17 @@ static int vdec_h264_slice_lat_decode(void
> > *h_vdec, struct mtk_vcodec_mem *bs,
> > return err;
> > }
> >
> > -static int vdec_h264_slice_single_decode(void *h_vdec, struct
> > mtk_vcodec_mem *bs,
> > - struct vdec_fb *unused,
> > bool *res_chg)
> > +static int vdec_h264_slice_single_decode_ex(void *h_vdec, struct
> > mtk_vcodec_mem *bs,
>
> s/decode_ex/decode_ext/
>
> > + struct vdec_fb *unused,
> > bool *res_chg)
> > {
> > struct vdec_h264_slice_inst *inst = h_vdec;
> > struct vdec_vpu_inst *vpu = &inst->vpu;
> > struct mtk_video_dec_buf *src_buf_info, *dst_buf_info;
> > struct vdec_fb *fb;
> > - unsigned char *buf;
> > unsigned int data[2], i;
> > u64 y_fb_dma, c_fb_dma;
> > struct mtk_vcodec_mem *mem;
> > - int err, nal_start_idx;
> > + int err;
> >
> > /* bs NULL means flush decoder */
> > if (!bs)
> > @@ -735,6 +1028,96 @@ static int vdec_h264_slice_single_decode(void
> > *h_vdec, struct mtk_vcodec_mem *bs
> > mtk_vdec_debug(inst->ctx, "[h264-dec] [%d] y_dma=%llx
> > c_dma=%llx",
> > inst->ctx->decoded_frame_cnt, y_fb_dma,
> > c_fb_dma);
> >
> > + inst->vsi_ctx_ex.bs.dma_addr = (u64)bs->dma_addr;
> > + inst->vsi_ctx_ex.bs.size = bs->size;
> > + inst->vsi_ctx_ex.fb.y.dma_addr = y_fb_dma;
> > + inst->vsi_ctx_ex.fb.c.dma_addr = c_fb_dma;
> > + inst->vsi_ctx_ex.dec.vdec_fb_va = (u64)(uintptr_t)fb;
> > +
> > + v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb,
> > + &dst_buf_info->m2m_buf.vb, true);
> > + err = get_vdec_sig_decode_parameters(inst);
> > + if (err)
> > + goto err_free_fb_out;
> > +
> > + memcpy(&inst->vsi_ctx_ex.h264_slice_params, &inst-
> > >h264_slice_param,
> > + sizeof(inst->vsi_ctx_ex.h264_slice_params));
> > +
> > + *res_chg = inst->resolution_changed;
> > + if (inst->resolution_changed) {
> > + mtk_vdec_debug(inst->ctx, "- resolution changed -");
> > + if (inst->realloc_mv_buf) {
> > + err = vdec_h264_slice_alloc_mv_buf(inst,
> > &inst->ctx->picinfo);
> > + inst->realloc_mv_buf = false;
> > + if (err)
> > + goto err_free_fb_out;
> > + }
> > + inst->resolution_changed = false;
> > +
> > + for (i = 0; i < H264_MAX_MV_NUM; i++) {
> > + mem = &inst->mv_buf[i];
> > + inst->vsi_ctx_ex.mv_buf_dma[i].dma_addr =
> > mem->dma_addr;
> > + }
> > + }
> > +
> > + memcpy(inst->vpu.vsi, &inst->vsi_ctx_ex, sizeof(inst-
> > >vsi_ctx_ex));
> > + err = vpu_dec_start(vpu, data, 2);
> > + if (err)
> > + goto err_free_fb_out;
> > +
> > + /* wait decoder done interrupt */
> > + err = mtk_vcodec_wait_for_done_ctx(inst->ctx,
> > MTK_INST_IRQ_RECEIVED,
> > + WAIT_INTR_TIMEOUT_MS,
> > MTK_VDEC_CORE);
> > + if (err)
> > + mtk_vdec_err(inst->ctx, "decode timeout: pic_%d",
> > inst->ctx->decoded_frame_cnt);
> > +
> > + inst->vsi_ex->dec.timeout = !!err;
> > + err = vpu_dec_end(vpu);
> > + if (err)
> > + goto err_free_fb_out;
> > +
> > + memcpy(&inst->vsi_ctx_ex, inst->vpu.vsi, sizeof(inst-
> > >vsi_ctx_ex));
> > + mtk_vdec_debug(inst->ctx, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x
> > 0x%x 0x%x 0x%x 0x%x",
> > + inst->ctx->decoded_frame_cnt,
> > + inst->vsi_ctx_ex.dec.crc[0], inst-
> > >vsi_ctx_ex.dec.crc[1],
> > + inst->vsi_ctx_ex.dec.crc[2], inst-
> > >vsi_ctx_ex.dec.crc[3],
> > + inst->vsi_ctx_ex.dec.crc[4], inst-
> > >vsi_ctx_ex.dec.crc[5],
> > + inst->vsi_ctx_ex.dec.crc[6], inst-
> > >vsi_ctx_ex.dec.crc[7]);
> > +
> > + inst->ctx->decoded_frame_cnt++;
> > + return 0;
> > +
> > +err_free_fb_out:
> > + mtk_vdec_err(inst->ctx, "dec frame number: %d err: %d",
> > inst->ctx->decoded_frame_cnt, err);
> > + return err;
> > +}
> > +
> > +static int vdec_h264_slice_single_decode(void *h_vdec, struct
> > mtk_vcodec_mem *bs,
> > + struct vdec_fb *unused,
> > bool *res_chg)
> > +{
> > + struct vdec_h264_slice_inst *inst = h_vdec;
> > + struct vdec_vpu_inst *vpu = &inst->vpu;
> > + struct mtk_video_dec_buf *src_buf_info, *dst_buf_info;
> > + struct vdec_fb *fb;
> > + unsigned char *buf;
> > + unsigned int data[2], i;
> > + u64 y_fb_dma, c_fb_dma;
> > + struct mtk_vcodec_mem *mem;
> > + int err, nal_start_idx;
> > +
> > + /* bs NULL means flush decoder */
> > + if (!bs)
> > + return vpu_dec_reset(vpu);
> > +
> > + fb = inst->ctx->dev->vdec_pdata->get_cap_buffer(inst->ctx);
> > + src_buf_info = container_of(bs, struct mtk_video_dec_buf,
> > bs_buffer);
> > + dst_buf_info = container_of(fb, struct mtk_video_dec_buf,
> > frame_buffer);
> > +
> > + y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
> > + c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
> > + mtk_vdec_debug(inst->ctx, "[h264-dec] [%d] y_dma=%llx
> > c_dma=%llx",
> > + inst->ctx->decoded_frame_cnt, y_fb_dma,
> > c_fb_dma);
> > +
> > inst->vsi_ctx.dec.bs_buf_addr = (u64)bs->dma_addr;
> > inst->vsi_ctx.dec.bs_buf_size = bs->size;
> > inst->vsi_ctx.dec.y_fb_dma = y_fb_dma;
> > @@ -807,21 +1190,95 @@ static int
> > vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem
> > *bs
> > return err;
> > }
> >
> > +static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx *ctx)
> > +{
> > + struct vdec_h264_slice_inst *inst;
> > + int err, vsi_size;
> > + unsigned char *temp;
> > +
> > + inst = kzalloc(sizeof(*inst), GFP_KERNEL);
> > + if (!inst)
> > + return -ENOMEM;
> > +
> > + inst->ctx = ctx;
> > +
> > + inst->vpu.id = SCP_IPI_VDEC_LAT;
> > + inst->vpu.core_id = SCP_IPI_VDEC_CORE;
> > + inst->vpu.ctx = ctx;
> > + inst->vpu.codec_type = ctx->current_codec;
> > + inst->vpu.capture_type = ctx->capture_fourcc;
> > +
> > + err = vpu_dec_init(&inst->vpu);
> > + if (err) {
> > + mtk_vdec_err(ctx, "vdec_h264 init err=%d", err);
> > + goto error_free_inst;
> > + }
> > +
> > + if (IS_VDEC_SUPPORT_EX(ctx->dev->dec_capability)) {
>
> s/SUPPORT_EX/SUPPORT_EXT/
>
> same treatment for the other variables below ending with ex
>
> > + vsi_size = sizeof(struct vdec_h264_slice_vsi_ex);
> > +
> > + vsi_size = round_up(vsi_size,
> > VCODEC_DEC_ALIGNED_64);
> > + inst->vsi_ex = inst->vpu.vsi;
> > + temp = (unsigned char *)inst->vsi_ex;
> > + inst->vsi_core_ex = (struct vdec_h264_slice_vsi_ex
> > *)(temp + vsi_size);
> > +
> > + if (inst->ctx->dev->vdec_pdata->hw_arch ==
> > MTK_VDEC_PURE_SINGLE_CORE)
> > + inst->decode =
> > vdec_h264_slice_single_decode_ex;
> > + else
> > + inst->decode =
> > vdec_h264_slice_lat_decode_ex;
> > + } else {
> > + vsi_size = sizeof(struct vdec_h264_slice_vsi);
> > +
> > + vsi_size = round_up(vsi_size,
> > VCODEC_DEC_ALIGNED_64);
> > + inst->vsi = inst->vpu.vsi;
> > + temp = (unsigned char *)inst->vsi;
> > + inst->vsi_core = (struct vdec_h264_slice_vsi *)(temp
> > + vsi_size);
> > +
> > + if (inst->ctx->dev->vdec_pdata->hw_arch ==
> > MTK_VDEC_PURE_SINGLE_CORE)
> > + inst->decode =
> > vdec_h264_slice_single_decode;
> > + else
> > + inst->decode = vdec_h264_slice_lat_decode;
> > + }
>
> This looks all so extremely similar to me ... Please help me out
> here,
> why do we need a vsi_core and a vsi_core_ext ? You could easily
> assign
> the same value that you assign to vsi_core_ext to vsi_core in case
> the
> architecture supports the extended VSI. So why do you need to have a
> the
> vsi structs besides the vsi_ext structs?
vsi extend is added many parameters to support some special feature,
vsi_core and vsi_core_ext are big different.
>
> > + inst->resolution_changed = true;
> > + inst->realloc_mv_buf = true;
> > +
> > + mtk_vdec_debug(ctx, "lat struct size = %d,%d,%d,%d vsi:
> > %d\n",
> > + (int)sizeof(struct mtk_h264_sps_param),
> > + (int)sizeof(struct mtk_h264_pps_param),
> > + (int)sizeof(struct
> > vdec_h264_slice_lat_dec_param),
> > + (int)sizeof(struct mtk_h264_dpb_info),
> > + vsi_size);
> > + mtk_vdec_debug(ctx, "lat H264 instance >> %p, codec_type =
> > 0x%x",
> > + inst, inst->vpu.codec_type);
> > +
> > + ctx->drv_handle = inst;
> > + return 0;
> > +
> > +error_free_inst:
> > + kfree(inst);
> > + return err;
> > +}
> > +
> > +static void vdec_h264_slice_deinit(void *h_vdec)
> > +{
> > + struct vdec_h264_slice_inst *inst = h_vdec;
> > +
> > + vpu_dec_deinit(&inst->vpu);
> > + vdec_h264_slice_free_mv_buf(inst);
> > + vdec_msg_queue_deinit(&inst->ctx->msg_queue, inst->ctx);
> > +
> > + kfree(inst);
> > +}
> > +
> > static int vdec_h264_slice_decode(void *h_vdec, struct
> > mtk_vcodec_mem *bs,
> > struct vdec_fb *unused, bool
> > *res_chg)
> > {
> > struct vdec_h264_slice_inst *inst = h_vdec;
> > - int ret;
> >
> > if (!h_vdec)
> > return -EINVAL;
> >
> > - if (inst->ctx->dev->vdec_pdata->hw_arch ==
> > MTK_VDEC_PURE_SINGLE_CORE)
> > - ret = vdec_h264_slice_single_decode(h_vdec, bs,
> > unused, res_chg);
> > - else
> > - ret = vdec_h264_slice_lat_decode(h_vdec, bs, unused,
> > res_chg);
> > -
> > - return ret;
> > + return inst->decode(h_vdec, bs, unused, res_chg);
>
> One reason more to try avoiding the split into separate functions for
> extended and non-extended, more callbacks make the code just harder
> and
> harder to navigate and understand.
>
If the driver not add one callback for each architecture, need to using
many condition to separate here, looks much more complex.
Best Regards,
Yunfei Dong
> > }
> >
> > static int vdec_h264_slice_get_param(void *h_vdec, enum
> > vdec_get_param_type type,
> > --
> > 2.46.0
> >
> >
>
> Regards,
> Sebastian Fricke
Powered by blists - more mailing lists