lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <831518109ba0885f6cd3ee8c32316f9aaf386c5c.camel@collabora.com>
Date: Fri, 14 Nov 2025 16:27:05 -0500
From: Nicolas Dufresne <nicolas.dufresne@...labora.com>
To: Kyrie Wu <kyrie.wu@...iatek.com>, Tiffany Lin
 <tiffany.lin@...iatek.com>,  Andrew-CT Chen <andrew-ct.chen@...iatek.com>,
 Yunfei Dong <yunfei.dong@...iatek.com>, Mauro Carvalho Chehab	
 <mchehab@...nel.org>, Rob Herring <robh@...nel.org>, Krzysztof Kozlowski	
 <krzk+dt@...nel.org>, Conor Dooley <conor+dt@...nel.org>, Matthias Brugger	
 <matthias.bgg@...il.com>, AngeloGioacchino Del Regno	
 <angelogioacchino.delregno@...labora.com>, Hans Verkuil
 <hverkuil@...all.nl>,  Christophe JAILLET <christophe.jaillet@...adoo.fr>,
 Sebastian Fricke <sebastian.fricke@...labora.com>, Nathan Hebert	
 <nhebert@...omium.org>, Arnd Bergmann <arnd@...db.de>, Irui Wang	
 <irui.wang@...iatek.com>, George Sun <george.sun@...iatek.com>, 
	linux-media@...r.kernel.org, devicetree@...r.kernel.org, 
	linux-kernel@...r.kernel.org, linux-arm-kernel@...ts.infradead.org, 
	linux-mediatek@...ts.infradead.org
Cc: Neil Armstrong <neil.armstrong@...aro.org>, Andrzej Pietrasiewicz
	 <andrzejtp2010@...il.com>
Subject: Re: [PATCH v3 1/6] media: mediatek: encoder: Add a new encoder
 driver interface

Hi,

Le jeudi 14 août 2025 à 16:56 +0800, Kyrie Wu a écrit :
> From: Irui Wang <irui.wang@...iatek.com>
> 
> Introduce a new encoder kernel driver interface to ensure compatibility
> with the updated encoder software driver running in firmware.
> The new driver interface is expected to support more encoder formats,
> share more encode parameters between kernel and firmware.
> 
> Signed-off-by: Irui Wang <irui.wang@...iatek.com>

I notice some possible redundancy with common/mtk_vcodec_util.c, so something to
keep in mind for future to avoid inflating this driver forever, but looks
overall good. I don't like the fact it waits synchrously on IRQ, but this is
true for the integrity of the driver.

Reviewed-by: Nicolas Dufresne <nicolas.dufresne@...labora.com>

> ---
>  .../mediatek/vcodec/common/mtk_vcodec_fw.c    |  13 +
>  .../mediatek/vcodec/common/mtk_vcodec_fw.h    |   1 +
>  .../platform/mediatek/vcodec/encoder/Makefile |   1 +
>  .../mediatek/vcodec/encoder/mtk_vcodec_enc.c  |  14 +-
>  .../vcodec/encoder/mtk_vcodec_enc_drv.h       |   8 +-
>  .../vcodec/encoder/venc/venc_common_if.c      | 672 ++++++++++++++++++
>  .../vcodec/encoder/venc/venc_h264_if.c        |   8 +-
>  .../mediatek/vcodec/encoder/venc_drv_if.h     |  11 +-
>  8 files changed, 710 insertions(+), 18 deletions(-)
>  create mode 100644 drivers/media/platform/mediatek/vcodec/encoder/venc/venc_common_if.c
> 
> diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw.c b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw.c
> index 4ed7639dfa30..0381acceda25 100644
> --- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw.c
> +++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw.c
> @@ -18,6 +18,19 @@ int mtk_vcodec_fw_get_ipi(enum mtk_vcodec_fw_type type, int hw_id)
>  }
>  EXPORT_SYMBOL_GPL(mtk_vcodec_fw_get_ipi);
>  
> +int mtk_vcodec_fw_get_venc_ipi(enum mtk_vcodec_fw_type type)
> +{
> +	switch (type) {
> +	case SCP:
> +		return SCP_IPI_VENC_H264;
> +	case VCP:
> +		return VCP_IPI_ENCODER;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +EXPORT_SYMBOL_GPL(mtk_vcodec_fw_get_venc_ipi);
> +
>  struct mtk_vcodec_fw *mtk_vcodec_fw_select(void *priv, enum mtk_vcodec_fw_type type,
>  					   enum mtk_vcodec_fw_use fw_use)
>  {
> diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw.h b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw.h
> index 142e2e87905c..e7304a7dd3e0 100644
> --- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw.h
> +++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw.h
> @@ -42,5 +42,6 @@ int mtk_vcodec_fw_ipi_send(struct mtk_vcodec_fw *fw, int id,
>  			   void *buf, unsigned int len, unsigned int wait);
>  int mtk_vcodec_fw_get_type(struct mtk_vcodec_fw *fw);
>  int mtk_vcodec_fw_get_ipi(enum mtk_vcodec_fw_type type, int hw_id);
> +int mtk_vcodec_fw_get_venc_ipi(enum mtk_vcodec_fw_type type);
>  
>  #endif /* _MTK_VCODEC_FW_H_ */
> diff --git a/drivers/media/platform/mediatek/vcodec/encoder/Makefile b/drivers/media/platform/mediatek/vcodec/encoder/Makefile
> index e621b5b7e5e6..9d3229d56e39 100644
> --- a/drivers/media/platform/mediatek/vcodec/encoder/Makefile
> +++ b/drivers/media/platform/mediatek/vcodec/encoder/Makefile
> @@ -4,6 +4,7 @@ obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-enc.o
>  
>  mtk-vcodec-enc-y := venc/venc_vp8_if.o \
>  		venc/venc_h264_if.o \
> +		venc/venc_common_if.o \
>  		mtk_vcodec_enc.o \
>  		mtk_vcodec_enc_drv.o \
>  		mtk_vcodec_enc_pm.o \
> diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c
> index dcafb1303c29..03512bf7a072 100644
> --- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c
> +++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c
> @@ -81,11 +81,11 @@ static int vidioc_venc_s_ctrl(struct v4l2_ctrl *ctrl)
>  		break;
>  	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
>  		mtk_v4l2_venc_dbg(2, ctx, "V4L2_CID_MPEG_VIDEO_H264_PROFILE val = %d", ctrl->val);
> -		p->h264_profile = ctrl->val;
> +		p->profile = ctrl->val;
>  		break;
>  	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
>  		mtk_v4l2_venc_dbg(2, ctx, "V4L2_CID_MPEG_VIDEO_H264_LEVEL val = %d", ctrl->val);
> -		p->h264_level = ctrl->val;
> +		p->level = ctrl->val;
>  		break;
>  	case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
>  		mtk_v4l2_venc_dbg(2, ctx, "V4L2_CID_MPEG_VIDEO_H264_I_PERIOD val = %d", ctrl->val);
> @@ -386,8 +386,8 @@ static void mtk_venc_set_param(struct mtk_vcodec_enc_ctx *ctx,
>  		mtk_v4l2_venc_err(ctx, "Unsupported fourcc =%d", q_data_src->fmt->fourcc);
>  		break;
>  	}
> -	param->h264_profile = enc_params->h264_profile;
> -	param->h264_level = enc_params->h264_level;
> +	param->profile = enc_params->profile;
> +	param->level = enc_params->level;
>  
>  	/* Config visible resolution */
>  	param->width = q_data_src->visible_width;
> @@ -403,8 +403,8 @@ static void mtk_venc_set_param(struct mtk_vcodec_enc_ctx *ctx,
>  
>  	mtk_v4l2_venc_dbg(0, ctx,
>  			  "fmt 0x%x, P/L %d/%d w/h %d/%d buf %d/%d fps/bps %d/%d gop %d i_per %d",
> -			  param->input_yuv_fmt, param->h264_profile,
> -			  param->h264_level, param->width, param->height,
> +			  param->input_yuv_fmt, param->profile,
> +			  param->level, param->width, param->height,
>  			  param->buf_width, param->buf_height,
>  			  param->frm_rate, param->bitrate,
>  			  param->gop_size, param->intra_period);
> @@ -1174,6 +1174,8 @@ static void mtk_venc_worker(struct work_struct *work)
>  		frm_buf.fb_addr[i].size =
>  				(size_t)src_buf->vb2_buf.planes[i].length;
>  	}
> +	frm_buf.num_planes = src_buf->vb2_buf.num_planes;
> +
>  	bs_buf.va = vb2_plane_vaddr(&dst_buf->vb2_buf, 0);
>  	bs_buf.dma_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
>  	bs_buf.size = (size_t)dst_buf->vb2_buf.planes[0].length;
> diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h
> index 0bd85d0fb379..b1277bcfcf53 100644
> --- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h
> +++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h
> @@ -69,8 +69,8 @@ enum mtk_encode_param {
>   * @framerate_denom: frame rate denominator. ex: framerate_num=30 and
>   *		     framerate_denom=1 means FPS is 30
>   * @h264_max_qp: Max value for H.264 quantization parameter
> - * @h264_profile: V4L2 defined H.264 profile
> - * @h264_level: V4L2 defined H.264 level
> + * @profile: V4L2 defined profile
> + * @level: V4L2 defined level
>   * @force_intra: force/insert intra frame
>   */
>  struct mtk_enc_params {
> @@ -84,8 +84,8 @@ struct mtk_enc_params {
>  	unsigned int	framerate_num;
>  	unsigned int	framerate_denom;
>  	unsigned int	h264_max_qp;
> -	unsigned int	h264_profile;
> -	unsigned int	h264_level;
> +	unsigned int	profile;
> +	unsigned int	level;
>  	unsigned int	force_intra;
>  };
>  
> diff --git a/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_common_if.c b/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_common_if.c
> new file mode 100644
> index 000000000000..da7cf90bd54b
> --- /dev/null
> +++ b/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_common_if.c
> @@ -0,0 +1,672 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + */
> +
> +#include "../mtk_vcodec_enc.h"
> +#include "../mtk_vcodec_enc_drv.h"
> +#include "../venc_drv_base.h"
> +#include "../venc_drv_if.h"
> +#include "../venc_vpu_if.h"
> +#include "../../common/mtk_vcodec_intr.h"
> +#include "../../common/mtk_vcodec_util.h"
> +
> +#define SEQ_HEADER_SIZE 1024
> +#define PPS_SIZE 128
> +#define MAX_DPB_SIZE 16
> +#define MAX_VENC_CORE 3
> +#define VENC_CONFIG_LENGTH 115
> +#define VENC_CONFIG_DATA 128
> +#define VENC_PIC_BITSTREAM_BYTE_CNT 0x0098
> +
> +/**
> + * enum venc_bs_mode - encode bitstream mode
> + * @VENC_BS_MODE_SPS: encode sps
> + * @VENC_BS_MODE_PPS: encode pps
> + * @VENC_BS_MODE_VPS: encode vps
> + * @VENC_BS_MODE_SEQ_HDR: encode sequence header
> + * @VENC_BS_MODE_FRAME: encode frame
> + * @VENC_BS_MODE_FRAME_FINAL: encode final frame
> + * @VENC_BS_MODE_MAX: max value
> + */
> +enum venc_bs_mode {
> +	VENC_BS_MODE_SPS = 0,
> +	VENC_BS_MODE_PPS,
> +	VENC_BS_MODE_VPS,
> +	VENC_BS_MODE_SEQ_HDR,
> +	VENC_BS_MODE_FRAME,
> +	VENC_BS_MODE_FRAME_FINAL,
> +	VENC_BS_MODE_MAX
> +};
> +
> +/**
> + * struct venc_config - Structure for encoder configuration
> + *                      AP-W/R : AP is writer/reader on this item
> + *                      MCU-W/R: MCU is write/reader on this item
> + * @input_fourcc: input format fourcc
> + * @bitrate: target bitrate (in bps)
> + * @pic_w: visible width of resolution
> + * @pic_h: visible height of resolution
> + * @buf_w: buffer alignment width of resolution
> + * @buf_h: buffer alignment height of resolution
> + * @gop_size: group of picture size (IDR frame period)
> + * @intra_period: I frame period
> + * @framerate: frame rate in fps
> + * @profile: profile_idc in SPS
> + * @level: level_idc in SPS
> + * @core_num: encoder core num
> + * @dpb_size: encode dpb size
> + * @reserved: reserved fields config
> + */
> +struct venc_config {
> +	__u32 input_fourcc;
> +	__u32 bitrate;
> +	__u32 pic_w;
> +	__u32 pic_h;
> +	__u32 buf_w;
> +	__u32 buf_h;
> +	__u32 gop_size;
> +	__u32 intra_period;
> +	__u32 framerate;
> +	__u32 profile;
> +	__u32 level;
> +	__u32 core_num;
> +	__u32 dpb_size;
> +	__u32 reserved[VENC_CONFIG_LENGTH];
> +};
> +
> +/**
> + * struct venc_config_data - Structure for configuration data
> + * @config_data: extended configuration data besides the basic configuration
> + */
> +struct venc_config_data {
> +	unsigned int config_data[VENC_CONFIG_DATA];
> +};
> +
> +/**
> + * struct venc_work_buf - Structure for working buffer information
> + *                               AP-W/R : AP is writer/reader on this item
> + *                               MCU-W/R: MCU is write/reader on this item
> + * @iova: IO virtual address
> + * @pa: physical address
> + * @pa_64: for 64bit pa padding
> + * @va: virtual address
> + * @va_padding: for 64bit va padding
> + * @size: buffer size
> + * @size_padding: for 64bit size padding
> + */
> +struct venc_work_buf {
> +	unsigned long long iova;
> +	union {
> +		unsigned int pa;
> +		unsigned long long pa_64;
> +	};
> +	union {
> +		void *va;
> +		unsigned long long va_padding;
> +	};
> +	union {
> +		unsigned int size;
> +		unsigned long long size_padding;
> +	};
> +};
> +
> +/**
> + * struct venc_work_buf_list - Structure for encode working buffer list
> + * @rc_code: RC code buffer
> + * @rc_info: RC info buffer
> + * @luma: luma buffer
> + * @chroma: chroma buffer
> + * @sub_luma: sub luma buffer
> + * @sub_write: sub write buffer
> + * @col_mv: col_mv buffer
> + * @wpp: wpp buffer
> + * @wpp_nbm: wpp nbm buffer
> + * @skip_frame: skip frame buffer
> + */
> +struct venc_work_buf_list {
> +	struct venc_work_buf rc_code;
> +	struct venc_work_buf rc_info[MAX_VENC_CORE];
> +	struct venc_work_buf luma[MAX_DPB_SIZE];
> +	struct venc_work_buf chroma[MAX_DPB_SIZE];
> +	struct venc_work_buf sub_luma[MAX_DPB_SIZE];
> +	struct venc_work_buf sub_write[MAX_DPB_SIZE];
> +	struct venc_work_buf col_mv[MAX_DPB_SIZE];
> +	struct venc_work_buf wpp[MAX_VENC_CORE];
> +	struct venc_work_buf wpp_nbm[MAX_VENC_CORE];
> +	struct venc_work_buf skip_frame;
> +};
> +
> +/**
> + * struct venc_info -  Structure for encode frame and bs information
> + * @fb_addr: frame buffer address array
> + * @fb_size: frame buffer size array
> + * @bs_addr: bitstream buffer address
> + * @bs_size: bitstream buffer size
> + */
> +struct venc_info {
> +	unsigned long long fb_addr[VIDEO_MAX_PLANES];
> +	unsigned int fb_size[VIDEO_MAX_PLANES];
> +	unsigned long long bs_addr;
> +	unsigned long long bs_size;
> +};
> +
> +/**
> + * struct venc_vsi - Structure for VCP driver control and info share
> + *                   AP-W/R : AP is writer/reader on this item
> + *                   VCP-W/R: VCP is write/reader on this item
> + * @config: encoder configuration
> + * @data: encoder configuration data
> + * @bufs: encoder working buffers
> + * @venc: encoder information
> + */
> +struct venc_vsi {
> +	struct venc_config config;
> +	struct venc_config_data data;
> +	struct venc_work_buf_list bufs;
> +	struct venc_info venc;
> +};
> +
> +/**
> + * struct venc_inst - Structure for encoder instance
> + * @hw_base: hardware io address
> + * @pps_buf: PPS buffer
> + * @seq_buf: sequence header buffer
> + * @work_buf_allocated: work buffer allocated or not
> + * @frm_cnt: encoded frame count
> + * @skip_frm_cnt: encoded skip frame count
> + * @prepend_hdr: prepend header flag
> + * @vpu_inst: vpu instance
> + * @vsi: encode vsi
> + * @ctx: encoder context
> + */
> +struct venc_inst {
> +	void __iomem *hw_base;
> +	struct mtk_vcodec_mem pps_buf;
> +	struct mtk_vcodec_mem seq_buf;
> +	bool work_buf_allocated;
> +	unsigned int frm_cnt;
> +	unsigned int skip_frm_cnt;
> +	unsigned int prepend_hdr;
> +	struct venc_vpu_inst vpu_inst;
> +	struct venc_vsi *vsi;
> +	struct mtk_vcodec_enc_ctx *ctx;
> +};
> +
> +static int venc_init(struct mtk_vcodec_enc_ctx *ctx)
> +{
> +	int ret = 0;
> +	struct venc_inst *inst;
> +
> +	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
> +	if (!inst)
> +		return -ENOMEM;
> +
> +	inst->ctx = ctx;
> +	inst->vpu_inst.ctx = ctx;
> +	inst->vpu_inst.id = mtk_vcodec_fw_get_venc_ipi(ctx->dev->fw_handler->type);
> +	inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx->dev->reg_base, VENC_SYS);
> +
> +	ret = vpu_enc_init(&inst->vpu_inst);
> +	inst->vsi = (struct venc_vsi *)inst->vpu_inst.vsi;
> +
> +	if (ret)
> +		kfree(inst);
> +	else
> +		ctx->drv_handle = inst;
> +
> +	return ret;
> +}
> +
> +static inline u32 venc_read_reg(struct venc_inst *inst, u32 addr)
> +{
> +	return readl(inst->hw_base + addr);
> +}
> +
> +static unsigned int venc_wait_encode_done(struct venc_inst *inst)
> +{
> +	unsigned int irq_status = 0;
> +	struct mtk_vcodec_enc_ctx *ctx = (struct mtk_vcodec_enc_ctx *)inst->ctx;
> +
> +	if (!mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED,
> +					  WAIT_INTR_TIMEOUT_MS, 0)) {
> +		irq_status = ctx->irq_status;
> +		mtk_venc_debug(ctx, "irq_status %x <-", irq_status);
> +	}
> +	return irq_status;
> +}
> +
> +static void venc_set_bufs(struct venc_inst *inst,
> +			  struct venc_frm_buf *frm_buf,
> +			  struct mtk_vcodec_mem *bs_buf)
> +{
> +	unsigned int i;
> +
> +	if (frm_buf) {
> +		for (i = 0; i < frm_buf->num_planes; i++) {
> +			inst->vsi->venc.fb_addr[i] = frm_buf->fb_addr[i].dma_addr;
> +			inst->vsi->venc.fb_size[i] = frm_buf->fb_addr[i].size;
> +			mtk_venc_debug(inst->ctx, "%s: fb_buf[%d]: %llx(%d)\n",
> +				       __func__, i,
> +				       inst->vsi->venc.fb_addr[i],
> +				       inst->vsi->venc.fb_size[i]);
> +		}
> +	}
> +
> +	if (bs_buf) {
> +		inst->vsi->venc.bs_addr = bs_buf->dma_addr;
> +		inst->vsi->venc.bs_size = bs_buf->size;
> +		mtk_venc_debug(inst->ctx, "%s: bs_buf: %llx(%d)\n",
> +			       __func__,
> +			       inst->vsi->venc.bs_addr,
> +			       (unsigned int)inst->vsi->venc.bs_size);
> +	}
> +}
> +
> +static int venc_encode_sps(struct venc_inst *inst,
> +			   struct mtk_vcodec_mem *bs_buf,
> +			   unsigned int *bs_size)
> +{
> +	int ret = 0;
> +	unsigned int irq_status;
> +
> +	venc_set_bufs(inst, NULL, bs_buf);
> +	ret = vpu_enc_encode(&inst->vpu_inst, VENC_BS_MODE_SPS, NULL, bs_buf, NULL);
> +	if (ret)
> +		return ret;
> +
> +	irq_status = venc_wait_encode_done(inst);
> +	if (irq_status != MTK_VENC_IRQ_STATUS_SPS) {
> +		mtk_venc_err(inst->ctx, "expect irq status %d", MTK_VENC_IRQ_STATUS_SPS);
> +		return -EINVAL;
> +	}
> +
> +	*bs_size = venc_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
> +	mtk_venc_debug(inst->ctx, "sps bs size %d <-", *bs_size);
> +
> +	return ret;
> +}
> +
> +static int venc_encode_pps(struct venc_inst *inst,
> +			   struct mtk_vcodec_mem *bs_buf,
> +			   unsigned int *bs_size)
> +{
> +	int ret = 0;
> +	unsigned int irq_status;
> +
> +	venc_set_bufs(inst, NULL, bs_buf);
> +	ret = vpu_enc_encode(&inst->vpu_inst, VENC_BS_MODE_PPS, NULL, bs_buf, NULL);
> +	if (ret)
> +		return ret;
> +
> +	irq_status = venc_wait_encode_done(inst);
> +	if (irq_status != MTK_VENC_IRQ_STATUS_PPS) {
> +		mtk_venc_err(inst->ctx, "expect irq status %d", MTK_VENC_IRQ_STATUS_PPS);
> +		return -EINVAL;
> +	}
> +
> +	*bs_size = venc_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
> +	mtk_venc_debug(inst->ctx, "pps bs size %d <-", *bs_size);
> +
> +	return ret;
> +}
> +
> +static int venc_encode_header(struct venc_inst *inst,
> +			      struct mtk_vcodec_mem *bs_buf,
> +			      unsigned int *bs_size)
> +{
> +	int ret = 0;
> +	unsigned int bs_size_sps;
> +	unsigned int bs_size_pps;
> +
> +	ret = venc_encode_sps(inst, bs_buf, &bs_size_sps);
> +	if (ret)
> +		return ret;
> +
> +	ret = venc_encode_pps(inst, &inst->pps_buf, &bs_size_pps);
> +	if (ret)
> +		return ret;
> +
> +	memcpy(bs_buf->va + bs_size_sps, inst->pps_buf.va, bs_size_pps);
> +	*bs_size = bs_size_sps + bs_size_pps;
> +
> +	return ret;
> +}
> +
> +static int venc_encode_frame(struct venc_inst *inst,
> +			     struct venc_frm_buf *frm_buf,
> +			     struct mtk_vcodec_mem *bs_buf,
> +			     unsigned int *bs_size)
> +{
> +	int ret = 0;
> +	unsigned int irq_status;
> +
> +	venc_set_bufs(inst, frm_buf, bs_buf);
> +	ret = vpu_enc_encode(&inst->vpu_inst, VENC_BS_MODE_FRAME, frm_buf, bs_buf, NULL);
> +	if (ret)
> +		return ret;
> +
> +	irq_status = venc_wait_encode_done(inst);
> +	if (irq_status != MTK_VENC_IRQ_STATUS_FRM) {
> +		mtk_venc_err(inst->ctx, "expect irq status %d", MTK_VENC_IRQ_STATUS_FRM);
> +		return -EINVAL;
> +	}
> +
> +	*bs_size = venc_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
> +
> +	++inst->frm_cnt;
> +
> +	return ret;
> +}
> +
> +static int venc_encode(void *handle,
> +		       enum venc_start_opt opt,
> +		       struct venc_frm_buf *frm_buf,
> +		       struct mtk_vcodec_mem *bs_buf,
> +		       struct venc_done_result *result)
> +{
> +	int ret = 0;
> +	struct venc_inst *inst = (struct venc_inst *)handle;
> +	struct mtk_vcodec_enc_ctx *ctx;
> +	unsigned int bs_size_hdr;
> +
> +	if (WARN_ON(!inst || !inst->vsi))
> +		return -EINVAL;
> +
> +	ctx = inst->ctx;
> +
> +	mtk_venc_debug(ctx, "%s: opt: %d\n", __func__, opt);
> +
> +	enable_irq(ctx->dev->enc_irq);
> +	switch (opt) {
> +	case VENC_START_OPT_ENCODE_SEQUENCE_HEADER: {
> +		ret = venc_encode_header(inst, bs_buf, &bs_size_hdr);
> +		if (ret)
> +			goto encode_err;
> +
> +		result->bs_size = bs_size_hdr;
> +		result->is_key_frm = false;
> +		break;
> +	}
> +
> +	case VENC_START_OPT_ENCODE_FRAME: {
> +		if (!inst->prepend_hdr) {
> +			ret = venc_encode_frame(inst, frm_buf, bs_buf, &result->bs_size);
> +			if (ret)
> +				goto encode_err;
> +
> +			result->is_key_frm = inst->vpu_inst.is_key_frm;
> +			break;
> +		}
> +
> +		ret = venc_encode_header(inst, &inst->seq_buf, &bs_size_hdr);
> +		if (ret)
> +			goto encode_err;
> +
> +		ret = venc_encode_frame(inst, frm_buf, bs_buf, &result->bs_size);
> +		if (ret)
> +			goto encode_err;
> +
> +		memmove(bs_buf->va + bs_size_hdr, bs_buf->va, result->bs_size);
> +		memcpy(bs_buf->va, inst->seq_buf.va, bs_size_hdr);
> +		result->bs_size += bs_size_hdr;
> +
> +		inst->prepend_hdr = 0;
> +		result->is_key_frm = inst->vpu_inst.is_key_frm;
> +		break;
> +	}
> +
> +	default:
> +		mtk_venc_err(inst->ctx, "venc_opt %d not supported", opt);
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +encode_err:
> +	disable_irq(ctx->dev->enc_irq);
> +	mtk_venc_debug(ctx, "opt %d, return %d", opt, ret);
> +
> +	return ret;
> +}
> +
> +static int mtk_venc_mem_alloc(struct venc_inst *inst,
> +			      struct device *dev,
> +			      struct venc_work_buf *buf)
> +{
> +	dma_addr_t dma_addr;
> +
> +	if (WARN_ON(!dev || !buf))
> +		return -EINVAL;
> +
> +	if (buf->size == 0)
> +		return 0;
> +
> +	buf->va = dma_alloc_coherent(dev, buf->size, &dma_addr, GFP_KERNEL);
> +	if (!buf->va)
> +		return -ENOMEM;
> +
> +	buf->iova = (unsigned long long)dma_addr;
> +
> +	mtk_venc_debug(inst->ctx, "allocate buffer, size: %d, va: %p, iova: 0x%llx",
> +		       buf->size, buf->va, buf->iova);
> +
> +	return 0;
> +}
> +
> +static void mtk_venc_mem_free(struct venc_inst *inst,
> +			      struct device *dev,
> +			      struct venc_work_buf *buf)
> +{
> +	if (WARN_ON(!dev || !buf))
> +		return;
> +
> +	if (!buf->va)
> +		return;
> +
> +	mtk_venc_debug(inst->ctx, "free buffer, size: %d, va: %p, iova: 0x%llx",
> +		       buf->size, buf->va, buf->iova);
> +
> +	dma_free_coherent(dev, buf->size, buf->va, buf->iova);
> +	buf->va = NULL;
> +	buf->iova = 0;
> +	buf->size = 0;
> +}
> +
> +static void venc_free_rc_buf(struct venc_inst *inst,
> +			     struct venc_work_buf_list *bufs,
> +			     unsigned int core_num)
> +{
> +	int i;
> +	struct device *dev;
> +
> +	dev = &inst->ctx->dev->plat_dev->dev;
> +	mtk_venc_mem_free(inst, dev, &bufs->rc_code);
> +
> +	for (i = 0; i < core_num; i++)
> +		mtk_venc_mem_free(inst, dev, &bufs->rc_info[i]);
> +}
> +
> +static void venc_free_work_buf(struct venc_inst *inst)
> +{
> +	int i;
> +	struct venc_work_buf_list *bufs = &inst->vsi->bufs;
> +	unsigned int core_num = inst->vsi->config.core_num;
> +	unsigned int dpb_size = inst->vsi->config.dpb_size;
> +	struct device *dev;
> +
> +	if (bufs->rc_code.va)
> +		venc_free_rc_buf(inst, bufs, core_num);
> +
> +	dev = &inst->ctx->dev->plat_dev->dev;
> +
> +	for (i = 0; i < core_num; i++) {
> +		mtk_venc_mem_free(inst, dev, &bufs->wpp[i]);
> +		mtk_venc_mem_free(inst, dev, &bufs->wpp_nbm[i]);
> +	}
> +
> +	for (i = 0; i < dpb_size; i++) {
> +		mtk_venc_mem_free(inst, dev, &bufs->luma[i]);
> +		mtk_venc_mem_free(inst, dev, &bufs->chroma[i]);
> +		mtk_venc_mem_free(inst, dev, &bufs->sub_luma[i]);
> +		mtk_venc_mem_free(inst, dev, &bufs->sub_write[i]);
> +		mtk_venc_mem_free(inst, dev, &bufs->col_mv[i]);
> +	}
> +
> +	if (inst->pps_buf.va)
> +		mtk_vcodec_mem_free(inst->ctx, &inst->pps_buf);
> +
> +	if (inst->seq_buf.va)
> +		mtk_vcodec_mem_free(inst->ctx, &inst->seq_buf);
> +}
> +
> +static int venc_alloc_rc_buf(struct venc_inst *inst,
> +			     struct venc_work_buf_list *bufs,
> +			     unsigned int core_num)
> +{
> +	int i;
> +	struct mtk_vcodec_fw *fw = inst->ctx->dev->fw_handler;
> +	struct device *dev;
> +	void *tmp_va;
> +
> +	dev = &inst->ctx->dev->plat_dev->dev;
> +	if (mtk_venc_mem_alloc(inst, dev, &bufs->rc_code))
> +		return -ENOMEM;
> +
> +	tmp_va = mtk_vcodec_fw_map_dm_addr(fw, bufs->rc_code.pa);
> +	memcpy(bufs->rc_code.va, tmp_va, bufs->rc_code.size);
> +
> +	for (i = 0; i < core_num; i++) {
> +		if (mtk_venc_mem_alloc(inst, dev, &bufs->rc_info[i]))
> +			goto err_rc_buf;
> +	}
> +
> +	return 0;
> +
> +err_rc_buf:
> +	venc_free_rc_buf(inst, bufs, core_num);
> +
> +	return -ENOMEM;
> +}
> +
> +static int venc_alloc_work_buf(struct venc_inst *inst)
> +{
> +	int i, ret;
> +	struct venc_work_buf_list *bufs = &inst->vsi->bufs;
> +	unsigned int core_num = inst->vsi->config.core_num;
> +	unsigned int dpb_size = inst->vsi->config.dpb_size;
> +	struct device *dev;
> +
> +	if (bufs->rc_code.size != 0) {
> +		ret = venc_alloc_rc_buf(inst, bufs, core_num);
> +		if (ret) {
> +			mtk_venc_err(inst->ctx, "cannot allocate rc buf");
> +			return -ENOMEM;
> +		}
> +	}
> +
> +	dev = &inst->ctx->dev->plat_dev->dev;
> +
> +	for (i = 0; i < core_num; i++) {
> +		if (mtk_venc_mem_alloc(inst, dev, &bufs->wpp[i]) ||
> +		    mtk_venc_mem_alloc(inst, dev, &bufs->wpp_nbm[i]))
> +			goto err_alloc;
> +	}
> +
> +	for (i = 0; i < dpb_size; i++) {
> +		if (mtk_venc_mem_alloc(inst, dev, &bufs->luma[i]) ||
> +		    mtk_venc_mem_alloc(inst, dev, &bufs->chroma[i]) ||
> +		    mtk_venc_mem_alloc(inst, dev, &bufs->sub_luma[i]) ||
> +		    mtk_venc_mem_alloc(inst, dev, &bufs->sub_write[i]) ||
> +		    mtk_venc_mem_alloc(inst, dev, &bufs->col_mv[i]))
> +			goto err_alloc;
> +	}
> +
> +	/* the pps_buf and seq_buf are used by AP side only */
> +	inst->pps_buf.size = PPS_SIZE;
> +	ret = mtk_vcodec_mem_alloc(inst->ctx, &inst->pps_buf);
> +	if (ret) {
> +		mtk_venc_err(inst->ctx, "cannot allocate pps_buf");
> +		goto err_alloc;
> +	}
> +
> +	inst->seq_buf.size = SEQ_HEADER_SIZE;
> +	ret = mtk_vcodec_mem_alloc(inst->ctx, &inst->seq_buf);
> +	if (ret) {
> +		mtk_venc_err(inst->ctx, "cannot allocate seq_buf");
> +		goto err_alloc;
> +	}
> +	return 0;
> +
> +err_alloc:
> +	venc_free_work_buf(inst);
> +	return -ENOMEM;
> +}
> +
> +static int venc_set_param(void *handle,
> +			  enum venc_set_param_type type,
> +			  struct venc_enc_param *enc_prm)
> +{
> +	int ret = 0;
> +	struct venc_inst *inst = (struct venc_inst *)handle;
> +
> +	switch (type) {
> +	case VENC_SET_PARAM_ENC:
> +		if (WARN_ON(!inst->vsi))
> +			return -EINVAL;
> +		inst->vsi->config.input_fourcc = enc_prm->input_yuv_fmt;
> +		inst->vsi->config.bitrate = enc_prm->bitrate;
> +		inst->vsi->config.pic_w = enc_prm->width;
> +		inst->vsi->config.pic_h = enc_prm->height;
> +		inst->vsi->config.buf_w = enc_prm->buf_width;
> +		inst->vsi->config.buf_h = enc_prm->buf_height;
> +		inst->vsi->config.gop_size = enc_prm->gop_size;
> +		inst->vsi->config.framerate = enc_prm->frm_rate;
> +		inst->vsi->config.intra_period = enc_prm->intra_period;
> +		inst->vsi->config.profile = enc_prm->profile;
> +		inst->vsi->config.level = enc_prm->level;
> +
> +		ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
> +		if (ret)
> +			break;
> +
> +		if (inst->work_buf_allocated) {
> +			venc_free_work_buf(inst);
> +			inst->work_buf_allocated = false;
> +		}
> +		ret = venc_alloc_work_buf(inst);
> +		if (ret)
> +			break;
> +		inst->work_buf_allocated = true;
> +		break;
> +	case VENC_SET_PARAM_PREPEND_HEADER:
> +		inst->prepend_hdr = 1;
> +		break;
> +	default:
> +		ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static int venc_deinit(void *handle)
> +{
> +	int ret = 0;
> +	struct venc_inst *inst = (struct venc_inst *)handle;
> +
> +	ret = vpu_enc_deinit(&inst->vpu_inst);
> +
> +	if (inst->work_buf_allocated)
> +		venc_free_work_buf(inst);
> +
> +	kfree(inst);
> +
> +	return ret;
> +}
> +
> +const struct venc_common_if venc_if = {
> +	.init = venc_init,
> +	.encode = venc_encode,
> +	.set_param = venc_set_param,
> +	.deinit = venc_deinit,
> +};
> diff --git a/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c b/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c
> index 0f63657d8bad..4160dc995806 100644
> --- a/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c
> +++ b/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c
> @@ -723,9 +723,9 @@ static void h264_enc_set_vsi_configs(struct venc_h264_inst *inst,
>  	inst->vsi->config.framerate = enc_prm->frm_rate;
>  	inst->vsi->config.intra_period = enc_prm->intra_period;
>  	inst->vsi->config.profile =
> -		h264_get_profile(inst, enc_prm->h264_profile);
> +		h264_get_profile(inst, enc_prm->profile);
>  	inst->vsi->config.level =
> -		h264_get_level(inst, enc_prm->h264_level);
> +		h264_get_level(inst, enc_prm->level);
>  	inst->vsi->config.wfd = 0;
>  }
>  
> @@ -742,9 +742,9 @@ static void h264_enc_set_vsi_34_configs(struct venc_h264_inst *inst,
>  	inst->vsi_34->config.framerate = enc_prm->frm_rate;
>  	inst->vsi_34->config.intra_period = enc_prm->intra_period;
>  	inst->vsi_34->config.profile =
> -		h264_get_profile(inst, enc_prm->h264_profile);
> +		h264_get_profile(inst, enc_prm->profile);
>  	inst->vsi_34->config.level =
> -		h264_get_level(inst, enc_prm->h264_level);
> +		h264_get_level(inst, enc_prm->level);
>  	inst->vsi_34->config.wfd = 0;
>  }
>  
> diff --git a/drivers/media/platform/mediatek/vcodec/encoder/venc_drv_if.h b/drivers/media/platform/mediatek/vcodec/encoder/venc_drv_if.h
> index 889440a436b6..3c2a1b5e9312 100644
> --- a/drivers/media/platform/mediatek/vcodec/encoder/venc_drv_if.h
> +++ b/drivers/media/platform/mediatek/vcodec/encoder/venc_drv_if.h
> @@ -66,8 +66,8 @@ enum venc_set_param_type {
>   * struct venc_enc_prm - encoder settings for VENC_SET_PARAM_ENC used in
>   *					  venc_if_set_param()
>   * @input_fourcc: input yuv format
> - * @h264_profile: V4L2 defined H.264 profile
> - * @h264_level: V4L2 defined H.264 level
> + * @profile: V4L2 defined profile
> + * @level: V4L2 defined level
>   * @width: image width
>   * @height: image height
>   * @buf_width: buffer width
> @@ -79,8 +79,8 @@ enum venc_set_param_type {
>   */
>  struct venc_enc_param {
>  	enum venc_yuv_fmt input_yuv_fmt;
> -	unsigned int h264_profile;
> -	unsigned int h264_level;
> +	unsigned int profile;
> +	unsigned int level;
>  	unsigned int width;
>  	unsigned int height;
>  	unsigned int buf_width;
> @@ -107,9 +107,11 @@ struct venc_frame_info {
>  /*
>   * struct venc_frm_buf - frame buffer information used in venc_if_encode()
>   * @fb_addr: plane frame buffer addresses
> + * @num_planes: number of planes
>   */
>  struct venc_frm_buf {
>  	struct mtk_vcodec_fb fb_addr[MTK_VCODEC_MAX_PLANES];
> +	unsigned int num_planes;
>  };
>  
>  /*
> @@ -124,6 +126,7 @@ struct venc_done_result {
>  
>  extern const struct venc_common_if venc_h264_if;
>  extern const struct venc_common_if venc_vp8_if;
> +extern const struct venc_common_if venc_if;
>  
>  /*
>   * venc_if_init - Create the driver handle

Download attachment "signature.asc" of type "application/pgp-signature" (229 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ