[PATCH v6, 17/24] media: mediatek: vcodec: re-construct h264 driver to support svp mode

2024-05-16 Thread Yunfei Dong
Need secure buffer size to convert secure handle to secure
pa in optee-os, re-construct the vsi struct to store each
secure buffer size.

Separate svp and normal wait interrupt condition for svp mode
waiting hardware interrupt in optee-os.

Signed-off-by: Yunfei Dong 
---
 .../decoder/vdec/vdec_h264_req_multi_if.c | 261 +++---
 .../mediatek/vcodec/decoder/vdec_msg_queue.c  |   9 +-
 2 files changed, 168 insertions(+), 102 deletions(-)

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 d7fec1887ab5..40836673f7fe 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
@@ -60,14 +60,36 @@ struct vdec_h264_slice_lat_dec_param {
  * @crc:   Used to check whether hardware's status is right
  */
 struct vdec_h264_slice_info {
+   u64 wdma_end_addr_offset;
u16 nal_info;
u16 timeout;
-   u32 bs_buf_size;
-   u64 bs_buf_addr;
-   u64 y_fb_dma;
-   u64 c_fb_dma;
u64 vdec_fb_va;
u32 crc[8];
+   u32 reserved;
+};
+
+/*
+ * struct vdec_h264_slice_mem - memory address and size
+ */
+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
+ * @y:  current y buffer address info
+ * @c:  current c buffer address info
+ */
+struct vdec_h264_slice_fb {
+   struct vdec_h264_slice_mem y;
+   struct vdec_h264_slice_mem c;
 };
 
 /**
@@ -92,18 +114,16 @@ struct vdec_h264_slice_info {
  */
 struct vdec_h264_slice_vsi {
/* LAT dec addr */
-   u64 wdma_err_addr;
-   u64 wdma_start_addr;
-   u64 wdma_end_addr;
-   u64 slice_bc_start_addr;
-   u64 slice_bc_end_addr;
-   u64 row_info_start_addr;
-   u64 row_info_end_addr;
-   u64 trans_start;
-   u64 trans_end;
-   u64 wdma_end_addr_offset;
+   struct vdec_h264_slice_mem bs;
+   struct vdec_h264_slice_fb fb;
 
-   u64 mv_buf_dma[H264_MAX_MV_NUM];
+   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 dec;
struct vdec_h264_slice_lat_dec_param h264_slice_params;
 };
@@ -392,6 +412,100 @@ static void vdec_h264_slice_get_crop_info(struct 
vdec_h264_slice_inst *inst,
   cr->left, cr->top, cr->width, cr->height);
 }
 
+static void vdec_h264_slice_setup_lat_buffer(struct vdec_h264_slice_inst *inst,
+struct mtk_vcodec_mem *bs,
+struct vdec_lat_buf *lat_buf)
+{
+   struct mtk_vcodec_mem *mem;
+   int i;
+
+   inst->vsi->bs.dma_addr = (u64)bs->dma_addr;
+   inst->vsi->bs.size = bs->size;
+
+   for (i = 0; i < H264_MAX_MV_NUM; i++) {
+   mem = >mv_buf[i];
+   inst->vsi->mv_buf_dma[i].dma_addr = mem->dma_addr;
+   inst->vsi->mv_buf_dma[i].size = mem->size;
+   }
+   inst->vsi->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
+   inst->vsi->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size;
+
+   inst->vsi->row_info.dma_addr = 0;
+   inst->vsi->row_info.size = 0;
+
+   inst->vsi->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr;
+   inst->vsi->err_map.size = lat_buf->wdma_err_addr.size;
+
+   inst->vsi->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr;
+   inst->vsi->slice_bc.size = lat_buf->slice_bc_addr.size;
+
+   inst->vsi->trans.dma_addr_end = inst->ctx->msg_queue.wdma_rptr_addr;
+   inst->vsi->trans.dma_addr = inst->ctx->msg_queue.wdma_wptr_addr;
+}
+
+static int vdec_h264_slice_setup_core_buffer(struct vdec_h264_slice_inst *inst,
+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");
+   return -EBUSY;
+   }
+
+   y_fb_dma = (u64)fb->base_y.dma_addr;
+   if

[PATCH v6, 11/24] media: mediatek: vcodec: initialize msg and vsi information

2024-05-16 Thread Yunfei Dong
Need to initialize msg and vsi information before sending to optee-os, then
calling optee invoke command to send the information to optee-os.

For the optee communication interface is different with scp, using
flag to separate them.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_drv.h   |  2 +
 .../mediatek/vcodec/decoder/vdec_vpu_if.c | 49 ---
 .../mediatek/vcodec/decoder/vdec_vpu_if.h |  4 ++
 3 files changed, 49 insertions(+), 6 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 76a0323f993c..1540cb8bfe5c 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
@@ -175,6 +175,7 @@ struct mtk_vcodec_dec_pdata {
  * @vpu_inst: vpu instance pointer.
  *
  * @is_10bit_bitstream: set to true if it's 10bit bitstream
+ * @is_secure_playback: Secure Video Playback (SVP) mode
  */
 struct mtk_vcodec_dec_ctx {
enum mtk_instance_type type;
@@ -220,6 +221,7 @@ struct mtk_vcodec_dec_ctx {
void *vpu_inst;
 
bool is_10bit_bitstream;
+   bool is_secure_playback;
 };
 
 /**
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
index 82e57ae983d5..5336769a3fb5 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
@@ -148,7 +148,10 @@ static void vpu_dec_ipi_handler(void *data, unsigned int 
len, void *priv)
 
 static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, void *msg, int len)
 {
-   int err, id, msgid;
+   struct mtk_vdec_optee_data_to_shm *optee_data;
+   int data_size, id, hw_id, msgid;
+   void *ack_msg, *data_msg;
+   int err;
 
msgid = *(uint32_t *)msg;
mtk_vdec_debug(vpu->ctx, "id=%X", msgid);
@@ -158,16 +161,46 @@ static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, 
void *msg, int len)
 
if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) {
if (msgid == AP_IPIMSG_DEC_CORE ||
-   msgid == AP_IPIMSG_DEC_CORE_END)
+   msgid == AP_IPIMSG_DEC_CORE_END) {
+   optee_data = >core_optee_info;
id = vpu->core_id;
-   else
+   } else {
+   optee_data = >lat_optee_info;
id = vpu->id;
+   }
} else {
+   optee_data = >lat_optee_info;
id = vpu->id;
}
 
-   err = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, id, msg,
-len, 2000);
+   if (!vpu->ctx->is_secure_playback) {
+   err = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, id, 
msg, len, 2000);
+   } else {
+   hw_id = (id == SCP_IPI_VDEC_LAT) ? MTK_VDEC_LAT0 : 
MTK_VDEC_CORE;
+
+   mtk_vcodec_dec_optee_set_data(optee_data, msg, len, 
OPTEE_MSG_INDEX);
+
+   /* There is no need to copy the data (VSI) message to shared 
memory,
+* but we still need to set the buffer size to a non-zero value.
+*/
+   if (msgid == AP_IPIMSG_DEC_CORE || msgid == 
AP_IPIMSG_DEC_START) {
+   data_msg = 
mtk_vcodec_dec_get_shm_buffer_va(vpu->ctx->dev->optee_private,
+   hw_id, 
OPTEE_DATA_INDEX);
+   data_size = 
mtk_vcodec_dec_get_shm_buffer_size(vpu->ctx->dev->optee_private,
+  hw_id, 
OPTEE_DATA_INDEX);
+   mtk_vcodec_dec_optee_set_data(optee_data, data_msg, 
data_size,
+ OPTEE_DATA_INDEX);
+   }
+
+   err = 
mtk_vcodec_dec_optee_invokd_cmd(vpu->ctx->dev->optee_private,
+ hw_id, optee_data);
+   vpu->failure = err;
+
+   ack_msg = 
mtk_vcodec_dec_get_shm_buffer_va(vpu->ctx->dev->optee_private, hw_id,
+  OPTEE_MSG_INDEX);
+   vpu_dec_ipi_handler(ack_msg, 0, vpu->ctx->dev);
+   }
+
if (err) {
mtk_vdec_err(vpu->ctx, "send fail vpu_id=%d msg_id=%X 
status=%d",
 id, msgid, err);
@@ -213,7 +246,11 @@ int vpu_dec_init(struct vdec_vpu_inst *vpu)
return err;
}
 
-   if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) {
+   /* Using tee interface to communicate with op

[PATCH v6, 18/24] media: mediatek: vcodec: remove parse nal_info in kernel

2024-05-16 Thread Yunfei Dong
The hardware can parse syntax to get nal_info, needn't to use cpu.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/vdec/vdec_h264_req_multi_if.c| 13 ++---
 1 file changed, 2 insertions(+), 11 deletions(-)

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 40836673f7fe..f27d326f00ba 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
@@ -645,11 +645,10 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, 
struct mtk_vcodec_mem *bs,
struct vdec_h264_slice_inst *inst = h_vdec;
struct vdec_vpu_inst *vpu = >vpu;
struct mtk_video_dec_buf *src_buf_info;
-   int nal_start_idx, err, timeout = 0;
+   int err, timeout = 0;
unsigned int data[2];
struct vdec_lat_buf *lat_buf;
struct vdec_h264_slice_share_info *share_info;
-   unsigned char *buf;
 
if (vdec_msg_queue_init(>ctx->msg_queue, inst->ctx,
vdec_h264_slice_core_decode,
@@ -673,14 +672,6 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct 
mtk_vcodec_mem *bs,
share_info = lat_buf->private_data;
src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer);
 
-   buf = (unsigned char *)bs->va;
-   nal_start_idx = mtk_vdec_h264_find_start_code(buf, bs->size);
-   if (nal_start_idx < 0) {
-   err = -EINVAL;
-   goto err_free_fb_out;
-   }
-
-   inst->vsi->dec.nal_info = buf[nal_start_idx];
lat_buf->src_buf_req = src_buf_info->m2m_buf.vb.vb2_buf.req_obj.req;
v4l2_m2m_buf_copy_metadata(_buf_info->m2m_buf.vb, 
_buf->ts_info, true);
 
@@ -689,7 +680,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct 
mtk_vcodec_mem *bs,
goto err_free_fb_out;
 
if (!inst->ctx->is_secure_playback)
-   vdec_h264_insert_startcode(inst->ctx->dev, buf, >size,
+   vdec_h264_insert_startcode(inst->ctx->dev, bs->va, >size,
   _info->h264_slice_params.pps);
 
*res_chg = inst->resolution_changed;
-- 
2.25.1



[PATCH v6,09/24] media: mediatek: vcodec: allocate tee share memory

2024-05-16 Thread Yunfei Dong
Allocate two share memory for each lat and core hardware used to share
information with optee-os. Msg buffer used to send ipi command and get ack
command with optee-os, data buffer used to store vsi information which
used for hardware decode.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 80 ++-
 .../vcodec/decoder/mtk_vcodec_dec_optee.h | 32 
 2 files changed, 111 insertions(+), 1 deletion(-)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
index 38d9c1c1785a..611fb0e56480 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
@@ -47,13 +47,69 @@ int mtk_vcodec_dec_optee_private_init(struct 
mtk_vcodec_dec_dev *vcodec_dev)
 }
 EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_private_init);
 
+static void mtk_vcodec_dec_optee_deinit_memref(struct mtk_vdec_optee_ca_info 
*ca_info,
+  enum mtk_vdec_optee_data_index 
data_index)
+{
+   tee_shm_free(ca_info->shm_memref[data_index].msg_shm);
+}
+
+static int mtk_vcodec_dec_optee_init_memref(struct tee_context *tee_vdec_ctx,
+   struct mtk_vdec_optee_ca_info 
*ca_info,
+   enum mtk_vdec_optee_data_index 
data_index)
+{
+   struct mtk_vdec_optee_shm_memref *shm_memref;
+   int alloc_size = 0, err = 0;
+   u64 shm_param_type = 0;
+   bool copy_buffer;
+
+   switch (data_index) {
+   case OPTEE_MSG_INDEX:
+   shm_param_type = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+   alloc_size = MTK_VDEC_OPTEE_MSG_SIZE;
+   copy_buffer = true;
+   break;
+   case OPTEE_DATA_INDEX:
+   shm_param_type = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+   alloc_size = MTK_VDEC_OPTEE_HW_SIZE;
+   copy_buffer = false;
+   break;
+   default:
+   pr_err(MTK_DBG_VCODEC_STR "tee invalid data_index: %d.\n", 
data_index);
+   return -EINVAL;
+   }
+
+   shm_memref = _info->shm_memref[data_index];
+
+   /* Allocate dynamic shared memory with decoder TA */
+   shm_memref->msg_shm_size = alloc_size;
+   shm_memref->param_type = shm_param_type;
+   shm_memref->copy_to_ta = copy_buffer;
+   shm_memref->msg_shm = tee_shm_alloc_kernel_buf(tee_vdec_ctx, 
shm_memref->msg_shm_size);
+   if (IS_ERR(shm_memref->msg_shm)) {
+   pr_err(MTK_DBG_VCODEC_STR "tee alloc buf fail: 
data_index:%d.\n", data_index);
+   return -ENOMEM;
+   }
+
+   shm_memref->msg_shm_ca_buf = tee_shm_get_va(shm_memref->msg_shm, 0);
+   if (IS_ERR(shm_memref->msg_shm_ca_buf)) {
+   pr_err(MTK_DBG_VCODEC_STR "tee get shm va fail: 
data_index:%d.\n", data_index);
+   err = PTR_ERR(shm_memref->msg_shm_ca_buf);
+   goto err_get_msg_va;
+   }
+
+   return err;
+err_get_msg_va:
+   tee_shm_free(shm_memref->msg_shm);
+   return err;
+}
+
 static int mtk_vcodec_dec_optee_init_hw_info(struct mtk_vdec_optee_private 
*optee_private,
 enum mtk_vdec_hw_id hardware_index)
 {
struct device *dev = _private->vcodec_dev->plat_dev->dev;
struct tee_ioctl_open_session_arg session_arg;
struct mtk_vdec_optee_ca_info *ca_info;
-   int err = 0, session_func;
+   int err, i, j, session_func;
 
/* Open lat and core session with vdec TA. */
switch (hardware_index) {
@@ -87,6 +143,24 @@ static int mtk_vcodec_dec_optee_init_hw_info(struct 
mtk_vdec_optee_private *opte
dev_dbg(dev, MTK_DBG_VCODEC_STR "open vdec tee session hw_id:%d 
session_id=%x.\n",
hardware_index, ca_info->vdec_session_id);
 
+   /* Allocate dynamic shared memory with decoder TA */
+   for (i = 0; i < OPTEE_MAX_INDEX; i++) {
+   err = 
mtk_vcodec_dec_optee_init_memref(optee_private->tee_vdec_ctx, ca_info, i);
+   if (err) {
+   dev_err(dev, MTK_DBG_VCODEC_STR "init vdec memref 
failed: %d.\n", i);
+   goto err_init_memref;
+   }
+   }
+
+   return err;
+err_init_memref:
+   if (i != 0) {
+   for (j = 0; j < i; j++)
+   mtk_vcodec_dec_optee_deinit_memref(ca_info, j);
+   }
+
+   tee_client_close_session(optee_private->tee_vdec_ctx, 
ca_info->vdec_session_id);
+
return err;
 }
 
@@ -94,12 +168,16 @@ static void mtk_vcodec_dec_optee_deinit_hw_info(struct 
mtk_vdec_optee_private *o
enum mtk_vdec_hw_id hw_id)
 {
struct mtk_

[PATCH v6, 23/24] media: mediatek: vcodec: support av1 svp decoder for mt8188

2024-05-16 Thread Yunfei Dong
From: Xiaoyong Lu 

Change av1 driver to support secure video playback(svp) for
mt8188. Need to map shared memory with optee interface and
wait interrupt in optee-os.

Signed-off-by: Xiaoyong Lu 
Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/vdec/vdec_av1_req_lat_if.c | 97 ---
 1 file changed, 63 insertions(+), 34 deletions(-)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c
index bf21f2467a0f..a3ad35df7f73 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c
@@ -58,6 +58,9 @@
 #define SEG_LVL_ALT_Q 0
 #define SECONDARY_FILTER_STRENGTH_NUM_BITS 2
 
+#define AV1_IQ_TABLE_SIZE  0x12200
+#define AV1_CDF_TABLE_SIZE 0xFE80
+
 static const short div_lut[DIV_LUT_NUM + 1] = {
16384, 16320, 16257, 16194, 16132, 16070, 16009, 15948, 15888, 15828, 
15768,
15709, 15650, 15592, 15534, 15477, 15420, 15364, 15308, 15252, 15197, 
15142,
@@ -641,6 +644,8 @@ struct vdec_av1_slice_fb {
  * @frame: current frame info
  * @state: status after decode done
  * @cur_lst_tile_id:   tile id for large scale
+ * @tile_group:tile group info
+ * @reservd:   reserved
  */
 struct vdec_av1_slice_vsi {
/* lat */
@@ -665,6 +670,8 @@ struct vdec_av1_slice_vsi {
struct vdec_av1_slice_frame frame;
struct vdec_av1_slice_state state;
u32 cur_lst_tile_id;
+   struct vdec_av1_slice_tile_group tile_group;
+   unsigned int reservd[4];
 };
 
 /**
@@ -692,7 +699,6 @@ struct vdec_av1_slice_pfc {
  * @cdf_temp:   cdf temp buffer
  * @tile:   tile buffer
  * @slots:  slots info
- * @tile_group: tile_group entry
  * @level:  level of current resolution
  * @width:  width of last picture
  * @height: height of last picture
@@ -717,7 +723,6 @@ struct vdec_av1_slice_instance {
struct mtk_vcodec_mem cdf_temp;
struct mtk_vcodec_mem tile;
struct vdec_av1_slice_slot slots;
-   struct vdec_av1_slice_tile_group tile_group;
 
/* for resolution change and get_pic_info */
enum vdec_av1_slice_resolution_level level;
@@ -774,24 +779,28 @@ static int vdec_av1_slice_init_cdf_table(struct 
vdec_av1_slice_instance *instanc
 
ctx = instance->ctx;
vsi = instance->vpu.vsi;
-   remote_cdf_table = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
-(u32)vsi->cdf_table_addr);
-   if (IS_ERR(remote_cdf_table)) {
-   mtk_vdec_err(ctx, "failed to map cdf table\n");
-   return PTR_ERR(remote_cdf_table);
-   }
-
-   mtk_vdec_debug(ctx, "map cdf table to 0x%p\n", remote_cdf_table);
 
if (instance->cdf_table.va)
mtk_vcodec_mem_free(ctx, >cdf_table);
+   vsi->cdf_table_size = AV1_CDF_TABLE_SIZE;
+   mtk_vdec_debug(ctx, "svp %d. cdf table size 0x%x\n",
+  instance->ctx->is_secure_playback, vsi->cdf_table_size);
instance->cdf_table.size = vsi->cdf_table_size;
 
ret = mtk_vcodec_mem_alloc(ctx, >cdf_table);
if (ret)
return ret;
 
-   memcpy(instance->cdf_table.va, remote_cdf_table, vsi->cdf_table_size);
+   if (!instance->ctx->is_secure_playback) {
+   remote_cdf_table = 
mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
+
(u32)vsi->cdf_table_addr);
+   if (IS_ERR(remote_cdf_table)) {
+   mtk_vdec_err(ctx, "failed to map cdf table\n");
+   return PTR_ERR(remote_cdf_table);
+   }
+
+   memcpy(instance->cdf_table.va, remote_cdf_table, 
vsi->cdf_table_size);
+   }
 
return 0;
 }
@@ -805,25 +814,26 @@ static int vdec_av1_slice_init_iq_table(struct 
vdec_av1_slice_instance *instance
 
ctx = instance->ctx;
vsi = instance->vpu.vsi;
-   remote_iq_table = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
-   (u32)vsi->iq_table_addr);
-   if (IS_ERR(remote_iq_table)) {
-   mtk_vdec_err(ctx, "failed to map iq table\n");
-   return PTR_ERR(remote_iq_table);
-   }
-
-   mtk_vdec_debug(ctx, "map iq table to 0x%p\n", remote_iq_table);
 
if (instance->iq_table.va)
mtk_vcodec_mem_free(ctx, >iq_table);
+   vsi->iq_table_size = AV1_IQ_TABLE_SIZE;
instance->iq_table.size = vsi->iq_table_size;
 
ret = mtk_vcodec_mem_alloc(ctx, >iq_table);
   

[PATCH v6,15/24] media: mediatek: vcodec: Add one plane format

2024-05-16 Thread Yunfei Dong
Adding capture formats to support V4L2_PIX_FMT_MS21. This format has
one plane and only be used for secure video playback at current period.

Signed-off-by: Yunfei Dong 
---
 .../platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c| 4 +++-
 .../mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c   | 9 -
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index 9107707de6c4..192b01ff3ede 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -49,7 +49,9 @@ static bool mtk_vdec_get_cap_fmt(struct mtk_vcodec_dec_ctx 
*ctx, int format_inde
num_frame_count++;
}
 
-   if (num_frame_count == 1 || (!ctx->is_10bit_bitstream && fmt->fourcc == 
V4L2_PIX_FMT_MM21))
+   if ((!ctx->is_10bit_bitstream && fmt->fourcc == V4L2_PIX_FMT_MM21) ||
+   (ctx->is_secure_playback && fmt->fourcc == V4L2_PIX_FMT_MS21) ||
+   num_frame_count == 1)
return true;
 
q_data = >q_data[MTK_Q_DATA_SRC];
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index b903e39fee89..fbea00517565 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -229,7 +229,7 @@ static const struct mtk_stateless_control 
mtk_stateless_controls[] = {
 
 #define NUM_CTRLS ARRAY_SIZE(mtk_stateless_controls)
 
-static struct mtk_video_fmt mtk_video_formats[9];
+static struct mtk_video_fmt mtk_video_formats[10];
 
 static struct mtk_video_fmt default_out_format;
 static struct mtk_video_fmt default_cap_format;
@@ -770,6 +770,11 @@ static void mtk_vcodec_add_formats(unsigned int fourcc,
mtk_video_formats[count_formats].type = MTK_FMT_FRAME;
mtk_video_formats[count_formats].num_planes = 2;
break;
+   case V4L2_PIX_FMT_MS21:
+   mtk_video_formats[count_formats].fourcc = fourcc;
+   mtk_video_formats[count_formats].type = MTK_FMT_FRAME;
+   mtk_video_formats[count_formats].num_planes = 1;
+   break;
default:
mtk_v4l2_vdec_err(ctx, "Can not add unsupported format type");
return;
@@ -798,6 +803,8 @@ static void mtk_vcodec_get_supported_formats(struct 
mtk_vcodec_dec_ctx *ctx)
cap_format_count++;
}
if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_MM21) {
+   mtk_vcodec_add_formats(V4L2_PIX_FMT_MS21, ctx);
+   cap_format_count++;
mtk_vcodec_add_formats(V4L2_PIX_FMT_MM21, ctx);
cap_format_count++;
}
-- 
2.25.1



[PATCH v6,20/24] media: mediatek: vcodec: support tee decoder

2024-05-16 Thread Yunfei Dong
Initialize tee private data to support secure decoder.
Release tee related information for each instance when decoder
done.

Signed-off-by: Yunfei Dong 
---
 .../platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
index f47c98faf068..08e7d250487b 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
@@ -310,6 +310,9 @@ static int fops_vcodec_release(struct file *file)
v4l2_fh_exit(>fh);
v4l2_ctrl_handler_free(>ctrl_hdl);
 
+   if (ctx->is_secure_playback)
+   mtk_vcodec_dec_optee_release(dev->optee_private);
+
mtk_vcodec_dbgfs_remove(dev, ctx->id);
list_del_init(>list);
kfree(ctx);
@@ -466,6 +469,11 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
atomic_set(>dec_active_cnt, 0);
memset(dev->vdec_racing_info, 0, sizeof(dev->vdec_racing_info));
mutex_init(>dec_racing_info_mutex);
+   ret = mtk_vcodec_dec_optee_private_init(dev);
+   if (ret) {
+   dev_err(>dev, "Failed to init svp private.");
+   goto err_reg_cont;
+   }
 
ret = video_register_device(vfd_dec, VFL_TYPE_VIDEO, -1);
if (ret) {
-- 
2.25.1



[PATCH v6, 21/24] media: mediatek: vcodec: move vdec init interface to setup callback

2024-05-16 Thread Yunfei Dong
Getting secure video playback (svp) flag when request output buffer, then
calling init interface to init svp parameters in optee-os.

Signed-off-by: Yunfei Dong 
---
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c  | 139 +++---
 1 file changed, 89 insertions(+), 50 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index ebe21064616c..a07b6ba0ea82 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -184,6 +184,69 @@ void mtk_vcodec_dec_set_default_params(struct 
mtk_vcodec_dec_ctx *ctx)
q_data->bytesperline[1] = q_data->coded_width;
 }
 
+static int mtk_vcodec_dec_init_pic_info(struct mtk_vcodec_dec_ctx *ctx, enum 
v4l2_buf_type type)
+{
+   const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata;
+   struct mtk_q_data *q_data;
+   int ret;
+
+   if (!ctx->current_codec)
+   return 0;
+
+   if (V4L2_TYPE_IS_OUTPUT(type) && ctx->state == MTK_STATE_FREE) {
+   q_data = mtk_vdec_get_q_data(ctx, 
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+   if (!q_data)
+   return -EINVAL;
+
+   ret = vdec_if_init(ctx, q_data->fmt->fourcc);
+   if (ret) {
+   mtk_v4l2_vdec_err(ctx, "[%d]: vdec_if_init() fail 
ret=%d",
+ ctx->id, ret);
+   return -EINVAL;
+   }
+   ctx->state = MTK_STATE_INIT;
+   }
+
+   if (!dec_pdata->uses_stateless_api)
+   return 0;
+
+   /*
+* If get pic info fail, need to use the default pic info params, or
+* v4l2-compliance will fail
+*/
+   ret = vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, >picinfo);
+   if (ret)
+   mtk_v4l2_vdec_err(ctx, "[%d]Error!! Get GET_PARAM_PICTURE_INFO 
Fail",
+ ctx->id);
+
+   q_data = mtk_vdec_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+   if (q_data->fmt->num_planes == 1) {
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0] + 
ctx->picinfo.fb_sz[1];
+   q_data->bytesperline[0] = ctx->picinfo.buf_w;
+   } else {
+   if (ctx->is_secure_playback)
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0] + 
ctx->picinfo.fb_sz[1];
+   else
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0];
+
+   q_data->bytesperline[0] = ctx->picinfo.buf_w;
+   q_data->sizeimage[1] = ctx->picinfo.fb_sz[1];
+   q_data->bytesperline[1] = ctx->picinfo.buf_w;
+   }
+
+   q_data->coded_width = ctx->picinfo.buf_w;
+   q_data->coded_height = ctx->picinfo.buf_h;
+
+   ctx->last_decoded_picinfo = ctx->picinfo;
+   mtk_v4l2_vdec_dbg(2, ctx,
+ "[%d] init() plane:%d wxh=%dx%d pic wxh=%dx%d 
sz=0x%x_0x%x",
+ ctx->id, q_data->fmt->num_planes,
+ ctx->picinfo.buf_w, ctx->picinfo.buf_h,
+ ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+ q_data->sizeimage[0], q_data->sizeimage[1]);
+   return 0;
+}
+
 static int vidioc_vdec_qbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
 {
@@ -479,17 +542,7 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv,
ctx->ycbcr_enc = pix_mp->ycbcr_enc;
ctx->quantization = pix_mp->quantization;
ctx->xfer_func = pix_mp->xfer_func;
-
ctx->current_codec = fmt->fourcc;
-   if (ctx->state == MTK_STATE_FREE) {
-   ret = vdec_if_init(ctx, q_data->fmt->fourcc);
-   if (ret) {
-   mtk_v4l2_vdec_err(ctx, "[%d]: vdec_if_init() 
fail ret=%d",
- ctx->id, ret);
-   return -EINVAL;
-   }
-   ctx->state = MTK_STATE_INIT;
-   }
} else {
ctx->capture_fourcc = fmt->fourcc;
}
@@ -502,46 +555,11 @@ static int vidioc_vdec_s_fmt(struct file *file, void 
*priv,
ctx->picinfo.pic_w = pix_mp->width;
ctx->picinfo.pic_h = pix_mp->height;
 
-   /*
-* If get pic info fail, need to use the default pic info 
params, or
-* v4l2-compliance will fail
-*/
-   ret = vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, >picinfo);
-

[PATCH v6, 22/24] media: mediatek: vcodec: support hevc svp for mt8188

2024-05-16 Thread Yunfei Dong
Change hevc driver to support secure video playback(svp) for
mt8188. Need to map shared memory with optee interface and
wait interrupt in optee-os.

Signed-off-by: Yunfei Dong 
---
 .../decoder/vdec/vdec_hevc_req_multi_if.c | 89 +++
 1 file changed, 54 insertions(+), 35 deletions(-)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
index fe0a8508d632..30c85d053f18 100644
--- 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
+++ 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
@@ -415,11 +415,14 @@ static void vdec_hevc_fill_dpb_info(struct 
mtk_vcodec_dec_ctx *ctx,
hevc_dpb_info[index].field = dpb->field_pic;
 
hevc_dpb_info[index].y_dma_addr = 
vb2_dma_contig_plane_dma_addr(vb, 0);
-   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2)
-   hevc_dpb_info[index].c_dma_addr = 
vb2_dma_contig_plane_dma_addr(vb, 1);
-   else
-   hevc_dpb_info[index].c_dma_addr =
-   hevc_dpb_info[index].y_dma_addr + 
ctx->picinfo.fb_sz[0];
+   if (!ctx->is_secure_playback) {
+   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2)
+   hevc_dpb_info[index].c_dma_addr =
+   vb2_dma_contig_plane_dma_addr(vb, 1);
+   else
+   hevc_dpb_info[index].c_dma_addr =
+   hevc_dpb_info[index].y_dma_addr + 
ctx->picinfo.fb_sz[0];
+   }
}
 }
 
@@ -800,7 +803,7 @@ static int vdec_hevc_slice_setup_core_buffer(struct 
vdec_hevc_slice_inst *inst,
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;
+   u64 y_fb_dma, c_fb_dma = 0;
int i;
 
fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx);
@@ -810,18 +813,20 @@ static int vdec_hevc_slice_setup_core_buffer(struct 
vdec_hevc_slice_inst *inst,
}
 
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;
-   else
-   c_fb_dma = (u64)fb->base_c.dma_addr;
+   if (!ctx->is_secure_playback) {
+   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;
+   else
+   c_fb_dma = (u64)fb->base_c.dma_addr;
+   }
 
mtk_vdec_debug(inst->ctx, "[hevc-core] y/c addr = 0x%llx 0x%llx", 
y_fb_dma, c_fb_dma);
 
inst->vsi_core->fb.y.dma_addr = y_fb_dma;
inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[0];
inst->vsi_core->fb.c.dma_addr = c_fb_dma;
-   inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[1];
+   inst->vsi_core->fb.c.size = ctx->picinfo.fb_sz[1];
 
inst->vsi_core->dec.vdec_fb_va = (unsigned long)fb;
 
@@ -878,8 +883,13 @@ static int vdec_hevc_slice_init(struct mtk_vcodec_dec_ctx 
*ctx)
 
vsi_size = round_up(sizeof(struct vdec_hevc_slice_vsi), 
VCODEC_DEC_ALIGNED_64);
inst->vsi = inst->vpu.vsi;
-   inst->vsi_core =
-   (struct vdec_hevc_slice_vsi *)(((char *)inst->vpu.vsi) + 
vsi_size);
+   if (ctx->is_secure_playback)
+   inst->vsi_core =
+   
mtk_vcodec_dec_get_shm_buffer_va(ctx->dev->optee_private, MTK_VDEC_CORE,
+OPTEE_DATA_INDEX);
+   else
+   inst->vsi_core =
+   (struct vdec_hevc_slice_vsi *)(((char *)inst->vpu.vsi) 
+ vsi_size);
 
inst->resolution_changed = true;
inst->realloc_mv_buf = true;
@@ -944,21 +954,22 @@ static int vdec_hevc_slice_core_decode(struct 
vdec_lat_buf *lat_buf)
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);
-   inst->vsi_core->dec.timeout = !!timeout;
+   if (!vpu->ctx->is_secure_playback) {
+   /* wait decoder done interrupt */
+   timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, 
MTK_INST_IRQ_R

[PATCH v6, 13/24] media: mediatek: vcodec: using shared memory as vsi address

2024-05-16 Thread Yunfei Dong
The vsi buffer is allocated by tee share memory for svp mode, need to
use the share memory as the vsi address to store vsi data.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/vdec/vdec_h264_req_multi_if.c | 9 +++--
 .../media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c | 8 ++--
 2 files changed, 13 insertions(+), 4 deletions(-)

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 2d4611e7fa0b..d7fec1887ab5 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
@@ -417,8 +417,13 @@ static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx 
*ctx)
 
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);
+   if (ctx->is_secure_playback)
+   inst->vsi_core =
+   
mtk_vcodec_dec_get_shm_buffer_va(ctx->dev->optee_private, MTK_VDEC_CORE,
+OPTEE_DATA_INDEX);
+   else
+   inst->vsi_core =
+   (struct vdec_h264_slice_vsi *)(((char *)inst->vpu.vsi) 
+ vsi_size);
inst->resolution_changed = true;
inst->realloc_mv_buf = true;
 
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
index 5336769a3fb5..5c31641e9abe 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
@@ -18,8 +18,12 @@ static void handle_init_ack_msg(const struct 
vdec_vpu_ipi_init_ack *msg)
 
/* mapping VPU address to kernel virtual address */
/* the content in vsi is initialized to 0 in VPU */
-   vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->fw_handler,
-msg->vpu_inst_addr);
+   if (vpu->ctx->is_secure_playback)
+   vpu->vsi = 
mtk_vcodec_dec_get_shm_buffer_va(vpu->ctx->dev->optee_private,
+   MTK_VDEC_LAT0, 
OPTEE_DATA_INDEX);
+   else
+   vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->fw_handler,
+msg->vpu_inst_addr);
vpu->inst_addr = msg->vpu_inst_addr;
 
mtk_vdec_debug(vpu->ctx, "- vpu_inst_addr = 0x%x", vpu->inst_addr);
-- 
2.25.1



[PATCH v6, 14/24] media: mediatek: vcodec: Add capture format to support one plane memory

2024-05-16 Thread Yunfei Dong
Define one uncompressed capture format V4L2_PIX_FMT_MS21 in order to
support one plane memory. The buffer size is luma + chroma, luma is
stored at the start and chrome is stored at the end.

Signed-off-by: Yunfei Dong 
---
 Documentation/userspace-api/media/v4l/pixfmt-reserved.rst | 8 
 drivers/media/v4l2-core/v4l2-common.c | 2 ++
 drivers/media/v4l2-core/v4l2-ioctl.c  | 1 +
 include/uapi/linux/videodev2.h| 1 +
 4 files changed, 12 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst 
b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
index 886ba7b08d6b..6ec899649d50 100644
--- a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
+++ b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
@@ -295,6 +295,14 @@ please make a proposal on the linux-media mailing list.
   - Compressed format used by Nuvoton NPCM video driver. This format is
 defined in Remote Framebuffer Protocol (RFC 6143, chapter 7.7.4 Hextile
 Encoding).
+* .. _V4L2-PIX-FMT-MS21:
+
+  - ``V4L2_PIX_FMT_MS21``
+  - 'MS21'
+  - This format has one plane, luma and chroma are stored in a contiguous
+memory. Luma pixel in 16x32 tiles at the start, chroma pixel in 16x16
+tiles at the end. The image height must be aligned with 32 and the 
image
+width must be aligned with 16.
 .. raw:: latex
 
 \normalsize
diff --git a/drivers/media/v4l2-core/v4l2-common.c 
b/drivers/media/v4l2-core/v4l2-common.c
index 4165c815faef..5ae54cf48dc7 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -271,6 +271,8 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
  .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
{ .format = V4L2_PIX_FMT_MT2110R, .pixel_enc = 
V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, 
.bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
  .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
+   { .format = V4L2_PIX_FMT_MS21, pixel_enc = V4L2_PIXEL_ENC_YUV, 
.mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 
1 }, .hdiv = 2, .vdiv = 2,
+ .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
 
/* YUV planar formats */
{ .format = V4L2_PIX_FMT_NV12,.pixel_enc = 
V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, 
.bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 4c76d17b4629..3a68f2b9e7a4 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1529,6 +1529,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_MT2110T:  descr = "Mediatek 10bit Tile 
Mode"; break;
case V4L2_PIX_FMT_MT2110R:  descr = "Mediatek 10bit Raster 
Mode"; break;
case V4L2_PIX_FMT_HEXTILE:  descr = "Hextile Compressed 
Format"; break;
+   case V4L2_PIX_FMT_MS21: descr = "MediaTek One Plane 
Format"; break;
default:
if (fmt->description[0])
return;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 89eb1a3c6555..7aff2f2c8f9c 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -800,6 +800,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_MM21 v4l2_fourcc('M', 'M', '2', '1') /* Mediatek 
8-bit block mode, two non-contiguous planes */
 #define V4L2_PIX_FMT_MT2110T  v4l2_fourcc('M', 'T', '2', 'T') /* Mediatek 
10-bit block tile mode */
 #define V4L2_PIX_FMT_MT2110R  v4l2_fourcc('M', 'T', '2', 'R') /* Mediatek 
10-bit block raster mode */
+#define V4L2_PIX_FMT_MS21 v4l2_fourcc('M', 'S', '2', '1') /* MediaTek 
8-bit block mode with one plane */
 #define V4L2_PIX_FMT_INZI v4l2_fourcc('I', 'N', 'Z', 'I') /* Intel Planar 
Greyscale 10-bit and Depth 16-bit */
 #define V4L2_PIX_FMT_CNF4 v4l2_fourcc('C', 'N', 'F', '4') /* Intel 4-bit 
packed depth confidence information */
 #define V4L2_PIX_FMT_HI240v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit 
dithered RGB */
-- 
2.25.1



[PATCH v6, 24/24] media: mediatek: vcodec: support vp9 svp decoder for mt8188

2024-05-16 Thread Yunfei Dong
From: Yilong Zhou 

Change vp9 driver to support secure video playback(svp) for
mt8188. Need to map shared memory with optee interface and
wait interrupt in optee-os.

Signed-off-by: Yilong Zhou 
Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/vdec/vdec_vp9_req_lat_if.c | 91 ---
 1 file changed, 59 insertions(+), 32 deletions(-)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c
index cf48d09b78d7..9f64661800af 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c
@@ -141,6 +141,7 @@ struct vdec_vp9_slice_frame_counts {
  * @skip:  skip counts.
  * @y_mode:Y prediction mode counts.
  * @filter:interpolation filter counts.
+ * @mv_joint:  motion vector joint counts.
  * @sign:  motion vector sign counts.
  * @classes:   motion vector class counts.
  * @class0:motion vector class0 bit counts.
@@ -804,6 +805,9 @@ static void vdec_vp9_slice_setup_frame_ctx(struct 
vdec_vp9_slice_instance *insta
error_resilient_mode = HDR_FLAG(ERROR_RESILIENT);
reset_frame_context = uh->reset_frame_context;
 
+   if (instance->ctx->is_secure_playback)
+   return;
+
/*
 * according to "6.2 Uncompressed header syntax" in
 * "VP9 Bitstream & Decoding Process Specification",
@@ -818,8 +822,7 @@ static void vdec_vp9_slice_setup_frame_ctx(struct 
vdec_vp9_slice_instance *insta
 * 2 resets just the context specified in the frame header
 * 3 resets all contexts
 */
-   if (key_frame || error_resilient_mode ||
-   reset_frame_context == 3) {
+   if (key_frame || error_resilient_mode || reset_frame_context == 
3) {
/* use default table */
for (i = 0; i < 4; i++)
instance->dirty[i] = 0;
@@ -1042,6 +1045,9 @@ static void vdec_vp9_slice_setup_seg_buffer(struct 
vdec_vp9_slice_instance *inst
 {
struct vdec_vp9_slice_uncompressed_header *uh;
 
+   if (instance->ctx->is_secure_playback)
+   return;
+
/* reset segment buffer */
uh = >frame.uh;
if (uh->frame_type == 0 ||
@@ -1172,15 +1178,16 @@ static int vdec_vp9_slice_setup_lat(struct 
vdec_vp9_slice_instance *instance,
 
vdec_vp9_slice_setup_seg_buffer(instance, vsi, >seg[0]);
 
-   /* setup prob/tile buffers for LAT */
-
-   ret = vdec_vp9_slice_setup_prob_buffer(instance, vsi);
-   if (ret)
-   goto err;
+   if (!instance->ctx->is_secure_playback) {
+   /* setup prob/tile buffers for LAT */
+   ret = vdec_vp9_slice_setup_prob_buffer(instance, vsi);
+   if (ret)
+   goto err;
 
-   ret = vdec_vp9_slice_setup_tile_buffer(instance, vsi, bs);
-   if (ret)
-   goto err;
+   ret = vdec_vp9_slice_setup_tile_buffer(instance, vsi, bs);
+   if (ret)
+   goto err;
+   }
 
return 0;
 
@@ -1599,7 +1606,8 @@ static int vdec_vp9_slice_update_single(struct 
vdec_vp9_slice_instance *instance
   pfc->seq, vsi->state.crc[4], vsi->state.crc[5],
   vsi->state.crc[6], vsi->state.crc[7]);
 
-   vdec_vp9_slice_update_prob(instance, vsi);
+   if (!instance->ctx->is_secure_playback)
+   vdec_vp9_slice_update_prob(instance, vsi);
 
instance->width = vsi->frame.uh.frame_width;
instance->height = vsi->frame.uh.frame_height;
@@ -1632,7 +1640,8 @@ static int vdec_vp9_slice_update_lat(struct 
vdec_vp9_slice_instance *instance,
return -EAGAIN;
}
 
-   vdec_vp9_slice_update_prob(instance, vsi);
+   if (!instance->ctx->is_secure_playback)
+   vdec_vp9_slice_update_prob(instance, vsi);
 
instance->width = vsi->frame.uh.frame_width;
instance->height = vsi->frame.uh.frame_height;
@@ -1694,8 +1703,13 @@ static int vdec_vp9_slice_setup_core_buffer(struct 
vdec_vp9_slice_instance *inst
return -EINVAL;
 
/* update internal buffer's width/height */
-   instance->dpb[vb->index].width = w;
-   instance->dpb[vb->index].height = h;
+   for (i = 0; i < vq->num_buffers; i++) {
+   if (vb == vq->bufs[i]) {
+   instance->dpb[i].width = w;
+   instance->dpb[i].height = h;
+   break;
+   }
+   }
 
/*
 * get buffer's width/height from instance
@@ -1779,7 +1793,8 @@ static int vdec_vp9_slice_setup_core(struct 
vdec_vp9_slice_instance *instance

[PATCH v6, 19/24] media: mediatek: vcodec: disable wait interrupt for svp mode

2024-05-16 Thread Yunfei Dong
Waiting interrupt in optee-os for svp mode, need to disable it in kernel
in case of interrupt is cleaned.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_hw.c| 34 +--
 .../vcodec/decoder/mtk_vcodec_dec_pm.c|  6 +-
 .../decoder/vdec/vdec_h264_req_multi_if.c | 57 +++
 3 files changed, 54 insertions(+), 43 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
index 881d5de41e05..1982c088c6da 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
@@ -72,26 +72,28 @@ static irqreturn_t mtk_vdec_hw_irq_handler(int irq, void 
*priv)
 
ctx = mtk_vcodec_get_curr_ctx(dev->main_dev, dev->hw_idx);
 
-   /* check if HW active or not */
-   cg_status = readl(dev->reg_base[VDEC_HW_SYS] + VDEC_HW_ACTIVE_ADDR);
-   if (cg_status & VDEC_HW_ACTIVE_MASK) {
-   mtk_v4l2_vdec_err(ctx, "vdec active is not 0x0 (0x%08x)", 
cg_status);
-   return IRQ_HANDLED;
-   }
+   if (!ctx->is_secure_playback) {
+   /* check if HW active or not */
+   cg_status = readl(dev->reg_base[VDEC_HW_SYS] + 
VDEC_HW_ACTIVE_ADDR);
+   if (cg_status & VDEC_HW_ACTIVE_MASK) {
+   mtk_v4l2_vdec_err(ctx, "vdec active is not 0x0 
(0x%08x)", cg_status);
+   return IRQ_HANDLED;
+   }
 
-   dec_done_status = readl(vdec_misc_addr);
-   if ((dec_done_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) !=
-   MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
-   return IRQ_HANDLED;
+   dec_done_status = readl(vdec_misc_addr);
+   if ((dec_done_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) !=
+   MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
+   return IRQ_HANDLED;
 
-   /* clear interrupt */
-   writel(dec_done_status | VDEC_IRQ_CFG, vdec_misc_addr);
-   writel(dec_done_status & ~VDEC_IRQ_CLR, vdec_misc_addr);
+   /* clear interrupt */
+   writel(dec_done_status | VDEC_IRQ_CFG, vdec_misc_addr);
+   writel(dec_done_status & ~VDEC_IRQ_CLR, vdec_misc_addr);
 
-   wake_up_dec_ctx(ctx, MTK_INST_IRQ_RECEIVED, dev->hw_idx);
+   wake_up_dec_ctx(ctx, MTK_INST_IRQ_RECEIVED, dev->hw_idx);
 
-   mtk_v4l2_vdec_dbg(3, ctx, "wake up ctx %d, dec_done_status=%x",
- ctx->id, dec_done_status);
+   mtk_v4l2_vdec_dbg(3, ctx, "wake up ctx %d, dec_done_status=%x",
+ ctx->id, dec_done_status);
+   }
 
return IRQ_HANDLED;
 }
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c
index aefd3e9e3061..a94eda936f16 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c
@@ -238,7 +238,8 @@ void mtk_vcodec_dec_enable_hardware(struct 
mtk_vcodec_dec_ctx *ctx, int hw_idx)
mtk_vcodec_dec_child_dev_on(ctx->dev, MTK_VDEC_LAT0);
mtk_vcodec_dec_child_dev_on(ctx->dev, hw_idx);
 
-   mtk_vcodec_dec_enable_irq(ctx->dev, hw_idx);
+   if (!ctx->is_secure_playback)
+   mtk_vcodec_dec_enable_irq(ctx->dev, hw_idx);
 
if (IS_VDEC_INNER_RACING(ctx->dev->dec_capability))
mtk_vcodec_load_racing_info(ctx);
@@ -250,7 +251,8 @@ void mtk_vcodec_dec_disable_hardware(struct 
mtk_vcodec_dec_ctx *ctx, int hw_idx)
if (IS_VDEC_INNER_RACING(ctx->dev->dec_capability))
mtk_vcodec_record_racing_info(ctx);
 
-   mtk_vcodec_dec_disable_irq(ctx->dev, hw_idx);
+   if (!ctx->is_secure_playback)
+   mtk_vcodec_dec_disable_irq(ctx->dev, hw_idx);
 
mtk_vcodec_dec_child_dev_off(ctx->dev, hw_idx);
if (IS_VDEC_LAT_ARCH(ctx->dev->vdec_pdata->hw_arch) &&
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 f27d326f00ba..3186777dcc13 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
@@ -593,14 +593,16 @@ static int vdec_h264_slice_core_decode(struct 
vdec_lat_buf *lat_buf)
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);
-   i

[PATCH v6, 16/24] media: mediatek: vcodec: support one plane capture buffer

2024-05-16 Thread Yunfei Dong
The capture buffer has two planes for format MM21, but user space only
allocate secure memory for plane[0], and the size is Y data + uv data.
The driver need to support one plane decoder for svp mode.

Signed-off-by: Yunfei Dong 
---
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c  |  7 -
 .../vcodec/decoder/mtk_vcodec_dec_stateless.c | 26 ++-
 .../decoder/vdec/vdec_h264_req_common.c   | 18 ++---
 .../mediatek/vcodec/decoder/vdec_drv_if.c |  4 +--
 4 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index 192b01ff3ede..ebe21064616c 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -653,7 +653,12 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv,
 * So we just return picinfo yet, and update picinfo in
 * stop_streaming hook function
 */
-   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0];
+
+   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1 || 
ctx->is_secure_playback)
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0] + 
ctx->picinfo.fb_sz[1];
+   else
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0];
+
q_data->sizeimage[1] = ctx->picinfo.fb_sz[1];
q_data->bytesperline[0] = ctx->last_decoded_picinfo.buf_w;
q_data->bytesperline[1] = ctx->last_decoded_picinfo.buf_w;
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index fbea00517565..a1a99878f2c6 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -285,14 +285,14 @@ static struct vdec_fb *vdec_get_cap_buffer(struct 
mtk_vcodec_dec_ctx *ctx)
framebuf = container_of(vb2_v4l2, struct mtk_video_dec_buf, m2m_buf.vb);
 
pfb = >frame_buffer;
-   pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0);
+   if (!ctx->is_secure_playback)
+   pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0);
pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
pfb->base_y.size = ctx->q_data[MTK_Q_DATA_DST].sizeimage[0];
 
-   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2) {
+   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2 && 
!ctx->is_secure_playback) {
pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1);
-   pfb->base_c.dma_addr =
-   vb2_dma_contig_plane_dma_addr(dst_buf, 1);
+   pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 
1);
pfb->base_c.size = ctx->q_data[MTK_Q_DATA_DST].sizeimage[1];
}
mtk_v4l2_vdec_dbg(1, ctx,
@@ -339,16 +339,18 @@ static void mtk_vdec_worker(struct work_struct *work)
mtk_v4l2_vdec_dbg(3, ctx, "[%d] (%d) id=%d, vb=%p", ctx->id,
  vb2_src->vb2_queue->type, vb2_src->index, vb2_src);
 
-   bs_src->va = vb2_plane_vaddr(vb2_src, 0);
-   bs_src->dma_addr = vb2_dma_contig_plane_dma_addr(vb2_src, 0);
-   bs_src->size = (size_t)vb2_src->planes[0].bytesused;
-   if (!bs_src->va) {
-   v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
-   mtk_v4l2_vdec_err(ctx, "[%d] id=%d source buffer is NULL", 
ctx->id,
- vb2_src->index);
-   return;
+   if (!ctx->is_secure_playback) {
+   bs_src->va = vb2_plane_vaddr(vb2_src, 0);
+   if (!bs_src->va) {
+   v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+   mtk_v4l2_vdec_err(ctx, "[%d] id=%d source buffer is 
NULL", ctx->id,
+ vb2_src->index);
+   return;
+   }
}
 
+   bs_src->dma_addr = vb2_dma_contig_plane_dma_addr(vb2_src, 0);
+   bs_src->size = (size_t)vb2_src->planes[0].bytesused;
mtk_v4l2_vdec_dbg(3, ctx, "[%d] Bitstream VA=%p DMA=%pad Size=%zx 
vb=%p",
  ctx->id, bs_src->va, _src->dma_addr, bs_src->size, 
vb2_src);
/* Apply request controls. */
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c
index 5ca20d75dc8e..5e0d55218363 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c
+++ b

[PATCH v6, 10/24] media: mediatek: vcodec: send share memory data to optee

2024-05-16 Thread Yunfei Dong
Setting msg and vsi information to shared buffer, then call tee invoke
function to send it to optee-os.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 140 ++
 .../vcodec/decoder/mtk_vcodec_dec_optee.h |  51 +++
 2 files changed, 191 insertions(+)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
index 611fb0e56480..f29a8d143fee 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
@@ -241,3 +241,143 @@ void mtk_vcodec_dec_optee_release(struct 
mtk_vdec_optee_private *optee_private)
mutex_unlock(_private->tee_mutex);
 }
 EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_release);
+
+static int mtk_vcodec_dec_optee_fill_shm(struct tee_param *command_params,
+struct mtk_vdec_optee_shm_memref 
*shm_memref,
+struct mtk_vdec_optee_data_to_shm 
*data,
+int index, struct device *dev)
+{
+   if (!data->msg_buf_size[index] || !data->msg_buf[index]) {
+   pr_err(MTK_DBG_VCODEC_STR "tee invalid buf param: %d.\n", 
index);
+   return -EINVAL;
+   }
+
+   *command_params = (struct tee_param) {
+   .attr = shm_memref->param_type,
+   .u.memref = {
+   .shm = shm_memref->msg_shm,
+   .size = data->msg_buf_size[index],
+   .shm_offs = 0,
+   },
+   };
+
+   if (!shm_memref->copy_to_ta) {
+   dev_dbg(dev, MTK_DBG_VCODEC_STR "share memref data: 0x%x 
param_type:%llu.\n",
+   *((unsigned int *)shm_memref->msg_shm_ca_buf), 
shm_memref->param_type);
+   return 0;
+   }
+
+   memset(shm_memref->msg_shm_ca_buf, 0, shm_memref->msg_shm_size);
+   memcpy(shm_memref->msg_shm_ca_buf, data->msg_buf[index], 
data->msg_buf_size[index]);
+
+   dev_dbg(dev, MTK_DBG_VCODEC_STR "share memref data => msg id:0x%x 0x%x 
param_type:%llu.\n",
+   *((unsigned int *)data->msg_buf[index]),
+   *((unsigned int *)shm_memref->msg_shm_ca_buf),
+   shm_memref->param_type);
+
+   return 0;
+}
+
+void mtk_vcodec_dec_optee_set_data(struct mtk_vdec_optee_data_to_shm *data,
+  void *buf, int buf_size,
+  enum mtk_vdec_optee_data_index index)
+{
+   data->msg_buf[index] = buf;
+   data->msg_buf_size[index] = buf_size;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_set_data);
+
+int mtk_vcodec_dec_optee_invokd_cmd(struct mtk_vdec_optee_private 
*optee_private,
+   enum mtk_vdec_hw_id hw_id,
+   struct mtk_vdec_optee_data_to_shm *data)
+{
+   struct device *dev = _private->vcodec_dev->plat_dev->dev;
+   struct tee_ioctl_invoke_arg trans_args;
+   struct tee_param command_params[MTK_OPTEE_MAX_TEE_PARAMS];
+   struct mtk_vdec_optee_ca_info *ca_info;
+   struct mtk_vdec_optee_shm_memref *shm_memref;
+   int ret, index;
+
+   if (hw_id == MTK_VDEC_LAT0)
+   ca_info = _private->lat_ca;
+   else
+   ca_info = _private->core_ca;
+
+   memset(_args, 0, sizeof(trans_args));
+   memset(command_params, 0, sizeof(command_params));
+
+   trans_args = (struct tee_ioctl_invoke_arg) {
+   .func = ca_info->vdec_session_func,
+   .session = ca_info->vdec_session_id,
+   .num_params = MTK_OPTEE_MAX_TEE_PARAMS,
+   };
+
+   /* Fill msg command parameters */
+   for (index = 0; index < MTK_OPTEE_MAX_TEE_PARAMS; index++) {
+   shm_memref = _info->shm_memref[index];
+
+   if (shm_memref->param_type == TEE_IOCTL_PARAM_ATTR_TYPE_NONE ||
+   data->msg_buf_size[index] == 0)
+   continue;
+
+   dev_dbg(dev, MTK_DBG_VCODEC_STR "tee share memory data size: %d 
-> %d.\n",
+   data->msg_buf_size[index], shm_memref->msg_shm_size);
+
+   if (data->msg_buf_size[index] > shm_memref->msg_shm_size) {
+   dev_err(dev, MTK_DBG_VCODEC_STR "tee buf size big than 
shm (%d -> %d).\n",
+   data->msg_buf_size[index], 
shm_memref->msg_shm_size);
+   return -EINVAL;
+   }
+
+   ret = mtk_vcodec_dec_optee_fill_shm(_params[index], 
shm_memref,
+   data, index, dev);
+   if (ret)
+   return ret;
+ 

[PATCH v6, 12/24] media: mediatek: vcodec: add interface to allocate/free secure memory

2024-05-16 Thread Yunfei Dong
Need to call dma heap interface to allocate/free secure memory when playing
secure video.

Signed-off-by: Yunfei Dong 
---
 .../media/platform/mediatek/vcodec/Kconfig|   1 +
 .../mediatek/vcodec/common/mtk_vcodec_util.c  | 122 +-
 .../mediatek/vcodec/common/mtk_vcodec_util.h  |   3 +
 3 files changed, 123 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/Kconfig 
b/drivers/media/platform/mediatek/vcodec/Kconfig
index bc8292232530..707865703e61 100644
--- a/drivers/media/platform/mediatek/vcodec/Kconfig
+++ b/drivers/media/platform/mediatek/vcodec/Kconfig
@@ -17,6 +17,7 @@ config VIDEO_MEDIATEK_VCODEC
depends on VIDEO_MEDIATEK_VPU || !VIDEO_MEDIATEK_VPU
depends on MTK_SCP || !MTK_SCP
depends on MTK_SMI || (COMPILE_TEST && MTK_SMI=n)
+   depends on DMABUF_HEAPS
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
select VIDEO_MEDIATEK_VCODEC_VPU if VIDEO_MEDIATEK_VPU
diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c 
b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c
index c60e4c193b25..5958dcd7965a 100644
--- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c
+++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c
@@ -5,9 +5,11 @@
 *  Tiffany Lin 
 */
 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "../decoder/mtk_vcodec_dec_drv.h"
 #include "../encoder/mtk_vcodec_enc_drv.h"
@@ -45,7 +47,7 @@ int mtk_vcodec_write_vdecsys(struct mtk_vcodec_dec_ctx *ctx, 
unsigned int reg,
 }
 EXPORT_SYMBOL(mtk_vcodec_write_vdecsys);
 
-int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem *mem)
+static int mtk_vcodec_mem_alloc_nor(void *priv, struct mtk_vcodec_mem *mem)
 {
enum mtk_instance_type inst_type = *((unsigned int *)priv);
struct platform_device *plat_dev;
@@ -75,9 +77,71 @@ int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem 
*mem)
 
return 0;
 }
-EXPORT_SYMBOL(mtk_vcodec_mem_alloc);
 
-void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem *mem)
+static int mtk_vcodec_mem_alloc_sec(struct mtk_vcodec_dec_ctx *ctx, struct 
mtk_vcodec_mem *mem)
+{
+   struct device *dev = >dev->plat_dev->dev;
+   struct dma_buf *dma_buffer;
+   struct dma_heap *vdec_heap;
+   struct dma_buf_attachment *attach;
+   struct sg_table *sgt;
+   unsigned long size = mem->size;
+   int ret = 0;
+
+   if (!size)
+   return -EINVAL;
+
+   vdec_heap = dma_heap_find("restricted_mtk_cma");
+   if (!vdec_heap) {
+   mtk_v4l2_vdec_err(ctx, "dma heap find failed!");
+   return -EPERM;
+   }
+
+   dma_buffer = dma_heap_buffer_alloc(vdec_heap, size, 
DMA_HEAP_VALID_FD_FLAGS,
+  DMA_HEAP_VALID_HEAP_FLAGS);
+   if (IS_ERR_OR_NULL(dma_buffer)) {
+   mtk_v4l2_vdec_err(ctx, "dma heap alloc size=0x%lx failed!", 
size);
+   return PTR_ERR(dma_buffer);
+   }
+
+   attach = dma_buf_attach(dma_buffer, dev);
+   if (IS_ERR_OR_NULL(attach)) {
+   mtk_v4l2_vdec_err(ctx, "dma attach size=0x%lx failed!", size);
+   ret = PTR_ERR(attach);
+   goto err_attach;
+   }
+
+   sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+   if (IS_ERR_OR_NULL(sgt)) {
+   mtk_v4l2_vdec_err(ctx, "dma map attach size=0x%lx failed!", 
size);
+   ret = PTR_ERR(sgt);
+   goto err_sgt;
+   }
+
+   mem->va = dma_buffer;
+   mem->dma_addr = (dma_addr_t)sg_dma_address((sgt)->sgl);
+
+   if (!mem->va || !mem->dma_addr) {
+   mtk_v4l2_vdec_err(ctx, "dma buffer size=0x%lx failed!", size);
+   ret = -EPERM;
+   goto err_addr;
+   }
+
+   mem->attach = attach;
+   mem->sgt = sgt;
+
+   return 0;
+err_addr:
+   dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+err_sgt:
+   dma_buf_detach(dma_buffer, attach);
+err_attach:
+   dma_buf_put(dma_buffer);
+
+   return ret;
+}
+
+static void mtk_vcodec_mem_free_nor(void *priv, struct mtk_vcodec_mem *mem)
 {
enum mtk_instance_type inst_type = *((unsigned int *)priv);
struct platform_device *plat_dev;
@@ -110,6 +174,57 @@ void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem 
*mem)
mem->dma_addr = 0;
mem->size = 0;
 }
+
+static void mtk_vcodec_mem_free_sec(struct mtk_vcodec_mem *mem)
+{
+   if (mem->sgt)
+   dma_buf_unmap_attachment(mem->attach, mem->sgt, 
DMA_BIDIRECTIONAL);
+   dma_buf_detach((struct dma_buf *)mem->va, mem->attach);
+   dma_buf_put((struct dma_buf *)mem->va);
+
+   mem->attach = NULL;
+   mem->sgt = NULL;
+   mem->va = NULL;
+   me

[PATCH v6, 07/24] dma-heap: Provide accessors so that in-kernel drivers can allocate dmabufs from specific heaps

2024-05-16 Thread Yunfei Dong
From: John Stultz 

This allows drivers who don't want to create their own
DMA-BUF exporter to be able to allocate DMA-BUFs directly
from existing DMA-BUF Heaps.

There is some concern that the premise of DMA-BUF heaps is
that userland knows better about what type of heap memory
is needed for a pipeline, so it would likely be best for
drivers to import and fill DMA-BUFs allocated by userland
instead of allocating one themselves, but this is still
up for debate.

Signed-off-by: John Stultz 
Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Fix the checkpatch alignment warning]
Signed-off-by: Yunfei Dong 
---
 drivers/dma-buf/dma-heap.c | 83 ++
 include/linux/dma-heap.h   |  6 +++
 2 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 97025ee8500f..6efe833a4b10 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -51,12 +51,24 @@ static dev_t dma_heap_devt;
 static struct class *dma_heap_class;
 static DEFINE_XARRAY_ALLOC(dma_heap_minors);
 
-static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
-unsigned int fd_flags,
-unsigned int heap_flags)
+/**
+ * dma_heap_buffer_alloc - Allocate dma-buf from a dma_heap
+ * @heap:  DMA-Heap to allocate from
+ * @len:   size to allocate in bytes
+ * @fd_flags:  flags to set on returned dma-buf fd
+ * @heap_flags: flags to pass to the dma heap
+ *
+ * This is for internal dma-buf allocations only. Free returned buffers with 
dma_buf_put().
+ */
+struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
+ unsigned int fd_flags,
+ unsigned int heap_flags)
 {
-   struct dma_buf *dmabuf;
-   int fd;
+   if (fd_flags & ~DMA_HEAP_VALID_FD_FLAGS)
+   return ERR_PTR(-EINVAL);
+
+   if (heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
+   return ERR_PTR(-EINVAL);
 
/*
 * Allocations from all heaps have to begin
@@ -64,9 +76,20 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, 
size_t len,
 */
len = PAGE_ALIGN(len);
if (!len)
-   return -EINVAL;
+   return ERR_PTR(-EINVAL);
+
+   return heap->ops->allocate(heap, len, fd_flags, heap_flags);
+}
+EXPORT_SYMBOL_GPL(dma_heap_buffer_alloc);
 
-   dmabuf = heap->ops->allocate(heap, len, fd_flags, heap_flags);
+static int dma_heap_bufferfd_alloc(struct dma_heap *heap, size_t len,
+  unsigned int fd_flags,
+  unsigned int heap_flags)
+{
+   struct dma_buf *dmabuf;
+   int fd;
+
+   dmabuf = dma_heap_buffer_alloc(heap, len, fd_flags, heap_flags);
if (IS_ERR(dmabuf))
return PTR_ERR(dmabuf);
 
@@ -104,15 +127,9 @@ static long dma_heap_ioctl_allocate(struct file *file, 
void *data)
if (heap_allocation->fd)
return -EINVAL;
 
-   if (heap_allocation->fd_flags & ~DMA_HEAP_VALID_FD_FLAGS)
-   return -EINVAL;
-
-   if (heap_allocation->heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
-   return -EINVAL;
-
-   fd = dma_heap_buffer_alloc(heap, heap_allocation->len,
-  heap_allocation->fd_flags,
-  heap_allocation->heap_flags);
+   fd = dma_heap_bufferfd_alloc(heap, heap_allocation->len,
+heap_allocation->fd_flags,
+heap_allocation->heap_flags);
if (fd < 0)
return fd;
 
@@ -205,6 +222,7 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
 {
return heap->priv;
 }
+EXPORT_SYMBOL_GPL(dma_heap_get_drvdata);
 
 /**
  * dma_heap_get_name - get heap name
@@ -217,6 +235,7 @@ const char *dma_heap_get_name(struct dma_heap *heap)
 {
return heap->name;
 }
+EXPORT_SYMBOL_GPL(dma_heap_get_name);
 
 /**
  * dma_heap_add - adds a heap to dmabuf heaps
@@ -307,6 +326,37 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
kfree(heap);
return err_ret;
 }
+EXPORT_SYMBOL_GPL(dma_heap_add);
+
+/**
+ * dma_heap_find - get the heap registered with the specified name
+ * @name: Name of the DMA-Heap to find
+ *
+ * Returns:
+ * The DMA-Heap with the provided name.
+ *
+ * NOTE: DMA-Heaps returned from this function MUST be released using
+ * dma_heap_put() when the user is done to enable the heap to be unloaded.
+ */
+struct dma_heap *dma_heap_find(const char *name)
+{
+   struct dma_heap *h;
+
+   mutex_lock(_list_lock);
+   list_for_each_entry(h, _list, list) {
+   if (!kref_get_unless_zero(>refcount))
+   continue;
+
+   if (!strcmp(h->name, name)) {
+ 

[PATCH v6, 08/24] media: mediatek: vcodec: add tee client interface to communiate with optee-os

2024-05-16 Thread Yunfei Dong
Open tee context to initialize the environment in order to communication
with optee-os, then open tee session as the communication pipeline for
lat and core to send data for hardware decode.

Signed-off-by: Yunfei Dong 
---
 .../platform/mediatek/vcodec/decoder/Makefile |   1 +
 .../vcodec/decoder/mtk_vcodec_dec_drv.h   |   5 +
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 165 ++
 .../vcodec/decoder/mtk_vcodec_dec_optee.h |  73 
 4 files changed, 244 insertions(+)
 create mode 100644 
drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
 create mode 100644 
drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/Makefile 
b/drivers/media/platform/mediatek/vcodec/decoder/Makefile
index 904cd22def84..1624933dfd5e 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/Makefile
+++ b/drivers/media/platform/mediatek/vcodec/decoder/Makefile
@@ -21,5 +21,6 @@ mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
mtk_vcodec_dec_stateful.o \
mtk_vcodec_dec_stateless.o \
mtk_vcodec_dec_pm.o \
+   mtk_vcodec_dec_optee.o \
 
 mtk-vcodec-dec-hw-y := mtk_vcodec_dec_hw.o
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 f975db4293da..76a0323f993c 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
@@ -11,6 +11,7 @@
 #include "../common/mtk_vcodec_dbgfs.h"
 #include "../common/mtk_vcodec_fw_priv.h"
 #include "../common/mtk_vcodec_util.h"
+#include "mtk_vcodec_dec_optee.h"
 #include "vdec_msg_queue.h"
 
 #define MTK_VCODEC_DEC_NAME"mtk-vcodec-dec"
@@ -261,6 +262,8 @@ struct mtk_vcodec_dec_ctx {
  * @dbgfs: debug log related information
  *
  * @chip_name: used to distinguish platforms and select the correct codec 
configuration values
+ *
+ * @optee_private: optee private data
  */
 struct mtk_vcodec_dec_dev {
struct v4l2_device v4l2_dev;
@@ -303,6 +306,8 @@ struct mtk_vcodec_dec_dev {
struct mtk_vcodec_dbgfs dbgfs;
 
enum mtk_vcodec_dec_chip_name chip_name;
+
+   struct mtk_vdec_optee_private *optee_private;
 };
 
 static inline struct mtk_vcodec_dec_ctx *fh_to_dec_ctx(struct v4l2_fh *fh)
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
new file mode 100644
index ..38d9c1c1785a
--- /dev/null
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Yunfei Dong 
+ */
+
+#include "mtk_vcodec_dec_drv.h"
+#include "mtk_vcodec_dec_optee.h"
+
+/*
+ * Randomly generated, and must correspond to the GUID on the TA side.
+ */
+static const uuid_t mtk_vdec_lat_uuid =
+   UUID_INIT(0xBC50D971, 0xD4C9, 0x42C4,
+ 0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x90);
+
+static const uuid_t mtk_vdec_core_uuid =
+   UUID_INIT(0xBC50D971, 0xD4C9, 0x42C4,
+ 0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x91);
+
+/*
+ * Check whether this driver supports decoder TA in the TEE instance,
+ * represented by the params (ver/data) of this function.
+ */
+static int mtk_vcodec_dec_optee_match(struct tee_ioctl_version_data *ver_data, 
const void *not_used)
+{
+   if (ver_data->impl_id == TEE_IMPL_ID_OPTEE)
+   return 1;
+   else
+   return 0;
+}
+
+int mtk_vcodec_dec_optee_private_init(struct mtk_vcodec_dec_dev *vcodec_dev)
+{
+   vcodec_dev->optee_private = devm_kzalloc(_dev->plat_dev->dev,
+
sizeof(*vcodec_dev->optee_private),
+GFP_KERNEL);
+   if (!vcodec_dev->optee_private)
+   return -ENOMEM;
+
+   vcodec_dev->optee_private->vcodec_dev = vcodec_dev;
+
+   atomic_set(_dev->optee_private->tee_active_cnt, 0);
+   mutex_init(_dev->optee_private->tee_mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_private_init);
+
+static int mtk_vcodec_dec_optee_init_hw_info(struct mtk_vdec_optee_private 
*optee_private,
+enum mtk_vdec_hw_id hardware_index)
+{
+   struct device *dev = _private->vcodec_dev->plat_dev->dev;
+   struct tee_ioctl_open_session_arg session_arg;
+   struct mtk_vdec_optee_ca_info *ca_info;
+   int err = 0, session_func;
+
+   /* Open lat and core session with vdec TA. */
+   switch (hardware_index) {
+   case MTK_VDEC_LAT0:
+   export_uuid(session_arg.uuid, _vd

[PATCH v6,06/24] dma-heap: Add proper kref handling on dma-buf heaps

2024-05-16 Thread Yunfei Dong
From: John Stultz 

Add proper refcounting on the dma_heap structure.
While existing heaps are built-in, we may eventually
have heaps loaded from modules, and we'll need to be
able to properly handle the references to the heaps

Signed-off-by: John Stultz 
Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Just add comment for "minor" and "refcount"]
Signed-off-by: Yunfei Dong 
---
 drivers/dma-buf/dma-heap.c | 29 +
 include/linux/dma-heap.h   |  2 ++
 2 files changed, 31 insertions(+)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 22f6c193db0d..97025ee8500f 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -30,6 +31,7 @@
  * @heap_devt: heap device node
  * @list:  list head connecting to list of heaps
  * @heap_cdev: heap char device
+ * @refcount:  reference counter for this heap device
  *
  * Represents a heap of memory from which buffers can be made.
  */
@@ -40,6 +42,7 @@ struct dma_heap {
dev_t heap_devt;
struct list_head list;
struct cdev heap_cdev;
+   struct kref refcount;
 };
 
 static LIST_HEAD(heap_list);
@@ -240,6 +243,7 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
if (!heap)
return ERR_PTR(-ENOMEM);
 
+   kref_init(>refcount);
heap->name = exp_info->name;
heap->ops = exp_info->ops;
heap->priv = exp_info->priv;
@@ -304,6 +308,31 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
return err_ret;
 }
 
+static void dma_heap_release(struct kref *ref)
+{
+   struct dma_heap *heap = container_of(ref, struct dma_heap, refcount);
+   unsigned int minor = MINOR(heap->heap_devt);
+
+   mutex_lock(_list_lock);
+   list_del(>list);
+   mutex_unlock(_list_lock);
+
+   device_destroy(dma_heap_class, heap->heap_devt);
+   cdev_del(>heap_cdev);
+   xa_erase(_heap_minors, minor);
+
+   kfree(heap);
+}
+
+/**
+ * dma_heap_put - drops a reference to a dmabuf heap, potentially freeing it
+ * @heap: DMA-Heap whose reference count to decrement
+ */
+void dma_heap_put(struct dma_heap *heap)
+{
+   kref_put(>refcount, dma_heap_release);
+}
+
 static char *dma_heap_devnode(const struct device *dev, umode_t *mode)
 {
return kasprintf(GFP_KERNEL, "dma_heap/%s", dev_name(dev));
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index fbe86ec889a8..d57593f8a1bc 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -46,4 +46,6 @@ const char *dma_heap_get_name(struct dma_heap *heap);
 
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
+void dma_heap_put(struct dma_heap *heap);
+
 #endif /* _DMA_HEAPS_H */
-- 
2.25.1



[PATCH v6,02/24] v4l2: handle restricted memory flags in queue setup

2024-05-16 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Validates the restricted memory flags when setting up a queue and
ensures the queue has the proper capability.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 .../media/common/videobuf2/videobuf2-core.c   | 21 +++
 .../media/common/videobuf2/videobuf2-v4l2.c   |  4 +++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 358f1fe42975..fe4c0594ab81 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -831,6 +831,15 @@ static bool verify_coherency_flags(struct vb2_queue *q, 
bool non_coherent_mem)
return true;
 }
 
+static bool verify_restricted_mem_flags(struct vb2_queue *q, bool 
restricted_mem)
+{
+   if (restricted_mem != q->restricted_mem) {
+   dprintk(q, 1, "restricted memory model mismatch\n");
+   return false;
+   }
+   return true;
+}
+
 static int vb2_core_allocated_buffers_storage(struct vb2_queue *q)
 {
if (!q->bufs)
@@ -864,6 +873,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
unsigned int q_num_bufs = vb2_get_num_buffers(q);
unsigned plane_sizes[VB2_MAX_PLANES] = { };
bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
+   bool restricted_mem = flags & V4L2_MEMORY_FLAG_RESTRICTED;
unsigned int i, first_index;
int ret = 0;
 
@@ -907,6 +917,9 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
return 0;
}
 
+   if (restricted_mem && (!q->allow_restricted_mem || memory != 
VB2_MEMORY_DMABUF))
+   return -EINVAL;
+
/*
 * Make sure the requested values and current defaults are sane.
 */
@@ -924,6 +937,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
if (ret)
return ret;
set_queue_coherency(q, non_coherent_mem);
+   q->restricted_mem = restricted_mem;
 
/*
 * Ask the driver how many buffers and planes per buffer it requires.
@@ -1032,6 +1046,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
unsigned plane_sizes[VB2_MAX_PLANES] = { };
bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
unsigned int q_num_bufs = vb2_get_num_buffers(q);
+   bool restricted_mem = flags & V4L2_MEMORY_FLAG_RESTRICTED;
bool no_previous_buffers = !q_num_bufs;
int ret = 0;
 
@@ -1040,6 +1055,9 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
return -ENOBUFS;
}
 
+   if (restricted_mem && (!q->allow_restricted_mem || memory != 
VB2_MEMORY_DMABUF))
+   return -EINVAL;
+
if (no_previous_buffers) {
if (q->waiting_in_dqbuf && *count) {
dprintk(q, 1, "another dup()ped fd is waiting for a 
buffer\n");
@@ -1058,6 +1076,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
return ret;
q->waiting_for_buffers = !q->is_output;
set_queue_coherency(q, non_coherent_mem);
+   q->restricted_mem = restricted_mem;
} else {
if (q->memory != memory) {
dprintk(q, 1, "memory model mismatch\n");
@@ -1065,6 +1084,8 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
}
if (!verify_coherency_flags(q, non_coherent_mem))
return -EINVAL;
+   if (!verify_restricted_mem_flags(q, restricted_mem))
+   return -EINVAL;
}
 
num_buffers = min(*count, q->max_num_buffers - q_num_bufs);
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 293f3d5f1c4e..9ee24e537e0c 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -682,7 +682,7 @@ static void vb2_set_flags_and_caps(struct vb2_queue *q, u32 
memory,
*flags = 0;
} else {
/* Clear all unknown flags. */
-   *flags &= V4L2_MEMORY_FLAG_NON_COHERENT;
+   *flags &= V4L2_MEMORY_FLAG_NON_COHERENT | 
V4L2_MEMORY_FLAG_RESTRICTED;
}
 
*caps |= V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS;
@@ -698,6 +698,8 @@ static void vb2_set_flags_and_caps(struct vb2_queue *q, u32 
memory,
*caps |= V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS;
if (q->supports_requests)
*caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS;
+   if (q->allow_restricted_mem && q->io_modes & VB2_DMABUF)
+

[PATCH v6, 03/24] v4l2: verify restricted dmabufs are used in restricted queue

2024-05-16 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Verfies in the dmabuf implementations that if the restricted memory
flag is set for a queue that the dmabuf submitted to the queue is
unmappable.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 drivers/media/common/videobuf2/videobuf2-dma-contig.c | 8 
 drivers/media/common/videobuf2/videobuf2-dma-sg.c | 8 
 2 files changed, 16 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c 
b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index 3d4fd4ef5310..35a3c1c01eae 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -710,6 +710,14 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
return -EINVAL;
}
 
+   /* Verify the dmabuf is restricted if we are in restricted mode, this 
is done
+* by validating there is no page entry for the dmabuf.
+*/
+   if (buf->vb->vb2_queue->restricted_mem && 
!sg_dma_is_restricted(sgt->sgl)) {
+   pr_err("restricted queue requires restricted dma_buf");
+   return -EINVAL;
+   }
+
/* checking if dmabuf is big enough to store contiguous chunk */
contig_size = vb2_dc_get_contiguous_size(sgt);
if (contig_size < buf->size) {
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c 
b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
index 6975a71d740f..2399a9c074ba 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
@@ -570,6 +570,14 @@ static int vb2_dma_sg_map_dmabuf(void *mem_priv)
return -EINVAL;
}
 
+   /* Verify the dmabuf is restricted if we are in restricted mode, this 
is done
+* by validating there is no page entry for the dmabuf.
+*/
+   if (buf->vb->vb2_queue->restricted_mem && 
!sg_dma_is_restricted(sgt->sgl)) {
+   pr_err("restricted queue requires restricted dma_buf");
+   return -EINVAL;
+   }
+
buf->dma_sgt = sgt;
buf->vaddr = NULL;
 
-- 
2.25.1



[PATCH v6,04/24] v4l: add documentation for restricted memory flag

2024-05-16 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Adds documentation for V4L2_MEMORY_FLAG_RESTRICTED.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 Documentation/userspace-api/media/v4l/buffer.rst | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/Documentation/userspace-api/media/v4l/buffer.rst 
b/Documentation/userspace-api/media/v4l/buffer.rst
index 52bbee81c080..807e43bfed2b 100644
--- a/Documentation/userspace-api/media/v4l/buffer.rst
+++ b/Documentation/userspace-api/media/v4l/buffer.rst
@@ -696,7 +696,7 @@ enum v4l2_memory
 
 .. _memory-flags:
 
-Memory Consistency Flags
+Memory Flags
 
 
 .. raw:: latex
@@ -728,6 +728,14 @@ Memory Consistency Flags
only if the buffer is used for :ref:`memory mapping ` I/O and the
queue reports the :ref:`V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS
` capability.
+* .. _`V4L2-MEMORY-FLAG-RESTRICTED`:
+
+  - ``V4L2_MEMORY_FLAG_RESTRICTED``
+  - 0x0002
+  - The queued buffers are expected to be in restricted memory. If not, an
+   error will be returned. This flag can only be used with 
``V4L2_MEMORY_DMABUF``.
+   Typically restricted buffers are allocated using a restricted dma-heap. 
This flag
+   can only be specified if the ``V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM`` 
is set.
 
 .. raw:: latex
 
-- 
2.25.1



[PATCH v6, 05/24] dma-buf: heaps: Deduplicate docs and adopt common format

2024-05-16 Thread Yunfei Dong
From: "T.J. Mercier" 

The docs for dma_heap_get_name were incorrect, and since they were
duplicated in the header they were wrong there too.

The docs formatting was inconsistent so I tried to make it more
consistent across functions since I'm already in here doing cleanup.

Remove multiple unused includes and alphabetize.

Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Just add a comment for "priv" to mute build warning]
Signed-off-by: Yunfei Dong 
---
 drivers/dma-buf/dma-heap.c | 27 +++
 include/linux/dma-heap.h   | 21 +
 2 files changed, 16 insertions(+), 32 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 84ae708fafe7..22f6c193db0d 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -7,17 +7,15 @@
  */
 
 #include 
-#include 
 #include 
 #include 
+#include 
 #include 
-#include 
 #include 
-#include 
 #include 
-#include 
 #include 
-#include 
+#include 
+#include 
 #include 
 
 #define DEVNAME "dma_heap"
@@ -28,9 +26,10 @@
  * struct dma_heap - represents a dmabuf heap in the system
  * @name:  used for debugging/device-node name
  * @ops:   ops struct for this heap
- * @heap_devt  heap device node
- * @list   list head connecting to list of heaps
- * @heap_cdev  heap char device
+ * @priv:  private data for this heap
+ * @heap_devt: heap device node
+ * @list:  list head connecting to list of heaps
+ * @heap_cdev: heap char device
  *
  * Represents a heap of memory from which buffers can be made.
  */
@@ -193,11 +192,11 @@ static const struct file_operations dma_heap_fops = {
 };
 
 /**
- * dma_heap_get_drvdata() - get per-subdriver data for the heap
+ * dma_heap_get_drvdata - get per-heap driver data
  * @heap: DMA-Heap to retrieve private data for
  *
  * Returns:
- * The per-subdriver data for the heap.
+ * The per-heap data for the heap.
  */
 void *dma_heap_get_drvdata(struct dma_heap *heap)
 {
@@ -205,8 +204,8 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
 }
 
 /**
- * dma_heap_get_name() - get heap name
- * @heap: DMA-Heap to retrieve private data for
+ * dma_heap_get_name - get heap name
+ * @heap: DMA-Heap to retrieve the name of
  *
  * Returns:
  * The char* for the heap name.
@@ -216,6 +215,10 @@ const char *dma_heap_get_name(struct dma_heap *heap)
return heap->name;
 }
 
+/**
+ * dma_heap_add - adds a heap to dmabuf heaps
+ * @exp_info: information needed to register this heap
+ */
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
 {
struct dma_heap *heap, *h, *err_ret;
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index 0c05561cad6e..fbe86ec889a8 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -9,14 +9,13 @@
 #ifndef _DMA_HEAPS_H
 #define _DMA_HEAPS_H
 
-#include 
 #include 
 
 struct dma_heap;
 
 /**
  * struct dma_heap_ops - ops to operate on a given heap
- * @allocate:  allocate dmabuf and return struct dma_buf ptr
+ * @allocate:  allocate dmabuf and return struct dma_buf ptr
  *
  * allocate returns dmabuf on success, ERR_PTR(-errno) on error.
  */
@@ -41,28 +40,10 @@ struct dma_heap_export_info {
void *priv;
 };
 
-/**
- * dma_heap_get_drvdata() - get per-heap driver data
- * @heap: DMA-Heap to retrieve private data for
- *
- * Returns:
- * The per-heap data for the heap.
- */
 void *dma_heap_get_drvdata(struct dma_heap *heap);
 
-/**
- * dma_heap_get_name() - get heap name
- * @heap: DMA-Heap to retrieve private data for
- *
- * Returns:
- * The char* for the heap name.
- */
 const char *dma_heap_get_name(struct dma_heap *heap);
 
-/**
- * dma_heap_add - adds a heap to dmabuf heaps
- * @exp_info:  information needed to register this heap
- */
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
 #endif /* _DMA_HEAPS_H */
-- 
2.25.1



[PATCH v6,01/24] v4l2: add restricted memory flags

2024-05-16 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Adds a V4L2 flag which indicates that a queue is using restricted
dmabufs and the corresponding capability flag.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 include/media/videobuf2-core.h | 8 +++-
 include/uapi/linux/videodev2.h | 2 ++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 955237ac503d..afd497e93a37 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -517,6 +517,9 @@ struct vb2_buf_ops {
  * ->finish().
  * @non_coherent_mem: when set queue will attempt to allocate buffers using
  * non-coherent memory.
+ * @allow_restricted_mem: when set user-space can pass the 
%V4L2_MEMORY_FLAG_RESTRICTED
+ * flag to indicate the dma bufs are restricted.
+ * @restricted_mem: when set queue will verify that the dma bufs are 
restricted.
  * @lock:  pointer to a mutex that protects the  vb2_queue. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -621,6 +624,8 @@ struct vb2_queue {
unsigned intuses_requests:1;
unsigned intallow_cache_hints:1;
unsigned intnon_coherent_mem:1;
+   unsigned intallow_restricted_mem:1;
+   unsigned intrestricted_mem:1;
 
struct mutex*lock;
void*owner;
@@ -792,7 +797,8 @@ void vb2_core_querybuf(struct vb2_queue *q, struct 
vb2_buffer *vb, void *pb);
  * @q: pointer to  vb2_queue with videobuf2 queue.
  * @memory:memory type, as defined by  vb2_memory.
  * @flags: auxiliary queue/buffer management flags. Currently, the only
- * used flag is %V4L2_MEMORY_FLAG_NON_COHERENT.
+ * used flags are %V4L2_MEMORY_FLAG_NON_COHERENT and
+ * %V4L2_MEMORY_FLAG_RESTRICTED.
  * @count: requested buffer count.
  *
  * Videobuf2 core helper to implement VIDIOC_REQBUF() operation. It is called
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index fe6b67e83751..89eb1a3c6555 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1043,6 +1043,7 @@ struct v4l2_requestbuffers {
 };
 
 #define V4L2_MEMORY_FLAG_NON_COHERENT  (1 << 0)
+#define V4L2_MEMORY_FLAG_RESTRICTED(1 << 1)
 
 /* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */
 #define V4L2_BUF_CAP_SUPPORTS_MMAP (1 << 0)
@@ -1054,6 +1055,7 @@ struct v4l2_requestbuffers {
 #define V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS (1 << 6)
 #define V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS  (1 << 7)
 #define V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS  (1 << 8)
+#define V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM   (1 << 9)
 
 /**
  * struct v4l2_plane - plane info for multi-planar buffers
-- 
2.25.1



[PATCH v6, 00/24] media: mediatek: add driver to support secure video decoder

2024-05-16 Thread Yunfei Dong
The patch series used to enable secure video playback (SVP) on MediaTek
hardware in the Linux kernel.

Memory Definitions:
secure memory - Memory allocated in the TEE (Trusted Execution
Environment) which is inaccessible in the REE (Rich Execution
Environment, i.e. linux kernel/user space).
secure handle - Integer value which acts as reference to 'secure
memory'. Used in communication between TEE and REE to reference
'secure memory'.
secure buffer - 'secure memory' that is used to store decrypted,
compressed video or for other general purposes in the TEE.
secure surface - 'secure memory' that is used to store graphic buffers.

Memory Usage in SVP:
The overall flow of SVP starts with encrypted video coming in from an
outside source into the REE. The REE will then allocate a 'secure
buffer' and send the corresponding 'secure handle' along with the
encrypted, compressed video data to the TEE. The TEE will then decrypt
the video and store the result in the 'secure buffer'. The REE will
then allocate a 'secure surface'. The REE will pass the 'secure
handles' for both the 'secure buffer' and 'secure surface' into the
TEE for video decoding. The video decoder HW will then decode the
contents of the 'secure buffer' and place the result in the 'secure
surface'. The REE will then attach the 'secure surface' to the overlay
plane for rendering of the video.

Everything relating to ensuring security of the actual contents of the
'secure buffer' and 'secure surface' is out of scope for the REE and
is the responsibility of the TEE.

This patch series is consists of four parts. The first is from Jeffrey,
adding secure memory flag in v4l2 framework to support request secure
buffer.

The second and third parts are from John and T.J, adding some heap
interfaces, then our kernel users could allocate buffer from special
heap. The patch v1 is inside below dmabuf link.
https://lore.kernel.org/linux-mediatek/20230911023038.30649-1-yong...@mediatek.com/
To avoid confusing, move them into vcodec patch set since we use the
new interfaces directly.

The last part is mediatek video decoder driver, adding tee interface and
decoder driver to support secure video playback.

This patch set depends on "dma-buf: heaps: Add restricted heap"[1]

[1] https://patchwork.kernel.org/project/linux-mediatek/list/?series=853380
---
Changed in v6:
- fix review unreasonable logic for patch 2/3/23
- add to support vp9 for patch 24

Changed in v5:
- fix merge conflict when rebase to latest media stage for patch 1/2
- change allocate memory type to cma for patch 12
- add to support av1 for patch 23

Changed in v4:
- change the driver according to maintainer advice for patch 1/2/3/4
- replace secure with restricted for patch 1/2/3/4
- fix svp decoder error for patch 21
- add to support hevc for patch 22

Changed in v3:
- rewrite the cover-letter of this patch series
- disable irq for svp mode
- rebase the driver based on the latest media stage

Changed in v2:
- remove setting decoder mode and getting secure handle from decode
- add Jeffrey's patch
- add John and T.J's patch
- getting secure flag with request buffer
- fix some comments from patch v1
---
Jeffrey Kardatzke (4):
  v4l2: add restricted memory flags
  v4l2: handle restricted memory flags in queue setup
  v4l2: verify restricted dmabufs are used in restricted queue
  v4l: add documentation for restricted memory flag

John Stultz (2):
  dma-heap: Add proper kref handling on dma-buf heaps
  dma-heap: Provide accessors so that in-kernel drivers can allocate
dmabufs from specific heaps

T.J. Mercier (1):
  dma-buf: heaps: Deduplicate docs and adopt common format

Xiaoyong Lu (1):
  media: mediatek: vcodec: support av1 svp decoder for mt8188

Yilong Zhou (1):
  media: mediatek: vcodec: support vp9 svp decoder for mt8188

Yunfei Dong (15):
  media: mediatek: vcodec: add tee client interface to communiate with
optee-os
  media: mediatek: vcodec: allocate tee share memory
  media: mediatek: vcodec: send share memory data to optee
  media: mediatek: vcodec: initialize msg and vsi information
  media: mediatek: vcodec: add interface to allocate/free secure memory
  media: mediatek: vcodec: using shared memory as vsi address
  media: mediatek: vcodec: Add capture format to support one plane
memory
  media: mediatek: vcodec: Add one plane format
  media: mediatek: vcodec: support one plane capture buffer
  media: mediatek: vcodec: re-construct h264 driver to support svp mode
  media: mediatek: vcodec: remove parse nal_info in kernel
  media: mediatek: vcodec: disable wait interrupt for svp mode
  media: mediatek: vcodec: support tee decoder
  media: mediatek: vcodec: move vdec init interface to setup callback
  media: mediatek: vcodec: support hevc svp for mt8188

 .../userspace-api/media/v4l/buffer.rst|  10 +-
 .../media/v4l/pixfmt-reserved.rst |   8 +
 drivers/dma-buf/dma-heap.c| 139 +--
 .../media/common/videobuf2/videobuf2-core

[PATCH v5, 18/23] media: mediatek: vcodec: remove parse nal_info in kernel

2024-04-12 Thread Yunfei Dong
The hardware can parse syntax to get nal_info, needn't to use cpu.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/vdec/vdec_h264_req_multi_if.c| 13 ++---
 1 file changed, 2 insertions(+), 11 deletions(-)

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 40836673f7fe..f27d326f00ba 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
@@ -645,11 +645,10 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, 
struct mtk_vcodec_mem *bs,
struct vdec_h264_slice_inst *inst = h_vdec;
struct vdec_vpu_inst *vpu = >vpu;
struct mtk_video_dec_buf *src_buf_info;
-   int nal_start_idx, err, timeout = 0;
+   int err, timeout = 0;
unsigned int data[2];
struct vdec_lat_buf *lat_buf;
struct vdec_h264_slice_share_info *share_info;
-   unsigned char *buf;
 
if (vdec_msg_queue_init(>ctx->msg_queue, inst->ctx,
vdec_h264_slice_core_decode,
@@ -673,14 +672,6 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct 
mtk_vcodec_mem *bs,
share_info = lat_buf->private_data;
src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer);
 
-   buf = (unsigned char *)bs->va;
-   nal_start_idx = mtk_vdec_h264_find_start_code(buf, bs->size);
-   if (nal_start_idx < 0) {
-   err = -EINVAL;
-   goto err_free_fb_out;
-   }
-
-   inst->vsi->dec.nal_info = buf[nal_start_idx];
lat_buf->src_buf_req = src_buf_info->m2m_buf.vb.vb2_buf.req_obj.req;
v4l2_m2m_buf_copy_metadata(_buf_info->m2m_buf.vb, 
_buf->ts_info, true);
 
@@ -689,7 +680,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct 
mtk_vcodec_mem *bs,
goto err_free_fb_out;
 
if (!inst->ctx->is_secure_playback)
-   vdec_h264_insert_startcode(inst->ctx->dev, buf, >size,
+   vdec_h264_insert_startcode(inst->ctx->dev, bs->va, >size,
   _info->h264_slice_params.pps);
 
*res_chg = inst->resolution_changed;
-- 
2.18.0



[PATCH v5, 19/23] media: mediatek: vcodec: disable wait interrupt for svp mode

2024-04-12 Thread Yunfei Dong
Waiting interrupt in optee-os for svp mode, need to disable it in kernel
in case of interrupt is cleaned.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_hw.c| 34 +--
 .../vcodec/decoder/mtk_vcodec_dec_pm.c|  6 +-
 .../decoder/vdec/vdec_h264_req_multi_if.c | 57 +++
 3 files changed, 54 insertions(+), 43 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
index 881d5de41e05..1982c088c6da 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
@@ -72,26 +72,28 @@ static irqreturn_t mtk_vdec_hw_irq_handler(int irq, void 
*priv)
 
ctx = mtk_vcodec_get_curr_ctx(dev->main_dev, dev->hw_idx);
 
-   /* check if HW active or not */
-   cg_status = readl(dev->reg_base[VDEC_HW_SYS] + VDEC_HW_ACTIVE_ADDR);
-   if (cg_status & VDEC_HW_ACTIVE_MASK) {
-   mtk_v4l2_vdec_err(ctx, "vdec active is not 0x0 (0x%08x)", 
cg_status);
-   return IRQ_HANDLED;
-   }
+   if (!ctx->is_secure_playback) {
+   /* check if HW active or not */
+   cg_status = readl(dev->reg_base[VDEC_HW_SYS] + 
VDEC_HW_ACTIVE_ADDR);
+   if (cg_status & VDEC_HW_ACTIVE_MASK) {
+   mtk_v4l2_vdec_err(ctx, "vdec active is not 0x0 
(0x%08x)", cg_status);
+   return IRQ_HANDLED;
+   }
 
-   dec_done_status = readl(vdec_misc_addr);
-   if ((dec_done_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) !=
-   MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
-   return IRQ_HANDLED;
+   dec_done_status = readl(vdec_misc_addr);
+   if ((dec_done_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) !=
+   MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
+   return IRQ_HANDLED;
 
-   /* clear interrupt */
-   writel(dec_done_status | VDEC_IRQ_CFG, vdec_misc_addr);
-   writel(dec_done_status & ~VDEC_IRQ_CLR, vdec_misc_addr);
+   /* clear interrupt */
+   writel(dec_done_status | VDEC_IRQ_CFG, vdec_misc_addr);
+   writel(dec_done_status & ~VDEC_IRQ_CLR, vdec_misc_addr);
 
-   wake_up_dec_ctx(ctx, MTK_INST_IRQ_RECEIVED, dev->hw_idx);
+   wake_up_dec_ctx(ctx, MTK_INST_IRQ_RECEIVED, dev->hw_idx);
 
-   mtk_v4l2_vdec_dbg(3, ctx, "wake up ctx %d, dec_done_status=%x",
- ctx->id, dec_done_status);
+   mtk_v4l2_vdec_dbg(3, ctx, "wake up ctx %d, dec_done_status=%x",
+ ctx->id, dec_done_status);
+   }
 
return IRQ_HANDLED;
 }
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c
index aefd3e9e3061..a94eda936f16 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c
@@ -238,7 +238,8 @@ void mtk_vcodec_dec_enable_hardware(struct 
mtk_vcodec_dec_ctx *ctx, int hw_idx)
mtk_vcodec_dec_child_dev_on(ctx->dev, MTK_VDEC_LAT0);
mtk_vcodec_dec_child_dev_on(ctx->dev, hw_idx);
 
-   mtk_vcodec_dec_enable_irq(ctx->dev, hw_idx);
+   if (!ctx->is_secure_playback)
+   mtk_vcodec_dec_enable_irq(ctx->dev, hw_idx);
 
if (IS_VDEC_INNER_RACING(ctx->dev->dec_capability))
mtk_vcodec_load_racing_info(ctx);
@@ -250,7 +251,8 @@ void mtk_vcodec_dec_disable_hardware(struct 
mtk_vcodec_dec_ctx *ctx, int hw_idx)
if (IS_VDEC_INNER_RACING(ctx->dev->dec_capability))
mtk_vcodec_record_racing_info(ctx);
 
-   mtk_vcodec_dec_disable_irq(ctx->dev, hw_idx);
+   if (!ctx->is_secure_playback)
+   mtk_vcodec_dec_disable_irq(ctx->dev, hw_idx);
 
mtk_vcodec_dec_child_dev_off(ctx->dev, hw_idx);
if (IS_VDEC_LAT_ARCH(ctx->dev->vdec_pdata->hw_arch) &&
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 f27d326f00ba..3186777dcc13 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
@@ -593,14 +593,16 @@ static int vdec_h264_slice_core_decode(struct 
vdec_lat_buf *lat_buf)
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);
-   i

[PATCH v5, 21/23] media: mediatek: vcodec: move vdec init interface to setup callback

2024-04-12 Thread Yunfei Dong
Getting secure video playback (svp) flag when request output buffer, then
calling init interface to init svp parameters in optee-os.

Signed-off-by: Yunfei Dong 
---
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c  | 139 +++---
 1 file changed, 89 insertions(+), 50 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index ebe21064616c..a07b6ba0ea82 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -184,6 +184,69 @@ void mtk_vcodec_dec_set_default_params(struct 
mtk_vcodec_dec_ctx *ctx)
q_data->bytesperline[1] = q_data->coded_width;
 }
 
+static int mtk_vcodec_dec_init_pic_info(struct mtk_vcodec_dec_ctx *ctx, enum 
v4l2_buf_type type)
+{
+   const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata;
+   struct mtk_q_data *q_data;
+   int ret;
+
+   if (!ctx->current_codec)
+   return 0;
+
+   if (V4L2_TYPE_IS_OUTPUT(type) && ctx->state == MTK_STATE_FREE) {
+   q_data = mtk_vdec_get_q_data(ctx, 
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+   if (!q_data)
+   return -EINVAL;
+
+   ret = vdec_if_init(ctx, q_data->fmt->fourcc);
+   if (ret) {
+   mtk_v4l2_vdec_err(ctx, "[%d]: vdec_if_init() fail 
ret=%d",
+ ctx->id, ret);
+   return -EINVAL;
+   }
+   ctx->state = MTK_STATE_INIT;
+   }
+
+   if (!dec_pdata->uses_stateless_api)
+   return 0;
+
+   /*
+* If get pic info fail, need to use the default pic info params, or
+* v4l2-compliance will fail
+*/
+   ret = vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, >picinfo);
+   if (ret)
+   mtk_v4l2_vdec_err(ctx, "[%d]Error!! Get GET_PARAM_PICTURE_INFO 
Fail",
+ ctx->id);
+
+   q_data = mtk_vdec_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+   if (q_data->fmt->num_planes == 1) {
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0] + 
ctx->picinfo.fb_sz[1];
+   q_data->bytesperline[0] = ctx->picinfo.buf_w;
+   } else {
+   if (ctx->is_secure_playback)
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0] + 
ctx->picinfo.fb_sz[1];
+   else
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0];
+
+   q_data->bytesperline[0] = ctx->picinfo.buf_w;
+   q_data->sizeimage[1] = ctx->picinfo.fb_sz[1];
+   q_data->bytesperline[1] = ctx->picinfo.buf_w;
+   }
+
+   q_data->coded_width = ctx->picinfo.buf_w;
+   q_data->coded_height = ctx->picinfo.buf_h;
+
+   ctx->last_decoded_picinfo = ctx->picinfo;
+   mtk_v4l2_vdec_dbg(2, ctx,
+ "[%d] init() plane:%d wxh=%dx%d pic wxh=%dx%d 
sz=0x%x_0x%x",
+ ctx->id, q_data->fmt->num_planes,
+ ctx->picinfo.buf_w, ctx->picinfo.buf_h,
+ ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+ q_data->sizeimage[0], q_data->sizeimage[1]);
+   return 0;
+}
+
 static int vidioc_vdec_qbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
 {
@@ -479,17 +542,7 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv,
ctx->ycbcr_enc = pix_mp->ycbcr_enc;
ctx->quantization = pix_mp->quantization;
ctx->xfer_func = pix_mp->xfer_func;
-
ctx->current_codec = fmt->fourcc;
-   if (ctx->state == MTK_STATE_FREE) {
-   ret = vdec_if_init(ctx, q_data->fmt->fourcc);
-   if (ret) {
-   mtk_v4l2_vdec_err(ctx, "[%d]: vdec_if_init() 
fail ret=%d",
- ctx->id, ret);
-   return -EINVAL;
-   }
-   ctx->state = MTK_STATE_INIT;
-   }
} else {
ctx->capture_fourcc = fmt->fourcc;
}
@@ -502,46 +555,11 @@ static int vidioc_vdec_s_fmt(struct file *file, void 
*priv,
ctx->picinfo.pic_w = pix_mp->width;
ctx->picinfo.pic_h = pix_mp->height;
 
-   /*
-* If get pic info fail, need to use the default pic info 
params, or
-* v4l2-compliance will fail
-*/
-   ret = vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, >picinfo);
-

[PATCH v5, 11/23] media: mediatek: vcodec: initialize msg and vsi information

2024-04-12 Thread Yunfei Dong
Need to initialize msg and vsi information before sending to optee-os, then
calling optee invoke command to send the information to optee-os.

For the optee communication interface is different with scp, using
flag to separate them.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_drv.h   |  2 +
 .../mediatek/vcodec/decoder/vdec_vpu_if.c | 49 ---
 .../mediatek/vcodec/decoder/vdec_vpu_if.h |  4 ++
 3 files changed, 49 insertions(+), 6 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 76a0323f993c..1540cb8bfe5c 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
@@ -175,6 +175,7 @@ struct mtk_vcodec_dec_pdata {
  * @vpu_inst: vpu instance pointer.
  *
  * @is_10bit_bitstream: set to true if it's 10bit bitstream
+ * @is_secure_playback: Secure Video Playback (SVP) mode
  */
 struct mtk_vcodec_dec_ctx {
enum mtk_instance_type type;
@@ -220,6 +221,7 @@ struct mtk_vcodec_dec_ctx {
void *vpu_inst;
 
bool is_10bit_bitstream;
+   bool is_secure_playback;
 };
 
 /**
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
index 82e57ae983d5..5336769a3fb5 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
@@ -148,7 +148,10 @@ static void vpu_dec_ipi_handler(void *data, unsigned int 
len, void *priv)
 
 static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, void *msg, int len)
 {
-   int err, id, msgid;
+   struct mtk_vdec_optee_data_to_shm *optee_data;
+   int data_size, id, hw_id, msgid;
+   void *ack_msg, *data_msg;
+   int err;
 
msgid = *(uint32_t *)msg;
mtk_vdec_debug(vpu->ctx, "id=%X", msgid);
@@ -158,16 +161,46 @@ static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, 
void *msg, int len)
 
if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) {
if (msgid == AP_IPIMSG_DEC_CORE ||
-   msgid == AP_IPIMSG_DEC_CORE_END)
+   msgid == AP_IPIMSG_DEC_CORE_END) {
+   optee_data = >core_optee_info;
id = vpu->core_id;
-   else
+   } else {
+   optee_data = >lat_optee_info;
id = vpu->id;
+   }
} else {
+   optee_data = >lat_optee_info;
id = vpu->id;
}
 
-   err = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, id, msg,
-len, 2000);
+   if (!vpu->ctx->is_secure_playback) {
+   err = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, id, 
msg, len, 2000);
+   } else {
+   hw_id = (id == SCP_IPI_VDEC_LAT) ? MTK_VDEC_LAT0 : 
MTK_VDEC_CORE;
+
+   mtk_vcodec_dec_optee_set_data(optee_data, msg, len, 
OPTEE_MSG_INDEX);
+
+   /* There is no need to copy the data (VSI) message to shared 
memory,
+* but we still need to set the buffer size to a non-zero value.
+*/
+   if (msgid == AP_IPIMSG_DEC_CORE || msgid == 
AP_IPIMSG_DEC_START) {
+   data_msg = 
mtk_vcodec_dec_get_shm_buffer_va(vpu->ctx->dev->optee_private,
+   hw_id, 
OPTEE_DATA_INDEX);
+   data_size = 
mtk_vcodec_dec_get_shm_buffer_size(vpu->ctx->dev->optee_private,
+  hw_id, 
OPTEE_DATA_INDEX);
+   mtk_vcodec_dec_optee_set_data(optee_data, data_msg, 
data_size,
+ OPTEE_DATA_INDEX);
+   }
+
+   err = 
mtk_vcodec_dec_optee_invokd_cmd(vpu->ctx->dev->optee_private,
+ hw_id, optee_data);
+   vpu->failure = err;
+
+   ack_msg = 
mtk_vcodec_dec_get_shm_buffer_va(vpu->ctx->dev->optee_private, hw_id,
+  OPTEE_MSG_INDEX);
+   vpu_dec_ipi_handler(ack_msg, 0, vpu->ctx->dev);
+   }
+
if (err) {
mtk_vdec_err(vpu->ctx, "send fail vpu_id=%d msg_id=%X 
status=%d",
 id, msgid, err);
@@ -213,7 +246,11 @@ int vpu_dec_init(struct vdec_vpu_inst *vpu)
return err;
}
 
-   if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) {
+   /* Using tee interface to communicate with op

[PATCH v5, 16/23] media: mediatek: vcodec: support one plane capture buffer

2024-04-12 Thread Yunfei Dong
The capture buffer has two planes for format MM21, but user space only
allocate secure memory for plane[0], and the size is Y data + uv data.
The driver need to support one plane decoder for svp mode.

Signed-off-by: Yunfei Dong 
---
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c  |  7 -
 .../vcodec/decoder/mtk_vcodec_dec_stateless.c | 26 ++-
 .../decoder/vdec/vdec_h264_req_common.c   | 18 ++---
 .../mediatek/vcodec/decoder/vdec_drv_if.c |  4 +--
 4 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index 192b01ff3ede..ebe21064616c 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -653,7 +653,12 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv,
 * So we just return picinfo yet, and update picinfo in
 * stop_streaming hook function
 */
-   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0];
+
+   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1 || 
ctx->is_secure_playback)
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0] + 
ctx->picinfo.fb_sz[1];
+   else
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0];
+
q_data->sizeimage[1] = ctx->picinfo.fb_sz[1];
q_data->bytesperline[0] = ctx->last_decoded_picinfo.buf_w;
q_data->bytesperline[1] = ctx->last_decoded_picinfo.buf_w;
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index fbea00517565..a1a99878f2c6 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -285,14 +285,14 @@ static struct vdec_fb *vdec_get_cap_buffer(struct 
mtk_vcodec_dec_ctx *ctx)
framebuf = container_of(vb2_v4l2, struct mtk_video_dec_buf, m2m_buf.vb);
 
pfb = >frame_buffer;
-   pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0);
+   if (!ctx->is_secure_playback)
+   pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0);
pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
pfb->base_y.size = ctx->q_data[MTK_Q_DATA_DST].sizeimage[0];
 
-   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2) {
+   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2 && 
!ctx->is_secure_playback) {
pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1);
-   pfb->base_c.dma_addr =
-   vb2_dma_contig_plane_dma_addr(dst_buf, 1);
+   pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 
1);
pfb->base_c.size = ctx->q_data[MTK_Q_DATA_DST].sizeimage[1];
}
mtk_v4l2_vdec_dbg(1, ctx,
@@ -339,16 +339,18 @@ static void mtk_vdec_worker(struct work_struct *work)
mtk_v4l2_vdec_dbg(3, ctx, "[%d] (%d) id=%d, vb=%p", ctx->id,
  vb2_src->vb2_queue->type, vb2_src->index, vb2_src);
 
-   bs_src->va = vb2_plane_vaddr(vb2_src, 0);
-   bs_src->dma_addr = vb2_dma_contig_plane_dma_addr(vb2_src, 0);
-   bs_src->size = (size_t)vb2_src->planes[0].bytesused;
-   if (!bs_src->va) {
-   v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
-   mtk_v4l2_vdec_err(ctx, "[%d] id=%d source buffer is NULL", 
ctx->id,
- vb2_src->index);
-   return;
+   if (!ctx->is_secure_playback) {
+   bs_src->va = vb2_plane_vaddr(vb2_src, 0);
+   if (!bs_src->va) {
+   v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+   mtk_v4l2_vdec_err(ctx, "[%d] id=%d source buffer is 
NULL", ctx->id,
+ vb2_src->index);
+   return;
+   }
}
 
+   bs_src->dma_addr = vb2_dma_contig_plane_dma_addr(vb2_src, 0);
+   bs_src->size = (size_t)vb2_src->planes[0].bytesused;
mtk_v4l2_vdec_dbg(3, ctx, "[%d] Bitstream VA=%p DMA=%pad Size=%zx 
vb=%p",
  ctx->id, bs_src->va, _src->dma_addr, bs_src->size, 
vb2_src);
/* Apply request controls. */
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c
index 5ca20d75dc8e..5e0d55218363 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c
+++ b

[PATCH v5,20/23] media: mediatek: vcodec: support tee decoder

2024-04-12 Thread Yunfei Dong
Initialize tee private data to support secure decoder.
Release tee related information for each instance when decoder
done.

Signed-off-by: Yunfei Dong 
---
 .../platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
index f47c98faf068..08e7d250487b 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
@@ -310,6 +310,9 @@ static int fops_vcodec_release(struct file *file)
v4l2_fh_exit(>fh);
v4l2_ctrl_handler_free(>ctrl_hdl);
 
+   if (ctx->is_secure_playback)
+   mtk_vcodec_dec_optee_release(dev->optee_private);
+
mtk_vcodec_dbgfs_remove(dev, ctx->id);
list_del_init(>list);
kfree(ctx);
@@ -466,6 +469,11 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
atomic_set(>dec_active_cnt, 0);
memset(dev->vdec_racing_info, 0, sizeof(dev->vdec_racing_info));
mutex_init(>dec_racing_info_mutex);
+   ret = mtk_vcodec_dec_optee_private_init(dev);
+   if (ret) {
+   dev_err(>dev, "Failed to init svp private.");
+   goto err_reg_cont;
+   }
 
ret = video_register_device(vfd_dec, VFL_TYPE_VIDEO, -1);
if (ret) {
-- 
2.18.0



[PATCH v5, 23/23] WIP: media: mediatek: vcodec: support av1 svp decoder for mt8188

2024-04-12 Thread Yunfei Dong
From: Xiaoyong Lu 

Change av1 driver to support secure video playback(svp) for
mt8188. Need to map shared memory with optee interface and
wait interrupt in optee-os.

Signed-off-by: Xiaoyong Lu 
Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/vdec/vdec_av1_req_lat_if.c | 97 ---
 1 file changed, 63 insertions(+), 34 deletions(-)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c
index a081e12d67d6..c40ee2646b6c 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c
@@ -58,6 +58,9 @@
 #define SEG_LVL_ALT_Q 0
 #define SECONDARY_FILTER_STRENGTH_NUM_BITS 2
 
+#define AV1_IQ_TABLE_SIZE  0x12200
+#define AV1_CDF_TABLE_SIZE 0xFE80
+
 static const short div_lut[DIV_LUT_NUM + 1] = {
16384, 16320, 16257, 16194, 16132, 16070, 16009, 15948, 15888, 15828, 
15768,
15709, 15650, 15592, 15534, 15477, 15420, 15364, 15308, 15252, 15197, 
15142,
@@ -641,6 +644,8 @@ struct vdec_av1_slice_fb {
  * @frame: current frame info
  * @state: status after decode done
  * @cur_lst_tile_id:   tile id for large scale
+ * @tile_group:tile group info
+ * @reservd:   reserved
  */
 struct vdec_av1_slice_vsi {
/* lat */
@@ -665,6 +670,8 @@ struct vdec_av1_slice_vsi {
struct vdec_av1_slice_frame frame;
struct vdec_av1_slice_state state;
u32 cur_lst_tile_id;
+   struct vdec_av1_slice_tile_group tile_group;
+   unsigned int reservd[4];
 };
 
 /**
@@ -692,7 +699,6 @@ struct vdec_av1_slice_pfc {
  * @cdf_temp:   cdf temp buffer
  * @tile:   tile buffer
  * @slots:  slots info
- * @tile_group: tile_group entry
  * @level:  level of current resolution
  * @width:  width of last picture
  * @height: height of last picture
@@ -717,7 +723,6 @@ struct vdec_av1_slice_instance {
struct mtk_vcodec_mem cdf_temp;
struct mtk_vcodec_mem tile;
struct vdec_av1_slice_slot slots;
-   struct vdec_av1_slice_tile_group tile_group;
 
/* for resolution change and get_pic_info */
enum vdec_av1_slice_resolution_level level;
@@ -774,24 +779,28 @@ static int vdec_av1_slice_init_cdf_table(struct 
vdec_av1_slice_instance *instanc
 
ctx = instance->ctx;
vsi = instance->vpu.vsi;
-   remote_cdf_table = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
-(u32)vsi->cdf_table_addr);
-   if (IS_ERR(remote_cdf_table)) {
-   mtk_vdec_err(ctx, "failed to map cdf table\n");
-   return PTR_ERR(remote_cdf_table);
-   }
-
-   mtk_vdec_debug(ctx, "map cdf table to 0x%p\n", remote_cdf_table);
 
if (instance->cdf_table.va)
mtk_vcodec_mem_free(ctx, >cdf_table);
+   vsi->cdf_table_size = AV1_CDF_TABLE_SIZE;
+   mtk_vdec_debug(ctx, "svp %d. cdf table size 0x%x\n",
+  instance->ctx->is_secure_playback, vsi->cdf_table_size);
instance->cdf_table.size = vsi->cdf_table_size;
 
ret = mtk_vcodec_mem_alloc(ctx, >cdf_table);
if (ret)
return ret;
 
-   memcpy(instance->cdf_table.va, remote_cdf_table, vsi->cdf_table_size);
+   if (!instance->ctx->is_secure_playback) {
+   remote_cdf_table = 
mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
+
(u32)vsi->cdf_table_addr);
+   if (IS_ERR(remote_cdf_table)) {
+   mtk_vdec_err(ctx, "failed to map cdf table\n");
+   return PTR_ERR(remote_cdf_table);
+   }
+
+   memcpy(instance->cdf_table.va, remote_cdf_table, 
vsi->cdf_table_size);
+   }
 
return 0;
 }
@@ -805,25 +814,26 @@ static int vdec_av1_slice_init_iq_table(struct 
vdec_av1_slice_instance *instance
 
ctx = instance->ctx;
vsi = instance->vpu.vsi;
-   remote_iq_table = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
-   (u32)vsi->iq_table_addr);
-   if (IS_ERR(remote_iq_table)) {
-   mtk_vdec_err(ctx, "failed to map iq table\n");
-   return PTR_ERR(remote_iq_table);
-   }
-
-   mtk_vdec_debug(ctx, "map iq table to 0x%p\n", remote_iq_table);
 
if (instance->iq_table.va)
mtk_vcodec_mem_free(ctx, >iq_table);
+   vsi->iq_table_size = AV1_IQ_TABLE_SIZE;
instance->iq_table.size = vsi->iq_table_size;
 
ret = mtk_vcodec_mem_alloc(ctx, >iq_table);
   

[PATCH v5, 22/23] media: mediatek: vcodec: support hevc svp for mt8188

2024-04-12 Thread Yunfei Dong
Change hevc driver to support secure video playback(svp) for
mt8188. Need to map shared memory with optee interface and
wait interrupt in optee-os.

Signed-off-by: Yunfei Dong 
---
 .../decoder/vdec/vdec_hevc_req_multi_if.c | 89 +++
 1 file changed, 54 insertions(+), 35 deletions(-)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
index fe0a8508d632..30c85d053f18 100644
--- 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
+++ 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
@@ -415,11 +415,14 @@ static void vdec_hevc_fill_dpb_info(struct 
mtk_vcodec_dec_ctx *ctx,
hevc_dpb_info[index].field = dpb->field_pic;
 
hevc_dpb_info[index].y_dma_addr = 
vb2_dma_contig_plane_dma_addr(vb, 0);
-   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2)
-   hevc_dpb_info[index].c_dma_addr = 
vb2_dma_contig_plane_dma_addr(vb, 1);
-   else
-   hevc_dpb_info[index].c_dma_addr =
-   hevc_dpb_info[index].y_dma_addr + 
ctx->picinfo.fb_sz[0];
+   if (!ctx->is_secure_playback) {
+   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2)
+   hevc_dpb_info[index].c_dma_addr =
+   vb2_dma_contig_plane_dma_addr(vb, 1);
+   else
+   hevc_dpb_info[index].c_dma_addr =
+   hevc_dpb_info[index].y_dma_addr + 
ctx->picinfo.fb_sz[0];
+   }
}
 }
 
@@ -800,7 +803,7 @@ static int vdec_hevc_slice_setup_core_buffer(struct 
vdec_hevc_slice_inst *inst,
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;
+   u64 y_fb_dma, c_fb_dma = 0;
int i;
 
fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx);
@@ -810,18 +813,20 @@ static int vdec_hevc_slice_setup_core_buffer(struct 
vdec_hevc_slice_inst *inst,
}
 
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;
-   else
-   c_fb_dma = (u64)fb->base_c.dma_addr;
+   if (!ctx->is_secure_playback) {
+   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;
+   else
+   c_fb_dma = (u64)fb->base_c.dma_addr;
+   }
 
mtk_vdec_debug(inst->ctx, "[hevc-core] y/c addr = 0x%llx 0x%llx", 
y_fb_dma, c_fb_dma);
 
inst->vsi_core->fb.y.dma_addr = y_fb_dma;
inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[0];
inst->vsi_core->fb.c.dma_addr = c_fb_dma;
-   inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[1];
+   inst->vsi_core->fb.c.size = ctx->picinfo.fb_sz[1];
 
inst->vsi_core->dec.vdec_fb_va = (unsigned long)fb;
 
@@ -878,8 +883,13 @@ static int vdec_hevc_slice_init(struct mtk_vcodec_dec_ctx 
*ctx)
 
vsi_size = round_up(sizeof(struct vdec_hevc_slice_vsi), 
VCODEC_DEC_ALIGNED_64);
inst->vsi = inst->vpu.vsi;
-   inst->vsi_core =
-   (struct vdec_hevc_slice_vsi *)(((char *)inst->vpu.vsi) + 
vsi_size);
+   if (ctx->is_secure_playback)
+   inst->vsi_core =
+   
mtk_vcodec_dec_get_shm_buffer_va(ctx->dev->optee_private, MTK_VDEC_CORE,
+OPTEE_DATA_INDEX);
+   else
+   inst->vsi_core =
+   (struct vdec_hevc_slice_vsi *)(((char *)inst->vpu.vsi) 
+ vsi_size);
 
inst->resolution_changed = true;
inst->realloc_mv_buf = true;
@@ -944,21 +954,22 @@ static int vdec_hevc_slice_core_decode(struct 
vdec_lat_buf *lat_buf)
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);
-   inst->vsi_core->dec.timeout = !!timeout;
+   if (!vpu->ctx->is_secure_playback) {
+   /* wait decoder done interrupt */
+   timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, 
MTK_INST_IRQ_R

[PATCH v5, 12/23] media: mediatek: vcodec: add interface to allocate/free secure memory

2024-04-12 Thread Yunfei Dong
Need to call dma heap interface to allocate/free secure memory when playing
secure video.

Signed-off-by: Yunfei Dong 
---
 .../media/platform/mediatek/vcodec/Kconfig|   1 +
 .../mediatek/vcodec/common/mtk_vcodec_util.c  | 122 +-
 .../mediatek/vcodec/common/mtk_vcodec_util.h  |   3 +
 3 files changed, 123 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/Kconfig 
b/drivers/media/platform/mediatek/vcodec/Kconfig
index bc8292232530..707865703e61 100644
--- a/drivers/media/platform/mediatek/vcodec/Kconfig
+++ b/drivers/media/platform/mediatek/vcodec/Kconfig
@@ -17,6 +17,7 @@ config VIDEO_MEDIATEK_VCODEC
depends on VIDEO_MEDIATEK_VPU || !VIDEO_MEDIATEK_VPU
depends on MTK_SCP || !MTK_SCP
depends on MTK_SMI || (COMPILE_TEST && MTK_SMI=n)
+   depends on DMABUF_HEAPS
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
select VIDEO_MEDIATEK_VCODEC_VPU if VIDEO_MEDIATEK_VPU
diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c 
b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c
index 9ce34a3b5ee6..b1c1b0a8a2c6 100644
--- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c
+++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c
@@ -5,9 +5,11 @@
 *  Tiffany Lin 
 */
 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "../decoder/mtk_vcodec_dec_drv.h"
 #include "../encoder/mtk_vcodec_enc_drv.h"
@@ -45,7 +47,7 @@ int mtk_vcodec_write_vdecsys(struct mtk_vcodec_dec_ctx *ctx, 
unsigned int reg,
 }
 EXPORT_SYMBOL(mtk_vcodec_write_vdecsys);
 
-int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem *mem)
+static int mtk_vcodec_mem_alloc_nor(void *priv, struct mtk_vcodec_mem *mem)
 {
enum mtk_instance_type inst_type = *((unsigned int *)priv);
struct platform_device *plat_dev;
@@ -76,9 +78,71 @@ int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem 
*mem)
 
return 0;
 }
-EXPORT_SYMBOL(mtk_vcodec_mem_alloc);
 
-void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem *mem)
+static int mtk_vcodec_mem_alloc_sec(struct mtk_vcodec_dec_ctx *ctx, struct 
mtk_vcodec_mem *mem)
+{
+   struct device *dev = >dev->plat_dev->dev;
+   struct dma_buf *dma_buffer;
+   struct dma_heap *vdec_heap;
+   struct dma_buf_attachment *attach;
+   struct sg_table *sgt;
+   unsigned long size = mem->size;
+   int ret = 0;
+
+   if (!size)
+   return -EINVAL;
+
+   vdec_heap = dma_heap_find("restricted_mtk_cma");
+   if (!vdec_heap) {
+   mtk_v4l2_vdec_err(ctx, "dma heap find failed!");
+   return -EPERM;
+   }
+
+   dma_buffer = dma_heap_buffer_alloc(vdec_heap, size, 
DMA_HEAP_VALID_FD_FLAGS,
+  DMA_HEAP_VALID_HEAP_FLAGS);
+   if (IS_ERR_OR_NULL(dma_buffer)) {
+   mtk_v4l2_vdec_err(ctx, "dma heap alloc size=0x%lx failed!", 
size);
+   return PTR_ERR(dma_buffer);
+   }
+
+   attach = dma_buf_attach(dma_buffer, dev);
+   if (IS_ERR_OR_NULL(attach)) {
+   mtk_v4l2_vdec_err(ctx, "dma attach size=0x%lx failed!", size);
+   ret = PTR_ERR(attach);
+   goto err_attach;
+   }
+
+   sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+   if (IS_ERR_OR_NULL(sgt)) {
+   mtk_v4l2_vdec_err(ctx, "dma map attach size=0x%lx failed!", 
size);
+   ret = PTR_ERR(sgt);
+   goto err_sgt;
+   }
+
+   mem->va = dma_buffer;
+   mem->dma_addr = (dma_addr_t)sg_dma_address((sgt)->sgl);
+
+   if (!mem->va || !mem->dma_addr) {
+   mtk_v4l2_vdec_err(ctx, "dma buffer size=0x%lx failed!", size);
+   ret = -EPERM;
+   goto err_addr;
+   }
+
+   mem->attach = attach;
+   mem->sgt = sgt;
+
+   return 0;
+err_addr:
+   dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+err_sgt:
+   dma_buf_detach(dma_buffer, attach);
+err_attach:
+   dma_buf_put(dma_buffer);
+
+   return ret;
+}
+
+static void mtk_vcodec_mem_free_nor(void *priv, struct mtk_vcodec_mem *mem)
 {
enum mtk_instance_type inst_type = *((unsigned int *)priv);
struct platform_device *plat_dev;
@@ -111,6 +175,57 @@ void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem 
*mem)
mem->dma_addr = 0;
mem->size = 0;
 }
+
+static void mtk_vcodec_mem_free_sec(struct mtk_vcodec_mem *mem)
+{
+   if (mem->sgt)
+   dma_buf_unmap_attachment(mem->attach, mem->sgt, 
DMA_BIDIRECTIONAL);
+   dma_buf_detach((struct dma_buf *)mem->va, mem->attach);
+   dma_buf_put((struct dma_buf *)mem->va);
+
+   mem->attach = NULL;
+   mem->sgt = NULL;
+   mem->va = NULL;
+   me

[PATCH v5, 17/23] media: mediatek: vcodec: re-construct h264 driver to support svp mode

2024-04-12 Thread Yunfei Dong
Need secure buffer size to convert secure handle to secure
pa in optee-os, re-construct the vsi struct to store each
secure buffer size.

Separate svp and normal wait interrupt condition for svp mode
waiting hardware interrupt in optee-os.

Signed-off-by: Yunfei Dong 
---
 .../decoder/vdec/vdec_h264_req_multi_if.c | 261 +++---
 .../mediatek/vcodec/decoder/vdec_msg_queue.c  |   9 +-
 2 files changed, 168 insertions(+), 102 deletions(-)

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 d7fec1887ab5..40836673f7fe 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
@@ -60,14 +60,36 @@ struct vdec_h264_slice_lat_dec_param {
  * @crc:   Used to check whether hardware's status is right
  */
 struct vdec_h264_slice_info {
+   u64 wdma_end_addr_offset;
u16 nal_info;
u16 timeout;
-   u32 bs_buf_size;
-   u64 bs_buf_addr;
-   u64 y_fb_dma;
-   u64 c_fb_dma;
u64 vdec_fb_va;
u32 crc[8];
+   u32 reserved;
+};
+
+/*
+ * struct vdec_h264_slice_mem - memory address and size
+ */
+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
+ * @y:  current y buffer address info
+ * @c:  current c buffer address info
+ */
+struct vdec_h264_slice_fb {
+   struct vdec_h264_slice_mem y;
+   struct vdec_h264_slice_mem c;
 };
 
 /**
@@ -92,18 +114,16 @@ struct vdec_h264_slice_info {
  */
 struct vdec_h264_slice_vsi {
/* LAT dec addr */
-   u64 wdma_err_addr;
-   u64 wdma_start_addr;
-   u64 wdma_end_addr;
-   u64 slice_bc_start_addr;
-   u64 slice_bc_end_addr;
-   u64 row_info_start_addr;
-   u64 row_info_end_addr;
-   u64 trans_start;
-   u64 trans_end;
-   u64 wdma_end_addr_offset;
+   struct vdec_h264_slice_mem bs;
+   struct vdec_h264_slice_fb fb;
 
-   u64 mv_buf_dma[H264_MAX_MV_NUM];
+   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 dec;
struct vdec_h264_slice_lat_dec_param h264_slice_params;
 };
@@ -392,6 +412,100 @@ static void vdec_h264_slice_get_crop_info(struct 
vdec_h264_slice_inst *inst,
   cr->left, cr->top, cr->width, cr->height);
 }
 
+static void vdec_h264_slice_setup_lat_buffer(struct vdec_h264_slice_inst *inst,
+struct mtk_vcodec_mem *bs,
+struct vdec_lat_buf *lat_buf)
+{
+   struct mtk_vcodec_mem *mem;
+   int i;
+
+   inst->vsi->bs.dma_addr = (u64)bs->dma_addr;
+   inst->vsi->bs.size = bs->size;
+
+   for (i = 0; i < H264_MAX_MV_NUM; i++) {
+   mem = >mv_buf[i];
+   inst->vsi->mv_buf_dma[i].dma_addr = mem->dma_addr;
+   inst->vsi->mv_buf_dma[i].size = mem->size;
+   }
+   inst->vsi->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
+   inst->vsi->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size;
+
+   inst->vsi->row_info.dma_addr = 0;
+   inst->vsi->row_info.size = 0;
+
+   inst->vsi->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr;
+   inst->vsi->err_map.size = lat_buf->wdma_err_addr.size;
+
+   inst->vsi->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr;
+   inst->vsi->slice_bc.size = lat_buf->slice_bc_addr.size;
+
+   inst->vsi->trans.dma_addr_end = inst->ctx->msg_queue.wdma_rptr_addr;
+   inst->vsi->trans.dma_addr = inst->ctx->msg_queue.wdma_wptr_addr;
+}
+
+static int vdec_h264_slice_setup_core_buffer(struct vdec_h264_slice_inst *inst,
+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");
+   return -EBUSY;
+   }
+
+   y_fb_dma = (u64)fb->base_y.dma_addr;
+   if

[PATCH v5,15/23] media: mediatek: vcodec: Add one plane format

2024-04-12 Thread Yunfei Dong
Adding capture formats to support V4L2_PIX_FMT_MS21. This format has
one plane and only be used for secure video playback at current period.

Signed-off-by: Yunfei Dong 
---
 .../platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c| 4 +++-
 .../mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c   | 9 -
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index 9107707de6c4..192b01ff3ede 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -49,7 +49,9 @@ static bool mtk_vdec_get_cap_fmt(struct mtk_vcodec_dec_ctx 
*ctx, int format_inde
num_frame_count++;
}
 
-   if (num_frame_count == 1 || (!ctx->is_10bit_bitstream && fmt->fourcc == 
V4L2_PIX_FMT_MM21))
+   if ((!ctx->is_10bit_bitstream && fmt->fourcc == V4L2_PIX_FMT_MM21) ||
+   (ctx->is_secure_playback && fmt->fourcc == V4L2_PIX_FMT_MS21) ||
+   num_frame_count == 1)
return true;
 
q_data = >q_data[MTK_Q_DATA_SRC];
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index b903e39fee89..fbea00517565 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -229,7 +229,7 @@ static const struct mtk_stateless_control 
mtk_stateless_controls[] = {
 
 #define NUM_CTRLS ARRAY_SIZE(mtk_stateless_controls)
 
-static struct mtk_video_fmt mtk_video_formats[9];
+static struct mtk_video_fmt mtk_video_formats[10];
 
 static struct mtk_video_fmt default_out_format;
 static struct mtk_video_fmt default_cap_format;
@@ -770,6 +770,11 @@ static void mtk_vcodec_add_formats(unsigned int fourcc,
mtk_video_formats[count_formats].type = MTK_FMT_FRAME;
mtk_video_formats[count_formats].num_planes = 2;
break;
+   case V4L2_PIX_FMT_MS21:
+   mtk_video_formats[count_formats].fourcc = fourcc;
+   mtk_video_formats[count_formats].type = MTK_FMT_FRAME;
+   mtk_video_formats[count_formats].num_planes = 1;
+   break;
default:
mtk_v4l2_vdec_err(ctx, "Can not add unsupported format type");
return;
@@ -798,6 +803,8 @@ static void mtk_vcodec_get_supported_formats(struct 
mtk_vcodec_dec_ctx *ctx)
cap_format_count++;
}
if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_MM21) {
+   mtk_vcodec_add_formats(V4L2_PIX_FMT_MS21, ctx);
+   cap_format_count++;
mtk_vcodec_add_formats(V4L2_PIX_FMT_MM21, ctx);
cap_format_count++;
}
-- 
2.18.0



[PATCH v5, 10/23] media: mediatek: vcodec: send share memory data to optee

2024-04-12 Thread Yunfei Dong
Setting msg and vsi information to shared buffer, then call tee invoke
function to send it to optee-os.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 140 ++
 .../vcodec/decoder/mtk_vcodec_dec_optee.h |  51 +++
 2 files changed, 191 insertions(+)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
index 611fb0e56480..f29a8d143fee 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
@@ -241,3 +241,143 @@ void mtk_vcodec_dec_optee_release(struct 
mtk_vdec_optee_private *optee_private)
mutex_unlock(_private->tee_mutex);
 }
 EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_release);
+
+static int mtk_vcodec_dec_optee_fill_shm(struct tee_param *command_params,
+struct mtk_vdec_optee_shm_memref 
*shm_memref,
+struct mtk_vdec_optee_data_to_shm 
*data,
+int index, struct device *dev)
+{
+   if (!data->msg_buf_size[index] || !data->msg_buf[index]) {
+   pr_err(MTK_DBG_VCODEC_STR "tee invalid buf param: %d.\n", 
index);
+   return -EINVAL;
+   }
+
+   *command_params = (struct tee_param) {
+   .attr = shm_memref->param_type,
+   .u.memref = {
+   .shm = shm_memref->msg_shm,
+   .size = data->msg_buf_size[index],
+   .shm_offs = 0,
+   },
+   };
+
+   if (!shm_memref->copy_to_ta) {
+   dev_dbg(dev, MTK_DBG_VCODEC_STR "share memref data: 0x%x 
param_type:%llu.\n",
+   *((unsigned int *)shm_memref->msg_shm_ca_buf), 
shm_memref->param_type);
+   return 0;
+   }
+
+   memset(shm_memref->msg_shm_ca_buf, 0, shm_memref->msg_shm_size);
+   memcpy(shm_memref->msg_shm_ca_buf, data->msg_buf[index], 
data->msg_buf_size[index]);
+
+   dev_dbg(dev, MTK_DBG_VCODEC_STR "share memref data => msg id:0x%x 0x%x 
param_type:%llu.\n",
+   *((unsigned int *)data->msg_buf[index]),
+   *((unsigned int *)shm_memref->msg_shm_ca_buf),
+   shm_memref->param_type);
+
+   return 0;
+}
+
+void mtk_vcodec_dec_optee_set_data(struct mtk_vdec_optee_data_to_shm *data,
+  void *buf, int buf_size,
+  enum mtk_vdec_optee_data_index index)
+{
+   data->msg_buf[index] = buf;
+   data->msg_buf_size[index] = buf_size;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_set_data);
+
+int mtk_vcodec_dec_optee_invokd_cmd(struct mtk_vdec_optee_private 
*optee_private,
+   enum mtk_vdec_hw_id hw_id,
+   struct mtk_vdec_optee_data_to_shm *data)
+{
+   struct device *dev = _private->vcodec_dev->plat_dev->dev;
+   struct tee_ioctl_invoke_arg trans_args;
+   struct tee_param command_params[MTK_OPTEE_MAX_TEE_PARAMS];
+   struct mtk_vdec_optee_ca_info *ca_info;
+   struct mtk_vdec_optee_shm_memref *shm_memref;
+   int ret, index;
+
+   if (hw_id == MTK_VDEC_LAT0)
+   ca_info = _private->lat_ca;
+   else
+   ca_info = _private->core_ca;
+
+   memset(_args, 0, sizeof(trans_args));
+   memset(command_params, 0, sizeof(command_params));
+
+   trans_args = (struct tee_ioctl_invoke_arg) {
+   .func = ca_info->vdec_session_func,
+   .session = ca_info->vdec_session_id,
+   .num_params = MTK_OPTEE_MAX_TEE_PARAMS,
+   };
+
+   /* Fill msg command parameters */
+   for (index = 0; index < MTK_OPTEE_MAX_TEE_PARAMS; index++) {
+   shm_memref = _info->shm_memref[index];
+
+   if (shm_memref->param_type == TEE_IOCTL_PARAM_ATTR_TYPE_NONE ||
+   data->msg_buf_size[index] == 0)
+   continue;
+
+   dev_dbg(dev, MTK_DBG_VCODEC_STR "tee share memory data size: %d 
-> %d.\n",
+   data->msg_buf_size[index], shm_memref->msg_shm_size);
+
+   if (data->msg_buf_size[index] > shm_memref->msg_shm_size) {
+   dev_err(dev, MTK_DBG_VCODEC_STR "tee buf size big than 
shm (%d -> %d).\n",
+   data->msg_buf_size[index], 
shm_memref->msg_shm_size);
+   return -EINVAL;
+   }
+
+   ret = mtk_vcodec_dec_optee_fill_shm(_params[index], 
shm_memref,
+   data, index, dev);
+   if (ret)
+   return ret;
+ 

[PATCH v5, 13/23] media: mediatek: vcodec: using shared memory as vsi address

2024-04-12 Thread Yunfei Dong
The vsi buffer is allocated by tee share memory for svp mode, need to
use the share memory as the vsi address to store vsi data.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/vdec/vdec_h264_req_multi_if.c | 9 +++--
 .../media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c | 8 ++--
 2 files changed, 13 insertions(+), 4 deletions(-)

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 2d4611e7fa0b..d7fec1887ab5 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
@@ -417,8 +417,13 @@ static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx 
*ctx)
 
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);
+   if (ctx->is_secure_playback)
+   inst->vsi_core =
+   
mtk_vcodec_dec_get_shm_buffer_va(ctx->dev->optee_private, MTK_VDEC_CORE,
+OPTEE_DATA_INDEX);
+   else
+   inst->vsi_core =
+   (struct vdec_h264_slice_vsi *)(((char *)inst->vpu.vsi) 
+ vsi_size);
inst->resolution_changed = true;
inst->realloc_mv_buf = true;
 
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
index 5336769a3fb5..5c31641e9abe 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
@@ -18,8 +18,12 @@ static void handle_init_ack_msg(const struct 
vdec_vpu_ipi_init_ack *msg)
 
/* mapping VPU address to kernel virtual address */
/* the content in vsi is initialized to 0 in VPU */
-   vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->fw_handler,
-msg->vpu_inst_addr);
+   if (vpu->ctx->is_secure_playback)
+   vpu->vsi = 
mtk_vcodec_dec_get_shm_buffer_va(vpu->ctx->dev->optee_private,
+   MTK_VDEC_LAT0, 
OPTEE_DATA_INDEX);
+   else
+   vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->fw_handler,
+msg->vpu_inst_addr);
vpu->inst_addr = msg->vpu_inst_addr;
 
mtk_vdec_debug(vpu->ctx, "- vpu_inst_addr = 0x%x", vpu->inst_addr);
-- 
2.18.0



[PATCH v5, 14/23] media: mediatek: vcodec: Add capture format to support one plane memory

2024-04-12 Thread Yunfei Dong
Define one uncompressed capture format V4L2_PIX_FMT_MS21 in order to
support one plane memory. The buffer size is luma + chroma, luma is
stored at the start and chrome is stored at the end.

Signed-off-by: Yunfei Dong 
---
 Documentation/userspace-api/media/v4l/pixfmt-reserved.rst | 8 
 drivers/media/v4l2-core/v4l2-common.c | 2 ++
 drivers/media/v4l2-core/v4l2-ioctl.c  | 1 +
 include/uapi/linux/videodev2.h| 1 +
 4 files changed, 12 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst 
b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
index 886ba7b08d6b..6ec899649d50 100644
--- a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
+++ b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
@@ -295,6 +295,14 @@ please make a proposal on the linux-media mailing list.
   - Compressed format used by Nuvoton NPCM video driver. This format is
 defined in Remote Framebuffer Protocol (RFC 6143, chapter 7.7.4 Hextile
 Encoding).
+* .. _V4L2-PIX-FMT-MS21:
+
+  - ``V4L2_PIX_FMT_MS21``
+  - 'MS21'
+  - This format has one plane, luma and chroma are stored in a contiguous
+memory. Luma pixel in 16x32 tiles at the start, chroma pixel in 16x16
+tiles at the end. The image height must be aligned with 32 and the 
image
+width must be aligned with 16.
 .. raw:: latex
 
 \normalsize
diff --git a/drivers/media/v4l2-core/v4l2-common.c 
b/drivers/media/v4l2-core/v4l2-common.c
index 4165c815faef..117a8f526f5f 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -271,6 +271,8 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
  .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
{ .format = V4L2_PIX_FMT_MT2110R, .pixel_enc = 
V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, 
.bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
  .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
+   { .format = V4L2_PIX_FMT_MS21,.pixel_enc = 
V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, 
.bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
+ .block_w = { 64, 64, 0, 0 }, .block_h = { 64, 64, 0, 0 }},
 
/* YUV planar formats */
{ .format = V4L2_PIX_FMT_NV12,.pixel_enc = 
V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, 
.bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 5aeff5519407..dc7df3978e55 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1519,6 +1519,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_MT2110T:  descr = "Mediatek 10bit Tile 
Mode"; break;
case V4L2_PIX_FMT_MT2110R:  descr = "Mediatek 10bit Raster 
Mode"; break;
case V4L2_PIX_FMT_HEXTILE:  descr = "Hextile Compressed 
Format"; break;
+   case V4L2_PIX_FMT_MS21: descr = "MediaTek One Plane 
Format"; break;
default:
if (fmt->description[0])
return;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index b6fbbd276bf1..419dec606bfe 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -798,6 +798,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_MM21 v4l2_fourcc('M', 'M', '2', '1') /* Mediatek 
8-bit block mode, two non-contiguous planes */
 #define V4L2_PIX_FMT_MT2110T  v4l2_fourcc('M', 'T', '2', 'T') /* Mediatek 
10-bit block tile mode */
 #define V4L2_PIX_FMT_MT2110R  v4l2_fourcc('M', 'T', '2', 'R') /* Mediatek 
10-bit block raster mode */
+#define V4L2_PIX_FMT_MS21 v4l2_fourcc('M', 'S', '2', '1') /* MediaTek 
8-bit block mode with one plane */
 #define V4L2_PIX_FMT_INZI v4l2_fourcc('I', 'N', 'Z', 'I') /* Intel Planar 
Greyscale 10-bit and Depth 16-bit */
 #define V4L2_PIX_FMT_CNF4 v4l2_fourcc('C', 'N', 'F', '4') /* Intel 4-bit 
packed depth confidence information */
 #define V4L2_PIX_FMT_HI240v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit 
dithered RGB */
-- 
2.18.0



[PATCH v5, 08/23] media: mediatek: vcodec: add tee client interface to communiate with optee-os

2024-04-12 Thread Yunfei Dong
Open tee context to initialize the environment in order to communication
with optee-os, then open tee session as the communication pipeline for
lat and core to send data for hardware decode.

Signed-off-by: Yunfei Dong 
---
 .../platform/mediatek/vcodec/decoder/Makefile |   1 +
 .../vcodec/decoder/mtk_vcodec_dec_drv.h   |   5 +
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 165 ++
 .../vcodec/decoder/mtk_vcodec_dec_optee.h |  73 
 4 files changed, 244 insertions(+)
 create mode 100644 
drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
 create mode 100644 
drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/Makefile 
b/drivers/media/platform/mediatek/vcodec/decoder/Makefile
index 904cd22def84..1624933dfd5e 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/Makefile
+++ b/drivers/media/platform/mediatek/vcodec/decoder/Makefile
@@ -21,5 +21,6 @@ mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
mtk_vcodec_dec_stateful.o \
mtk_vcodec_dec_stateless.o \
mtk_vcodec_dec_pm.o \
+   mtk_vcodec_dec_optee.o \
 
 mtk-vcodec-dec-hw-y := mtk_vcodec_dec_hw.o
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 f975db4293da..76a0323f993c 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
@@ -11,6 +11,7 @@
 #include "../common/mtk_vcodec_dbgfs.h"
 #include "../common/mtk_vcodec_fw_priv.h"
 #include "../common/mtk_vcodec_util.h"
+#include "mtk_vcodec_dec_optee.h"
 #include "vdec_msg_queue.h"
 
 #define MTK_VCODEC_DEC_NAME"mtk-vcodec-dec"
@@ -261,6 +262,8 @@ struct mtk_vcodec_dec_ctx {
  * @dbgfs: debug log related information
  *
  * @chip_name: used to distinguish platforms and select the correct codec 
configuration values
+ *
+ * @optee_private: optee private data
  */
 struct mtk_vcodec_dec_dev {
struct v4l2_device v4l2_dev;
@@ -303,6 +306,8 @@ struct mtk_vcodec_dec_dev {
struct mtk_vcodec_dbgfs dbgfs;
 
enum mtk_vcodec_dec_chip_name chip_name;
+
+   struct mtk_vdec_optee_private *optee_private;
 };
 
 static inline struct mtk_vcodec_dec_ctx *fh_to_dec_ctx(struct v4l2_fh *fh)
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
new file mode 100644
index ..38d9c1c1785a
--- /dev/null
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Yunfei Dong 
+ */
+
+#include "mtk_vcodec_dec_drv.h"
+#include "mtk_vcodec_dec_optee.h"
+
+/*
+ * Randomly generated, and must correspond to the GUID on the TA side.
+ */
+static const uuid_t mtk_vdec_lat_uuid =
+   UUID_INIT(0xBC50D971, 0xD4C9, 0x42C4,
+ 0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x90);
+
+static const uuid_t mtk_vdec_core_uuid =
+   UUID_INIT(0xBC50D971, 0xD4C9, 0x42C4,
+ 0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x91);
+
+/*
+ * Check whether this driver supports decoder TA in the TEE instance,
+ * represented by the params (ver/data) of this function.
+ */
+static int mtk_vcodec_dec_optee_match(struct tee_ioctl_version_data *ver_data, 
const void *not_used)
+{
+   if (ver_data->impl_id == TEE_IMPL_ID_OPTEE)
+   return 1;
+   else
+   return 0;
+}
+
+int mtk_vcodec_dec_optee_private_init(struct mtk_vcodec_dec_dev *vcodec_dev)
+{
+   vcodec_dev->optee_private = devm_kzalloc(_dev->plat_dev->dev,
+
sizeof(*vcodec_dev->optee_private),
+GFP_KERNEL);
+   if (!vcodec_dev->optee_private)
+   return -ENOMEM;
+
+   vcodec_dev->optee_private->vcodec_dev = vcodec_dev;
+
+   atomic_set(_dev->optee_private->tee_active_cnt, 0);
+   mutex_init(_dev->optee_private->tee_mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_private_init);
+
+static int mtk_vcodec_dec_optee_init_hw_info(struct mtk_vdec_optee_private 
*optee_private,
+enum mtk_vdec_hw_id hardware_index)
+{
+   struct device *dev = _private->vcodec_dev->plat_dev->dev;
+   struct tee_ioctl_open_session_arg session_arg;
+   struct mtk_vdec_optee_ca_info *ca_info;
+   int err = 0, session_func;
+
+   /* Open lat and core session with vdec TA. */
+   switch (hardware_index) {
+   case MTK_VDEC_LAT0:
+   export_uuid(session_arg.uuid, _vd

[PATCH v5,09/23] media: mediatek: vcodec: allocate tee share memory

2024-04-12 Thread Yunfei Dong
Allocate two share memory for each lat and core hardware used to share
information with optee-os. Msg buffer used to send ipi command and get ack
command with optee-os, data buffer used to store vsi information which
used for hardware decode.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 80 ++-
 .../vcodec/decoder/mtk_vcodec_dec_optee.h | 32 
 2 files changed, 111 insertions(+), 1 deletion(-)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
index 38d9c1c1785a..611fb0e56480 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
@@ -47,13 +47,69 @@ int mtk_vcodec_dec_optee_private_init(struct 
mtk_vcodec_dec_dev *vcodec_dev)
 }
 EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_private_init);
 
+static void mtk_vcodec_dec_optee_deinit_memref(struct mtk_vdec_optee_ca_info 
*ca_info,
+  enum mtk_vdec_optee_data_index 
data_index)
+{
+   tee_shm_free(ca_info->shm_memref[data_index].msg_shm);
+}
+
+static int mtk_vcodec_dec_optee_init_memref(struct tee_context *tee_vdec_ctx,
+   struct mtk_vdec_optee_ca_info 
*ca_info,
+   enum mtk_vdec_optee_data_index 
data_index)
+{
+   struct mtk_vdec_optee_shm_memref *shm_memref;
+   int alloc_size = 0, err = 0;
+   u64 shm_param_type = 0;
+   bool copy_buffer;
+
+   switch (data_index) {
+   case OPTEE_MSG_INDEX:
+   shm_param_type = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+   alloc_size = MTK_VDEC_OPTEE_MSG_SIZE;
+   copy_buffer = true;
+   break;
+   case OPTEE_DATA_INDEX:
+   shm_param_type = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+   alloc_size = MTK_VDEC_OPTEE_HW_SIZE;
+   copy_buffer = false;
+   break;
+   default:
+   pr_err(MTK_DBG_VCODEC_STR "tee invalid data_index: %d.\n", 
data_index);
+   return -EINVAL;
+   }
+
+   shm_memref = _info->shm_memref[data_index];
+
+   /* Allocate dynamic shared memory with decoder TA */
+   shm_memref->msg_shm_size = alloc_size;
+   shm_memref->param_type = shm_param_type;
+   shm_memref->copy_to_ta = copy_buffer;
+   shm_memref->msg_shm = tee_shm_alloc_kernel_buf(tee_vdec_ctx, 
shm_memref->msg_shm_size);
+   if (IS_ERR(shm_memref->msg_shm)) {
+   pr_err(MTK_DBG_VCODEC_STR "tee alloc buf fail: 
data_index:%d.\n", data_index);
+   return -ENOMEM;
+   }
+
+   shm_memref->msg_shm_ca_buf = tee_shm_get_va(shm_memref->msg_shm, 0);
+   if (IS_ERR(shm_memref->msg_shm_ca_buf)) {
+   pr_err(MTK_DBG_VCODEC_STR "tee get shm va fail: 
data_index:%d.\n", data_index);
+   err = PTR_ERR(shm_memref->msg_shm_ca_buf);
+   goto err_get_msg_va;
+   }
+
+   return err;
+err_get_msg_va:
+   tee_shm_free(shm_memref->msg_shm);
+   return err;
+}
+
 static int mtk_vcodec_dec_optee_init_hw_info(struct mtk_vdec_optee_private 
*optee_private,
 enum mtk_vdec_hw_id hardware_index)
 {
struct device *dev = _private->vcodec_dev->plat_dev->dev;
struct tee_ioctl_open_session_arg session_arg;
struct mtk_vdec_optee_ca_info *ca_info;
-   int err = 0, session_func;
+   int err, i, j, session_func;
 
/* Open lat and core session with vdec TA. */
switch (hardware_index) {
@@ -87,6 +143,24 @@ static int mtk_vcodec_dec_optee_init_hw_info(struct 
mtk_vdec_optee_private *opte
dev_dbg(dev, MTK_DBG_VCODEC_STR "open vdec tee session hw_id:%d 
session_id=%x.\n",
hardware_index, ca_info->vdec_session_id);
 
+   /* Allocate dynamic shared memory with decoder TA */
+   for (i = 0; i < OPTEE_MAX_INDEX; i++) {
+   err = 
mtk_vcodec_dec_optee_init_memref(optee_private->tee_vdec_ctx, ca_info, i);
+   if (err) {
+   dev_err(dev, MTK_DBG_VCODEC_STR "init vdec memref 
failed: %d.\n", i);
+   goto err_init_memref;
+   }
+   }
+
+   return err;
+err_init_memref:
+   if (i != 0) {
+   for (j = 0; j < i; j++)
+   mtk_vcodec_dec_optee_deinit_memref(ca_info, j);
+   }
+
+   tee_client_close_session(optee_private->tee_vdec_ctx, 
ca_info->vdec_session_id);
+
return err;
 }
 
@@ -94,12 +168,16 @@ static void mtk_vcodec_dec_optee_deinit_hw_info(struct 
mtk_vdec_optee_private *o
enum mtk_vdec_hw_id hw_id)
 {
struct mtk_

[PATCH v5, 07/23] dma-heap: Provide accessors so that in-kernel drivers can allocate dmabufs from specific heaps

2024-04-12 Thread Yunfei Dong
From: John Stultz 

This allows drivers who don't want to create their own
DMA-BUF exporter to be able to allocate DMA-BUFs directly
from existing DMA-BUF Heaps.

There is some concern that the premise of DMA-BUF heaps is
that userland knows better about what type of heap memory
is needed for a pipeline, so it would likely be best for
drivers to import and fill DMA-BUFs allocated by userland
instead of allocating one themselves, but this is still
up for debate.

Signed-off-by: John Stultz 
Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Fix the checkpatch alignment warning]
Signed-off-by: Yunfei Dong 
---
 drivers/dma-buf/dma-heap.c | 83 ++
 include/linux/dma-heap.h   |  6 +++
 2 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 97025ee8500f..6efe833a4b10 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -51,12 +51,24 @@ static dev_t dma_heap_devt;
 static struct class *dma_heap_class;
 static DEFINE_XARRAY_ALLOC(dma_heap_minors);
 
-static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
-unsigned int fd_flags,
-unsigned int heap_flags)
+/**
+ * dma_heap_buffer_alloc - Allocate dma-buf from a dma_heap
+ * @heap:  DMA-Heap to allocate from
+ * @len:   size to allocate in bytes
+ * @fd_flags:  flags to set on returned dma-buf fd
+ * @heap_flags: flags to pass to the dma heap
+ *
+ * This is for internal dma-buf allocations only. Free returned buffers with 
dma_buf_put().
+ */
+struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
+ unsigned int fd_flags,
+ unsigned int heap_flags)
 {
-   struct dma_buf *dmabuf;
-   int fd;
+   if (fd_flags & ~DMA_HEAP_VALID_FD_FLAGS)
+   return ERR_PTR(-EINVAL);
+
+   if (heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
+   return ERR_PTR(-EINVAL);
 
/*
 * Allocations from all heaps have to begin
@@ -64,9 +76,20 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, 
size_t len,
 */
len = PAGE_ALIGN(len);
if (!len)
-   return -EINVAL;
+   return ERR_PTR(-EINVAL);
+
+   return heap->ops->allocate(heap, len, fd_flags, heap_flags);
+}
+EXPORT_SYMBOL_GPL(dma_heap_buffer_alloc);
 
-   dmabuf = heap->ops->allocate(heap, len, fd_flags, heap_flags);
+static int dma_heap_bufferfd_alloc(struct dma_heap *heap, size_t len,
+  unsigned int fd_flags,
+  unsigned int heap_flags)
+{
+   struct dma_buf *dmabuf;
+   int fd;
+
+   dmabuf = dma_heap_buffer_alloc(heap, len, fd_flags, heap_flags);
if (IS_ERR(dmabuf))
return PTR_ERR(dmabuf);
 
@@ -104,15 +127,9 @@ static long dma_heap_ioctl_allocate(struct file *file, 
void *data)
if (heap_allocation->fd)
return -EINVAL;
 
-   if (heap_allocation->fd_flags & ~DMA_HEAP_VALID_FD_FLAGS)
-   return -EINVAL;
-
-   if (heap_allocation->heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
-   return -EINVAL;
-
-   fd = dma_heap_buffer_alloc(heap, heap_allocation->len,
-  heap_allocation->fd_flags,
-  heap_allocation->heap_flags);
+   fd = dma_heap_bufferfd_alloc(heap, heap_allocation->len,
+heap_allocation->fd_flags,
+heap_allocation->heap_flags);
if (fd < 0)
return fd;
 
@@ -205,6 +222,7 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
 {
return heap->priv;
 }
+EXPORT_SYMBOL_GPL(dma_heap_get_drvdata);
 
 /**
  * dma_heap_get_name - get heap name
@@ -217,6 +235,7 @@ const char *dma_heap_get_name(struct dma_heap *heap)
 {
return heap->name;
 }
+EXPORT_SYMBOL_GPL(dma_heap_get_name);
 
 /**
  * dma_heap_add - adds a heap to dmabuf heaps
@@ -307,6 +326,37 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
kfree(heap);
return err_ret;
 }
+EXPORT_SYMBOL_GPL(dma_heap_add);
+
+/**
+ * dma_heap_find - get the heap registered with the specified name
+ * @name: Name of the DMA-Heap to find
+ *
+ * Returns:
+ * The DMA-Heap with the provided name.
+ *
+ * NOTE: DMA-Heaps returned from this function MUST be released using
+ * dma_heap_put() when the user is done to enable the heap to be unloaded.
+ */
+struct dma_heap *dma_heap_find(const char *name)
+{
+   struct dma_heap *h;
+
+   mutex_lock(_list_lock);
+   list_for_each_entry(h, _list, list) {
+   if (!kref_get_unless_zero(>refcount))
+   continue;
+
+   if (!strcmp(h->name, name)) {
+ 

[PATCH v5, 05/23] dma-buf: heaps: Deduplicate docs and adopt common format

2024-04-12 Thread Yunfei Dong
From: "T.J. Mercier" 

The docs for dma_heap_get_name were incorrect, and since they were
duplicated in the header they were wrong there too.

The docs formatting was inconsistent so I tried to make it more
consistent across functions since I'm already in here doing cleanup.

Remove multiple unused includes and alphabetize.

Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Just add a comment for "priv" to mute build warning]
Signed-off-by: Yunfei Dong 
---
 drivers/dma-buf/dma-heap.c | 27 +++
 include/linux/dma-heap.h   | 21 +
 2 files changed, 16 insertions(+), 32 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 84ae708fafe7..22f6c193db0d 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -7,17 +7,15 @@
  */
 
 #include 
-#include 
 #include 
 #include 
+#include 
 #include 
-#include 
 #include 
-#include 
 #include 
-#include 
 #include 
-#include 
+#include 
+#include 
 #include 
 
 #define DEVNAME "dma_heap"
@@ -28,9 +26,10 @@
  * struct dma_heap - represents a dmabuf heap in the system
  * @name:  used for debugging/device-node name
  * @ops:   ops struct for this heap
- * @heap_devt  heap device node
- * @list   list head connecting to list of heaps
- * @heap_cdev  heap char device
+ * @priv:  private data for this heap
+ * @heap_devt: heap device node
+ * @list:  list head connecting to list of heaps
+ * @heap_cdev: heap char device
  *
  * Represents a heap of memory from which buffers can be made.
  */
@@ -193,11 +192,11 @@ static const struct file_operations dma_heap_fops = {
 };
 
 /**
- * dma_heap_get_drvdata() - get per-subdriver data for the heap
+ * dma_heap_get_drvdata - get per-heap driver data
  * @heap: DMA-Heap to retrieve private data for
  *
  * Returns:
- * The per-subdriver data for the heap.
+ * The per-heap data for the heap.
  */
 void *dma_heap_get_drvdata(struct dma_heap *heap)
 {
@@ -205,8 +204,8 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
 }
 
 /**
- * dma_heap_get_name() - get heap name
- * @heap: DMA-Heap to retrieve private data for
+ * dma_heap_get_name - get heap name
+ * @heap: DMA-Heap to retrieve the name of
  *
  * Returns:
  * The char* for the heap name.
@@ -216,6 +215,10 @@ const char *dma_heap_get_name(struct dma_heap *heap)
return heap->name;
 }
 
+/**
+ * dma_heap_add - adds a heap to dmabuf heaps
+ * @exp_info: information needed to register this heap
+ */
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
 {
struct dma_heap *heap, *h, *err_ret;
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index 0c05561cad6e..fbe86ec889a8 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -9,14 +9,13 @@
 #ifndef _DMA_HEAPS_H
 #define _DMA_HEAPS_H
 
-#include 
 #include 
 
 struct dma_heap;
 
 /**
  * struct dma_heap_ops - ops to operate on a given heap
- * @allocate:  allocate dmabuf and return struct dma_buf ptr
+ * @allocate:  allocate dmabuf and return struct dma_buf ptr
  *
  * allocate returns dmabuf on success, ERR_PTR(-errno) on error.
  */
@@ -41,28 +40,10 @@ struct dma_heap_export_info {
void *priv;
 };
 
-/**
- * dma_heap_get_drvdata() - get per-heap driver data
- * @heap: DMA-Heap to retrieve private data for
- *
- * Returns:
- * The per-heap data for the heap.
- */
 void *dma_heap_get_drvdata(struct dma_heap *heap);
 
-/**
- * dma_heap_get_name() - get heap name
- * @heap: DMA-Heap to retrieve private data for
- *
- * Returns:
- * The char* for the heap name.
- */
 const char *dma_heap_get_name(struct dma_heap *heap);
 
-/**
- * dma_heap_add - adds a heap to dmabuf heaps
- * @exp_info:  information needed to register this heap
- */
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
 #endif /* _DMA_HEAPS_H */
-- 
2.18.0



[PATCH v5,06/23] dma-heap: Add proper kref handling on dma-buf heaps

2024-04-12 Thread Yunfei Dong
From: John Stultz 

Add proper refcounting on the dma_heap structure.
While existing heaps are built-in, we may eventually
have heaps loaded from modules, and we'll need to be
able to properly handle the references to the heaps

Signed-off-by: John Stultz 
Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Just add comment for "minor" and "refcount"]
Signed-off-by: Yunfei Dong 
---
 drivers/dma-buf/dma-heap.c | 29 +
 include/linux/dma-heap.h   |  2 ++
 2 files changed, 31 insertions(+)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 22f6c193db0d..97025ee8500f 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -30,6 +31,7 @@
  * @heap_devt: heap device node
  * @list:  list head connecting to list of heaps
  * @heap_cdev: heap char device
+ * @refcount:  reference counter for this heap device
  *
  * Represents a heap of memory from which buffers can be made.
  */
@@ -40,6 +42,7 @@ struct dma_heap {
dev_t heap_devt;
struct list_head list;
struct cdev heap_cdev;
+   struct kref refcount;
 };
 
 static LIST_HEAD(heap_list);
@@ -240,6 +243,7 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
if (!heap)
return ERR_PTR(-ENOMEM);
 
+   kref_init(>refcount);
heap->name = exp_info->name;
heap->ops = exp_info->ops;
heap->priv = exp_info->priv;
@@ -304,6 +308,31 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
return err_ret;
 }
 
+static void dma_heap_release(struct kref *ref)
+{
+   struct dma_heap *heap = container_of(ref, struct dma_heap, refcount);
+   unsigned int minor = MINOR(heap->heap_devt);
+
+   mutex_lock(_list_lock);
+   list_del(>list);
+   mutex_unlock(_list_lock);
+
+   device_destroy(dma_heap_class, heap->heap_devt);
+   cdev_del(>heap_cdev);
+   xa_erase(_heap_minors, minor);
+
+   kfree(heap);
+}
+
+/**
+ * dma_heap_put - drops a reference to a dmabuf heap, potentially freeing it
+ * @heap: DMA-Heap whose reference count to decrement
+ */
+void dma_heap_put(struct dma_heap *heap)
+{
+   kref_put(>refcount, dma_heap_release);
+}
+
 static char *dma_heap_devnode(const struct device *dev, umode_t *mode)
 {
return kasprintf(GFP_KERNEL, "dma_heap/%s", dev_name(dev));
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index fbe86ec889a8..d57593f8a1bc 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -46,4 +46,6 @@ const char *dma_heap_get_name(struct dma_heap *heap);
 
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
+void dma_heap_put(struct dma_heap *heap);
+
 #endif /* _DMA_HEAPS_H */
-- 
2.18.0



[PATCH v5,04/23] v4l: add documentation for restricted memory flag

2024-04-12 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Adds documentation for V4L2_MEMORY_FLAG_RESTRICTED.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 Documentation/userspace-api/media/v4l/buffer.rst | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/Documentation/userspace-api/media/v4l/buffer.rst 
b/Documentation/userspace-api/media/v4l/buffer.rst
index 52bbee81c080..807e43bfed2b 100644
--- a/Documentation/userspace-api/media/v4l/buffer.rst
+++ b/Documentation/userspace-api/media/v4l/buffer.rst
@@ -696,7 +696,7 @@ enum v4l2_memory
 
 .. _memory-flags:
 
-Memory Consistency Flags
+Memory Flags
 
 
 .. raw:: latex
@@ -728,6 +728,14 @@ Memory Consistency Flags
only if the buffer is used for :ref:`memory mapping ` I/O and the
queue reports the :ref:`V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS
` capability.
+* .. _`V4L2-MEMORY-FLAG-RESTRICTED`:
+
+  - ``V4L2_MEMORY_FLAG_RESTRICTED``
+  - 0x0002
+  - The queued buffers are expected to be in restricted memory. If not, an
+   error will be returned. This flag can only be used with 
``V4L2_MEMORY_DMABUF``.
+   Typically restricted buffers are allocated using a restricted dma-heap. 
This flag
+   can only be specified if the ``V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM`` 
is set.
 
 .. raw:: latex
 
-- 
2.18.0



[PATCH v5, 03/23] v4l2: verify restricted dmabufs are used in restricted queue

2024-04-12 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Verfies in the dmabuf implementations that if the restricted memory
flag is set for a queue that the dmabuf submitted to the queue is
unmappable.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 drivers/media/common/videobuf2/videobuf2-dma-contig.c | 8 
 drivers/media/common/videobuf2/videobuf2-dma-sg.c | 8 
 2 files changed, 16 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c 
b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index 3d4fd4ef5310..f953570fef27 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -710,6 +710,14 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
return -EINVAL;
}
 
+   /* Verify the dmabuf is restricted if we are in restricted mode, this 
is done
+* by validating there is no page entry for the dmabuf.
+*/
+   if (buf->vb->vb2_queue->restricted_mem && sg_page(sgt->sgl)) {
+   pr_err("restricted queue requires restricted dma_buf");
+   return -EINVAL;
+   }
+
/* checking if dmabuf is big enough to store contiguous chunk */
contig_size = vb2_dc_get_contiguous_size(sgt);
if (contig_size < buf->size) {
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c 
b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
index 6975a71d740f..f87bd3f40b9b 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
@@ -570,6 +570,14 @@ static int vb2_dma_sg_map_dmabuf(void *mem_priv)
return -EINVAL;
}
 
+   /* Verify the dmabuf is restricted if we are in restricted mode, this 
is done
+* by validating there is no page entry for the dmabuf.
+*/
+   if (buf->vb->vb2_queue->restricted_mem && !sg_page(sgt->sgl)) {
+   pr_err("restricted queue requires restricted dma_buf");
+   return -EINVAL;
+   }
+
buf->dma_sgt = sgt;
buf->vaddr = NULL;
 
-- 
2.18.0



[PATCH v5,01/23] v4l2: add restricted memory flags

2024-04-12 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Adds a V4L2 flag which indicates that a queue is using restricted
dmabufs and the corresponding capability flag.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 include/media/videobuf2-core.h | 8 +++-
 include/uapi/linux/videodev2.h | 2 ++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 955237ac503d..afd497e93a37 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -517,6 +517,9 @@ struct vb2_buf_ops {
  * ->finish().
  * @non_coherent_mem: when set queue will attempt to allocate buffers using
  * non-coherent memory.
+ * @allow_restricted_mem: when set user-space can pass the 
%V4L2_MEMORY_FLAG_RESTRICTED
+ * flag to indicate the dma bufs are restricted.
+ * @restricted_mem: when set queue will verify that the dma bufs are 
restricted.
  * @lock:  pointer to a mutex that protects the  vb2_queue. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -621,6 +624,8 @@ struct vb2_queue {
unsigned intuses_requests:1;
unsigned intallow_cache_hints:1;
unsigned intnon_coherent_mem:1;
+   unsigned intallow_restricted_mem:1;
+   unsigned intrestricted_mem:1;
 
struct mutex*lock;
void*owner;
@@ -792,7 +797,8 @@ void vb2_core_querybuf(struct vb2_queue *q, struct 
vb2_buffer *vb, void *pb);
  * @q: pointer to  vb2_queue with videobuf2 queue.
  * @memory:memory type, as defined by  vb2_memory.
  * @flags: auxiliary queue/buffer management flags. Currently, the only
- * used flag is %V4L2_MEMORY_FLAG_NON_COHERENT.
+ * used flags are %V4L2_MEMORY_FLAG_NON_COHERENT and
+ * %V4L2_MEMORY_FLAG_RESTRICTED.
  * @count: requested buffer count.
  *
  * Videobuf2 core helper to implement VIDIOC_REQBUF() operation. It is called
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 2663213b76a4..b6fbbd276bf1 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1026,6 +1026,7 @@ struct v4l2_requestbuffers {
 };
 
 #define V4L2_MEMORY_FLAG_NON_COHERENT  (1 << 0)
+#define V4L2_MEMORY_FLAG_RESTRICTED(1 << 1)
 
 /* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */
 #define V4L2_BUF_CAP_SUPPORTS_MMAP (1 << 0)
@@ -1037,6 +1038,7 @@ struct v4l2_requestbuffers {
 #define V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS (1 << 6)
 #define V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS  (1 << 7)
 #define V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS  (1 << 8)
+#define V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM   (1 << 9)
 
 /**
  * struct v4l2_plane - plane info for multi-planar buffers
-- 
2.18.0



[PATCH v5,02/23] v4l2: handle restricted memory flags in queue setup

2024-04-12 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Validates the restricted memory flags when setting up a queue and
ensures the queue has the proper capability.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 .../media/common/videobuf2/videobuf2-core.c   | 21 +++
 .../media/common/videobuf2/videobuf2-v4l2.c   |  4 +++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 0b2b48e1b2df..bd951ca5f5b5 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -831,6 +831,15 @@ static bool verify_coherency_flags(struct vb2_queue *q, 
bool non_coherent_mem)
return true;
 }
 
+static bool verify_restricted_mem_flags(struct vb2_queue *q, bool 
restricted_mem)
+{
+   if (restricted_mem != q->restricted_mem) {
+   dprintk(q, 1, "restricted memory model mismatch\n");
+   return false;
+   }
+   return true;
+}
+
 static int vb2_core_allocated_buffers_storage(struct vb2_queue *q)
 {
if (!q->bufs)
@@ -864,6 +873,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
unsigned int q_num_bufs = vb2_get_num_buffers(q);
unsigned plane_sizes[VB2_MAX_PLANES] = { };
bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
+   bool restricted_mem = flags & V4L2_MEMORY_FLAG_RESTRICTED;
unsigned int i, first_index;
int ret = 0;
 
@@ -907,6 +917,9 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
return 0;
}
 
+   if (restricted_mem && (!q->allow_restricted_mem || memory != 
V4L2_MEMORY_DMABUF))
+   return -EINVAL;
+
/*
 * Make sure the requested values and current defaults are sane.
 */
@@ -924,6 +937,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
if (ret)
return ret;
set_queue_coherency(q, non_coherent_mem);
+   q->restricted_mem = restricted_mem;
 
/*
 * Ask the driver how many buffers and planes per buffer it requires.
@@ -1032,6 +1046,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
unsigned plane_sizes[VB2_MAX_PLANES] = { };
bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
unsigned int q_num_bufs = vb2_get_num_buffers(q);
+   bool restricted_mem = flags & V4L2_MEMORY_FLAG_RESTRICTED;
bool no_previous_buffers = !q_num_bufs;
int ret = 0;
 
@@ -1040,6 +1055,9 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
return -ENOBUFS;
}
 
+   if (restricted_mem && (!q->allow_restricted_mem || memory != 
V4L2_MEMORY_DMABUF))
+   return -EINVAL;
+
if (no_previous_buffers) {
if (q->waiting_in_dqbuf && *count) {
dprintk(q, 1, "another dup()ped fd is waiting for a 
buffer\n");
@@ -1058,6 +1076,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
return ret;
q->waiting_for_buffers = !q->is_output;
set_queue_coherency(q, non_coherent_mem);
+   q->restricted_mem = restricted_mem;
} else {
if (q->memory != memory) {
dprintk(q, 1, "memory model mismatch\n");
@@ -1065,6 +1084,8 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
}
if (!verify_coherency_flags(q, non_coherent_mem))
return -EINVAL;
+   if (!verify_restricted_mem_flags(q, restricted_mem))
+   return -EINVAL;
}
 
num_buffers = min(*count, q->max_num_buffers - q_num_bufs);
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 293f3d5f1c4e..9ee24e537e0c 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -682,7 +682,7 @@ static void vb2_set_flags_and_caps(struct vb2_queue *q, u32 
memory,
*flags = 0;
} else {
/* Clear all unknown flags. */
-   *flags &= V4L2_MEMORY_FLAG_NON_COHERENT;
+   *flags &= V4L2_MEMORY_FLAG_NON_COHERENT | 
V4L2_MEMORY_FLAG_RESTRICTED;
}
 
*caps |= V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS;
@@ -698,6 +698,8 @@ static void vb2_set_flags_and_caps(struct vb2_queue *q, u32 
memory,
*caps |= V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS;
if (q->supports_requests)
*caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS;
+   if (q->allow_restricted_mem && q->io_modes & VB2_DMABUF)
+

[PATCH v5,00/22] media: add driver to support secure video decoder

2024-04-12 Thread Yunfei Dong
The patch series used to enable secure video playback (SVP) on MediaTek
hardware in the Linux kernel.

Memory Definitions:
secure memory - Memory allocated in the TEE (Trusted Execution
Environment) which is inaccessible in the REE (Rich Execution
Environment, i.e. linux kernel/user space).
secure handle - Integer value which acts as reference to 'secure
memory'. Used in communication between TEE and REE to reference
'secure memory'.
secure buffer - 'secure memory' that is used to store decrypted,
compressed video or for other general purposes in the TEE.
secure surface - 'secure memory' that is used to store graphic buffers.

Memory Usage in SVP:
The overall flow of SVP starts with encrypted video coming in from an
outside source into the REE. The REE will then allocate a 'secure
buffer' and send the corresponding 'secure handle' along with the
encrypted, compressed video data to the TEE. The TEE will then decrypt
the video and store the result in the 'secure buffer'. The REE will
then allocate a 'secure surface'. The REE will pass the 'secure
handles' for both the 'secure buffer' and 'secure surface' into the
TEE for video decoding. The video decoder HW will then decode the
contents of the 'secure buffer' and place the result in the 'secure
surface'. The REE will then attach the 'secure surface' to the overlay
plane for rendering of the video.

Everything relating to ensuring security of the actual contents of the
'secure buffer' and 'secure surface' is out of scope for the REE and
is the responsibility of the TEE.

This patch series is consists of four parts. The first is from Jeffrey,
adding secure memory flag in v4l2 framework to support request secure
buffer.

The second and third parts are from John and T.J, adding some heap
interfaces, then our kernel users could allocate buffer from special
heap. The patch v1 is inside below dmabuf link.
https://lore.kernel.org/linux-mediatek/20230911023038.30649-1-yong...@mediatek.com/
To avoid confusing, move them into vcodec patch set since we use the
new interfaces directly.

The last part is mediaTek video decoder driver, adding tee interface to
support secure video decoder.

---
Changed in v5:
- fix merge conflict when rebase to latest media stage for patch 1/2
- change allocate memory type to cma for patch 12
- add to support av1 for patch 23

Changed in v4:
- change the driver according to maintainer advice for patch 1/2/3/4
- replace secure with restricted for patch 1/2/3/4
- fix svp decoder error for patch 21
- add to support hevc for patch 22

Changed in v3:
- rewrite the cover-letter of this patch series
- disable irq for svp mode
- rebase the driver based on the latest media stage

Changed in v2:
- remove setting decoder mode and getting secure handle from decode
- add Jeffrey's patch
- add John and T.J's patch
- getting secure flag with request buffer
- fix some comments from patch v1
---
Jeffrey Kardatzke (4):
  v4l2: add restricted memory flags
  v4l2: handle restricted memory flags in queue setup
  v4l2: verify restricted dmabufs are used in restricted queue
  v4l: add documentation for restricted memory flag

John Stultz (2):
  dma-heap: Add proper kref handling on dma-buf heaps
  dma-heap: Provide accessors so that in-kernel drivers can allocate
dmabufs from specific heaps

T.J. Mercier (1):
  dma-buf: heaps: Deduplicate docs and adopt common format

Xiaoyong Lu (1):
  WIP: media: mediatek: vcodec: support av1 svp decoder for mt8188

Yunfei Dong (15):
  media: mediatek: vcodec: add tee client interface to communiate with
optee-os
  media: mediatek: vcodec: allocate tee share memory
  media: mediatek: vcodec: send share memory data to optee
  media: mediatek: vcodec: initialize msg and vsi information
  media: mediatek: vcodec: add interface to allocate/free secure memory
  media: mediatek: vcodec: using shared memory as vsi address
  media: mediatek: vcodec: Add capture format to support one plane
memory
  media: mediatek: vcodec: Add one plane format
  media: mediatek: vcodec: support one plane capture buffer
  media: mediatek: vcodec: re-construct h264 driver to support svp mode
  media: mediatek: vcodec: remove parse nal_info in kernel
  media: mediatek: vcodec: disable wait interrupt for svp mode
  media: mediatek: vcodec: support tee decoder
  media: mediatek: vcodec: move vdec init interface to setup callback
  media: mediatek: vcodec: support hevc svp for mt8188

 .../userspace-api/media/v4l/buffer.rst|  10 +-
 .../media/v4l/pixfmt-reserved.rst |   8 +
 drivers/dma-buf/dma-heap.c| 139 +--
 .../media/common/videobuf2/videobuf2-core.c   |  21 +
 .../common/videobuf2/videobuf2-dma-contig.c   |   8 +
 .../media/common/videobuf2/videobuf2-dma-sg.c |   8 +
 .../media/common/videobuf2/videobuf2-v4l2.c   |   4 +-
 .../media/platform/mediatek/vcodec/Kconfig|   1 +
 .../mediatek/vcodec/common/mtk_vcodec_util.c  | 122 +-
 .../mediatek/vcodec/common/mtk_vcodec_util.h  |   3

[PATCH v4, 21/22] media: mediatek: vcodec: move vdec init interface to setup callback

2024-01-28 Thread Yunfei Dong
Getting secure video playback (svp) flag when request output buffer, then
calling init interface to init svp parameters in optee-os.

Signed-off-by: Yunfei Dong 
---
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c  | 139 +++---
 1 file changed, 89 insertions(+), 50 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index 5d876a31e566..667005ff49c0 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -184,6 +184,69 @@ void mtk_vcodec_dec_set_default_params(struct 
mtk_vcodec_dec_ctx *ctx)
q_data->bytesperline[1] = q_data->coded_width;
 }
 
+static int mtk_vcodec_dec_init_pic_info(struct mtk_vcodec_dec_ctx *ctx, enum 
v4l2_buf_type type)
+{
+   const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata;
+   struct mtk_q_data *q_data;
+   int ret;
+
+   if (!ctx->current_codec)
+   return 0;
+
+   if (V4L2_TYPE_IS_OUTPUT(type) && ctx->state == MTK_STATE_FREE) {
+   q_data = mtk_vdec_get_q_data(ctx, 
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+   if (!q_data)
+   return -EINVAL;
+
+   ret = vdec_if_init(ctx, q_data->fmt->fourcc);
+   if (ret) {
+   mtk_v4l2_vdec_err(ctx, "[%d]: vdec_if_init() fail 
ret=%d",
+ ctx->id, ret);
+   return -EINVAL;
+   }
+   ctx->state = MTK_STATE_INIT;
+   }
+
+   if (!dec_pdata->uses_stateless_api)
+   return 0;
+
+   /*
+* If get pic info fail, need to use the default pic info params, or
+* v4l2-compliance will fail
+*/
+   ret = vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, >picinfo);
+   if (ret)
+   mtk_v4l2_vdec_err(ctx, "[%d]Error!! Get GET_PARAM_PICTURE_INFO 
Fail",
+ ctx->id);
+
+   q_data = mtk_vdec_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+   if (q_data->fmt->num_planes == 1) {
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0] + 
ctx->picinfo.fb_sz[1];
+   q_data->bytesperline[0] = ctx->picinfo.buf_w;
+   } else {
+   if (ctx->is_secure_playback)
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0] + 
ctx->picinfo.fb_sz[1];
+   else
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0];
+
+   q_data->bytesperline[0] = ctx->picinfo.buf_w;
+   q_data->sizeimage[1] = ctx->picinfo.fb_sz[1];
+   q_data->bytesperline[1] = ctx->picinfo.buf_w;
+   }
+
+   q_data->coded_width = ctx->picinfo.buf_w;
+   q_data->coded_height = ctx->picinfo.buf_h;
+
+   ctx->last_decoded_picinfo = ctx->picinfo;
+   mtk_v4l2_vdec_dbg(2, ctx,
+ "[%d] init() plane:%d wxh=%dx%d pic wxh=%dx%d 
sz=0x%x_0x%x",
+ ctx->id, q_data->fmt->num_planes,
+ ctx->picinfo.buf_w, ctx->picinfo.buf_h,
+ ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+ q_data->sizeimage[0], q_data->sizeimage[1]);
+   return 0;
+}
+
 static int vidioc_vdec_qbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
 {
@@ -479,17 +542,7 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv,
ctx->ycbcr_enc = pix_mp->ycbcr_enc;
ctx->quantization = pix_mp->quantization;
ctx->xfer_func = pix_mp->xfer_func;
-
ctx->current_codec = fmt->fourcc;
-   if (ctx->state == MTK_STATE_FREE) {
-   ret = vdec_if_init(ctx, q_data->fmt->fourcc);
-   if (ret) {
-   mtk_v4l2_vdec_err(ctx, "[%d]: vdec_if_init() 
fail ret=%d",
- ctx->id, ret);
-   return -EINVAL;
-   }
-   ctx->state = MTK_STATE_INIT;
-   }
} else {
ctx->capture_fourcc = fmt->fourcc;
}
@@ -502,46 +555,11 @@ static int vidioc_vdec_s_fmt(struct file *file, void 
*priv,
ctx->picinfo.pic_w = pix_mp->width;
ctx->picinfo.pic_h = pix_mp->height;
 
-   /*
-* If get pic info fail, need to use the default pic info 
params, or
-* v4l2-compliance will fail
-*/
-   ret = vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, >picinfo);
-

[PATCH v4, 17/22] media: mediatek: vcodec: re-construct h264 driver to support svp mode

2024-01-28 Thread Yunfei Dong
Need secure buffer size to convert secure handle to secure
pa in optee-os, re-construct the vsi struct to store each
secure buffer size.

Separate svp and normal wait interrupt condition for svp mode
waiting hardware interrupt in optee-os.

Signed-off-by: Yunfei Dong 
---
 .../decoder/vdec/vdec_h264_req_multi_if.c | 261 +++---
 .../mediatek/vcodec/decoder/vdec_msg_queue.c  |   9 +-
 2 files changed, 168 insertions(+), 102 deletions(-)

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 4967e0f0984d..a1a68487131c 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
@@ -60,14 +60,36 @@ struct vdec_h264_slice_lat_dec_param {
  * @crc:   Used to check whether hardware's status is right
  */
 struct vdec_h264_slice_info {
+   u64 wdma_end_addr_offset;
u16 nal_info;
u16 timeout;
-   u32 bs_buf_size;
-   u64 bs_buf_addr;
-   u64 y_fb_dma;
-   u64 c_fb_dma;
u64 vdec_fb_va;
u32 crc[8];
+   u32 reserved;
+};
+
+/*
+ * struct vdec_h264_slice_mem - memory address and size
+ */
+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
+ * @y:  current y buffer address info
+ * @c:  current c buffer address info
+ */
+struct vdec_h264_slice_fb {
+   struct vdec_h264_slice_mem y;
+   struct vdec_h264_slice_mem c;
 };
 
 /**
@@ -92,18 +114,16 @@ struct vdec_h264_slice_info {
  */
 struct vdec_h264_slice_vsi {
/* LAT dec addr */
-   u64 wdma_err_addr;
-   u64 wdma_start_addr;
-   u64 wdma_end_addr;
-   u64 slice_bc_start_addr;
-   u64 slice_bc_end_addr;
-   u64 row_info_start_addr;
-   u64 row_info_end_addr;
-   u64 trans_start;
-   u64 trans_end;
-   u64 wdma_end_addr_offset;
+   struct vdec_h264_slice_mem bs;
+   struct vdec_h264_slice_fb fb;
 
-   u64 mv_buf_dma[H264_MAX_MV_NUM];
+   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 dec;
struct vdec_h264_slice_lat_dec_param h264_slice_params;
 };
@@ -392,6 +412,100 @@ static void vdec_h264_slice_get_crop_info(struct 
vdec_h264_slice_inst *inst,
   cr->left, cr->top, cr->width, cr->height);
 }
 
+static void vdec_h264_slice_setup_lat_buffer(struct vdec_h264_slice_inst *inst,
+struct mtk_vcodec_mem *bs,
+struct vdec_lat_buf *lat_buf)
+{
+   struct mtk_vcodec_mem *mem;
+   int i;
+
+   inst->vsi->bs.dma_addr = (u64)bs->dma_addr;
+   inst->vsi->bs.size = bs->size;
+
+   for (i = 0; i < H264_MAX_MV_NUM; i++) {
+   mem = >mv_buf[i];
+   inst->vsi->mv_buf_dma[i].dma_addr = mem->dma_addr;
+   inst->vsi->mv_buf_dma[i].size = mem->size;
+   }
+   inst->vsi->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
+   inst->vsi->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size;
+
+   inst->vsi->row_info.dma_addr = 0;
+   inst->vsi->row_info.size = 0;
+
+   inst->vsi->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr;
+   inst->vsi->err_map.size = lat_buf->wdma_err_addr.size;
+
+   inst->vsi->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr;
+   inst->vsi->slice_bc.size = lat_buf->slice_bc_addr.size;
+
+   inst->vsi->trans.dma_addr_end = inst->ctx->msg_queue.wdma_rptr_addr;
+   inst->vsi->trans.dma_addr = inst->ctx->msg_queue.wdma_wptr_addr;
+}
+
+static int vdec_h264_slice_setup_core_buffer(struct vdec_h264_slice_inst *inst,
+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");
+   return -EBUSY;
+   }
+
+   y_fb_dma = (u64)fb->base_y.dma_addr;
+   if

[PATCH v4, 16/22] media: mediatek: vcodec: support one plane capture buffer

2024-01-28 Thread Yunfei Dong
The capture buffer has two planes for format MM21, but user space only
allocate secure memory for plane[0], and the size is Y data + uv data.
The driver need to support one plane decoder for svp mode.

Signed-off-by: Yunfei Dong 
---
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c  |  7 -
 .../vcodec/decoder/mtk_vcodec_dec_stateless.c | 26 ++-
 .../decoder/vdec/vdec_h264_req_common.c   | 18 ++---
 .../mediatek/vcodec/decoder/vdec_drv_if.c |  4 +--
 4 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index 604fdc8ee3ce..5d876a31e566 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -653,7 +653,12 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv,
 * So we just return picinfo yet, and update picinfo in
 * stop_streaming hook function
 */
-   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0];
+
+   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1 || 
ctx->is_secure_playback)
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0] + 
ctx->picinfo.fb_sz[1];
+   else
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0];
+
q_data->sizeimage[1] = ctx->picinfo.fb_sz[1];
q_data->bytesperline[0] = ctx->last_decoded_picinfo.buf_w;
q_data->bytesperline[1] = ctx->last_decoded_picinfo.buf_w;
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index cc42c942eb8a..707ed57a412e 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -285,14 +285,14 @@ static struct vdec_fb *vdec_get_cap_buffer(struct 
mtk_vcodec_dec_ctx *ctx)
framebuf = container_of(vb2_v4l2, struct mtk_video_dec_buf, m2m_buf.vb);
 
pfb = >frame_buffer;
-   pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0);
+   if (!ctx->is_secure_playback)
+   pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0);
pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
pfb->base_y.size = ctx->q_data[MTK_Q_DATA_DST].sizeimage[0];
 
-   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2) {
+   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2 && 
!ctx->is_secure_playback) {
pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1);
-   pfb->base_c.dma_addr =
-   vb2_dma_contig_plane_dma_addr(dst_buf, 1);
+   pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 
1);
pfb->base_c.size = ctx->q_data[MTK_Q_DATA_DST].sizeimage[1];
}
mtk_v4l2_vdec_dbg(1, ctx,
@@ -339,16 +339,18 @@ static void mtk_vdec_worker(struct work_struct *work)
mtk_v4l2_vdec_dbg(3, ctx, "[%d] (%d) id=%d, vb=%p", ctx->id,
  vb2_src->vb2_queue->type, vb2_src->index, vb2_src);
 
-   bs_src->va = vb2_plane_vaddr(vb2_src, 0);
-   bs_src->dma_addr = vb2_dma_contig_plane_dma_addr(vb2_src, 0);
-   bs_src->size = (size_t)vb2_src->planes[0].bytesused;
-   if (!bs_src->va) {
-   v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
-   mtk_v4l2_vdec_err(ctx, "[%d] id=%d source buffer is NULL", 
ctx->id,
- vb2_src->index);
-   return;
+   if (!ctx->is_secure_playback) {
+   bs_src->va = vb2_plane_vaddr(vb2_src, 0);
+   if (!bs_src->va) {
+   v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+   mtk_v4l2_vdec_err(ctx, "[%d] id=%d source buffer is 
NULL", ctx->id,
+ vb2_src->index);
+   return;
+   }
}
 
+   bs_src->dma_addr = vb2_dma_contig_plane_dma_addr(vb2_src, 0);
+   bs_src->size = (size_t)vb2_src->planes[0].bytesused;
mtk_v4l2_vdec_dbg(3, ctx, "[%d] Bitstream VA=%p DMA=%pad Size=%zx 
vb=%p",
  ctx->id, bs_src->va, _src->dma_addr, bs_src->size, 
vb2_src);
/* Apply request controls. */
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c
index 5ca20d75dc8e..5e0d55218363 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c
+++ b

[PATCH v4,09/22] media: mediatek: vcodec: allocate tee share memory

2024-01-28 Thread Yunfei Dong
Allocate two share memory for each lat and core hardware used to share
information with optee-os. Msg buffer used to send ipi command and get ack
command with optee-os, data buffer used to store vsi information which
used for hardware decode.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 80 ++-
 .../vcodec/decoder/mtk_vcodec_dec_optee.h | 32 
 2 files changed, 111 insertions(+), 1 deletion(-)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
index 38d9c1c1785a..611fb0e56480 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
@@ -47,13 +47,69 @@ int mtk_vcodec_dec_optee_private_init(struct 
mtk_vcodec_dec_dev *vcodec_dev)
 }
 EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_private_init);
 
+static void mtk_vcodec_dec_optee_deinit_memref(struct mtk_vdec_optee_ca_info 
*ca_info,
+  enum mtk_vdec_optee_data_index 
data_index)
+{
+   tee_shm_free(ca_info->shm_memref[data_index].msg_shm);
+}
+
+static int mtk_vcodec_dec_optee_init_memref(struct tee_context *tee_vdec_ctx,
+   struct mtk_vdec_optee_ca_info 
*ca_info,
+   enum mtk_vdec_optee_data_index 
data_index)
+{
+   struct mtk_vdec_optee_shm_memref *shm_memref;
+   int alloc_size = 0, err = 0;
+   u64 shm_param_type = 0;
+   bool copy_buffer;
+
+   switch (data_index) {
+   case OPTEE_MSG_INDEX:
+   shm_param_type = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+   alloc_size = MTK_VDEC_OPTEE_MSG_SIZE;
+   copy_buffer = true;
+   break;
+   case OPTEE_DATA_INDEX:
+   shm_param_type = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+   alloc_size = MTK_VDEC_OPTEE_HW_SIZE;
+   copy_buffer = false;
+   break;
+   default:
+   pr_err(MTK_DBG_VCODEC_STR "tee invalid data_index: %d.\n", 
data_index);
+   return -EINVAL;
+   }
+
+   shm_memref = _info->shm_memref[data_index];
+
+   /* Allocate dynamic shared memory with decoder TA */
+   shm_memref->msg_shm_size = alloc_size;
+   shm_memref->param_type = shm_param_type;
+   shm_memref->copy_to_ta = copy_buffer;
+   shm_memref->msg_shm = tee_shm_alloc_kernel_buf(tee_vdec_ctx, 
shm_memref->msg_shm_size);
+   if (IS_ERR(shm_memref->msg_shm)) {
+   pr_err(MTK_DBG_VCODEC_STR "tee alloc buf fail: 
data_index:%d.\n", data_index);
+   return -ENOMEM;
+   }
+
+   shm_memref->msg_shm_ca_buf = tee_shm_get_va(shm_memref->msg_shm, 0);
+   if (IS_ERR(shm_memref->msg_shm_ca_buf)) {
+   pr_err(MTK_DBG_VCODEC_STR "tee get shm va fail: 
data_index:%d.\n", data_index);
+   err = PTR_ERR(shm_memref->msg_shm_ca_buf);
+   goto err_get_msg_va;
+   }
+
+   return err;
+err_get_msg_va:
+   tee_shm_free(shm_memref->msg_shm);
+   return err;
+}
+
 static int mtk_vcodec_dec_optee_init_hw_info(struct mtk_vdec_optee_private 
*optee_private,
 enum mtk_vdec_hw_id hardware_index)
 {
struct device *dev = _private->vcodec_dev->plat_dev->dev;
struct tee_ioctl_open_session_arg session_arg;
struct mtk_vdec_optee_ca_info *ca_info;
-   int err = 0, session_func;
+   int err, i, j, session_func;
 
/* Open lat and core session with vdec TA. */
switch (hardware_index) {
@@ -87,6 +143,24 @@ static int mtk_vcodec_dec_optee_init_hw_info(struct 
mtk_vdec_optee_private *opte
dev_dbg(dev, MTK_DBG_VCODEC_STR "open vdec tee session hw_id:%d 
session_id=%x.\n",
hardware_index, ca_info->vdec_session_id);
 
+   /* Allocate dynamic shared memory with decoder TA */
+   for (i = 0; i < OPTEE_MAX_INDEX; i++) {
+   err = 
mtk_vcodec_dec_optee_init_memref(optee_private->tee_vdec_ctx, ca_info, i);
+   if (err) {
+   dev_err(dev, MTK_DBG_VCODEC_STR "init vdec memref 
failed: %d.\n", i);
+   goto err_init_memref;
+   }
+   }
+
+   return err;
+err_init_memref:
+   if (i != 0) {
+   for (j = 0; j < i; j++)
+   mtk_vcodec_dec_optee_deinit_memref(ca_info, j);
+   }
+
+   tee_client_close_session(optee_private->tee_vdec_ctx, 
ca_info->vdec_session_id);
+
return err;
 }
 
@@ -94,12 +168,16 @@ static void mtk_vcodec_dec_optee_deinit_hw_info(struct 
mtk_vdec_optee_private *o
enum mtk_vdec_hw_id hw_id)
 {
struct mtk_

[PATCH v4, 13/22] media: mediatek: vcodec: using shared memory as vsi address

2024-01-28 Thread Yunfei Dong
The vsi buffer is allocated by tee share memory for svp mode, need to
use the share memory as the vsi address to store vsi data.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/vdec/vdec_h264_req_multi_if.c | 9 +++--
 .../media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c | 8 ++--
 2 files changed, 13 insertions(+), 4 deletions(-)

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 0e741e0dc8ba..4967e0f0984d 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
@@ -417,8 +417,13 @@ static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx 
*ctx)
 
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);
+   if (ctx->is_secure_playback)
+   inst->vsi_core =
+   
mtk_vcodec_dec_get_shm_buffer_va(ctx->dev->optee_private, MTK_VDEC_CORE,
+OPTEE_DATA_INDEX);
+   else
+   inst->vsi_core =
+   (struct vdec_h264_slice_vsi *)(((char *)inst->vpu.vsi) 
+ vsi_size);
inst->resolution_changed = true;
inst->realloc_mv_buf = true;
 
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
index 5336769a3fb5..5c31641e9abe 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
@@ -18,8 +18,12 @@ static void handle_init_ack_msg(const struct 
vdec_vpu_ipi_init_ack *msg)
 
/* mapping VPU address to kernel virtual address */
/* the content in vsi is initialized to 0 in VPU */
-   vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->fw_handler,
-msg->vpu_inst_addr);
+   if (vpu->ctx->is_secure_playback)
+   vpu->vsi = 
mtk_vcodec_dec_get_shm_buffer_va(vpu->ctx->dev->optee_private,
+   MTK_VDEC_LAT0, 
OPTEE_DATA_INDEX);
+   else
+   vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->fw_handler,
+msg->vpu_inst_addr);
vpu->inst_addr = msg->vpu_inst_addr;
 
mtk_vdec_debug(vpu->ctx, "- vpu_inst_addr = 0x%x", vpu->inst_addr);
-- 
2.18.0



[PATCH v4, 19/22] media: mediatek: vcodec: disable wait interrupt for svp mode

2024-01-28 Thread Yunfei Dong
Waiting interrupt in optee-os for svp mode, need to disable it in kernel
in case of interrupt is cleaned.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_hw.c| 34 +--
 .../vcodec/decoder/mtk_vcodec_dec_pm.c|  6 +-
 .../decoder/vdec/vdec_h264_req_multi_if.c | 57 +++
 3 files changed, 54 insertions(+), 43 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
index 881d5de41e05..1982c088c6da 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
@@ -72,26 +72,28 @@ static irqreturn_t mtk_vdec_hw_irq_handler(int irq, void 
*priv)
 
ctx = mtk_vcodec_get_curr_ctx(dev->main_dev, dev->hw_idx);
 
-   /* check if HW active or not */
-   cg_status = readl(dev->reg_base[VDEC_HW_SYS] + VDEC_HW_ACTIVE_ADDR);
-   if (cg_status & VDEC_HW_ACTIVE_MASK) {
-   mtk_v4l2_vdec_err(ctx, "vdec active is not 0x0 (0x%08x)", 
cg_status);
-   return IRQ_HANDLED;
-   }
+   if (!ctx->is_secure_playback) {
+   /* check if HW active or not */
+   cg_status = readl(dev->reg_base[VDEC_HW_SYS] + 
VDEC_HW_ACTIVE_ADDR);
+   if (cg_status & VDEC_HW_ACTIVE_MASK) {
+   mtk_v4l2_vdec_err(ctx, "vdec active is not 0x0 
(0x%08x)", cg_status);
+   return IRQ_HANDLED;
+   }
 
-   dec_done_status = readl(vdec_misc_addr);
-   if ((dec_done_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) !=
-   MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
-   return IRQ_HANDLED;
+   dec_done_status = readl(vdec_misc_addr);
+   if ((dec_done_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) !=
+   MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
+   return IRQ_HANDLED;
 
-   /* clear interrupt */
-   writel(dec_done_status | VDEC_IRQ_CFG, vdec_misc_addr);
-   writel(dec_done_status & ~VDEC_IRQ_CLR, vdec_misc_addr);
+   /* clear interrupt */
+   writel(dec_done_status | VDEC_IRQ_CFG, vdec_misc_addr);
+   writel(dec_done_status & ~VDEC_IRQ_CLR, vdec_misc_addr);
 
-   wake_up_dec_ctx(ctx, MTK_INST_IRQ_RECEIVED, dev->hw_idx);
+   wake_up_dec_ctx(ctx, MTK_INST_IRQ_RECEIVED, dev->hw_idx);
 
-   mtk_v4l2_vdec_dbg(3, ctx, "wake up ctx %d, dec_done_status=%x",
- ctx->id, dec_done_status);
+   mtk_v4l2_vdec_dbg(3, ctx, "wake up ctx %d, dec_done_status=%x",
+ ctx->id, dec_done_status);
+   }
 
return IRQ_HANDLED;
 }
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c
index aefd3e9e3061..a94eda936f16 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c
@@ -238,7 +238,8 @@ void mtk_vcodec_dec_enable_hardware(struct 
mtk_vcodec_dec_ctx *ctx, int hw_idx)
mtk_vcodec_dec_child_dev_on(ctx->dev, MTK_VDEC_LAT0);
mtk_vcodec_dec_child_dev_on(ctx->dev, hw_idx);
 
-   mtk_vcodec_dec_enable_irq(ctx->dev, hw_idx);
+   if (!ctx->is_secure_playback)
+   mtk_vcodec_dec_enable_irq(ctx->dev, hw_idx);
 
if (IS_VDEC_INNER_RACING(ctx->dev->dec_capability))
mtk_vcodec_load_racing_info(ctx);
@@ -250,7 +251,8 @@ void mtk_vcodec_dec_disable_hardware(struct 
mtk_vcodec_dec_ctx *ctx, int hw_idx)
if (IS_VDEC_INNER_RACING(ctx->dev->dec_capability))
mtk_vcodec_record_racing_info(ctx);
 
-   mtk_vcodec_dec_disable_irq(ctx->dev, hw_idx);
+   if (!ctx->is_secure_playback)
+   mtk_vcodec_dec_disable_irq(ctx->dev, hw_idx);
 
mtk_vcodec_dec_child_dev_off(ctx->dev, hw_idx);
if (IS_VDEC_LAT_ARCH(ctx->dev->vdec_pdata->hw_arch) &&
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 2dfb3043493e..3e2270399b6c 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
@@ -593,14 +593,16 @@ static int vdec_h264_slice_core_decode(struct 
vdec_lat_buf *lat_buf)
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);
-   i

[PATCH v4,20/22] media: mediatek: vcodec: support tee decoder

2024-01-28 Thread Yunfei Dong
Initialize tee private data to support secure decoder.
Release tee related information for each instance when decoder
done.

Signed-off-by: Yunfei Dong 
---
 .../platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
index f47c98faf068..08e7d250487b 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
@@ -310,6 +310,9 @@ static int fops_vcodec_release(struct file *file)
v4l2_fh_exit(>fh);
v4l2_ctrl_handler_free(>ctrl_hdl);
 
+   if (ctx->is_secure_playback)
+   mtk_vcodec_dec_optee_release(dev->optee_private);
+
mtk_vcodec_dbgfs_remove(dev, ctx->id);
list_del_init(>list);
kfree(ctx);
@@ -466,6 +469,11 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
atomic_set(>dec_active_cnt, 0);
memset(dev->vdec_racing_info, 0, sizeof(dev->vdec_racing_info));
mutex_init(>dec_racing_info_mutex);
+   ret = mtk_vcodec_dec_optee_private_init(dev);
+   if (ret) {
+   dev_err(>dev, "Failed to init svp private.");
+   goto err_reg_cont;
+   }
 
ret = video_register_device(vfd_dec, VFL_TYPE_VIDEO, -1);
if (ret) {
-- 
2.18.0



[PATCH v4, 22/22] media: mediatek: vcodec: support hevc svp for mt8188

2024-01-28 Thread Yunfei Dong
Change hevc driver to support secure video playback(svp) for
mt8188. Need to map shared memory with optee interface and
wait interrupt in optee-os.

Signed-off-by: Yunfei Dong 
---
 .../decoder/vdec/vdec_hevc_req_multi_if.c | 89 +++
 1 file changed, 54 insertions(+), 35 deletions(-)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
index 06ed47df693b..8bf4bc13ae2d 100644
--- 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
+++ 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
@@ -415,11 +415,14 @@ static void vdec_hevc_fill_dpb_info(struct 
mtk_vcodec_dec_ctx *ctx,
hevc_dpb_info[index].field = dpb->field_pic;
 
hevc_dpb_info[index].y_dma_addr = 
vb2_dma_contig_plane_dma_addr(vb, 0);
-   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2)
-   hevc_dpb_info[index].c_dma_addr = 
vb2_dma_contig_plane_dma_addr(vb, 1);
-   else
-   hevc_dpb_info[index].c_dma_addr =
-   hevc_dpb_info[index].y_dma_addr + 
ctx->picinfo.fb_sz[0];
+   if (!ctx->is_secure_playback) {
+   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2)
+   hevc_dpb_info[index].c_dma_addr =
+   vb2_dma_contig_plane_dma_addr(vb, 1);
+   else
+   hevc_dpb_info[index].c_dma_addr =
+   hevc_dpb_info[index].y_dma_addr + 
ctx->picinfo.fb_sz[0];
+   }
}
 }
 
@@ -800,7 +803,7 @@ static int vdec_hevc_slice_setup_core_buffer(struct 
vdec_hevc_slice_inst *inst,
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;
+   u64 y_fb_dma, c_fb_dma = 0;
int i;
 
fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx);
@@ -810,18 +813,20 @@ static int vdec_hevc_slice_setup_core_buffer(struct 
vdec_hevc_slice_inst *inst,
}
 
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;
-   else
-   c_fb_dma = (u64)fb->base_c.dma_addr;
+   if (!ctx->is_secure_playback) {
+   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;
+   else
+   c_fb_dma = (u64)fb->base_c.dma_addr;
+   }
 
mtk_vdec_debug(inst->ctx, "[hevc-core] y/c addr = 0x%llx 0x%llx", 
y_fb_dma, c_fb_dma);
 
inst->vsi_core->fb.y.dma_addr = y_fb_dma;
inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[0];
inst->vsi_core->fb.c.dma_addr = c_fb_dma;
-   inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[1];
+   inst->vsi_core->fb.c.size = ctx->picinfo.fb_sz[1];
 
inst->vsi_core->dec.vdec_fb_va = (unsigned long)fb;
 
@@ -878,8 +883,13 @@ static int vdec_hevc_slice_init(struct mtk_vcodec_dec_ctx 
*ctx)
 
vsi_size = round_up(sizeof(struct vdec_hevc_slice_vsi), 
VCODEC_DEC_ALIGNED_64);
inst->vsi = inst->vpu.vsi;
-   inst->vsi_core =
-   (struct vdec_hevc_slice_vsi *)(((char *)inst->vpu.vsi) + 
vsi_size);
+   if (ctx->is_secure_playback)
+   inst->vsi_core =
+   
mtk_vcodec_dec_get_shm_buffer_va(ctx->dev->optee_private, MTK_VDEC_CORE,
+OPTEE_DATA_INDEX);
+   else
+   inst->vsi_core =
+   (struct vdec_hevc_slice_vsi *)(((char *)inst->vpu.vsi) 
+ vsi_size);
 
inst->resolution_changed = true;
inst->realloc_mv_buf = true;
@@ -944,21 +954,22 @@ static int vdec_hevc_slice_core_decode(struct 
vdec_lat_buf *lat_buf)
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);
-   inst->vsi_core->dec.timeout = !!timeout;
+   if (!vpu->ctx->is_secure_playback) {
+   /* wait decoder done interrupt */
+   timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, 
MTK_INST_IRQ_R

[PATCH v4, 08/22] media: mediatek: vcodec: add tee client interface to communiate with optee-os

2024-01-28 Thread Yunfei Dong
Open tee context to initialize the environment in order to communication
with optee-os, then open tee session as the communication pipeline for
lat and core to send data for hardware decode.

Signed-off-by: Yunfei Dong 
---
 .../platform/mediatek/vcodec/decoder/Makefile |   1 +
 .../vcodec/decoder/mtk_vcodec_dec_drv.h   |   5 +
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 165 ++
 .../vcodec/decoder/mtk_vcodec_dec_optee.h |  73 
 4 files changed, 244 insertions(+)
 create mode 100644 
drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
 create mode 100644 
drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/Makefile 
b/drivers/media/platform/mediatek/vcodec/decoder/Makefile
index 904cd22def84..1624933dfd5e 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/Makefile
+++ b/drivers/media/platform/mediatek/vcodec/decoder/Makefile
@@ -21,5 +21,6 @@ mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
mtk_vcodec_dec_stateful.o \
mtk_vcodec_dec_stateless.o \
mtk_vcodec_dec_pm.o \
+   mtk_vcodec_dec_optee.o \
 
 mtk-vcodec-dec-hw-y := mtk_vcodec_dec_hw.o
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 849b89dd205c..b1a2107f2a1e 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
@@ -11,6 +11,7 @@
 #include "../common/mtk_vcodec_dbgfs.h"
 #include "../common/mtk_vcodec_fw_priv.h"
 #include "../common/mtk_vcodec_util.h"
+#include "mtk_vcodec_dec_optee.h"
 #include "vdec_msg_queue.h"
 
 #define MTK_VCODEC_DEC_NAME"mtk-vcodec-dec"
@@ -261,6 +262,8 @@ struct mtk_vcodec_dec_ctx {
  * @dbgfs: debug log related information
  *
  * @chip_name: used to distinguish platforms and select the correct codec 
configuration values
+ *
+ * @optee_private: optee private data
  */
 struct mtk_vcodec_dec_dev {
struct v4l2_device v4l2_dev;
@@ -303,6 +306,8 @@ struct mtk_vcodec_dec_dev {
struct mtk_vcodec_dbgfs dbgfs;
 
enum mtk_vcodec_dec_chip_name chip_name;
+
+   struct mtk_vdec_optee_private *optee_private;
 };
 
 static inline struct mtk_vcodec_dec_ctx *fh_to_dec_ctx(struct v4l2_fh *fh)
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
new file mode 100644
index ..38d9c1c1785a
--- /dev/null
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Yunfei Dong 
+ */
+
+#include "mtk_vcodec_dec_drv.h"
+#include "mtk_vcodec_dec_optee.h"
+
+/*
+ * Randomly generated, and must correspond to the GUID on the TA side.
+ */
+static const uuid_t mtk_vdec_lat_uuid =
+   UUID_INIT(0xBC50D971, 0xD4C9, 0x42C4,
+ 0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x90);
+
+static const uuid_t mtk_vdec_core_uuid =
+   UUID_INIT(0xBC50D971, 0xD4C9, 0x42C4,
+ 0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x91);
+
+/*
+ * Check whether this driver supports decoder TA in the TEE instance,
+ * represented by the params (ver/data) of this function.
+ */
+static int mtk_vcodec_dec_optee_match(struct tee_ioctl_version_data *ver_data, 
const void *not_used)
+{
+   if (ver_data->impl_id == TEE_IMPL_ID_OPTEE)
+   return 1;
+   else
+   return 0;
+}
+
+int mtk_vcodec_dec_optee_private_init(struct mtk_vcodec_dec_dev *vcodec_dev)
+{
+   vcodec_dev->optee_private = devm_kzalloc(_dev->plat_dev->dev,
+
sizeof(*vcodec_dev->optee_private),
+GFP_KERNEL);
+   if (!vcodec_dev->optee_private)
+   return -ENOMEM;
+
+   vcodec_dev->optee_private->vcodec_dev = vcodec_dev;
+
+   atomic_set(_dev->optee_private->tee_active_cnt, 0);
+   mutex_init(_dev->optee_private->tee_mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_private_init);
+
+static int mtk_vcodec_dec_optee_init_hw_info(struct mtk_vdec_optee_private 
*optee_private,
+enum mtk_vdec_hw_id hardware_index)
+{
+   struct device *dev = _private->vcodec_dev->plat_dev->dev;
+   struct tee_ioctl_open_session_arg session_arg;
+   struct mtk_vdec_optee_ca_info *ca_info;
+   int err = 0, session_func;
+
+   /* Open lat and core session with vdec TA. */
+   switch (hardware_index) {
+   case MTK_VDEC_LAT0:
+   export_uuid(session_arg.uuid, _vd

[PATCH v4, 18/22] media: mediatek: vcodec: remove parse nal_info in kernel

2024-01-28 Thread Yunfei Dong
The hardware can parse syntax to get nal_info, needn't to use cpu.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/vdec/vdec_h264_req_multi_if.c| 13 ++---
 1 file changed, 2 insertions(+), 11 deletions(-)

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 a1a68487131c..2dfb3043493e 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
@@ -645,11 +645,10 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, 
struct mtk_vcodec_mem *bs,
struct vdec_h264_slice_inst *inst = h_vdec;
struct vdec_vpu_inst *vpu = >vpu;
struct mtk_video_dec_buf *src_buf_info;
-   int nal_start_idx, err, timeout = 0;
+   int err, timeout = 0;
unsigned int data[2];
struct vdec_lat_buf *lat_buf;
struct vdec_h264_slice_share_info *share_info;
-   unsigned char *buf;
 
if (vdec_msg_queue_init(>ctx->msg_queue, inst->ctx,
vdec_h264_slice_core_decode,
@@ -673,14 +672,6 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct 
mtk_vcodec_mem *bs,
share_info = lat_buf->private_data;
src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer);
 
-   buf = (unsigned char *)bs->va;
-   nal_start_idx = mtk_vdec_h264_find_start_code(buf, bs->size);
-   if (nal_start_idx < 0) {
-   err = -EINVAL;
-   goto err_free_fb_out;
-   }
-
-   inst->vsi->dec.nal_info = buf[nal_start_idx];
lat_buf->src_buf_req = src_buf_info->m2m_buf.vb.vb2_buf.req_obj.req;
v4l2_m2m_buf_copy_metadata(_buf_info->m2m_buf.vb, 
_buf->ts_info, true);
 
@@ -689,7 +680,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct 
mtk_vcodec_mem *bs,
goto err_free_fb_out;
 
if (!inst->ctx->is_secure_playback)
-   vdec_h264_insert_startcode(inst->ctx->dev, buf, >size,
+   vdec_h264_insert_startcode(inst->ctx->dev, bs->va, >size,
   _info->h264_slice_params.pps);
 
*res_chg = inst->resolution_changed;
-- 
2.18.0



[PATCH v4, 14/22] media: mediatek: vcodec: Add capture format to support one plane memory

2024-01-28 Thread Yunfei Dong
Define one uncompressed capture format V4L2_PIX_FMT_MS21 in order to
support one plane memory. The buffer size is luma + chroma, luma is
stored at the start and chrome is stored at the end.

Signed-off-by: Yunfei Dong 
---
 Documentation/userspace-api/media/v4l/pixfmt-reserved.rst | 8 
 drivers/media/v4l2-core/v4l2-common.c | 2 ++
 drivers/media/v4l2-core/v4l2-ioctl.c  | 1 +
 include/uapi/linux/videodev2.h| 1 +
 4 files changed, 12 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst 
b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
index 886ba7b08d6b..6ec899649d50 100644
--- a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
+++ b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
@@ -295,6 +295,14 @@ please make a proposal on the linux-media mailing list.
   - Compressed format used by Nuvoton NPCM video driver. This format is
 defined in Remote Framebuffer Protocol (RFC 6143, chapter 7.7.4 Hextile
 Encoding).
+* .. _V4L2-PIX-FMT-MS21:
+
+  - ``V4L2_PIX_FMT_MS21``
+  - 'MS21'
+  - This format has one plane, luma and chroma are stored in a contiguous
+memory. Luma pixel in 16x32 tiles at the start, chroma pixel in 16x16
+tiles at the end. The image height must be aligned with 32 and the 
image
+width must be aligned with 16.
 .. raw:: latex
 
 \normalsize
diff --git a/drivers/media/v4l2-core/v4l2-common.c 
b/drivers/media/v4l2-core/v4l2-common.c
index 273d83de2a87..315b906ed730 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -269,6 +269,8 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
  .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
{ .format = V4L2_PIX_FMT_MT2110R, .pixel_enc = 
V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, 
.bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
  .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
+   { .format = V4L2_PIX_FMT_MS21,.pixel_enc = 
V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, 
.bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
+ .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
 
/* YUV planar formats */
{ .format = V4L2_PIX_FMT_NV12,.pixel_enc = 
V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, 
.bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 33076af4dfdb..c38b12511bdb 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1511,6 +1511,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_MT2110T:  descr = "Mediatek 10bit Tile 
Mode"; break;
case V4L2_PIX_FMT_MT2110R:  descr = "Mediatek 10bit Raster 
Mode"; break;
case V4L2_PIX_FMT_HEXTILE:  descr = "Hextile Compressed 
Format"; break;
+   case V4L2_PIX_FMT_MS21: descr = "MediaTek One Plane 
Format"; break;
default:
if (fmt->description[0])
return;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 3e3f8d4b7c81..53a3c908fcba 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -798,6 +798,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_MM21 v4l2_fourcc('M', 'M', '2', '1') /* Mediatek 
8-bit block mode, two non-contiguous planes */
 #define V4L2_PIX_FMT_MT2110T  v4l2_fourcc('M', 'T', '2', 'T') /* Mediatek 
10-bit block tile mode */
 #define V4L2_PIX_FMT_MT2110R  v4l2_fourcc('M', 'T', '2', 'R') /* Mediatek 
10-bit block raster mode */
+#define V4L2_PIX_FMT_MS21 v4l2_fourcc('M', 'S', '2', '1') /* MediaTek 
8-bit block mode with one plane */
 #define V4L2_PIX_FMT_INZI v4l2_fourcc('I', 'N', 'Z', 'I') /* Intel Planar 
Greyscale 10-bit and Depth 16-bit */
 #define V4L2_PIX_FMT_CNF4 v4l2_fourcc('C', 'N', 'F', '4') /* Intel 4-bit 
packed depth confidence information */
 #define V4L2_PIX_FMT_HI240v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit 
dithered RGB */
-- 
2.18.0



[PATCH v4,15/22] media: mediatek: vcodec: Add one plane format

2024-01-28 Thread Yunfei Dong
Adding capture formats to support V4L2_PIX_FMT_MS21. This format has
one plane and only be used for secure video playback at current period.

Signed-off-by: Yunfei Dong 
---
 .../platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c| 4 +++-
 .../mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c   | 9 -
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index ba742f0e391d..604fdc8ee3ce 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -49,7 +49,9 @@ static bool mtk_vdec_get_cap_fmt(struct mtk_vcodec_dec_ctx 
*ctx, int format_inde
num_frame_count++;
}
 
-   if (num_frame_count == 1 || (!ctx->is_10bit_bitstream && fmt->fourcc == 
V4L2_PIX_FMT_MM21))
+   if ((!ctx->is_10bit_bitstream && fmt->fourcc == V4L2_PIX_FMT_MM21) ||
+   (ctx->is_secure_playback && fmt->fourcc == V4L2_PIX_FMT_MS21) ||
+   num_frame_count == 1)
return true;
 
q_data = >q_data[MTK_Q_DATA_SRC];
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index d54b3833790d..cc42c942eb8a 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -229,7 +229,7 @@ static const struct mtk_stateless_control 
mtk_stateless_controls[] = {
 
 #define NUM_CTRLS ARRAY_SIZE(mtk_stateless_controls)
 
-static struct mtk_video_fmt mtk_video_formats[9];
+static struct mtk_video_fmt mtk_video_formats[10];
 
 static struct mtk_video_fmt default_out_format;
 static struct mtk_video_fmt default_cap_format;
@@ -770,6 +770,11 @@ static void mtk_vcodec_add_formats(unsigned int fourcc,
mtk_video_formats[count_formats].type = MTK_FMT_FRAME;
mtk_video_formats[count_formats].num_planes = 2;
break;
+   case V4L2_PIX_FMT_MS21:
+   mtk_video_formats[count_formats].fourcc = fourcc;
+   mtk_video_formats[count_formats].type = MTK_FMT_FRAME;
+   mtk_video_formats[count_formats].num_planes = 1;
+   break;
default:
mtk_v4l2_vdec_err(ctx, "Can not add unsupported format type");
return;
@@ -798,6 +803,8 @@ static void mtk_vcodec_get_supported_formats(struct 
mtk_vcodec_dec_ctx *ctx)
cap_format_count++;
}
if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_MM21) {
+   mtk_vcodec_add_formats(V4L2_PIX_FMT_MS21, ctx);
+   cap_format_count++;
mtk_vcodec_add_formats(V4L2_PIX_FMT_MM21, ctx);
cap_format_count++;
}
-- 
2.18.0



[PATCH v4, 10/22] media: mediatek: vcodec: send share memory data to optee

2024-01-28 Thread Yunfei Dong
Setting msg and vsi information to shared buffer, then call tee invoke
function to send it to optee-os.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 140 ++
 .../vcodec/decoder/mtk_vcodec_dec_optee.h |  51 +++
 2 files changed, 191 insertions(+)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
index 611fb0e56480..f29a8d143fee 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
@@ -241,3 +241,143 @@ void mtk_vcodec_dec_optee_release(struct 
mtk_vdec_optee_private *optee_private)
mutex_unlock(_private->tee_mutex);
 }
 EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_release);
+
+static int mtk_vcodec_dec_optee_fill_shm(struct tee_param *command_params,
+struct mtk_vdec_optee_shm_memref 
*shm_memref,
+struct mtk_vdec_optee_data_to_shm 
*data,
+int index, struct device *dev)
+{
+   if (!data->msg_buf_size[index] || !data->msg_buf[index]) {
+   pr_err(MTK_DBG_VCODEC_STR "tee invalid buf param: %d.\n", 
index);
+   return -EINVAL;
+   }
+
+   *command_params = (struct tee_param) {
+   .attr = shm_memref->param_type,
+   .u.memref = {
+   .shm = shm_memref->msg_shm,
+   .size = data->msg_buf_size[index],
+   .shm_offs = 0,
+   },
+   };
+
+   if (!shm_memref->copy_to_ta) {
+   dev_dbg(dev, MTK_DBG_VCODEC_STR "share memref data: 0x%x 
param_type:%llu.\n",
+   *((unsigned int *)shm_memref->msg_shm_ca_buf), 
shm_memref->param_type);
+   return 0;
+   }
+
+   memset(shm_memref->msg_shm_ca_buf, 0, shm_memref->msg_shm_size);
+   memcpy(shm_memref->msg_shm_ca_buf, data->msg_buf[index], 
data->msg_buf_size[index]);
+
+   dev_dbg(dev, MTK_DBG_VCODEC_STR "share memref data => msg id:0x%x 0x%x 
param_type:%llu.\n",
+   *((unsigned int *)data->msg_buf[index]),
+   *((unsigned int *)shm_memref->msg_shm_ca_buf),
+   shm_memref->param_type);
+
+   return 0;
+}
+
+void mtk_vcodec_dec_optee_set_data(struct mtk_vdec_optee_data_to_shm *data,
+  void *buf, int buf_size,
+  enum mtk_vdec_optee_data_index index)
+{
+   data->msg_buf[index] = buf;
+   data->msg_buf_size[index] = buf_size;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_set_data);
+
+int mtk_vcodec_dec_optee_invokd_cmd(struct mtk_vdec_optee_private 
*optee_private,
+   enum mtk_vdec_hw_id hw_id,
+   struct mtk_vdec_optee_data_to_shm *data)
+{
+   struct device *dev = _private->vcodec_dev->plat_dev->dev;
+   struct tee_ioctl_invoke_arg trans_args;
+   struct tee_param command_params[MTK_OPTEE_MAX_TEE_PARAMS];
+   struct mtk_vdec_optee_ca_info *ca_info;
+   struct mtk_vdec_optee_shm_memref *shm_memref;
+   int ret, index;
+
+   if (hw_id == MTK_VDEC_LAT0)
+   ca_info = _private->lat_ca;
+   else
+   ca_info = _private->core_ca;
+
+   memset(_args, 0, sizeof(trans_args));
+   memset(command_params, 0, sizeof(command_params));
+
+   trans_args = (struct tee_ioctl_invoke_arg) {
+   .func = ca_info->vdec_session_func,
+   .session = ca_info->vdec_session_id,
+   .num_params = MTK_OPTEE_MAX_TEE_PARAMS,
+   };
+
+   /* Fill msg command parameters */
+   for (index = 0; index < MTK_OPTEE_MAX_TEE_PARAMS; index++) {
+   shm_memref = _info->shm_memref[index];
+
+   if (shm_memref->param_type == TEE_IOCTL_PARAM_ATTR_TYPE_NONE ||
+   data->msg_buf_size[index] == 0)
+   continue;
+
+   dev_dbg(dev, MTK_DBG_VCODEC_STR "tee share memory data size: %d 
-> %d.\n",
+   data->msg_buf_size[index], shm_memref->msg_shm_size);
+
+   if (data->msg_buf_size[index] > shm_memref->msg_shm_size) {
+   dev_err(dev, MTK_DBG_VCODEC_STR "tee buf size big than 
shm (%d -> %d).\n",
+   data->msg_buf_size[index], 
shm_memref->msg_shm_size);
+   return -EINVAL;
+   }
+
+   ret = mtk_vcodec_dec_optee_fill_shm(_params[index], 
shm_memref,
+   data, index, dev);
+   if (ret)
+   return ret;
+ 

[PATCH v4, 12/22] media: mediatek: vcodec: add interface to allocate/free secure memory

2024-01-28 Thread Yunfei Dong
Need to call dma heap interface to allocate/free secure memory when playing
secure video.

Signed-off-by: Yunfei Dong 
---
 .../media/platform/mediatek/vcodec/Kconfig|   1 +
 .../mediatek/vcodec/common/mtk_vcodec_util.c  | 122 +-
 .../mediatek/vcodec/common/mtk_vcodec_util.h  |   3 +
 3 files changed, 123 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/Kconfig 
b/drivers/media/platform/mediatek/vcodec/Kconfig
index bc8292232530..707865703e61 100644
--- a/drivers/media/platform/mediatek/vcodec/Kconfig
+++ b/drivers/media/platform/mediatek/vcodec/Kconfig
@@ -17,6 +17,7 @@ config VIDEO_MEDIATEK_VCODEC
depends on VIDEO_MEDIATEK_VPU || !VIDEO_MEDIATEK_VPU
depends on MTK_SCP || !MTK_SCP
depends on MTK_SMI || (COMPILE_TEST && MTK_SMI=n)
+   depends on DMABUF_HEAPS
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
select VIDEO_MEDIATEK_VCODEC_VPU if VIDEO_MEDIATEK_VPU
diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c 
b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c
index 9ce34a3b5ee6..5cb7c347322b 100644
--- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c
+++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c
@@ -5,9 +5,11 @@
 *  Tiffany Lin 
 */
 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "../decoder/mtk_vcodec_dec_drv.h"
 #include "../encoder/mtk_vcodec_enc_drv.h"
@@ -45,7 +47,7 @@ int mtk_vcodec_write_vdecsys(struct mtk_vcodec_dec_ctx *ctx, 
unsigned int reg,
 }
 EXPORT_SYMBOL(mtk_vcodec_write_vdecsys);
 
-int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem *mem)
+static int mtk_vcodec_mem_alloc_nor(void *priv, struct mtk_vcodec_mem *mem)
 {
enum mtk_instance_type inst_type = *((unsigned int *)priv);
struct platform_device *plat_dev;
@@ -76,9 +78,71 @@ int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem 
*mem)
 
return 0;
 }
-EXPORT_SYMBOL(mtk_vcodec_mem_alloc);
 
-void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem *mem)
+static int mtk_vcodec_mem_alloc_sec(struct mtk_vcodec_dec_ctx *ctx, struct 
mtk_vcodec_mem *mem)
+{
+   struct device *dev = >dev->plat_dev->dev;
+   struct dma_buf *dma_buffer;
+   struct dma_heap *vdec_heap;
+   struct dma_buf_attachment *attach;
+   struct sg_table *sgt;
+   unsigned long size = mem->size;
+   int ret = 0;
+
+   if (!size)
+   return -EINVAL;
+
+   vdec_heap = dma_heap_find("restricted_mtk_cm");
+   if (!vdec_heap) {
+   mtk_v4l2_vdec_err(ctx, "dma heap find failed!");
+   return -EPERM;
+   }
+
+   dma_buffer = dma_heap_buffer_alloc(vdec_heap, size, 
DMA_HEAP_VALID_FD_FLAGS,
+  DMA_HEAP_VALID_HEAP_FLAGS);
+   if (IS_ERR_OR_NULL(dma_buffer)) {
+   mtk_v4l2_vdec_err(ctx, "dma heap alloc size=0x%lx failed!", 
size);
+   return PTR_ERR(dma_buffer);
+   }
+
+   attach = dma_buf_attach(dma_buffer, dev);
+   if (IS_ERR_OR_NULL(attach)) {
+   mtk_v4l2_vdec_err(ctx, "dma attach size=0x%lx failed!", size);
+   ret = PTR_ERR(attach);
+   goto err_attach;
+   }
+
+   sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+   if (IS_ERR_OR_NULL(sgt)) {
+   mtk_v4l2_vdec_err(ctx, "dma map attach size=0x%lx failed!", 
size);
+   ret = PTR_ERR(sgt);
+   goto err_sgt;
+   }
+
+   mem->va = dma_buffer;
+   mem->dma_addr = (dma_addr_t)sg_dma_address((sgt)->sgl);
+
+   if (!mem->va || !mem->dma_addr) {
+   mtk_v4l2_vdec_err(ctx, "dma buffer size=0x%lx failed!", size);
+   ret = -EPERM;
+   goto err_addr;
+   }
+
+   mem->attach = attach;
+   mem->sgt = sgt;
+
+   return 0;
+err_addr:
+   dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+err_sgt:
+   dma_buf_detach(dma_buffer, attach);
+err_attach:
+   dma_buf_put(dma_buffer);
+
+   return ret;
+}
+
+static void mtk_vcodec_mem_free_nor(void *priv, struct mtk_vcodec_mem *mem)
 {
enum mtk_instance_type inst_type = *((unsigned int *)priv);
struct platform_device *plat_dev;
@@ -111,6 +175,57 @@ void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem 
*mem)
mem->dma_addr = 0;
mem->size = 0;
 }
+
+static void mtk_vcodec_mem_free_sec(struct mtk_vcodec_mem *mem)
+{
+   if (mem->sgt)
+   dma_buf_unmap_attachment(mem->attach, mem->sgt, 
DMA_BIDIRECTIONAL);
+   dma_buf_detach((struct dma_buf *)mem->va, mem->attach);
+   dma_buf_put((struct dma_buf *)mem->va);
+
+   mem->attach = NULL;
+   mem->sgt = NULL;
+   mem->va = NULL;
+   me

[PATCH v4, 03/22] v4l2: verify restricted dmabufs are used in restricted queue

2024-01-28 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Verfies in the dmabuf implementations that if the restricted memory
flag is set for a queue that the dmabuf submitted to the queue is
unmappable.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 drivers/media/common/videobuf2/videobuf2-dma-contig.c | 8 
 drivers/media/common/videobuf2/videobuf2-dma-sg.c | 8 
 2 files changed, 16 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c 
b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index 3d4fd4ef5310..f953570fef27 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -710,6 +710,14 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
return -EINVAL;
}
 
+   /* Verify the dmabuf is restricted if we are in restricted mode, this 
is done
+* by validating there is no page entry for the dmabuf.
+*/
+   if (buf->vb->vb2_queue->restricted_mem && sg_page(sgt->sgl)) {
+   pr_err("restricted queue requires restricted dma_buf");
+   return -EINVAL;
+   }
+
/* checking if dmabuf is big enough to store contiguous chunk */
contig_size = vb2_dc_get_contiguous_size(sgt);
if (contig_size < buf->size) {
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c 
b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
index 6975a71d740f..f87bd3f40b9b 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
@@ -570,6 +570,14 @@ static int vb2_dma_sg_map_dmabuf(void *mem_priv)
return -EINVAL;
}
 
+   /* Verify the dmabuf is restricted if we are in restricted mode, this 
is done
+* by validating there is no page entry for the dmabuf.
+*/
+   if (buf->vb->vb2_queue->restricted_mem && !sg_page(sgt->sgl)) {
+   pr_err("restricted queue requires restricted dma_buf");
+   return -EINVAL;
+   }
+
buf->dma_sgt = sgt;
buf->vaddr = NULL;
 
-- 
2.18.0



[PATCH v4, 11/22] media: mediatek: vcodec: initialize msg and vsi information

2024-01-28 Thread Yunfei Dong
Need to initialize msg and vsi information before sending to optee-os, then
calling optee invoke command to send the information to optee-os.

For the optee communication interface is different with scp, using
flag to separate them.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_drv.h   |  2 +
 .../mediatek/vcodec/decoder/vdec_vpu_if.c | 49 ---
 .../mediatek/vcodec/decoder/vdec_vpu_if.h |  4 ++
 3 files changed, 49 insertions(+), 6 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 b1a2107f2a1e..47eca245dc07 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
@@ -175,6 +175,7 @@ struct mtk_vcodec_dec_pdata {
  * @vpu_inst: vpu instance pointer.
  *
  * @is_10bit_bitstream: set to true if it's 10bit bitstream
+ * @is_secure_playback: Secure Video Playback (SVP) mode
  */
 struct mtk_vcodec_dec_ctx {
enum mtk_instance_type type;
@@ -220,6 +221,7 @@ struct mtk_vcodec_dec_ctx {
void *vpu_inst;
 
bool is_10bit_bitstream;
+   bool is_secure_playback;
 };
 
 /**
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
index 82e57ae983d5..5336769a3fb5 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
@@ -148,7 +148,10 @@ static void vpu_dec_ipi_handler(void *data, unsigned int 
len, void *priv)
 
 static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, void *msg, int len)
 {
-   int err, id, msgid;
+   struct mtk_vdec_optee_data_to_shm *optee_data;
+   int data_size, id, hw_id, msgid;
+   void *ack_msg, *data_msg;
+   int err;
 
msgid = *(uint32_t *)msg;
mtk_vdec_debug(vpu->ctx, "id=%X", msgid);
@@ -158,16 +161,46 @@ static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, 
void *msg, int len)
 
if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) {
if (msgid == AP_IPIMSG_DEC_CORE ||
-   msgid == AP_IPIMSG_DEC_CORE_END)
+   msgid == AP_IPIMSG_DEC_CORE_END) {
+   optee_data = >core_optee_info;
id = vpu->core_id;
-   else
+   } else {
+   optee_data = >lat_optee_info;
id = vpu->id;
+   }
} else {
+   optee_data = >lat_optee_info;
id = vpu->id;
}
 
-   err = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, id, msg,
-len, 2000);
+   if (!vpu->ctx->is_secure_playback) {
+   err = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, id, 
msg, len, 2000);
+   } else {
+   hw_id = (id == SCP_IPI_VDEC_LAT) ? MTK_VDEC_LAT0 : 
MTK_VDEC_CORE;
+
+   mtk_vcodec_dec_optee_set_data(optee_data, msg, len, 
OPTEE_MSG_INDEX);
+
+   /* There is no need to copy the data (VSI) message to shared 
memory,
+* but we still need to set the buffer size to a non-zero value.
+*/
+   if (msgid == AP_IPIMSG_DEC_CORE || msgid == 
AP_IPIMSG_DEC_START) {
+   data_msg = 
mtk_vcodec_dec_get_shm_buffer_va(vpu->ctx->dev->optee_private,
+   hw_id, 
OPTEE_DATA_INDEX);
+   data_size = 
mtk_vcodec_dec_get_shm_buffer_size(vpu->ctx->dev->optee_private,
+  hw_id, 
OPTEE_DATA_INDEX);
+   mtk_vcodec_dec_optee_set_data(optee_data, data_msg, 
data_size,
+ OPTEE_DATA_INDEX);
+   }
+
+   err = 
mtk_vcodec_dec_optee_invokd_cmd(vpu->ctx->dev->optee_private,
+ hw_id, optee_data);
+   vpu->failure = err;
+
+   ack_msg = 
mtk_vcodec_dec_get_shm_buffer_va(vpu->ctx->dev->optee_private, hw_id,
+  OPTEE_MSG_INDEX);
+   vpu_dec_ipi_handler(ack_msg, 0, vpu->ctx->dev);
+   }
+
if (err) {
mtk_vdec_err(vpu->ctx, "send fail vpu_id=%d msg_id=%X 
status=%d",
 id, msgid, err);
@@ -213,7 +246,11 @@ int vpu_dec_init(struct vdec_vpu_inst *vpu)
return err;
}
 
-   if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) {
+   /* Using tee interface to communicate with op

[PATCH v4,04/22] v4l: add documentation for restricted memory flag

2024-01-28 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Adds documentation for V4L2_MEMORY_FLAG_RESTRICTED.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 Documentation/userspace-api/media/v4l/buffer.rst | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/Documentation/userspace-api/media/v4l/buffer.rst 
b/Documentation/userspace-api/media/v4l/buffer.rst
index 52bbee81c080..807e43bfed2b 100644
--- a/Documentation/userspace-api/media/v4l/buffer.rst
+++ b/Documentation/userspace-api/media/v4l/buffer.rst
@@ -696,7 +696,7 @@ enum v4l2_memory
 
 .. _memory-flags:
 
-Memory Consistency Flags
+Memory Flags
 
 
 .. raw:: latex
@@ -728,6 +728,14 @@ Memory Consistency Flags
only if the buffer is used for :ref:`memory mapping ` I/O and the
queue reports the :ref:`V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS
` capability.
+* .. _`V4L2-MEMORY-FLAG-RESTRICTED`:
+
+  - ``V4L2_MEMORY_FLAG_RESTRICTED``
+  - 0x0002
+  - The queued buffers are expected to be in restricted memory. If not, an
+   error will be returned. This flag can only be used with 
``V4L2_MEMORY_DMABUF``.
+   Typically restricted buffers are allocated using a restricted dma-heap. 
This flag
+   can only be specified if the ``V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM`` 
is set.
 
 .. raw:: latex
 
-- 
2.18.0



[PATCH v4,06/22] dma-heap: Add proper kref handling on dma-buf heaps

2024-01-28 Thread Yunfei Dong
From: John Stultz 

Add proper refcounting on the dma_heap structure.
While existing heaps are built-in, we may eventually
have heaps loaded from modules, and we'll need to be
able to properly handle the references to the heaps

Signed-off-by: John Stultz 
Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Just add comment for "minor" and "refcount"]
Signed-off-by: Yunfei Dong 
---
 drivers/dma-buf/dma-heap.c | 29 +
 include/linux/dma-heap.h   |  2 ++
 2 files changed, 31 insertions(+)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 22f6c193db0d..97025ee8500f 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -30,6 +31,7 @@
  * @heap_devt: heap device node
  * @list:  list head connecting to list of heaps
  * @heap_cdev: heap char device
+ * @refcount:  reference counter for this heap device
  *
  * Represents a heap of memory from which buffers can be made.
  */
@@ -40,6 +42,7 @@ struct dma_heap {
dev_t heap_devt;
struct list_head list;
struct cdev heap_cdev;
+   struct kref refcount;
 };
 
 static LIST_HEAD(heap_list);
@@ -240,6 +243,7 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
if (!heap)
return ERR_PTR(-ENOMEM);
 
+   kref_init(>refcount);
heap->name = exp_info->name;
heap->ops = exp_info->ops;
heap->priv = exp_info->priv;
@@ -304,6 +308,31 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
return err_ret;
 }
 
+static void dma_heap_release(struct kref *ref)
+{
+   struct dma_heap *heap = container_of(ref, struct dma_heap, refcount);
+   unsigned int minor = MINOR(heap->heap_devt);
+
+   mutex_lock(_list_lock);
+   list_del(>list);
+   mutex_unlock(_list_lock);
+
+   device_destroy(dma_heap_class, heap->heap_devt);
+   cdev_del(>heap_cdev);
+   xa_erase(_heap_minors, minor);
+
+   kfree(heap);
+}
+
+/**
+ * dma_heap_put - drops a reference to a dmabuf heap, potentially freeing it
+ * @heap: DMA-Heap whose reference count to decrement
+ */
+void dma_heap_put(struct dma_heap *heap)
+{
+   kref_put(>refcount, dma_heap_release);
+}
+
 static char *dma_heap_devnode(const struct device *dev, umode_t *mode)
 {
return kasprintf(GFP_KERNEL, "dma_heap/%s", dev_name(dev));
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index fbe86ec889a8..d57593f8a1bc 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -46,4 +46,6 @@ const char *dma_heap_get_name(struct dma_heap *heap);
 
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
+void dma_heap_put(struct dma_heap *heap);
+
 #endif /* _DMA_HEAPS_H */
-- 
2.18.0



[PATCH v4,00/22] media: add driver to support secure video decoder

2024-01-28 Thread Yunfei Dong
The patch series used to enable secure video playback (SVP) on MediaTek
hardware in the Linux kernel.

Memory Definitions:
secure memory - Memory allocated in the TEE (Trusted Execution
Environment) which is inaccessible in the REE (Rich Execution
Environment, i.e. linux kernel/user space).
secure handle - Integer value which acts as reference to 'secure
memory'. Used in communication between TEE and REE to reference
'secure memory'.
secure buffer - 'secure memory' that is used to store decrypted,
compressed video or for other general purposes in the TEE.
secure surface - 'secure memory' that is used to store graphic buffers.

Memory Usage in SVP:
The overall flow of SVP starts with encrypted video coming in from an
outside source into the REE. The REE will then allocate a 'secure
buffer' and send the corresponding 'secure handle' along with the
encrypted, compressed video data to the TEE. The TEE will then decrypt
the video and store the result in the 'secure buffer'. The REE will
then allocate a 'secure surface'. The REE will pass the 'secure
handles' for both the 'secure buffer' and 'secure surface' into the
TEE for video decoding. The video decoder HW will then decode the
contents of the 'secure buffer' and place the result in the 'secure
surface'. The REE will then attach the 'secure surface' to the overlay
plane for rendering of the video.

Everything relating to ensuring security of the actual contents of the
'secure buffer' and 'secure surface' is out of scope for the REE and
is the responsibility of the TEE.

This patch series is consists of four parts. The first is from Jeffrey,
adding secure memory flag in v4l2 framework to support request secure
buffer.

The second and third parts are from John and T.J, adding some heap
interfaces, then our kernel users could allocate buffer from special
heap. The patch v1 is inside below dmabuf link.
https://lore.kernel.org/linux-mediatek/20230911023038.30649-1-yong...@mediatek.com/
To avoid confusing, move them into vcodec patch set since we use the
new interfaces directly.

The last part is mediaTek video decoder driver, adding tee interface to
support secure video decoder.

---
Changed in v4:
- change the driver according to maintainer advice for patch 1/2/3/4
- replace secure with restricted for patch 1/2/3/4
- fix svp decoder error for patch 21
- add to support hevc for patch 22

Changed in v3:
- rewrite the cover-letter of this patch series
- disable irq for svp mode
- rebase the driver based on the latest media stage

Changed in v2:
- remove setting decoder mode and getting secure handle from decode
- add Jeffrey's patch
- add John and T.J's patch
- getting secure flag with request buffer
- fix some comments from patch v1
---
Jeffrey Kardatzke (4):
  v4l2: add restricted memory flags
  v4l2: handle restricted memory flags in queue setup
  v4l2: verify restricted dmabufs are used in restricted queue
  v4l: add documentation for restricted memory flag

John Stultz (2):
  dma-heap: Add proper kref handling on dma-buf heaps
  dma-heap: Provide accessors so that in-kernel drivers can allocate
dmabufs from specific heaps

T.J. Mercier (1):
  dma-buf: heaps: Deduplicate docs and adopt common format

Yunfei Dong (15):
  media: mediatek: vcodec: add tee client interface to communiate with
optee-os
  media: mediatek: vcodec: allocate tee share memory
  media: mediatek: vcodec: send share memory data to optee
  media: mediatek: vcodec: initialize msg and vsi information
  media: mediatek: vcodec: add interface to allocate/free secure memory
  media: mediatek: vcodec: using shared memory as vsi address
  media: mediatek: vcodec: Add capture format to support one plane
memory
  media: mediatek: vcodec: Add one plane format
  media: mediatek: vcodec: support one plane capture buffer
  media: mediatek: vcodec: re-construct h264 driver to support svp mode
  media: mediatek: vcodec: remove parse nal_info in kernel
  media: mediatek: vcodec: disable wait interrupt for svp mode
  media: mediatek: vcodec: support tee decoder
  media: mediatek: vcodec: move vdec init interface to setup callback
  media: mediatek: vcodec: support hevc svp for mt8188

 .../userspace-api/media/v4l/buffer.rst|  10 +-
 .../media/v4l/pixfmt-reserved.rst |   8 +
 drivers/dma-buf/dma-heap.c| 139 +--
 .../media/common/videobuf2/videobuf2-core.c   |  21 +
 .../common/videobuf2/videobuf2-dma-contig.c   |   8 +
 .../media/common/videobuf2/videobuf2-dma-sg.c |   8 +
 .../media/common/videobuf2/videobuf2-v4l2.c   |   4 +-
 .../media/platform/mediatek/vcodec/Kconfig|   1 +
 .../mediatek/vcodec/common/mtk_vcodec_util.c  | 122 +-
 .../mediatek/vcodec/common/mtk_vcodec_util.h  |   3 +
 .../platform/mediatek/vcodec/decoder/Makefile |   1 +
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c  | 150 ---
 .../vcodec/decoder/mtk_vcodec_dec_drv.c   |   8 +
 .../vcodec/decoder/mtk_vcodec_dec_drv.h   |   7 +
 .../vcodec/decoder

[PATCH v4, 07/22] dma-heap: Provide accessors so that in-kernel drivers can allocate dmabufs from specific heaps

2024-01-28 Thread Yunfei Dong
From: John Stultz 

This allows drivers who don't want to create their own
DMA-BUF exporter to be able to allocate DMA-BUFs directly
from existing DMA-BUF Heaps.

There is some concern that the premise of DMA-BUF heaps is
that userland knows better about what type of heap memory
is needed for a pipeline, so it would likely be best for
drivers to import and fill DMA-BUFs allocated by userland
instead of allocating one themselves, but this is still
up for debate.

Signed-off-by: John Stultz 
Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Fix the checkpatch alignment warning]
Signed-off-by: Yunfei Dong 
---
 drivers/dma-buf/dma-heap.c | 83 ++
 include/linux/dma-heap.h   |  6 +++
 2 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 97025ee8500f..6efe833a4b10 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -51,12 +51,24 @@ static dev_t dma_heap_devt;
 static struct class *dma_heap_class;
 static DEFINE_XARRAY_ALLOC(dma_heap_minors);
 
-static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
-unsigned int fd_flags,
-unsigned int heap_flags)
+/**
+ * dma_heap_buffer_alloc - Allocate dma-buf from a dma_heap
+ * @heap:  DMA-Heap to allocate from
+ * @len:   size to allocate in bytes
+ * @fd_flags:  flags to set on returned dma-buf fd
+ * @heap_flags: flags to pass to the dma heap
+ *
+ * This is for internal dma-buf allocations only. Free returned buffers with 
dma_buf_put().
+ */
+struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
+ unsigned int fd_flags,
+ unsigned int heap_flags)
 {
-   struct dma_buf *dmabuf;
-   int fd;
+   if (fd_flags & ~DMA_HEAP_VALID_FD_FLAGS)
+   return ERR_PTR(-EINVAL);
+
+   if (heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
+   return ERR_PTR(-EINVAL);
 
/*
 * Allocations from all heaps have to begin
@@ -64,9 +76,20 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, 
size_t len,
 */
len = PAGE_ALIGN(len);
if (!len)
-   return -EINVAL;
+   return ERR_PTR(-EINVAL);
+
+   return heap->ops->allocate(heap, len, fd_flags, heap_flags);
+}
+EXPORT_SYMBOL_GPL(dma_heap_buffer_alloc);
 
-   dmabuf = heap->ops->allocate(heap, len, fd_flags, heap_flags);
+static int dma_heap_bufferfd_alloc(struct dma_heap *heap, size_t len,
+  unsigned int fd_flags,
+  unsigned int heap_flags)
+{
+   struct dma_buf *dmabuf;
+   int fd;
+
+   dmabuf = dma_heap_buffer_alloc(heap, len, fd_flags, heap_flags);
if (IS_ERR(dmabuf))
return PTR_ERR(dmabuf);
 
@@ -104,15 +127,9 @@ static long dma_heap_ioctl_allocate(struct file *file, 
void *data)
if (heap_allocation->fd)
return -EINVAL;
 
-   if (heap_allocation->fd_flags & ~DMA_HEAP_VALID_FD_FLAGS)
-   return -EINVAL;
-
-   if (heap_allocation->heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
-   return -EINVAL;
-
-   fd = dma_heap_buffer_alloc(heap, heap_allocation->len,
-  heap_allocation->fd_flags,
-  heap_allocation->heap_flags);
+   fd = dma_heap_bufferfd_alloc(heap, heap_allocation->len,
+heap_allocation->fd_flags,
+heap_allocation->heap_flags);
if (fd < 0)
return fd;
 
@@ -205,6 +222,7 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
 {
return heap->priv;
 }
+EXPORT_SYMBOL_GPL(dma_heap_get_drvdata);
 
 /**
  * dma_heap_get_name - get heap name
@@ -217,6 +235,7 @@ const char *dma_heap_get_name(struct dma_heap *heap)
 {
return heap->name;
 }
+EXPORT_SYMBOL_GPL(dma_heap_get_name);
 
 /**
  * dma_heap_add - adds a heap to dmabuf heaps
@@ -307,6 +326,37 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
kfree(heap);
return err_ret;
 }
+EXPORT_SYMBOL_GPL(dma_heap_add);
+
+/**
+ * dma_heap_find - get the heap registered with the specified name
+ * @name: Name of the DMA-Heap to find
+ *
+ * Returns:
+ * The DMA-Heap with the provided name.
+ *
+ * NOTE: DMA-Heaps returned from this function MUST be released using
+ * dma_heap_put() when the user is done to enable the heap to be unloaded.
+ */
+struct dma_heap *dma_heap_find(const char *name)
+{
+   struct dma_heap *h;
+
+   mutex_lock(_list_lock);
+   list_for_each_entry(h, _list, list) {
+   if (!kref_get_unless_zero(>refcount))
+   continue;
+
+   if (!strcmp(h->name, name)) {
+ 

[PATCH v4, 05/22] dma-buf: heaps: Deduplicate docs and adopt common format

2024-01-28 Thread Yunfei Dong
From: "T.J. Mercier" 

The docs for dma_heap_get_name were incorrect, and since they were
duplicated in the header they were wrong there too.

The docs formatting was inconsistent so I tried to make it more
consistent across functions since I'm already in here doing cleanup.

Remove multiple unused includes and alphabetize.

Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Just add a comment for "priv" to mute build warning]
Signed-off-by: Yunfei Dong 
---
 drivers/dma-buf/dma-heap.c | 27 +++
 include/linux/dma-heap.h   | 21 +
 2 files changed, 16 insertions(+), 32 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 84ae708fafe7..22f6c193db0d 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -7,17 +7,15 @@
  */
 
 #include 
-#include 
 #include 
 #include 
+#include 
 #include 
-#include 
 #include 
-#include 
 #include 
-#include 
 #include 
-#include 
+#include 
+#include 
 #include 
 
 #define DEVNAME "dma_heap"
@@ -28,9 +26,10 @@
  * struct dma_heap - represents a dmabuf heap in the system
  * @name:  used for debugging/device-node name
  * @ops:   ops struct for this heap
- * @heap_devt  heap device node
- * @list   list head connecting to list of heaps
- * @heap_cdev  heap char device
+ * @priv:  private data for this heap
+ * @heap_devt: heap device node
+ * @list:  list head connecting to list of heaps
+ * @heap_cdev: heap char device
  *
  * Represents a heap of memory from which buffers can be made.
  */
@@ -193,11 +192,11 @@ static const struct file_operations dma_heap_fops = {
 };
 
 /**
- * dma_heap_get_drvdata() - get per-subdriver data for the heap
+ * dma_heap_get_drvdata - get per-heap driver data
  * @heap: DMA-Heap to retrieve private data for
  *
  * Returns:
- * The per-subdriver data for the heap.
+ * The per-heap data for the heap.
  */
 void *dma_heap_get_drvdata(struct dma_heap *heap)
 {
@@ -205,8 +204,8 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
 }
 
 /**
- * dma_heap_get_name() - get heap name
- * @heap: DMA-Heap to retrieve private data for
+ * dma_heap_get_name - get heap name
+ * @heap: DMA-Heap to retrieve the name of
  *
  * Returns:
  * The char* for the heap name.
@@ -216,6 +215,10 @@ const char *dma_heap_get_name(struct dma_heap *heap)
return heap->name;
 }
 
+/**
+ * dma_heap_add - adds a heap to dmabuf heaps
+ * @exp_info: information needed to register this heap
+ */
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
 {
struct dma_heap *heap, *h, *err_ret;
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index 0c05561cad6e..fbe86ec889a8 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -9,14 +9,13 @@
 #ifndef _DMA_HEAPS_H
 #define _DMA_HEAPS_H
 
-#include 
 #include 
 
 struct dma_heap;
 
 /**
  * struct dma_heap_ops - ops to operate on a given heap
- * @allocate:  allocate dmabuf and return struct dma_buf ptr
+ * @allocate:  allocate dmabuf and return struct dma_buf ptr
  *
  * allocate returns dmabuf on success, ERR_PTR(-errno) on error.
  */
@@ -41,28 +40,10 @@ struct dma_heap_export_info {
void *priv;
 };
 
-/**
- * dma_heap_get_drvdata() - get per-heap driver data
- * @heap: DMA-Heap to retrieve private data for
- *
- * Returns:
- * The per-heap data for the heap.
- */
 void *dma_heap_get_drvdata(struct dma_heap *heap);
 
-/**
- * dma_heap_get_name() - get heap name
- * @heap: DMA-Heap to retrieve private data for
- *
- * Returns:
- * The char* for the heap name.
- */
 const char *dma_heap_get_name(struct dma_heap *heap);
 
-/**
- * dma_heap_add - adds a heap to dmabuf heaps
- * @exp_info:  information needed to register this heap
- */
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
 #endif /* _DMA_HEAPS_H */
-- 
2.18.0



[PATCH v4,01/22] v4l2: add restricted memory flags

2024-01-28 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Adds a V4L2 flag which indicates that a queue is using restricted
dmabufs and the corresponding capability flag.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 include/media/videobuf2-core.h | 8 +++-
 include/uapi/linux/videodev2.h | 2 ++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 56719a26a46c..047d4798e423 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -518,6 +518,9 @@ struct vb2_buf_ops {
  * ->finish().
  * @non_coherent_mem: when set queue will attempt to allocate buffers using
  * non-coherent memory.
+ * @allow_restricted_mem: when set user-space can pass the 
%V4L2_MEMORY_FLAG_RESTRICTED
+ * flag to indicate the dma bufs are restricted.
+ * @restricted_mem: when set queue will verify that the dma bufs are 
restricted.
  * @lock:  pointer to a mutex that protects the  vb2_queue. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -604,6 +607,8 @@ struct vb2_queue {
unsigned intuses_requests:1;
unsigned intallow_cache_hints:1;
unsigned intnon_coherent_mem:1;
+   unsigned intallow_restricted_mem:1;
+   unsigned intrestricted_mem:1;
 
struct mutex*lock;
void*owner;
@@ -773,7 +778,8 @@ void vb2_core_querybuf(struct vb2_queue *q, struct 
vb2_buffer *vb, void *pb);
  * @q: pointer to  vb2_queue with videobuf2 queue.
  * @memory:memory type, as defined by  vb2_memory.
  * @flags: auxiliary queue/buffer management flags. Currently, the only
- * used flag is %V4L2_MEMORY_FLAG_NON_COHERENT.
+ * used flags are %V4L2_MEMORY_FLAG_NON_COHERENT and
+ * %V4L2_MEMORY_FLAG_RESTRICTED.
  * @count: requested buffer count.
  *
  * Videobuf2 core helper to implement VIDIOC_REQBUF() operation. It is called
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 68e7ac178cc2..3e3f8d4b7c81 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1026,6 +1026,7 @@ struct v4l2_requestbuffers {
 };
 
 #define V4L2_MEMORY_FLAG_NON_COHERENT  (1 << 0)
+#define V4L2_MEMORY_FLAG_RESTRICTED(1 << 1)
 
 /* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */
 #define V4L2_BUF_CAP_SUPPORTS_MMAP (1 << 0)
@@ -1036,6 +1037,7 @@ struct v4l2_requestbuffers {
 #define V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF (1 << 5)
 #define V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS (1 << 6)
 #define V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS  (1 << 7)
+#define V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM   (1 << 8)
 
 /**
  * struct v4l2_plane - plane info for multi-planar buffers
-- 
2.18.0



[PATCH v4,02/22] v4l2: handle restricted memory flags in queue setup

2024-01-28 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Validates the restricted memory flags when setting up a queue and
ensures the queue has the proper capability.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 .../media/common/videobuf2/videobuf2-core.c   | 21 +++
 .../media/common/videobuf2/videobuf2-v4l2.c   |  4 +++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 41a832dd1426..7f5fd9ec9117 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -813,6 +813,15 @@ static bool verify_coherency_flags(struct vb2_queue *q, 
bool non_coherent_mem)
return true;
 }
 
+static bool verify_restricted_mem_flags(struct vb2_queue *q, bool 
restricted_mem)
+{
+   if (restricted_mem != q->restricted_mem) {
+   dprintk(q, 1, "restricted memory model mismatch\n");
+   return false;
+   }
+   return true;
+}
+
 int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
 unsigned int flags, unsigned int *count)
 {
@@ -820,6 +829,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
unsigned int q_num_bufs = vb2_get_num_buffers(q);
unsigned plane_sizes[VB2_MAX_PLANES] = { };
bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
+   bool restricted_mem = flags & V4L2_MEMORY_FLAG_RESTRICTED;
unsigned int i;
int ret = 0;
 
@@ -862,6 +872,9 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
return 0;
}
 
+   if (restricted_mem && (!q->allow_restricted_mem || memory != 
V4L2_MEMORY_DMABUF))
+   return -EINVAL;
+
/*
 * Make sure the requested values and current defaults are sane.
 */
@@ -882,6 +895,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
if (ret)
return ret;
set_queue_coherency(q, non_coherent_mem);
+   q->restricted_mem = restricted_mem;
 
/*
 * Ask the driver how many buffers and planes per buffer it requires.
@@ -986,6 +1000,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
unsigned plane_sizes[VB2_MAX_PLANES] = { };
bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
unsigned int q_num_bufs = vb2_get_num_buffers(q);
+   bool restricted_mem = flags & V4L2_MEMORY_FLAG_RESTRICTED;
bool no_previous_buffers = !q_num_bufs;
int ret = 0;
 
@@ -994,6 +1009,9 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
return -ENOBUFS;
}
 
+   if (restricted_mem && (!q->allow_restricted_mem || memory != 
V4L2_MEMORY_DMABUF))
+   return -EINVAL;
+
if (no_previous_buffers) {
if (q->waiting_in_dqbuf && *count) {
dprintk(q, 1, "another dup()ped fd is waiting for a 
buffer\n");
@@ -1015,6 +1033,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
return ret;
q->waiting_for_buffers = !q->is_output;
set_queue_coherency(q, non_coherent_mem);
+   q->restricted_mem = restricted_mem;
} else {
if (q->memory != memory) {
dprintk(q, 1, "memory model mismatch\n");
@@ -1022,6 +1041,8 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
}
if (!verify_coherency_flags(q, non_coherent_mem))
return -EINVAL;
+   if (!verify_restricted_mem_flags(q, restricted_mem))
+   return -EINVAL;
}
 
num_buffers = min(*count, q->max_num_buffers - q_num_bufs);
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 54d572c3b515..e825b1e2e22f 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -686,6 +686,8 @@ static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
*caps |= V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS;
if (q->supports_requests)
*caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS;
+   if (q->allow_restricted_mem && q->io_modes & VB2_DMABUF)
+   *caps |= V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM;
 }
 
 static void validate_memory_flags(struct vb2_queue *q,
@@ -700,7 +702,7 @@ static void validate_memory_flags(struct vb2_queue *q,
*flags = 0;
} else {
/* Clear all unknown flags. */
-   *flags &= V4L2_MEMORY_FLAG_NON_COHERENT;
+   *flags &= V4L2_MEMORY_FLAG_NON_COHERENT | 
V4L2_MEMORY_FLAG_RESTRICTED;
}
 }
 
-- 
2.18.0



[PATCH v3,20/21] media: medkatek: vcodec: support tee decoder

2023-12-06 Thread Yunfei Dong
Initialize tee private data to support secure decoder.
Release tee related information for each instance when decoder
done.

Signed-off-by: Yunfei Dong 
---
 .../platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c | 8 
 1 file changed, 8 insertions(+)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
index f47c98faf068..08e7d250487b 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
@@ -310,6 +310,9 @@ static int fops_vcodec_release(struct file *file)
v4l2_fh_exit(>fh);
v4l2_ctrl_handler_free(>ctrl_hdl);
 
+   if (ctx->is_secure_playback)
+   mtk_vcodec_dec_optee_release(dev->optee_private);
+
mtk_vcodec_dbgfs_remove(dev, ctx->id);
list_del_init(>list);
kfree(ctx);
@@ -466,6 +469,11 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
atomic_set(>dec_active_cnt, 0);
memset(dev->vdec_racing_info, 0, sizeof(dev->vdec_racing_info));
mutex_init(>dec_racing_info_mutex);
+   ret = mtk_vcodec_dec_optee_private_init(dev);
+   if (ret) {
+   dev_err(>dev, "Failed to init svp private.");
+   goto err_reg_cont;
+   }
 
ret = video_register_device(vfd_dec, VFL_TYPE_VIDEO, -1);
if (ret) {
-- 
2.18.0



[PATCH v3, 10/21] media: mediatek: vcodec: send share memory data to optee

2023-12-06 Thread Yunfei Dong
Setting msg and vsi information to shared buffer, then call tee invoke
function to send it to optee-os.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 140 ++
 .../vcodec/decoder/mtk_vcodec_dec_optee.h |  51 +++
 2 files changed, 191 insertions(+)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
index 611fb0e56480..f29a8d143fee 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
@@ -241,3 +241,143 @@ void mtk_vcodec_dec_optee_release(struct 
mtk_vdec_optee_private *optee_private)
mutex_unlock(_private->tee_mutex);
 }
 EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_release);
+
+static int mtk_vcodec_dec_optee_fill_shm(struct tee_param *command_params,
+struct mtk_vdec_optee_shm_memref 
*shm_memref,
+struct mtk_vdec_optee_data_to_shm 
*data,
+int index, struct device *dev)
+{
+   if (!data->msg_buf_size[index] || !data->msg_buf[index]) {
+   pr_err(MTK_DBG_VCODEC_STR "tee invalid buf param: %d.\n", 
index);
+   return -EINVAL;
+   }
+
+   *command_params = (struct tee_param) {
+   .attr = shm_memref->param_type,
+   .u.memref = {
+   .shm = shm_memref->msg_shm,
+   .size = data->msg_buf_size[index],
+   .shm_offs = 0,
+   },
+   };
+
+   if (!shm_memref->copy_to_ta) {
+   dev_dbg(dev, MTK_DBG_VCODEC_STR "share memref data: 0x%x 
param_type:%llu.\n",
+   *((unsigned int *)shm_memref->msg_shm_ca_buf), 
shm_memref->param_type);
+   return 0;
+   }
+
+   memset(shm_memref->msg_shm_ca_buf, 0, shm_memref->msg_shm_size);
+   memcpy(shm_memref->msg_shm_ca_buf, data->msg_buf[index], 
data->msg_buf_size[index]);
+
+   dev_dbg(dev, MTK_DBG_VCODEC_STR "share memref data => msg id:0x%x 0x%x 
param_type:%llu.\n",
+   *((unsigned int *)data->msg_buf[index]),
+   *((unsigned int *)shm_memref->msg_shm_ca_buf),
+   shm_memref->param_type);
+
+   return 0;
+}
+
+void mtk_vcodec_dec_optee_set_data(struct mtk_vdec_optee_data_to_shm *data,
+  void *buf, int buf_size,
+  enum mtk_vdec_optee_data_index index)
+{
+   data->msg_buf[index] = buf;
+   data->msg_buf_size[index] = buf_size;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_set_data);
+
+int mtk_vcodec_dec_optee_invokd_cmd(struct mtk_vdec_optee_private 
*optee_private,
+   enum mtk_vdec_hw_id hw_id,
+   struct mtk_vdec_optee_data_to_shm *data)
+{
+   struct device *dev = _private->vcodec_dev->plat_dev->dev;
+   struct tee_ioctl_invoke_arg trans_args;
+   struct tee_param command_params[MTK_OPTEE_MAX_TEE_PARAMS];
+   struct mtk_vdec_optee_ca_info *ca_info;
+   struct mtk_vdec_optee_shm_memref *shm_memref;
+   int ret, index;
+
+   if (hw_id == MTK_VDEC_LAT0)
+   ca_info = _private->lat_ca;
+   else
+   ca_info = _private->core_ca;
+
+   memset(_args, 0, sizeof(trans_args));
+   memset(command_params, 0, sizeof(command_params));
+
+   trans_args = (struct tee_ioctl_invoke_arg) {
+   .func = ca_info->vdec_session_func,
+   .session = ca_info->vdec_session_id,
+   .num_params = MTK_OPTEE_MAX_TEE_PARAMS,
+   };
+
+   /* Fill msg command parameters */
+   for (index = 0; index < MTK_OPTEE_MAX_TEE_PARAMS; index++) {
+   shm_memref = _info->shm_memref[index];
+
+   if (shm_memref->param_type == TEE_IOCTL_PARAM_ATTR_TYPE_NONE ||
+   data->msg_buf_size[index] == 0)
+   continue;
+
+   dev_dbg(dev, MTK_DBG_VCODEC_STR "tee share memory data size: %d 
-> %d.\n",
+   data->msg_buf_size[index], shm_memref->msg_shm_size);
+
+   if (data->msg_buf_size[index] > shm_memref->msg_shm_size) {
+   dev_err(dev, MTK_DBG_VCODEC_STR "tee buf size big than 
shm (%d -> %d).\n",
+   data->msg_buf_size[index], 
shm_memref->msg_shm_size);
+   return -EINVAL;
+   }
+
+   ret = mtk_vcodec_dec_optee_fill_shm(_params[index], 
shm_memref,
+   data, index, dev);
+   if (ret)
+   return ret;
+ 

[PATCH v3, 19/21] media: medkatek: vcodec: disable wait interrupt for svp mode

2023-12-06 Thread Yunfei Dong
Waiting interrupt in optee-os for svp mode, need to disable it in kernel
in case of interrupt is cleaned.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_hw.c| 34 +--
 .../vcodec/decoder/mtk_vcodec_dec_pm.c|  6 +-
 .../decoder/vdec/vdec_h264_req_multi_if.c | 57 +++
 3 files changed, 54 insertions(+), 43 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
index 881d5de41e05..1982c088c6da 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
@@ -72,26 +72,28 @@ static irqreturn_t mtk_vdec_hw_irq_handler(int irq, void 
*priv)
 
ctx = mtk_vcodec_get_curr_ctx(dev->main_dev, dev->hw_idx);
 
-   /* check if HW active or not */
-   cg_status = readl(dev->reg_base[VDEC_HW_SYS] + VDEC_HW_ACTIVE_ADDR);
-   if (cg_status & VDEC_HW_ACTIVE_MASK) {
-   mtk_v4l2_vdec_err(ctx, "vdec active is not 0x0 (0x%08x)", 
cg_status);
-   return IRQ_HANDLED;
-   }
+   if (!ctx->is_secure_playback) {
+   /* check if HW active or not */
+   cg_status = readl(dev->reg_base[VDEC_HW_SYS] + 
VDEC_HW_ACTIVE_ADDR);
+   if (cg_status & VDEC_HW_ACTIVE_MASK) {
+   mtk_v4l2_vdec_err(ctx, "vdec active is not 0x0 
(0x%08x)", cg_status);
+   return IRQ_HANDLED;
+   }
 
-   dec_done_status = readl(vdec_misc_addr);
-   if ((dec_done_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) !=
-   MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
-   return IRQ_HANDLED;
+   dec_done_status = readl(vdec_misc_addr);
+   if ((dec_done_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) !=
+   MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
+   return IRQ_HANDLED;
 
-   /* clear interrupt */
-   writel(dec_done_status | VDEC_IRQ_CFG, vdec_misc_addr);
-   writel(dec_done_status & ~VDEC_IRQ_CLR, vdec_misc_addr);
+   /* clear interrupt */
+   writel(dec_done_status | VDEC_IRQ_CFG, vdec_misc_addr);
+   writel(dec_done_status & ~VDEC_IRQ_CLR, vdec_misc_addr);
 
-   wake_up_dec_ctx(ctx, MTK_INST_IRQ_RECEIVED, dev->hw_idx);
+   wake_up_dec_ctx(ctx, MTK_INST_IRQ_RECEIVED, dev->hw_idx);
 
-   mtk_v4l2_vdec_dbg(3, ctx, "wake up ctx %d, dec_done_status=%x",
- ctx->id, dec_done_status);
+   mtk_v4l2_vdec_dbg(3, ctx, "wake up ctx %d, dec_done_status=%x",
+ ctx->id, dec_done_status);
+   }
 
return IRQ_HANDLED;
 }
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c
index aefd3e9e3061..a94eda936f16 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c
@@ -238,7 +238,8 @@ void mtk_vcodec_dec_enable_hardware(struct 
mtk_vcodec_dec_ctx *ctx, int hw_idx)
mtk_vcodec_dec_child_dev_on(ctx->dev, MTK_VDEC_LAT0);
mtk_vcodec_dec_child_dev_on(ctx->dev, hw_idx);
 
-   mtk_vcodec_dec_enable_irq(ctx->dev, hw_idx);
+   if (!ctx->is_secure_playback)
+   mtk_vcodec_dec_enable_irq(ctx->dev, hw_idx);
 
if (IS_VDEC_INNER_RACING(ctx->dev->dec_capability))
mtk_vcodec_load_racing_info(ctx);
@@ -250,7 +251,8 @@ void mtk_vcodec_dec_disable_hardware(struct 
mtk_vcodec_dec_ctx *ctx, int hw_idx)
if (IS_VDEC_INNER_RACING(ctx->dev->dec_capability))
mtk_vcodec_record_racing_info(ctx);
 
-   mtk_vcodec_dec_disable_irq(ctx->dev, hw_idx);
+   if (!ctx->is_secure_playback)
+   mtk_vcodec_dec_disable_irq(ctx->dev, hw_idx);
 
mtk_vcodec_dec_child_dev_off(ctx->dev, hw_idx);
if (IS_VDEC_LAT_ARCH(ctx->dev->vdec_pdata->hw_arch) &&
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 2dfb3043493e..3e2270399b6c 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
@@ -593,14 +593,16 @@ static int vdec_h264_slice_core_decode(struct 
vdec_lat_buf *lat_buf)
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);
-   i

[PATCH v3, 21/21] media: mediatek: vcodec: move vdec init interface to setup callback

2023-12-06 Thread Yunfei Dong
Getting secure video playback (svp) flag when request output buffer, then
calling init interface to init svp parameters in optee-os.

Signed-off-by: Yunfei Dong 
---
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c  | 144 --
 1 file changed, 94 insertions(+), 50 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index ab922e8d2d37..3639beac20cb 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -184,6 +184,74 @@ void mtk_vcodec_dec_set_default_params(struct 
mtk_vcodec_dec_ctx *ctx)
q_data->bytesperline[1] = q_data->coded_width;
 }
 
+static int mtk_vcodec_dec_init_pic_info(struct mtk_vcodec_dec_ctx *ctx, enum 
v4l2_buf_type type)
+{
+   const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata;
+   struct mtk_q_data *q_data;
+   int ret;
+
+   if (!ctx->current_codec)
+   return 0;
+
+   if (V4L2_TYPE_IS_OUTPUT(type) && ctx->state == MTK_STATE_FREE) {
+   q_data = mtk_vdec_get_q_data(ctx, 
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+   if (!q_data)
+   return -EINVAL;
+
+   ret = vdec_if_init(ctx, q_data->fmt->fourcc);
+   if (ret) {
+   mtk_v4l2_vdec_err(ctx, "[%d]: vdec_if_init() fail 
ret=%d",
+ ctx->id, ret);
+   return -EINVAL;
+   }
+   ctx->state = MTK_STATE_INIT;
+   }
+
+   if (!dec_pdata->uses_stateless_api)
+   return 0;
+
+   /*
+* If get pic info fail, need to use the default pic info params, or
+* v4l2-compliance will fail
+*/
+   ret = vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, >picinfo);
+   if (ret) {
+   mtk_v4l2_vdec_err(ctx, "[%d]Error!! Get GET_PARAM_PICTURE_INFO 
Fail",
+ ctx->id);
+   }
+
+   ctx->last_decoded_picinfo = ctx->picinfo;
+
+   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1) {
+   ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
+   ctx->picinfo.fb_sz[0] +
+   ctx->picinfo.fb_sz[1];
+   ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] =
+   ctx->picinfo.buf_w;
+   } else {
+   if (ctx->is_secure_playback)
+   ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
+   ctx->picinfo.fb_sz[0] + ctx->picinfo.fb_sz[1];
+   else
+   ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] = 
ctx->picinfo.fb_sz[0];
+
+   ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] = 
ctx->picinfo.buf_w;
+   ctx->q_data[MTK_Q_DATA_DST].sizeimage[1] = 
ctx->picinfo.fb_sz[1];
+   ctx->q_data[MTK_Q_DATA_DST].bytesperline[1] = 
ctx->picinfo.buf_w;
+   }
+
+   ctx->q_data[MTK_Q_DATA_DST].coded_width = ctx->picinfo.buf_w;
+   ctx->q_data[MTK_Q_DATA_DST].coded_height = ctx->picinfo.buf_h;
+   mtk_v4l2_vdec_dbg(2, ctx,
+ "[%d] init() plane:%d wxh=%dx%d pic wxh=%dx%d 
sz=0x%x_0x%x",
+ ctx->id, q_data->fmt->num_planes,
+ ctx->picinfo.buf_w, ctx->picinfo.buf_h,
+ ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+ ctx->q_data[MTK_Q_DATA_DST].sizeimage[0],
+ ctx->q_data[MTK_Q_DATA_DST].sizeimage[1]);
+   return 0;
+}
+
 static int vidioc_vdec_qbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
 {
@@ -479,17 +547,7 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv,
ctx->ycbcr_enc = pix_mp->ycbcr_enc;
ctx->quantization = pix_mp->quantization;
ctx->xfer_func = pix_mp->xfer_func;
-
ctx->current_codec = fmt->fourcc;
-   if (ctx->state == MTK_STATE_FREE) {
-   ret = vdec_if_init(ctx, q_data->fmt->fourcc);
-   if (ret) {
-   mtk_v4l2_vdec_err(ctx, "[%d]: vdec_if_init() 
fail ret=%d",
- ctx->id, ret);
-   return -EINVAL;
-   }
-   ctx->state = MTK_STATE_INIT;
-   }
} else {
ctx->capture_fourcc = fmt->fourcc;
}
@@ -502,46 +560,11 @@ static int vidioc_vdec_s_fmt(struct file *file, void 
*priv,
ctx->picinfo.pic_w = pix_mp->width;
ctx->

[PATCH v3,15/21] media: mediatek: vcodec: Add one plane format

2023-12-06 Thread Yunfei Dong
Adding capture formats to support V4L2_PIX_FMT_MS21. This format has
one plane and only be used for secure video playback at current period.

Signed-off-by: Yunfei Dong 
---
 .../platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c| 4 +++-
 .../mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c   | 9 -
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index ba742f0e391d..604fdc8ee3ce 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -49,7 +49,9 @@ static bool mtk_vdec_get_cap_fmt(struct mtk_vcodec_dec_ctx 
*ctx, int format_inde
num_frame_count++;
}
 
-   if (num_frame_count == 1 || (!ctx->is_10bit_bitstream && fmt->fourcc == 
V4L2_PIX_FMT_MM21))
+   if ((!ctx->is_10bit_bitstream && fmt->fourcc == V4L2_PIX_FMT_MM21) ||
+   (ctx->is_secure_playback && fmt->fourcc == V4L2_PIX_FMT_MS21) ||
+   num_frame_count == 1)
return true;
 
q_data = >q_data[MTK_Q_DATA_SRC];
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index d54b3833790d..cc42c942eb8a 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -229,7 +229,7 @@ static const struct mtk_stateless_control 
mtk_stateless_controls[] = {
 
 #define NUM_CTRLS ARRAY_SIZE(mtk_stateless_controls)
 
-static struct mtk_video_fmt mtk_video_formats[9];
+static struct mtk_video_fmt mtk_video_formats[10];
 
 static struct mtk_video_fmt default_out_format;
 static struct mtk_video_fmt default_cap_format;
@@ -770,6 +770,11 @@ static void mtk_vcodec_add_formats(unsigned int fourcc,
mtk_video_formats[count_formats].type = MTK_FMT_FRAME;
mtk_video_formats[count_formats].num_planes = 2;
break;
+   case V4L2_PIX_FMT_MS21:
+   mtk_video_formats[count_formats].fourcc = fourcc;
+   mtk_video_formats[count_formats].type = MTK_FMT_FRAME;
+   mtk_video_formats[count_formats].num_planes = 1;
+   break;
default:
mtk_v4l2_vdec_err(ctx, "Can not add unsupported format type");
return;
@@ -798,6 +803,8 @@ static void mtk_vcodec_get_supported_formats(struct 
mtk_vcodec_dec_ctx *ctx)
cap_format_count++;
}
if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_MM21) {
+   mtk_vcodec_add_formats(V4L2_PIX_FMT_MS21, ctx);
+   cap_format_count++;
mtk_vcodec_add_formats(V4L2_PIX_FMT_MM21, ctx);
cap_format_count++;
}
-- 
2.18.0



[PATCH v3, 18/21] media: medkatek: vcodec: remove parse nal_info in kernel

2023-12-06 Thread Yunfei Dong
The hardware can parse syntax to get nal_info, needn't to use cpu.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/vdec/vdec_h264_req_multi_if.c| 13 ++---
 1 file changed, 2 insertions(+), 11 deletions(-)

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 a1a68487131c..2dfb3043493e 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
@@ -645,11 +645,10 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, 
struct mtk_vcodec_mem *bs,
struct vdec_h264_slice_inst *inst = h_vdec;
struct vdec_vpu_inst *vpu = >vpu;
struct mtk_video_dec_buf *src_buf_info;
-   int nal_start_idx, err, timeout = 0;
+   int err, timeout = 0;
unsigned int data[2];
struct vdec_lat_buf *lat_buf;
struct vdec_h264_slice_share_info *share_info;
-   unsigned char *buf;
 
if (vdec_msg_queue_init(>ctx->msg_queue, inst->ctx,
vdec_h264_slice_core_decode,
@@ -673,14 +672,6 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct 
mtk_vcodec_mem *bs,
share_info = lat_buf->private_data;
src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer);
 
-   buf = (unsigned char *)bs->va;
-   nal_start_idx = mtk_vdec_h264_find_start_code(buf, bs->size);
-   if (nal_start_idx < 0) {
-   err = -EINVAL;
-   goto err_free_fb_out;
-   }
-
-   inst->vsi->dec.nal_info = buf[nal_start_idx];
lat_buf->src_buf_req = src_buf_info->m2m_buf.vb.vb2_buf.req_obj.req;
v4l2_m2m_buf_copy_metadata(_buf_info->m2m_buf.vb, 
_buf->ts_info, true);
 
@@ -689,7 +680,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct 
mtk_vcodec_mem *bs,
goto err_free_fb_out;
 
if (!inst->ctx->is_secure_playback)
-   vdec_h264_insert_startcode(inst->ctx->dev, buf, >size,
+   vdec_h264_insert_startcode(inst->ctx->dev, bs->va, >size,
   _info->h264_slice_params.pps);
 
*res_chg = inst->resolution_changed;
-- 
2.18.0



[PATCH v3, 12/21] media: mediatek: vcodec: add interface to allocate/free secure memory

2023-12-06 Thread Yunfei Dong
Need to call dma heap interface to allocate/free secure memory when playing
secure video.

Signed-off-by: Yunfei Dong 
---
 .../media/platform/mediatek/vcodec/Kconfig|   1 +
 .../mediatek/vcodec/common/mtk_vcodec_util.c  | 122 +-
 .../mediatek/vcodec/common/mtk_vcodec_util.h  |   3 +
 3 files changed, 123 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/Kconfig 
b/drivers/media/platform/mediatek/vcodec/Kconfig
index bc8292232530..707865703e61 100644
--- a/drivers/media/platform/mediatek/vcodec/Kconfig
+++ b/drivers/media/platform/mediatek/vcodec/Kconfig
@@ -17,6 +17,7 @@ config VIDEO_MEDIATEK_VCODEC
depends on VIDEO_MEDIATEK_VPU || !VIDEO_MEDIATEK_VPU
depends on MTK_SCP || !MTK_SCP
depends on MTK_SMI || (COMPILE_TEST && MTK_SMI=n)
+   depends on DMABUF_HEAPS
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
select VIDEO_MEDIATEK_VCODEC_VPU if VIDEO_MEDIATEK_VPU
diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c 
b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c
index 9ce34a3b5ee6..2c44747f77a0 100644
--- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c
+++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c
@@ -5,9 +5,11 @@
 *  Tiffany Lin 
 */
 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "../decoder/mtk_vcodec_dec_drv.h"
 #include "../encoder/mtk_vcodec_enc_drv.h"
@@ -45,7 +47,7 @@ int mtk_vcodec_write_vdecsys(struct mtk_vcodec_dec_ctx *ctx, 
unsigned int reg,
 }
 EXPORT_SYMBOL(mtk_vcodec_write_vdecsys);
 
-int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem *mem)
+static int mtk_vcodec_mem_alloc_nor(void *priv, struct mtk_vcodec_mem *mem)
 {
enum mtk_instance_type inst_type = *((unsigned int *)priv);
struct platform_device *plat_dev;
@@ -76,9 +78,71 @@ int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem 
*mem)
 
return 0;
 }
-EXPORT_SYMBOL(mtk_vcodec_mem_alloc);
 
-void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem *mem)
+static int mtk_vcodec_mem_alloc_sec(struct mtk_vcodec_dec_ctx *ctx, struct 
mtk_vcodec_mem *mem)
+{
+   struct device *dev = >dev->plat_dev->dev;
+   struct dma_buf *dma_buffer;
+   struct dma_heap *vdec_heap;
+   struct dma_buf_attachment *attach;
+   struct sg_table *sgt;
+   unsigned long size = mem->size;
+   int ret = 0;
+
+   if (!size)
+   return -EINVAL;
+
+   vdec_heap = dma_heap_find("mtk_svp");
+   if (!vdec_heap) {
+   mtk_v4l2_vdec_err(ctx, "dma heap find failed!");
+   return -EPERM;
+   }
+
+   dma_buffer = dma_heap_buffer_alloc(vdec_heap, size, 
DMA_HEAP_VALID_FD_FLAGS,
+  DMA_HEAP_VALID_HEAP_FLAGS);
+   if (IS_ERR_OR_NULL(dma_buffer)) {
+   mtk_v4l2_vdec_err(ctx, "dma heap alloc size=0x%lx failed!", 
size);
+   return PTR_ERR(dma_buffer);
+   }
+
+   attach = dma_buf_attach(dma_buffer, dev);
+   if (IS_ERR_OR_NULL(attach)) {
+   mtk_v4l2_vdec_err(ctx, "dma attach size=0x%lx failed!", size);
+   ret = PTR_ERR(attach);
+   goto err_attach;
+   }
+
+   sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+   if (IS_ERR_OR_NULL(sgt)) {
+   mtk_v4l2_vdec_err(ctx, "dma map attach size=0x%lx failed!", 
size);
+   ret = PTR_ERR(sgt);
+   goto err_sgt;
+   }
+
+   mem->va = dma_buffer;
+   mem->dma_addr = (dma_addr_t)sg_dma_address((sgt)->sgl);
+
+   if (!mem->va || !mem->dma_addr) {
+   mtk_v4l2_vdec_err(ctx, "dma buffer size=0x%lx failed!", size);
+   ret = -EPERM;
+   goto err_addr;
+   }
+
+   mem->attach = attach;
+   mem->sgt = sgt;
+
+   return 0;
+err_addr:
+   dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+err_sgt:
+   dma_buf_detach(dma_buffer, attach);
+err_attach:
+   dma_buf_put(dma_buffer);
+
+   return ret;
+}
+
+static void mtk_vcodec_mem_free_nor(void *priv, struct mtk_vcodec_mem *mem)
 {
enum mtk_instance_type inst_type = *((unsigned int *)priv);
struct platform_device *plat_dev;
@@ -111,6 +175,57 @@ void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem 
*mem)
mem->dma_addr = 0;
mem->size = 0;
 }
+
+static void mtk_vcodec_mem_free_sec(struct mtk_vcodec_mem *mem)
+{
+   if (mem->sgt)
+   dma_buf_unmap_attachment(mem->attach, mem->sgt, 
DMA_BIDIRECTIONAL);
+   dma_buf_detach((struct dma_buf *)mem->va, mem->attach);
+   dma_buf_put((struct dma_buf *)mem->va);
+
+   mem->attach = NULL;
+   mem->sgt = NULL;
+   mem->va = NULL;
+   mem->dma_addr

[PATCH v3, 17/21] media: medkatek: vcodec: re-construct h264 driver to support svp mode

2023-12-06 Thread Yunfei Dong
Need secure buffer size to convert secure handle to secure
pa in optee-os, re-construct the vsi struct to store each
secure buffer size.

Separate svp and normal wait interrupt condition for svp mode
waiting hardware interrupt in optee-os.

Signed-off-by: Yunfei Dong 
---
 .../decoder/vdec/vdec_h264_req_multi_if.c | 261 +++---
 .../mediatek/vcodec/decoder/vdec_msg_queue.c  |   9 +-
 2 files changed, 168 insertions(+), 102 deletions(-)

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 4967e0f0984d..a1a68487131c 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
@@ -60,14 +60,36 @@ struct vdec_h264_slice_lat_dec_param {
  * @crc:   Used to check whether hardware's status is right
  */
 struct vdec_h264_slice_info {
+   u64 wdma_end_addr_offset;
u16 nal_info;
u16 timeout;
-   u32 bs_buf_size;
-   u64 bs_buf_addr;
-   u64 y_fb_dma;
-   u64 c_fb_dma;
u64 vdec_fb_va;
u32 crc[8];
+   u32 reserved;
+};
+
+/*
+ * struct vdec_h264_slice_mem - memory address and size
+ */
+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
+ * @y:  current y buffer address info
+ * @c:  current c buffer address info
+ */
+struct vdec_h264_slice_fb {
+   struct vdec_h264_slice_mem y;
+   struct vdec_h264_slice_mem c;
 };
 
 /**
@@ -92,18 +114,16 @@ struct vdec_h264_slice_info {
  */
 struct vdec_h264_slice_vsi {
/* LAT dec addr */
-   u64 wdma_err_addr;
-   u64 wdma_start_addr;
-   u64 wdma_end_addr;
-   u64 slice_bc_start_addr;
-   u64 slice_bc_end_addr;
-   u64 row_info_start_addr;
-   u64 row_info_end_addr;
-   u64 trans_start;
-   u64 trans_end;
-   u64 wdma_end_addr_offset;
+   struct vdec_h264_slice_mem bs;
+   struct vdec_h264_slice_fb fb;
 
-   u64 mv_buf_dma[H264_MAX_MV_NUM];
+   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 dec;
struct vdec_h264_slice_lat_dec_param h264_slice_params;
 };
@@ -392,6 +412,100 @@ static void vdec_h264_slice_get_crop_info(struct 
vdec_h264_slice_inst *inst,
   cr->left, cr->top, cr->width, cr->height);
 }
 
+static void vdec_h264_slice_setup_lat_buffer(struct vdec_h264_slice_inst *inst,
+struct mtk_vcodec_mem *bs,
+struct vdec_lat_buf *lat_buf)
+{
+   struct mtk_vcodec_mem *mem;
+   int i;
+
+   inst->vsi->bs.dma_addr = (u64)bs->dma_addr;
+   inst->vsi->bs.size = bs->size;
+
+   for (i = 0; i < H264_MAX_MV_NUM; i++) {
+   mem = >mv_buf[i];
+   inst->vsi->mv_buf_dma[i].dma_addr = mem->dma_addr;
+   inst->vsi->mv_buf_dma[i].size = mem->size;
+   }
+   inst->vsi->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
+   inst->vsi->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size;
+
+   inst->vsi->row_info.dma_addr = 0;
+   inst->vsi->row_info.size = 0;
+
+   inst->vsi->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr;
+   inst->vsi->err_map.size = lat_buf->wdma_err_addr.size;
+
+   inst->vsi->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr;
+   inst->vsi->slice_bc.size = lat_buf->slice_bc_addr.size;
+
+   inst->vsi->trans.dma_addr_end = inst->ctx->msg_queue.wdma_rptr_addr;
+   inst->vsi->trans.dma_addr = inst->ctx->msg_queue.wdma_wptr_addr;
+}
+
+static int vdec_h264_slice_setup_core_buffer(struct vdec_h264_slice_inst *inst,
+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");
+   return -EBUSY;
+   }
+
+   y_fb_dma = (u64)fb->base_y.dma_addr;
+   if

[PATCH v3, 16/21] media: medkatek: vcodec: support one plane capture buffer

2023-12-06 Thread Yunfei Dong
The capture buffer has two planes for format MM21, but user space only
allocate secure memory for plane[0], and the size is Y data + uv data.
The driver need to support one plane decoder for svp mode.

Signed-off-by: Yunfei Dong 
---
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c  |  7 -
 .../vcodec/decoder/mtk_vcodec_dec_stateless.c | 26 ++-
 .../decoder/vdec/vdec_h264_req_common.c   | 11 +++-
 .../mediatek/vcodec/decoder/vdec_drv_if.c |  4 +--
 4 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index 604fdc8ee3ce..ab922e8d2d37 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -653,7 +653,12 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv,
 * So we just return picinfo yet, and update picinfo in
 * stop_streaming hook function
 */
-   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0];
+
+   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1)
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0] + 
ctx->picinfo.fb_sz[1];
+   else
+   q_data->sizeimage[0] = ctx->picinfo.fb_sz[0];
+
q_data->sizeimage[1] = ctx->picinfo.fb_sz[1];
q_data->bytesperline[0] = ctx->last_decoded_picinfo.buf_w;
q_data->bytesperline[1] = ctx->last_decoded_picinfo.buf_w;
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index cc42c942eb8a..707ed57a412e 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -285,14 +285,14 @@ static struct vdec_fb *vdec_get_cap_buffer(struct 
mtk_vcodec_dec_ctx *ctx)
framebuf = container_of(vb2_v4l2, struct mtk_video_dec_buf, m2m_buf.vb);
 
pfb = >frame_buffer;
-   pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0);
+   if (!ctx->is_secure_playback)
+   pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0);
pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
pfb->base_y.size = ctx->q_data[MTK_Q_DATA_DST].sizeimage[0];
 
-   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2) {
+   if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2 && 
!ctx->is_secure_playback) {
pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1);
-   pfb->base_c.dma_addr =
-   vb2_dma_contig_plane_dma_addr(dst_buf, 1);
+   pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 
1);
pfb->base_c.size = ctx->q_data[MTK_Q_DATA_DST].sizeimage[1];
}
mtk_v4l2_vdec_dbg(1, ctx,
@@ -339,16 +339,18 @@ static void mtk_vdec_worker(struct work_struct *work)
mtk_v4l2_vdec_dbg(3, ctx, "[%d] (%d) id=%d, vb=%p", ctx->id,
  vb2_src->vb2_queue->type, vb2_src->index, vb2_src);
 
-   bs_src->va = vb2_plane_vaddr(vb2_src, 0);
-   bs_src->dma_addr = vb2_dma_contig_plane_dma_addr(vb2_src, 0);
-   bs_src->size = (size_t)vb2_src->planes[0].bytesused;
-   if (!bs_src->va) {
-   v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
-   mtk_v4l2_vdec_err(ctx, "[%d] id=%d source buffer is NULL", 
ctx->id,
- vb2_src->index);
-   return;
+   if (!ctx->is_secure_playback) {
+   bs_src->va = vb2_plane_vaddr(vb2_src, 0);
+   if (!bs_src->va) {
+   v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+   mtk_v4l2_vdec_err(ctx, "[%d] id=%d source buffer is 
NULL", ctx->id,
+ vb2_src->index);
+   return;
+   }
}
 
+   bs_src->dma_addr = vb2_dma_contig_plane_dma_addr(vb2_src, 0);
+   bs_src->size = (size_t)vb2_src->planes[0].bytesused;
mtk_v4l2_vdec_dbg(3, ctx, "[%d] Bitstream VA=%p DMA=%pad Size=%zx 
vb=%p",
  ctx->id, bs_src->va, _src->dma_addr, bs_src->size, 
vb2_src);
/* Apply request controls. */
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c
index 5ca20d75dc8e..2a57e689ec07 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c
+++ b/drivers/med

[PATCH v3, 05/21] dma-buf: heaps: Deduplicate docs and adopt common format

2023-12-06 Thread Yunfei Dong
From: "T.J. Mercier" 

The docs for dma_heap_get_name were incorrect, and since they were
duplicated in the header they were wrong there too.

The docs formatting was inconsistent so I tried to make it more
consistent across functions since I'm already in here doing cleanup.

Remove multiple unused includes and alphabetize.

Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Just add a comment for "priv" to mute build warning]
Signed-off-by: Yunfei Dong 
---
 drivers/dma-buf/dma-heap.c | 27 +++
 include/linux/dma-heap.h   | 21 +
 2 files changed, 16 insertions(+), 32 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 84ae708fafe7..22f6c193db0d 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -7,17 +7,15 @@
  */
 
 #include 
-#include 
 #include 
 #include 
+#include 
 #include 
-#include 
 #include 
-#include 
 #include 
-#include 
 #include 
-#include 
+#include 
+#include 
 #include 
 
 #define DEVNAME "dma_heap"
@@ -28,9 +26,10 @@
  * struct dma_heap - represents a dmabuf heap in the system
  * @name:  used for debugging/device-node name
  * @ops:   ops struct for this heap
- * @heap_devt  heap device node
- * @list   list head connecting to list of heaps
- * @heap_cdev  heap char device
+ * @priv:  private data for this heap
+ * @heap_devt: heap device node
+ * @list:  list head connecting to list of heaps
+ * @heap_cdev: heap char device
  *
  * Represents a heap of memory from which buffers can be made.
  */
@@ -193,11 +192,11 @@ static const struct file_operations dma_heap_fops = {
 };
 
 /**
- * dma_heap_get_drvdata() - get per-subdriver data for the heap
+ * dma_heap_get_drvdata - get per-heap driver data
  * @heap: DMA-Heap to retrieve private data for
  *
  * Returns:
- * The per-subdriver data for the heap.
+ * The per-heap data for the heap.
  */
 void *dma_heap_get_drvdata(struct dma_heap *heap)
 {
@@ -205,8 +204,8 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
 }
 
 /**
- * dma_heap_get_name() - get heap name
- * @heap: DMA-Heap to retrieve private data for
+ * dma_heap_get_name - get heap name
+ * @heap: DMA-Heap to retrieve the name of
  *
  * Returns:
  * The char* for the heap name.
@@ -216,6 +215,10 @@ const char *dma_heap_get_name(struct dma_heap *heap)
return heap->name;
 }
 
+/**
+ * dma_heap_add - adds a heap to dmabuf heaps
+ * @exp_info: information needed to register this heap
+ */
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
 {
struct dma_heap *heap, *h, *err_ret;
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index 0c05561cad6e..fbe86ec889a8 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -9,14 +9,13 @@
 #ifndef _DMA_HEAPS_H
 #define _DMA_HEAPS_H
 
-#include 
 #include 
 
 struct dma_heap;
 
 /**
  * struct dma_heap_ops - ops to operate on a given heap
- * @allocate:  allocate dmabuf and return struct dma_buf ptr
+ * @allocate:  allocate dmabuf and return struct dma_buf ptr
  *
  * allocate returns dmabuf on success, ERR_PTR(-errno) on error.
  */
@@ -41,28 +40,10 @@ struct dma_heap_export_info {
void *priv;
 };
 
-/**
- * dma_heap_get_drvdata() - get per-heap driver data
- * @heap: DMA-Heap to retrieve private data for
- *
- * Returns:
- * The per-heap data for the heap.
- */
 void *dma_heap_get_drvdata(struct dma_heap *heap);
 
-/**
- * dma_heap_get_name() - get heap name
- * @heap: DMA-Heap to retrieve private data for
- *
- * Returns:
- * The char* for the heap name.
- */
 const char *dma_heap_get_name(struct dma_heap *heap);
 
-/**
- * dma_heap_add - adds a heap to dmabuf heaps
- * @exp_info:  information needed to register this heap
- */
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
 #endif /* _DMA_HEAPS_H */
-- 
2.18.0



[PATCH v3, 13/21] media: mediatek: vcodec: using shared memory as vsi address

2023-12-06 Thread Yunfei Dong
The vsi buffer is allocated by tee share memory for svp mode, need to
use the share memory as the vsi address to store vsi data.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/vdec/vdec_h264_req_multi_if.c | 9 +++--
 .../media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c | 8 ++--
 2 files changed, 13 insertions(+), 4 deletions(-)

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 0e741e0dc8ba..4967e0f0984d 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
@@ -417,8 +417,13 @@ static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx 
*ctx)
 
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);
+   if (ctx->is_secure_playback)
+   inst->vsi_core =
+   
mtk_vcodec_dec_get_shm_buffer_va(ctx->dev->optee_private, MTK_VDEC_CORE,
+OPTEE_DATA_INDEX);
+   else
+   inst->vsi_core =
+   (struct vdec_h264_slice_vsi *)(((char *)inst->vpu.vsi) 
+ vsi_size);
inst->resolution_changed = true;
inst->realloc_mv_buf = true;
 
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
index 5336769a3fb5..5c31641e9abe 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
@@ -18,8 +18,12 @@ static void handle_init_ack_msg(const struct 
vdec_vpu_ipi_init_ack *msg)
 
/* mapping VPU address to kernel virtual address */
/* the content in vsi is initialized to 0 in VPU */
-   vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->fw_handler,
-msg->vpu_inst_addr);
+   if (vpu->ctx->is_secure_playback)
+   vpu->vsi = 
mtk_vcodec_dec_get_shm_buffer_va(vpu->ctx->dev->optee_private,
+   MTK_VDEC_LAT0, 
OPTEE_DATA_INDEX);
+   else
+   vpu->vsi = mtk_vcodec_fw_map_dm_addr(vpu->ctx->dev->fw_handler,
+msg->vpu_inst_addr);
vpu->inst_addr = msg->vpu_inst_addr;
 
mtk_vdec_debug(vpu->ctx, "- vpu_inst_addr = 0x%x", vpu->inst_addr);
-- 
2.18.0



[PATCH v3, 11/21] media: mediatek: vcodec: initialize msg and vsi information

2023-12-06 Thread Yunfei Dong
Need to initialize msg and vsi information before sending to optee-os, then
calling optee invoke command to send the information to optee-os.

For the optee communication interface is different with scp, using
flag to separate them.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_drv.h   |  2 +
 .../mediatek/vcodec/decoder/vdec_vpu_if.c | 49 ---
 .../mediatek/vcodec/decoder/vdec_vpu_if.h |  4 ++
 3 files changed, 49 insertions(+), 6 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 b1a2107f2a1e..47eca245dc07 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
@@ -175,6 +175,7 @@ struct mtk_vcodec_dec_pdata {
  * @vpu_inst: vpu instance pointer.
  *
  * @is_10bit_bitstream: set to true if it's 10bit bitstream
+ * @is_secure_playback: Secure Video Playback (SVP) mode
  */
 struct mtk_vcodec_dec_ctx {
enum mtk_instance_type type;
@@ -220,6 +221,7 @@ struct mtk_vcodec_dec_ctx {
void *vpu_inst;
 
bool is_10bit_bitstream;
+   bool is_secure_playback;
 };
 
 /**
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c 
b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
index 82e57ae983d5..5336769a3fb5 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
@@ -148,7 +148,10 @@ static void vpu_dec_ipi_handler(void *data, unsigned int 
len, void *priv)
 
 static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, void *msg, int len)
 {
-   int err, id, msgid;
+   struct mtk_vdec_optee_data_to_shm *optee_data;
+   int data_size, id, hw_id, msgid;
+   void *ack_msg, *data_msg;
+   int err;
 
msgid = *(uint32_t *)msg;
mtk_vdec_debug(vpu->ctx, "id=%X", msgid);
@@ -158,16 +161,46 @@ static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, 
void *msg, int len)
 
if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) {
if (msgid == AP_IPIMSG_DEC_CORE ||
-   msgid == AP_IPIMSG_DEC_CORE_END)
+   msgid == AP_IPIMSG_DEC_CORE_END) {
+   optee_data = >core_optee_info;
id = vpu->core_id;
-   else
+   } else {
+   optee_data = >lat_optee_info;
id = vpu->id;
+   }
} else {
+   optee_data = >lat_optee_info;
id = vpu->id;
}
 
-   err = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, id, msg,
-len, 2000);
+   if (!vpu->ctx->is_secure_playback) {
+   err = mtk_vcodec_fw_ipi_send(vpu->ctx->dev->fw_handler, id, 
msg, len, 2000);
+   } else {
+   hw_id = (id == SCP_IPI_VDEC_LAT) ? MTK_VDEC_LAT0 : 
MTK_VDEC_CORE;
+
+   mtk_vcodec_dec_optee_set_data(optee_data, msg, len, 
OPTEE_MSG_INDEX);
+
+   /* There is no need to copy the data (VSI) message to shared 
memory,
+* but we still need to set the buffer size to a non-zero value.
+*/
+   if (msgid == AP_IPIMSG_DEC_CORE || msgid == 
AP_IPIMSG_DEC_START) {
+   data_msg = 
mtk_vcodec_dec_get_shm_buffer_va(vpu->ctx->dev->optee_private,
+   hw_id, 
OPTEE_DATA_INDEX);
+   data_size = 
mtk_vcodec_dec_get_shm_buffer_size(vpu->ctx->dev->optee_private,
+  hw_id, 
OPTEE_DATA_INDEX);
+   mtk_vcodec_dec_optee_set_data(optee_data, data_msg, 
data_size,
+ OPTEE_DATA_INDEX);
+   }
+
+   err = 
mtk_vcodec_dec_optee_invokd_cmd(vpu->ctx->dev->optee_private,
+ hw_id, optee_data);
+   vpu->failure = err;
+
+   ack_msg = 
mtk_vcodec_dec_get_shm_buffer_va(vpu->ctx->dev->optee_private, hw_id,
+  OPTEE_MSG_INDEX);
+   vpu_dec_ipi_handler(ack_msg, 0, vpu->ctx->dev);
+   }
+
if (err) {
mtk_vdec_err(vpu->ctx, "send fail vpu_id=%d msg_id=%X 
status=%d",
 id, msgid, err);
@@ -213,7 +246,11 @@ int vpu_dec_init(struct vdec_vpu_inst *vpu)
return err;
}
 
-   if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) {
+   /* Using tee interface to communicate with op

[PATCH v3, 14/21] media: mediatek: vcodec: Add capture format to support one plane memory

2023-12-06 Thread Yunfei Dong
Define one uncompressed capture format V4L2_PIX_FMT_MS21 in order to
support one plane memory. The buffer size is luma + chroma, luma is
stored at the start and chrome is stored at the end.

Signed-off-by: Yunfei Dong 
---
 Documentation/userspace-api/media/v4l/pixfmt-reserved.rst | 8 
 drivers/media/v4l2-core/v4l2-common.c | 2 ++
 drivers/media/v4l2-core/v4l2-ioctl.c  | 1 +
 include/uapi/linux/videodev2.h| 1 +
 4 files changed, 12 insertions(+)

diff --git a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst 
b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
index 886ba7b08d6b..6ec899649d50 100644
--- a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
+++ b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
@@ -295,6 +295,14 @@ please make a proposal on the linux-media mailing list.
   - Compressed format used by Nuvoton NPCM video driver. This format is
 defined in Remote Framebuffer Protocol (RFC 6143, chapter 7.7.4 Hextile
 Encoding).
+* .. _V4L2-PIX-FMT-MS21:
+
+  - ``V4L2_PIX_FMT_MS21``
+  - 'MS21'
+  - This format has one plane, luma and chroma are stored in a contiguous
+memory. Luma pixel in 16x32 tiles at the start, chroma pixel in 16x16
+tiles at the end. The image height must be aligned with 32 and the 
image
+width must be aligned with 16.
 .. raw:: latex
 
 \normalsize
diff --git a/drivers/media/v4l2-core/v4l2-common.c 
b/drivers/media/v4l2-core/v4l2-common.c
index e9e7e70fa24e..85aa3319cbc6 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -269,6 +269,8 @@ const struct v4l2_format_info *v4l2_format_info(u32 format)
  .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
{ .format = V4L2_PIX_FMT_MT2110R, .pixel_enc = 
V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, 
.bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2,
  .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
+   { .format = V4L2_PIX_FMT_MS21,.pixel_enc = 
V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, 
.bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2,
+ .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }},
 
/* YUV planar formats */
{ .format = V4L2_PIX_FMT_NV12,.pixel_enc = 
V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, 
.bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 },
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 33076af4dfdb..26ffe4d1c28f 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1511,6 +1511,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_MT2110T:  descr = "Mediatek 10bit Tile 
Mode"; break;
case V4L2_PIX_FMT_MT2110R:  descr = "Mediatek 10bit Raster 
Mode"; break;
case V4L2_PIX_FMT_HEXTILE:  descr = "Hextile Compressed 
Format"; break;
+   case V4L2_PIX_FMT_MS21: descr = "Mediatek One Plane 
Format"; break;
default:
if (fmt->description[0])
return;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 570b11552818..6be0d0e35077 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -798,6 +798,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_MM21 v4l2_fourcc('M', 'M', '2', '1') /* Mediatek 
8-bit block mode, two non-contiguous planes */
 #define V4L2_PIX_FMT_MT2110T  v4l2_fourcc('M', 'T', '2', 'T') /* Mediatek 
10-bit block tile mode */
 #define V4L2_PIX_FMT_MT2110R  v4l2_fourcc('M', 'T', '2', 'R') /* Mediatek 
10-bit block raster mode */
+#define V4L2_PIX_FMT_MS21 v4l2_fourcc('M', 'S', '2', '1') /* Mediatek 
8-bit block mode with one plane */
 #define V4L2_PIX_FMT_INZI v4l2_fourcc('I', 'N', 'Z', 'I') /* Intel Planar 
Greyscale 10-bit and Depth 16-bit */
 #define V4L2_PIX_FMT_CNF4 v4l2_fourcc('C', 'N', 'F', '4') /* Intel 4-bit 
packed depth confidence information */
 #define V4L2_PIX_FMT_HI240v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit 
dithered RGB */
-- 
2.18.0



[PATCH v3, 08/21] media: mediatek: vcodec: add tee client interface to communiate with optee-os

2023-12-06 Thread Yunfei Dong
Open tee context to initialize the environment in order to communication
with optee-os, then open tee session as the communication pipeline for
lat and core to send data for hardware decode.

Signed-off-by: Yunfei Dong 
---
 .../platform/mediatek/vcodec/decoder/Makefile |   1 +
 .../vcodec/decoder/mtk_vcodec_dec_drv.h   |   5 +
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 165 ++
 .../vcodec/decoder/mtk_vcodec_dec_optee.h |  73 
 4 files changed, 244 insertions(+)
 create mode 100644 
drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
 create mode 100644 
drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/Makefile 
b/drivers/media/platform/mediatek/vcodec/decoder/Makefile
index 904cd22def84..1624933dfd5e 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/Makefile
+++ b/drivers/media/platform/mediatek/vcodec/decoder/Makefile
@@ -21,5 +21,6 @@ mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
mtk_vcodec_dec_stateful.o \
mtk_vcodec_dec_stateless.o \
mtk_vcodec_dec_pm.o \
+   mtk_vcodec_dec_optee.o \
 
 mtk-vcodec-dec-hw-y := mtk_vcodec_dec_hw.o
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 849b89dd205c..b1a2107f2a1e 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
@@ -11,6 +11,7 @@
 #include "../common/mtk_vcodec_dbgfs.h"
 #include "../common/mtk_vcodec_fw_priv.h"
 #include "../common/mtk_vcodec_util.h"
+#include "mtk_vcodec_dec_optee.h"
 #include "vdec_msg_queue.h"
 
 #define MTK_VCODEC_DEC_NAME"mtk-vcodec-dec"
@@ -261,6 +262,8 @@ struct mtk_vcodec_dec_ctx {
  * @dbgfs: debug log related information
  *
  * @chip_name: used to distinguish platforms and select the correct codec 
configuration values
+ *
+ * @optee_private: optee private data
  */
 struct mtk_vcodec_dec_dev {
struct v4l2_device v4l2_dev;
@@ -303,6 +306,8 @@ struct mtk_vcodec_dec_dev {
struct mtk_vcodec_dbgfs dbgfs;
 
enum mtk_vcodec_dec_chip_name chip_name;
+
+   struct mtk_vdec_optee_private *optee_private;
 };
 
 static inline struct mtk_vcodec_dec_ctx *fh_to_dec_ctx(struct v4l2_fh *fh)
diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
new file mode 100644
index ..38d9c1c1785a
--- /dev/null
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Yunfei Dong 
+ */
+
+#include "mtk_vcodec_dec_drv.h"
+#include "mtk_vcodec_dec_optee.h"
+
+/*
+ * Randomly generated, and must correspond to the GUID on the TA side.
+ */
+static const uuid_t mtk_vdec_lat_uuid =
+   UUID_INIT(0xBC50D971, 0xD4C9, 0x42C4,
+ 0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x90);
+
+static const uuid_t mtk_vdec_core_uuid =
+   UUID_INIT(0xBC50D971, 0xD4C9, 0x42C4,
+ 0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x91);
+
+/*
+ * Check whether this driver supports decoder TA in the TEE instance,
+ * represented by the params (ver/data) of this function.
+ */
+static int mtk_vcodec_dec_optee_match(struct tee_ioctl_version_data *ver_data, 
const void *not_used)
+{
+   if (ver_data->impl_id == TEE_IMPL_ID_OPTEE)
+   return 1;
+   else
+   return 0;
+}
+
+int mtk_vcodec_dec_optee_private_init(struct mtk_vcodec_dec_dev *vcodec_dev)
+{
+   vcodec_dev->optee_private = devm_kzalloc(_dev->plat_dev->dev,
+
sizeof(*vcodec_dev->optee_private),
+GFP_KERNEL);
+   if (!vcodec_dev->optee_private)
+   return -ENOMEM;
+
+   vcodec_dev->optee_private->vcodec_dev = vcodec_dev;
+
+   atomic_set(_dev->optee_private->tee_active_cnt, 0);
+   mutex_init(_dev->optee_private->tee_mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_private_init);
+
+static int mtk_vcodec_dec_optee_init_hw_info(struct mtk_vdec_optee_private 
*optee_private,
+enum mtk_vdec_hw_id hardware_index)
+{
+   struct device *dev = _private->vcodec_dev->plat_dev->dev;
+   struct tee_ioctl_open_session_arg session_arg;
+   struct mtk_vdec_optee_ca_info *ca_info;
+   int err = 0, session_func;
+
+   /* Open lat and core session with vdec TA. */
+   switch (hardware_index) {
+   case MTK_VDEC_LAT0:
+   export_uuid(session_arg.uuid, _vd

[PATCH v3,09/21] media: mediatek: vcodec: allocate tee share memory

2023-12-06 Thread Yunfei Dong
Allocate two share memory for each lat and core hardware used to share
information with optee-os. Msg buffer used to send ipi command and get ack
command with optee-os, data buffer used to store vsi information which
used for hardware decode.

Signed-off-by: Yunfei Dong 
---
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 80 ++-
 .../vcodec/decoder/mtk_vcodec_dec_optee.h | 32 
 2 files changed, 111 insertions(+), 1 deletion(-)

diff --git 
a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c 
b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
index 38d9c1c1785a..611fb0e56480 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.c
@@ -47,13 +47,69 @@ int mtk_vcodec_dec_optee_private_init(struct 
mtk_vcodec_dec_dev *vcodec_dev)
 }
 EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_private_init);
 
+static void mtk_vcodec_dec_optee_deinit_memref(struct mtk_vdec_optee_ca_info 
*ca_info,
+  enum mtk_vdec_optee_data_index 
data_index)
+{
+   tee_shm_free(ca_info->shm_memref[data_index].msg_shm);
+}
+
+static int mtk_vcodec_dec_optee_init_memref(struct tee_context *tee_vdec_ctx,
+   struct mtk_vdec_optee_ca_info 
*ca_info,
+   enum mtk_vdec_optee_data_index 
data_index)
+{
+   struct mtk_vdec_optee_shm_memref *shm_memref;
+   int alloc_size = 0, err = 0;
+   u64 shm_param_type = 0;
+   bool copy_buffer;
+
+   switch (data_index) {
+   case OPTEE_MSG_INDEX:
+   shm_param_type = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+   alloc_size = MTK_VDEC_OPTEE_MSG_SIZE;
+   copy_buffer = true;
+   break;
+   case OPTEE_DATA_INDEX:
+   shm_param_type = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+   alloc_size = MTK_VDEC_OPTEE_HW_SIZE;
+   copy_buffer = false;
+   break;
+   default:
+   pr_err(MTK_DBG_VCODEC_STR "tee invalid data_index: %d.\n", 
data_index);
+   return -EINVAL;
+   }
+
+   shm_memref = _info->shm_memref[data_index];
+
+   /* Allocate dynamic shared memory with decoder TA */
+   shm_memref->msg_shm_size = alloc_size;
+   shm_memref->param_type = shm_param_type;
+   shm_memref->copy_to_ta = copy_buffer;
+   shm_memref->msg_shm = tee_shm_alloc_kernel_buf(tee_vdec_ctx, 
shm_memref->msg_shm_size);
+   if (IS_ERR(shm_memref->msg_shm)) {
+   pr_err(MTK_DBG_VCODEC_STR "tee alloc buf fail: 
data_index:%d.\n", data_index);
+   return -ENOMEM;
+   }
+
+   shm_memref->msg_shm_ca_buf = tee_shm_get_va(shm_memref->msg_shm, 0);
+   if (IS_ERR(shm_memref->msg_shm_ca_buf)) {
+   pr_err(MTK_DBG_VCODEC_STR "tee get shm va fail: 
data_index:%d.\n", data_index);
+   err = PTR_ERR(shm_memref->msg_shm_ca_buf);
+   goto err_get_msg_va;
+   }
+
+   return err;
+err_get_msg_va:
+   tee_shm_free(shm_memref->msg_shm);
+   return err;
+}
+
 static int mtk_vcodec_dec_optee_init_hw_info(struct mtk_vdec_optee_private 
*optee_private,
 enum mtk_vdec_hw_id hardware_index)
 {
struct device *dev = _private->vcodec_dev->plat_dev->dev;
struct tee_ioctl_open_session_arg session_arg;
struct mtk_vdec_optee_ca_info *ca_info;
-   int err = 0, session_func;
+   int err, i, j, session_func;
 
/* Open lat and core session with vdec TA. */
switch (hardware_index) {
@@ -87,6 +143,24 @@ static int mtk_vcodec_dec_optee_init_hw_info(struct 
mtk_vdec_optee_private *opte
dev_dbg(dev, MTK_DBG_VCODEC_STR "open vdec tee session hw_id:%d 
session_id=%x.\n",
hardware_index, ca_info->vdec_session_id);
 
+   /* Allocate dynamic shared memory with decoder TA */
+   for (i = 0; i < OPTEE_MAX_INDEX; i++) {
+   err = 
mtk_vcodec_dec_optee_init_memref(optee_private->tee_vdec_ctx, ca_info, i);
+   if (err) {
+   dev_err(dev, MTK_DBG_VCODEC_STR "init vdec memref 
failed: %d.\n", i);
+   goto err_init_memref;
+   }
+   }
+
+   return err;
+err_init_memref:
+   if (i != 0) {
+   for (j = 0; j < i; j++)
+   mtk_vcodec_dec_optee_deinit_memref(ca_info, j);
+   }
+
+   tee_client_close_session(optee_private->tee_vdec_ctx, 
ca_info->vdec_session_id);
+
return err;
 }
 
@@ -94,12 +168,16 @@ static void mtk_vcodec_dec_optee_deinit_hw_info(struct 
mtk_vdec_optee_private *o
enum mtk_vdec_hw_id hw_id)
 {
struct mtk_

[PATCH v3,06/21] dma-heap: Add proper kref handling on dma-buf heaps

2023-12-06 Thread Yunfei Dong
From: John Stultz 

Add proper refcounting on the dma_heap structure.
While existing heaps are built-in, we may eventually
have heaps loaded from modules, and we'll need to be
able to properly handle the references to the heaps

Signed-off-by: John Stultz 
Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Just add comment for "minor" and "refcount"]
Signed-off-by: Yunfei Dong 
---
 drivers/dma-buf/dma-heap.c | 29 +
 include/linux/dma-heap.h   |  2 ++
 2 files changed, 31 insertions(+)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 22f6c193db0d..97025ee8500f 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -30,6 +31,7 @@
  * @heap_devt: heap device node
  * @list:  list head connecting to list of heaps
  * @heap_cdev: heap char device
+ * @refcount:  reference counter for this heap device
  *
  * Represents a heap of memory from which buffers can be made.
  */
@@ -40,6 +42,7 @@ struct dma_heap {
dev_t heap_devt;
struct list_head list;
struct cdev heap_cdev;
+   struct kref refcount;
 };
 
 static LIST_HEAD(heap_list);
@@ -240,6 +243,7 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
if (!heap)
return ERR_PTR(-ENOMEM);
 
+   kref_init(>refcount);
heap->name = exp_info->name;
heap->ops = exp_info->ops;
heap->priv = exp_info->priv;
@@ -304,6 +308,31 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
return err_ret;
 }
 
+static void dma_heap_release(struct kref *ref)
+{
+   struct dma_heap *heap = container_of(ref, struct dma_heap, refcount);
+   unsigned int minor = MINOR(heap->heap_devt);
+
+   mutex_lock(_list_lock);
+   list_del(>list);
+   mutex_unlock(_list_lock);
+
+   device_destroy(dma_heap_class, heap->heap_devt);
+   cdev_del(>heap_cdev);
+   xa_erase(_heap_minors, minor);
+
+   kfree(heap);
+}
+
+/**
+ * dma_heap_put - drops a reference to a dmabuf heap, potentially freeing it
+ * @heap: DMA-Heap whose reference count to decrement
+ */
+void dma_heap_put(struct dma_heap *heap)
+{
+   kref_put(>refcount, dma_heap_release);
+}
+
 static char *dma_heap_devnode(const struct device *dev, umode_t *mode)
 {
return kasprintf(GFP_KERNEL, "dma_heap/%s", dev_name(dev));
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index fbe86ec889a8..d57593f8a1bc 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -46,4 +46,6 @@ const char *dma_heap_get_name(struct dma_heap *heap);
 
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
+void dma_heap_put(struct dma_heap *heap);
+
 #endif /* _DMA_HEAPS_H */
-- 
2.18.0



[PATCH v3, 07/21] dma-heap: Provide accessors so that in-kernel drivers can allocate dmabufs from specific heaps

2023-12-06 Thread Yunfei Dong
From: John Stultz 

This allows drivers who don't want to create their own
DMA-BUF exporter to be able to allocate DMA-BUFs directly
from existing DMA-BUF Heaps.

There is some concern that the premise of DMA-BUF heaps is
that userland knows better about what type of heap memory
is needed for a pipeline, so it would likely be best for
drivers to import and fill DMA-BUFs allocated by userland
instead of allocating one themselves, but this is still
up for debate.

Signed-off-by: John Stultz 
Signed-off-by: T.J. Mercier 
Signed-off-by: Yong Wu 
[Yong: Fix the checkpatch alignment warning]
Signed-off-by: Yunfei Dong 
---
 drivers/dma-buf/dma-heap.c | 83 ++
 include/linux/dma-heap.h   |  6 +++
 2 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 97025ee8500f..6efe833a4b10 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -51,12 +51,24 @@ static dev_t dma_heap_devt;
 static struct class *dma_heap_class;
 static DEFINE_XARRAY_ALLOC(dma_heap_minors);
 
-static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
-unsigned int fd_flags,
-unsigned int heap_flags)
+/**
+ * dma_heap_buffer_alloc - Allocate dma-buf from a dma_heap
+ * @heap:  DMA-Heap to allocate from
+ * @len:   size to allocate in bytes
+ * @fd_flags:  flags to set on returned dma-buf fd
+ * @heap_flags: flags to pass to the dma heap
+ *
+ * This is for internal dma-buf allocations only. Free returned buffers with 
dma_buf_put().
+ */
+struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
+ unsigned int fd_flags,
+ unsigned int heap_flags)
 {
-   struct dma_buf *dmabuf;
-   int fd;
+   if (fd_flags & ~DMA_HEAP_VALID_FD_FLAGS)
+   return ERR_PTR(-EINVAL);
+
+   if (heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
+   return ERR_PTR(-EINVAL);
 
/*
 * Allocations from all heaps have to begin
@@ -64,9 +76,20 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, 
size_t len,
 */
len = PAGE_ALIGN(len);
if (!len)
-   return -EINVAL;
+   return ERR_PTR(-EINVAL);
+
+   return heap->ops->allocate(heap, len, fd_flags, heap_flags);
+}
+EXPORT_SYMBOL_GPL(dma_heap_buffer_alloc);
 
-   dmabuf = heap->ops->allocate(heap, len, fd_flags, heap_flags);
+static int dma_heap_bufferfd_alloc(struct dma_heap *heap, size_t len,
+  unsigned int fd_flags,
+  unsigned int heap_flags)
+{
+   struct dma_buf *dmabuf;
+   int fd;
+
+   dmabuf = dma_heap_buffer_alloc(heap, len, fd_flags, heap_flags);
if (IS_ERR(dmabuf))
return PTR_ERR(dmabuf);
 
@@ -104,15 +127,9 @@ static long dma_heap_ioctl_allocate(struct file *file, 
void *data)
if (heap_allocation->fd)
return -EINVAL;
 
-   if (heap_allocation->fd_flags & ~DMA_HEAP_VALID_FD_FLAGS)
-   return -EINVAL;
-
-   if (heap_allocation->heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
-   return -EINVAL;
-
-   fd = dma_heap_buffer_alloc(heap, heap_allocation->len,
-  heap_allocation->fd_flags,
-  heap_allocation->heap_flags);
+   fd = dma_heap_bufferfd_alloc(heap, heap_allocation->len,
+heap_allocation->fd_flags,
+heap_allocation->heap_flags);
if (fd < 0)
return fd;
 
@@ -205,6 +222,7 @@ void *dma_heap_get_drvdata(struct dma_heap *heap)
 {
return heap->priv;
 }
+EXPORT_SYMBOL_GPL(dma_heap_get_drvdata);
 
 /**
  * dma_heap_get_name - get heap name
@@ -217,6 +235,7 @@ const char *dma_heap_get_name(struct dma_heap *heap)
 {
return heap->name;
 }
+EXPORT_SYMBOL_GPL(dma_heap_get_name);
 
 /**
  * dma_heap_add - adds a heap to dmabuf heaps
@@ -307,6 +326,37 @@ struct dma_heap *dma_heap_add(const struct 
dma_heap_export_info *exp_info)
kfree(heap);
return err_ret;
 }
+EXPORT_SYMBOL_GPL(dma_heap_add);
+
+/**
+ * dma_heap_find - get the heap registered with the specified name
+ * @name: Name of the DMA-Heap to find
+ *
+ * Returns:
+ * The DMA-Heap with the provided name.
+ *
+ * NOTE: DMA-Heaps returned from this function MUST be released using
+ * dma_heap_put() when the user is done to enable the heap to be unloaded.
+ */
+struct dma_heap *dma_heap_find(const char *name)
+{
+   struct dma_heap *h;
+
+   mutex_lock(_list_lock);
+   list_for_each_entry(h, _list, list) {
+   if (!kref_get_unless_zero(>refcount))
+   continue;
+
+   if (!strcmp(h->name, name)) {
+ 

[PATCH v3, 03/21] v4l2: verify secure dmabufs are used in secure queue

2023-12-06 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Verfies in the dmabuf implementations that if the secure memory flag is
set for a queue that the dmabuf submitted to the queue is unmappable.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 drivers/media/common/videobuf2/videobuf2-dma-contig.c | 6 ++
 drivers/media/common/videobuf2/videobuf2-dma-sg.c | 6 ++
 2 files changed, 12 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c 
b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index 3d4fd4ef5310..ad58ef8dc231 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -710,6 +710,12 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
return -EINVAL;
}
 
+   /* verify the dmabuf is secure if we are in secure mode */
+   if (buf->vb->vb2_queue->secure_mem && sg_page(sgt->sgl)) {
+   pr_err("secure queue requires secure dma_buf");
+   return -EINVAL;
+   }
+
/* checking if dmabuf is big enough to store contiguous chunk */
contig_size = vb2_dc_get_contiguous_size(sgt);
if (contig_size < buf->size) {
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c 
b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
index 28f3fdfe23a2..55428c73c380 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
@@ -564,6 +564,12 @@ static int vb2_dma_sg_map_dmabuf(void *mem_priv)
return -EINVAL;
}
 
+   /* verify the dmabuf is secure if we are in secure mode */
+   if (buf->vb->vb2_queue->secure_mem && !sg_dma_secure(sgt->sgl)) {
+   pr_err("secure queue requires secure dma_buf");
+   return -EINVAL;
+   }
+
buf->dma_sgt = sgt;
buf->vaddr = NULL;
 
-- 
2.18.0



[PATCH v3,04/21] v4l: add documentation for secure memory flag

2023-12-06 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Adds documentation for V4L2_MEMORY_FLAG_SECURE.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 Documentation/userspace-api/media/v4l/buffer.rst | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Documentation/userspace-api/media/v4l/buffer.rst 
b/Documentation/userspace-api/media/v4l/buffer.rst
index 52bbee81c080..a5a7d1c72d53 100644
--- a/Documentation/userspace-api/media/v4l/buffer.rst
+++ b/Documentation/userspace-api/media/v4l/buffer.rst
@@ -696,7 +696,7 @@ enum v4l2_memory
 
 .. _memory-flags:
 
-Memory Consistency Flags
+Memory Flags
 
 
 .. raw:: latex
@@ -728,6 +728,12 @@ Memory Consistency Flags
only if the buffer is used for :ref:`memory mapping ` I/O and the
queue reports the :ref:`V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS
` capability.
+* .. _`V4L2-MEMORY-FLAG-SECURE`:
+
+  - ``V4L2_MEMORY_FLAG_SECURE``
+  - 0x0002
+  - DMA bufs passed into the queue will be validated to ensure they were
+   allocated from a secure dma-heap.
 
 .. raw:: latex
 
-- 
2.18.0



[PATCH v3,02/21] v4l2: handle secure memory flags in queue setup

2023-12-06 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Validates the secure memory flags when setting up a queue and ensures
the queue has the proper capability.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 .../media/common/videobuf2/videobuf2-core.c   | 23 +
 .../media/common/videobuf2/videobuf2-v4l2.c   | 34 +--
 2 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 8c1df829745b..09dc030484be 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -813,6 +813,15 @@ static bool verify_coherency_flags(struct vb2_queue *q, 
bool non_coherent_mem)
return true;
 }
 
+static bool verify_secure_mem_flags(struct vb2_queue *q, bool secure_mem)
+{
+   if (secure_mem != q->secure_mem) {
+   dprintk(q, 1, "secure memory model mismatch\n");
+   return false;
+   }
+   return true;
+}
+
 int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
 unsigned int flags, unsigned int *count)
 {
@@ -820,6 +829,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
unsigned int q_num_bufs = vb2_get_num_buffers(q);
unsigned plane_sizes[VB2_MAX_PLANES] = { };
bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
+   bool secure_mem = flags & V4L2_MEMORY_FLAG_SECURE;
unsigned int i;
int ret = 0;
 
@@ -836,6 +846,8 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
if (*count == 0 || q_num_bufs != 0 ||
(q->memory != VB2_MEMORY_UNKNOWN && q->memory != memory) ||
!verify_coherency_flags(q, non_coherent_mem)) {
+   bool no_previous_buffers = !q->num_buffers;
+
/*
 * We already have buffers allocated, so first check if they
 * are not in use and can be freed.
@@ -854,6 +866,12 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
__vb2_queue_free(q, q_num_bufs);
mutex_unlock(>mmap_lock);
 
+   /*
+* Do not allow switching secure buffer mode.
+*/
+   if (!no_previous_buffers && !verify_secure_mem_flags(q, 
secure_mem))
+   return -EINVAL;
+
/*
 * In case of REQBUFS(0) return immediately without calling
 * driver's queue_setup() callback and allocating resources.
@@ -882,6 +900,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
if (ret)
return ret;
set_queue_coherency(q, non_coherent_mem);
+   q->secure_mem = secure_mem;
 
/*
 * Ask the driver how many buffers and planes per buffer it requires.
@@ -986,6 +1005,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
unsigned plane_sizes[VB2_MAX_PLANES] = { };
bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
unsigned int q_num_bufs = vb2_get_num_buffers(q);
+   bool secure_mem = flags & V4L2_MEMORY_FLAG_SECURE;
bool no_previous_buffers = !q_num_bufs;
int ret = 0;
 
@@ -1015,6 +1035,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
return ret;
q->waiting_for_buffers = !q->is_output;
set_queue_coherency(q, non_coherent_mem);
+   q->secure_mem = secure_mem;
} else {
if (q->memory != memory) {
dprintk(q, 1, "memory model mismatch\n");
@@ -1022,6 +1043,8 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum 
vb2_memory memory,
}
if (!verify_coherency_flags(q, non_coherent_mem))
return -EINVAL;
+   if (!verify_secure_mem_flags(q, secure_mem))
+   return -EINVAL;
}
 
num_buffers = min(*count, q->max_num_buffers - q_num_bufs);
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 54d572c3b515..0a530830276c 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -686,22 +686,30 @@ static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
*caps |= V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS;
if (q->supports_requests)
*caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS;
+   if (q->allow_secure_mem && q->io_modes & VB2_DMABUF)
+   *caps |= V4L2_BUF_CAP_SUPPORTS_SECURE_MEM;
 }
 
-static void validate_memory_flags(struct vb2_queue *q,
+static bool validate_memory_flags(struct vb2_queue *q,
 

[PATCH v3,01/21] v4l2: add secure memory flags

2023-12-06 Thread Yunfei Dong
From: Jeffrey Kardatzke 

Adds a V4L2 flag which indicates that a queue is using secure dmabufs
and the corresponding capability flag.

Signed-off-by: Jeffrey Kardatzke 
Signed-off-by: Yunfei Dong 
---
 include/media/videobuf2-core.h | 8 +++-
 include/uapi/linux/videodev2.h | 2 ++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 5557d78b6f20..98eba43661c1 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -518,6 +518,9 @@ struct vb2_buf_ops {
  * ->finish().
  * @non_coherent_mem: when set queue will attempt to allocate buffers using
  * non-coherent memory.
+ * @allow_secure_mem: when set user-space can pass the %V4L2_MEMORY_FLAG_SECURE
+ * flag to indicate the dma bufs are secure.
+ * @secure_mem: when set queue will verify that the dma bufs are secure.
  * @lock:  pointer to a mutex that protects the  vb2_queue. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -601,6 +604,8 @@ struct vb2_queue {
unsigned intuses_requests:1;
unsigned intallow_cache_hints:1;
unsigned intnon_coherent_mem:1;
+   unsigned intallow_secure_mem:1;
+   unsigned intsecure_mem:1;
 
struct mutex*lock;
void*owner;
@@ -770,7 +775,8 @@ void vb2_core_querybuf(struct vb2_queue *q, struct 
vb2_buffer *vb, void *pb);
  * @q: pointer to  vb2_queue with videobuf2 queue.
  * @memory:memory type, as defined by  vb2_memory.
  * @flags: auxiliary queue/buffer management flags. Currently, the only
- * used flag is %V4L2_MEMORY_FLAG_NON_COHERENT.
+ * used flags are %V4L2_MEMORY_FLAG_NON_COHERENT and
+ * %V4L2_MEMORY_FLAG_SECURE.
  * @count: requested buffer count.
  *
  * Videobuf2 core helper to implement VIDIOC_REQBUF() operation. It is called
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 68e7ac178cc2..570b11552818 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1026,6 +1026,7 @@ struct v4l2_requestbuffers {
 };
 
 #define V4L2_MEMORY_FLAG_NON_COHERENT  (1 << 0)
+#define V4L2_MEMORY_FLAG_SECURE(1 << 1)
 
 /* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */
 #define V4L2_BUF_CAP_SUPPORTS_MMAP (1 << 0)
@@ -1036,6 +1037,7 @@ struct v4l2_requestbuffers {
 #define V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF (1 << 5)
 #define V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS (1 << 6)
 #define V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS  (1 << 7)
+#define V4L2_BUF_CAP_SUPPORTS_SECURE_MEM   (1 << 8)
 
 /**
  * struct v4l2_plane - plane info for multi-planar buffers
-- 
2.18.0



[PATCH v3,00/21] add driver to support secure video decoder

2023-12-06 Thread Yunfei Dong
The patch series used to enable secure video playback (SVP) on MediaTek
hardware in the Linux kernel.

Memory Definitions:
secure memory - Memory allocated in the TEE (Trusted Execution
Environment) which is inaccessible in the REE (Rich Execution
Environment, i.e. linux kernel/userspace).
secure handle - Integer value which acts as reference to 'secure
memory'. Used in communication between TEE and REE to reference
'secure memory'.
secure buffer - 'secure memory' that is used to store decrypted,
compressed video or for other general purposes in the TEE.
secure surface - 'secure memory' that is used to store graphic buffers.

Memory Usage in SVP:
The overall flow of SVP starts with encrypted video coming in from an
outside source into the REE. The REE will then allocate a 'secure
buffer' and send the corresponding 'secure handle' along with the
encrypted, compressed video data to the TEE. The TEE will then decrypt
the video and store the result in the 'secure buffer'. The REE will
then allocate a 'secure surface'. The REE will pass the 'secure
handles' for both the 'secure buffer' and 'secure surface' into the
TEE for video decoding. The video decoder HW will then decode the
contents of the 'secure buffer' and place the result in the 'secure
surface'. The REE will then attach the 'secure surface' to the overlay
plane for rendering of the video.

Everything relating to ensuring security of the actual contents of the
'secure buffer' and 'secure surface' is out of scope for the REE and
is the responsibility of the TEE.

This patch series is consists of four parts. The first is from Jeffrey,
adding secure memory flag in v4l2 framework to support request secure
buffer.

The second and third parts are from John and T.J, adding some heap
interfaces, then our kernel users could allocate buffer from special
heap. The patch v1 is inside below dmabuf link.
https://lore.kernel.org/linux-mediatek/20230911023038.30649-1-yong...@mediatek.com/
To avoid confusing, move them into vcodec patchset since we use the
new interfaces directly.

The fourth part is mediatek decoder driver, adding tee interface to
support secure video decoder.

---
Changed in v3:
- rewrite the cover-letter of this patch series
- disable irq for svp mode
- rebase the driver based on the latest media stage

Changed in v2:
- remove setting decoder mode and getting secure handle from decode
- add Jeffrey's patch
- add John and T.J's patch
- getting secure flag with request buffer
- fix some comments from patch v1
---
Jeffrey Kardatzke (4):
  v4l2: add secure memory flags
  v4l2: handle secure memory flags in queue setup
  v4l2: verify secure dmabufs are used in secure queue
  v4l: add documentation for secure memory flag

John Stultz (2):
  dma-heap: Add proper kref handling on dma-buf heaps
  dma-heap: Provide accessors so that in-kernel drivers can allocate
dmabufs from specific heaps

T.J. Mercier (1):
  dma-buf: heaps: Deduplicate docs and adopt common format

Yunfei Dong (14):
  media: mediatek: vcodec: add tee client interface to communiate with
optee-os
  media: mediatek: vcodec: allocate tee share memory
  media: mediatek: vcodec: send share memory data to optee
  media: mediatek: vcodec: initialize msg and vsi information
  media: mediatek: vcodec: add interface to allocate/free secure memory
  media: mediatek: vcodec: using shared memory as vsi address
  media: mediatek: vcodec: Add capture format to support one plane
memory
  media: mediatek: vcodec: Add one plane format
  media: medkatek: vcodec: support one plane capture buffer
  media: medkatek: vcodec: re-construct h264 driver to support svp mode
  media: medkatek: vcodec: remove parse nal_info in kernel
  media: medkatek: vcodec: disable wait interrupt for svp mode
  media: medkatek: vcodec: support tee decoder
  media: mediatek: vcodec: move vdec init interface to setup callback

 .../userspace-api/media/v4l/buffer.rst|   8 +-
 .../media/v4l/pixfmt-reserved.rst |   8 +
 drivers/dma-buf/dma-heap.c| 139 +--
 .../media/common/videobuf2/videobuf2-core.c   |  23 ++
 .../common/videobuf2/videobuf2-dma-contig.c   |   6 +
 .../media/common/videobuf2/videobuf2-dma-sg.c |   6 +
 .../media/common/videobuf2/videobuf2-v4l2.c   |  34 +-
 .../media/platform/mediatek/vcodec/Kconfig|   1 +
 .../mediatek/vcodec/common/mtk_vcodec_util.c  | 122 +-
 .../mediatek/vcodec/common/mtk_vcodec_util.h  |   3 +
 .../platform/mediatek/vcodec/decoder/Makefile |   1 +
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c  | 155 ---
 .../vcodec/decoder/mtk_vcodec_dec_drv.c   |   8 +
 .../vcodec/decoder/mtk_vcodec_dec_drv.h   |   7 +
 .../vcodec/decoder/mtk_vcodec_dec_hw.c|  34 +-
 .../vcodec/decoder/mtk_vcodec_dec_optee.c | 383 ++
 .../vcodec/decoder/mtk_vcodec_dec_optee.h | 156 +++
 .../vcodec/decoder/mtk_vcodec_dec_pm.c|   6 +-
 .../vcodec/decoder/mtk_vcodec_dec_stateless.c |  35 +-
 .../decoder/vdec

[PATCH v2, 5/7] media: mtk-vcodec: Different codec using different capture format

2022-01-27 Thread Yunfei Dong
Vp8 need to use MM21, but vp9 and h264 need to use HyFbc mode
for mt8195. Vp8/vp9/h264 use the same MM21 format for mt8192.

Signed-off-by: Yunfei Dong 
---
 .../platform/mtk-vcodec/mtk_vcodec_dec.c  | 41 +++
 1 file changed, 41 insertions(+)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
index 6ad17e69e32d..f2ced0147534 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
@@ -35,6 +35,44 @@ mtk_vdec_find_format(struct v4l2_format *f,
return NULL;
 }
 
+static bool mtk_vdec_get_cap_fmt(struct mtk_vcodec_ctx *ctx, int format_index)
+{
+   const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata;
+   const struct mtk_video_fmt *fmt;
+   struct mtk_q_data *q_data;
+   int num_frame_count = 0, i;
+   bool ret = true;
+
+   for (i = 0; i < *dec_pdata->num_formats; i++) {
+   if (dec_pdata->vdec_formats[i].type != MTK_FMT_FRAME)
+   continue;
+
+   num_frame_count++;
+   }
+
+   if (num_frame_count == 1)
+   return true;
+
+   fmt = _pdata->vdec_formats[format_index];
+   q_data = >q_data[MTK_Q_DATA_SRC];
+   switch (q_data->fmt->fourcc) {
+   case V4L2_PIX_FMT_VP8_FRAME:
+   if (fmt->fourcc == V4L2_PIX_FMT_MM21)
+   ret = true;
+   break;
+   case V4L2_PIX_FMT_H264_SLICE:
+   case V4L2_PIX_FMT_VP9_FRAME:
+   if (fmt->fourcc == V4L2_PIX_FMT_MM21)
+   ret = false;
+   break;
+   default:
+   ret = true;
+   break;
+   };
+
+   return ret;
+}
+
 static struct mtk_q_data *mtk_vdec_get_q_data(struct mtk_vcodec_ctx *ctx,
  enum v4l2_buf_type type)
 {
@@ -578,6 +616,9 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, void 
*priv,
dec_pdata->vdec_formats[i].type != MTK_FMT_FRAME)
continue;
 
+   if (!output_queue && !mtk_vdec_get_cap_fmt(ctx, i))
+   continue;
+
if (j == f->index)
break;
++j;
-- 
2.25.1


[PATCH v2, 1/7] dt-bindings: media: mtk-vcodec: Adds decoder dt-bindings for lat soc

2022-01-27 Thread Yunfei Dong
Adds decoder dt-bindings for compatible "mediatek,mtk-vcodec-lat-soc".

Signed-off-by: Yunfei Dong 
---
 .../media/mediatek,vcodec-subdev-decoder.yaml | 49 +++
 1 file changed, 49 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml 
b/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml
index 6415c9f29130..a3c892338ac0 100644
--- 
a/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml
+++ 
b/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml
@@ -189,6 +189,55 @@ patternProperties:
 
 additionalProperties: false
 
+  '^vcodec-lat-soc@[0-9a-f]+$':
+type: object
+
+properties:
+  compatible:
+const: mediatek,mtk-vcodec-lat-soc
+
+  reg:
+maxItems: 1
+
+  iommus:
+minItems: 1
+maxItems: 32
+description: |
+  List of the hardware port in respective IOMMU block for current Socs.
+  Refer to bindings/iommu/mediatek,iommu.yaml.
+
+  clocks:
+maxItems: 5
+
+  clock-names:
+items:
+  - const: sel
+  - const: soc-vdec
+  - const: soc-lat
+  - const: vdec
+  - const: top
+
+  assigned-clocks:
+maxItems: 1
+
+  assigned-clock-parents:
+maxItems: 1
+
+  power-domains:
+maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - iommus
+  - clocks
+  - clock-names
+  - assigned-clocks
+  - assigned-clock-parents
+  - power-domains
+
+additionalProperties: false
+
 required:
   - compatible
   - reg
-- 
2.25.1


[PATCH v2, 7/7] media: mtk-vcodec: Add to support H264 inner racing mode

2022-01-27 Thread Yunfei Dong
In order to reduce decoder latency, enable H264 inner racing mode.

Send lat trans buffer information to core when trigger lat to work,
need not to wait until lat decode done.

Signed-off-by: Yunfei Dong 
---
 .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c  |  4 +++
 .../platform/mtk-vcodec/mtk_vcodec_dec_pm.c   | 34 +++
 .../platform/mtk-vcodec/mtk_vcodec_drv.h  | 10 ++
 .../mtk-vcodec/vdec/vdec_h264_req_multi_if.c  | 23 ++---
 4 files changed, 66 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index 938bf14e4e8c..099dc28b7445 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -390,6 +390,10 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
}
}
 
+   atomic_set(>dec_active_cnt, 0);
+   memset(dev->vdec_racing_info, 0 , sizeof(dev->vdec_racing_info));
+   mutex_init(>dec_racing_info_mutex);
+
if (dev->vdec_pdata->uses_stateless_api) {
dev->mdev_dec.dev = >dev;
strscpy(dev->mdev_dec.model, MTK_VCODEC_DEC_NAME,
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
index 76e1442fc6f9..065d14a3d11f 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -173,6 +173,34 @@ static void mtk_vcodec_dec_disable_irq(struct 
mtk_vcodec_dev *vdec_dev, int hw_i
}
 }
 
+static void mtk_vcodec_load_racing_info(struct mtk_vcodec_ctx *ctx)
+{
+   void __iomem *vdec_racing_addr;
+   int j;
+
+   mutex_lock(>dev->dec_racing_info_mutex);
+   if (atomic_inc_return(>dev->dec_active_cnt) == 1) {
+   vdec_racing_addr = ctx->dev->reg_base[VDEC_MISC] + 0x100;
+   for (j = 0; j < 132; j++)
+   writel(ctx->dev->vdec_racing_info[j], vdec_racing_addr 
+ j * 4);
+   }
+   mutex_unlock(>dev->dec_racing_info_mutex);
+}
+
+static void mtk_vcodec_record_racing_info(struct mtk_vcodec_ctx *ctx)
+{
+   void __iomem *vdec_racing_addr;
+   int j;
+
+   mutex_lock(>dev->dec_racing_info_mutex);
+   if (atomic_dec_and_test(>dev->dec_active_cnt)) {
+   vdec_racing_addr = ctx->dev->reg_base[VDEC_MISC] + 0x100;
+   for (j = 0; j < 132; j++)
+   ctx->dev->vdec_racing_info[j] = readl(vdec_racing_addr 
+ j * 4);
+   }
+   mutex_unlock(>dev->dec_racing_info_mutex);
+}
+
 static struct mtk_vcodec_pm *mtk_vcodec_dec_get_pm(struct mtk_vcodec_dev 
*vdec_dev,
   int hw_idx)
 {
@@ -243,11 +271,17 @@ void mtk_vcodec_dec_enable_hardware(struct mtk_vcodec_ctx 
*ctx, int hw_idx)
mtk_vcodec_dec_child_dev_on(ctx->dev, hw_idx);
 
mtk_vcodec_dec_enable_irq(ctx->dev, hw_idx);
+
+   if (IS_VDEC_INNER_RACING(ctx->dev->dec_capability))
+   mtk_vcodec_load_racing_info(ctx);
 }
 EXPORT_SYMBOL_GPL(mtk_vcodec_dec_enable_hardware);
 
 void mtk_vcodec_dec_disable_hardware(struct mtk_vcodec_ctx *ctx, int hw_idx)
 {
+   if (IS_VDEC_INNER_RACING(ctx->dev->dec_capability))
+   mtk_vcodec_record_racing_info(ctx);
+
mtk_vcodec_dec_disable_irq(ctx->dev, hw_idx);
 
mtk_vcodec_dec_child_dev_off(ctx->dev, hw_idx);
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index 363b999dd709..4d6ace869b5a 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -28,6 +28,7 @@
 #define MTK_V4L2_BENCHMARK 0
 #define WAIT_INTR_TIMEOUT_MS   1000
 #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)
 
 /*
  * enum mtk_hw_reg_idx - MTK hw register base index
@@ -360,6 +361,7 @@ enum mtk_vdec_format_types {
MTK_VDEC_FORMAT_H264_SLICE = 0x100,
MTK_VDEC_FORMAT_VP8_FRAME = 0x200,
MTK_VDEC_FORMAT_VP9_FRAME = 0x400,
+   MTK_VCODEC_INNER_RACING = 0x2,
 };
 
 /**
@@ -480,6 +482,10 @@ struct mtk_vcodec_enc_pdata {
  * @subdev_dev: subdev hardware device
  * @subdev_prob_done: check whether all used hw device is prob done
  * @subdev_bitmap: used to record hardware is ready or not
+ *
+ * @dec_active_cnt: used to mark whether need to record register value
+ * @vdec_racing_info: record register value
+ * @dec_racing_info_mutex: mutex lock used for inner racing mode
  */
 struct mtk_vcodec_dev {
struct v4l2_device v4l2_dev;
@@ -525,6 +531,10 @@ struct mtk_vcodec_dev {
void *subdev_dev[MTK_VDEC_HW_M

[PATCH v2, 0/7] support mt8195 decoder

2022-01-27 Thread Yunfei Dong
Firstly, add mt8195 soc lat hardware and compatible, then add documents.
For vp8 only support MM21 mode, H264/vp9 support MT21C, need to separate
them. Lastly, enable H264 inner racing mode to reduce hardware latency.

Patch 1~4 add mt8195 soc lat hardware and compatible, then add documents.
Patch 5 using different format for different codecs.
Patch 6 prevent kernel crash when scp reboot.
Patch 7 enable H264 inner racing mode to reduce hardware latency.
---
This patch depends on "support mt8186 decoder"[1]

[1]  
https://patchwork.kernel.org/project/linux-mediatek/cover/20220122075606.19373-1-yunfei.d...@mediatek.com
---
changed with v1:
- separate "Init VP9 stateless decode params" patch and remove it to another 
one.
- add reviewed-by in patch v3/v4/v6
---
Tinghan Shen (1):
  media: mtk-vcodec: prevent kernel crash when scp ipi timeout

Yunfei Dong (6):
  dt-bindings: media: mtk-vcodec: Adds decoder dt-bindings for lat soc
  media: mtk-vcodec: Add to support lat soc hardware
  dt-bindings: media: mtk-vcodec: Adds decoder dt-bindings for mt8195
  media: mtk-vcodec: Adds compatible for mt8195
  media: mtk-vcodec: Different codec using different capture format
  media: mtk-vcodec: Add to support H264 inner racing mode

 .../media/mediatek,vcodec-subdev-decoder.yaml | 50 +++
 .../platform/mtk-vcodec/mtk_vcodec_dec.c  | 41 +++
 .../platform/mtk-vcodec/mtk_vcodec_dec_drv.c  |  8 +++
 .../platform/mtk-vcodec/mtk_vcodec_dec_hw.c   | 12 +++--
 .../platform/mtk-vcodec/mtk_vcodec_dec_hw.h   |  2 +
 .../platform/mtk-vcodec/mtk_vcodec_dec_pm.c   | 50 +++
 .../platform/mtk-vcodec/mtk_vcodec_drv.h  | 11 
 .../mtk-vcodec/vdec/vdec_h264_req_multi_if.c  | 23 +++--
 .../media/platform/mtk-vcodec/vdec_vpu_if.c   |  5 ++
 9 files changed, 194 insertions(+), 8 deletions(-)

-- 
2.25.1



[PATCH v2, 6/7] media: mtk-vcodec: prevent kernel crash when scp ipi timeout

2022-01-27 Thread Yunfei Dong
From: Tinghan Shen 

When SCP timeout during playing video, kernel crashes with following
message. It's caused by accessing NULL pointer in vpu_dec_ipi_handler.
This patch doesn't solve the root cause of NULL pointer, but merely
prevent kernel crashed when encounter the NULL pointer.

After applied this patch, kernel keeps alive, only the video player turns
to green screen.

[67242.065474] pc : vpu_dec_ipi_handler+0xa0/0xb20 [mtk_vcodec_dec]
[67242.065485] [MTK_V4L2] level=0 fops_vcodec_open(),334:
1800.vcodec_dec decoder [135]
[67242.065523] lr : scp_ipi_handler+0x11c/0x244 [mtk_scp]
[67242.065540] sp : ffbb4207fb10
[67242.065557] x29: ffbb4207fb30 x28: ffd00a1d5000
[67242.065592] x27: 1ffa0143aa24 x26: 
[67242.065625] x25: dfd0 x24: ffd0168bfdb0
[67242.065659] x23: 1ff76840ff74 x22: ffbb41fa8a88
[67242.065692] x21: ffbb4207fb9c x20: ffbb4207fba0
[67242.065725] x19: ffbb4207fb98 x18: 
[67242.065758] x17:  x16: ffd042022094
[67242.065791] x15: 1ff77ed4b71a x14: 1ff77ed4b719
[67242.065824] x13:  x12: 
[67242.065857] x11:  x10: dfd1
[67242.065890] x9 :  x8 : 0002
[67242.065923] x7 :  x6 : 003f
[67242.065956] x5 : 0040 x4 : ffe0
[67242.065989] x3 : ffd043b841b8 x2 : 
[67242.066021] x1 : 0010 x0 : 0010
[67242.066055] Call trace:
[67242.066092]  vpu_dec_ipi_handler+0xa0/0xb20 [mtk_vcodec_dec
12220d230d83a7426fc38c56b3e7bc6066955bae]
[67242.066119]  scp_ipi_handler+0x11c/0x244 [mtk_scp
8fb69c2ef141dd3192518b952b65aba35627b8bf]
[67242.066145]  mt8192_scp_irq_handler+0x70/0x128 [mtk_scp
8fb69c2ef141dd3192518b952b65aba35627b8bf]
[67242.066172]  scp_irq_handler+0xa0/0x114 [mtk_scp
8fb69c2ef141dd3192518b952b65aba35627b8bf]
[67242.066200]  irq_thread_fn+0x84/0xf8
[67242.066220]  irq_thread+0x170/0x1ec
[67242.066242]  kthread+0x2f8/0x3b8
[67242.066264]  ret_from_fork+0x10/0x30
[67242.066292] Code: 38f96908 35003628 91004340 d343fc08 (38f96908)

Signed-off-by: Tinghan Shen 
Signed-off-by: Yunfei Dong 
Reviewed-by: Macpaul Lin 
---
 drivers/media/platform/mtk-vcodec/vdec_vpu_if.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c 
b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
index 35f4d5583084..1041dd663e76 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
@@ -91,6 +91,11 @@ static void vpu_dec_ipi_handler(void *data, unsigned int 
len, void *priv)
struct vdec_vpu_inst *vpu = (struct vdec_vpu_inst *)
(unsigned long)msg->ap_inst_addr;
 
+   if (!vpu) {
+   mtk_v4l2_err("ap_inst_addr is NULL");
+   return;
+   }
+
mtk_vcodec_debug(vpu, "+ id=%X", msg->msg_id);
 
vpu->failure = msg->status;
-- 
2.25.1



[PATCH v2, 4/7] media: mtk-vcodec: Adds compatible for mt8195

2022-01-27 Thread Yunfei Dong
Adds compatible for mt8195 platform.

Signed-off-by: Yunfei Dong 
Reviewed-by: Macpaul Lin 
---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index 2d21d0010c9c..938bf14e4e8c 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -468,6 +468,10 @@ static const struct of_device_id mtk_vcodec_match[] = {
.compatible = "mediatek,mt8186-vcodec-dec",
.data = _vdec_single_core_pdata,
},
+   {
+   .compatible = "mediatek,mt8195-vcodec-dec",
+   .data = _lat_sig_core_pdata,
+   },
{},
 };
 
-- 
2.25.1



  1   2   3   4   5   >