2024-05-16 12:21:26

by Yunfei Dong (董云飞)

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

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/[email protected]/
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.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/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 +-
.../vcodec/decoder/vdec/vdec_av1_req_lat_if.c | 97 +++--
.../decoder/vdec/vdec_h264_req_common.c | 18 +-
.../decoder/vdec/vdec_h264_req_multi_if.c | 334 +++++++++------
.../decoder/vdec/vdec_hevc_req_multi_if.c | 89 ++--
.../vcodec/decoder/vdec/vdec_vp9_req_lat_if.c | 91 +++--
.../mediatek/vcodec/decoder/vdec_drv_if.c | 4 +-
.../mediatek/vcodec/decoder/vdec_msg_queue.c | 9 +-
.../mediatek/vcodec/decoder/vdec_vpu_if.c | 57 ++-
.../mediatek/vcodec/decoder/vdec_vpu_if.h | 4 +
drivers/media/v4l2-core/v4l2-common.c | 2 +
drivers/media/v4l2-core/v4l2-ioctl.c | 1 +
include/linux/dma-heap.h | 29 +-
include/media/videobuf2-core.h | 8 +-
include/uapi/linux/videodev2.h | 3 +
33 files changed, 1456 insertions(+), 394 deletions(-)
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

--
2.25.1



2024-05-16 12:21:40

by Yunfei Dong (董云飞)

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

From: John Stultz <[email protected]>

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 <[email protected]>
Signed-off-by: T.J. Mercier <[email protected]>
Signed-off-by: Yong Wu <[email protected]>
[Yong: Just add comment for "minor" and "refcount"]
Signed-off-by: Yunfei Dong <[email protected]>
---
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 <linux/dma-buf.h>
#include <linux/dma-heap.h>
#include <linux/err.h>
+#include <linux/kref.h>
#include <linux/list.h>
#include <linux/nospec.h>
#include <linux/syscalls.h>
@@ -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(&heap->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(&heap_list_lock);
+ list_del(&heap->list);
+ mutex_unlock(&heap_list_lock);
+
+ device_destroy(dma_heap_class, heap->heap_devt);
+ cdev_del(&heap->heap_cdev);
+ xa_erase(&dma_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(&heap->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


2024-05-16 12:21:54

by Yunfei Dong (董云飞)

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

From: Jeffrey Kardatzke <[email protected]>

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

Signed-off-by: Jeffrey Kardatzke <[email protected]>
Signed-off-by: Yunfei Dong <[email protected]>
---
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 &struct 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 int uses_requests:1;
unsigned int allow_cache_hints:1;
unsigned int non_coherent_mem:1;
+ unsigned int allow_restricted_mem:1;
+ unsigned int restricted_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 &struct vb2_queue with videobuf2 queue.
* @memory: memory type, as defined by &enum 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


2024-05-16 12:22:44

by Yunfei Dong (董云飞)

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

From: "T.J. Mercier" <[email protected]>

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 <[email protected]>
Signed-off-by: Yong Wu <[email protected]>
[Yong: Just add a comment for "priv" to mute build warning]
Signed-off-by: Yunfei Dong <[email protected]>
---
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 <linux/cdev.h>
-#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
+#include <linux/dma-heap.h>
#include <linux/err.h>
-#include <linux/xarray.h>
#include <linux/list.h>
-#include <linux/slab.h>
#include <linux/nospec.h>
-#include <linux/uaccess.h>
#include <linux/syscalls.h>
-#include <linux/dma-heap.h>
+#include <linux/uaccess.h>
+#include <linux/xarray.h>
#include <uapi/linux/dma-heap.h>

#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 <linux/cdev.h>
#include <linux/types.h>

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


2024-05-16 12:22:45

by Yunfei Dong (董云飞)

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

From: Jeffrey Kardatzke <[email protected]>

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

Signed-off-by: Jeffrey Kardatzke <[email protected]>
Signed-off-by: Yunfei Dong <[email protected]>
---
.../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)
+ *caps |= V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM;
if (max_num_bufs) {
*max_num_bufs = q->max_num_buffers;
*caps |= V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS;
--
2.25.1


2024-05-16 12:22:49

by Yunfei Dong (董云飞)

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

From: John Stultz <[email protected]>

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 <[email protected]>
Signed-off-by: T.J. Mercier <[email protected]>
Signed-off-by: Yong Wu <[email protected]>
[Yong: Fix the checkpatch alignment warning]
Signed-off-by: Yunfei Dong <[email protected]>
---
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(&heap_list_lock);
+ list_for_each_entry(h, &heap_list, list) {
+ if (!kref_get_unless_zero(&h->refcount))
+ continue;
+
+ if (!strcmp(h->name, name)) {
+ mutex_unlock(&heap_list_lock);
+ return h;
+ }
+ dma_heap_put(h);
+ }
+ mutex_unlock(&heap_list_lock);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(dma_heap_find);

static void dma_heap_release(struct kref *ref)
{
@@ -332,6 +382,7 @@ void dma_heap_put(struct dma_heap *heap)
{
kref_put(&heap->refcount, dma_heap_release);
}
+EXPORT_SYMBOL_GPL(dma_heap_put);

static char *dma_heap_devnode(const struct device *dev, umode_t *mode)
{
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index d57593f8a1bc..3cbf9bff2346 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -46,6 +46,12 @@ const char *dma_heap_get_name(struct dma_heap *heap);

struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);

+struct dma_heap *dma_heap_find(const char *name);
+
void dma_heap_put(struct dma_heap *heap);

+struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
+ unsigned int fd_flags,
+ unsigned int heap_flags);
+
#endif /* _DMA_HEAPS_H */
--
2.25.1


2024-05-16 12:23:06

by Yunfei Dong (董云飞)

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

From: Jeffrey Kardatzke <[email protected]>

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 <[email protected]>
Signed-off-by: Yunfei Dong <[email protected]>
---
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


2024-05-16 12:23:32

by Yunfei Dong (董云飞)

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

Setting msg and vsi information to shared buffer, then call tee invoke
function to send it to optee-os.

Signed-off-by: Yunfei Dong <[email protected]>
---
.../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(&optee_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 = &optee_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 = &optee_private->lat_ca;
+ else
+ ca_info = &optee_private->core_ca;
+
+ memset(&trans_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 = &ca_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(&command_params[index], shm_memref,
+ data, index, dev);
+ if (ret)
+ return ret;
+ }
+
+ ret = tee_client_invoke_func(optee_private->tee_vdec_ctx, &trans_args, command_params);
+ if (ret < 0 || trans_args.ret != 0) {
+ dev_err(dev, MTK_DBG_VCODEC_STR "tee submit command fail: 0x%x 0x%x.\n",
+ trans_args.ret, ret);
+ return (ret < 0) ? ret : trans_args.ret;
+ }
+
+ /* clear all attrs, set all command param to unused */
+ for (index = 0; index < MTK_OPTEE_MAX_TEE_PARAMS; index++) {
+ data->msg_buf[index] = NULL;
+ data->msg_buf_size[index] = 0;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_invokd_cmd);
+
+void *mtk_vcodec_dec_get_shm_buffer_va(struct mtk_vdec_optee_private *optee_private,
+ enum mtk_vdec_hw_id hw_id,
+ enum mtk_vdec_optee_data_index data_index)
+{
+ struct mtk_vdec_optee_ca_info *ca_info;
+
+ if (hw_id == MTK_VDEC_LAT0)
+ ca_info = &optee_private->lat_ca;
+ else
+ ca_info = &optee_private->core_ca;
+
+ return ca_info->shm_memref[data_index].msg_shm_ca_buf;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_get_shm_buffer_va);
+
+int mtk_vcodec_dec_get_shm_buffer_size(struct mtk_vdec_optee_private *optee_private,
+ enum mtk_vdec_hw_id hw_id,
+ enum mtk_vdec_optee_data_index data_index)
+{
+ struct mtk_vdec_optee_ca_info *ca_info;
+
+ if (hw_id == MTK_VDEC_LAT0)
+ ca_info = &optee_private->lat_ca;
+ else
+ ca_info = &optee_private->core_ca;
+
+ return ca_info->shm_memref[data_index].msg_shm_size;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_get_shm_buffer_size);
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
index 24aa63af9887..c24a567ec877 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
@@ -62,6 +62,16 @@ enum mtk_vdec_optee_data_index {
OPTEE_MAX_INDEX,
};

+/**
+ * struct mtk_vdec_optee_data_to_shm - shm data used for TA
+ * @msg_buf: msg information to TA.
+ * @msg_buf_len: length of msg information.
+ */
+struct mtk_vdec_optee_data_to_shm {
+ void *msg_buf[MTK_OPTEE_MAX_TEE_PARAMS];
+ int msg_buf_size[MTK_OPTEE_MAX_TEE_PARAMS];
+};
+
/**
* struct mtk_vdec_optee_private - optee private data
* @vcodec_dev: pointer to the mtk_vcodec_dev of the device
@@ -102,4 +112,45 @@ int mtk_vcodec_dec_optee_private_init(struct mtk_vcodec_dec_dev *vcodec_dev);
*/
void mtk_vcodec_dec_optee_release(struct mtk_vdec_optee_private *optee_private);

+/**
+ * mtk_vcodec_dec_optee_set_data - set buffer to share memref.
+ * @vcodec_dev: normal world data used to init optee share memory
+ * @buf: normal world buffer address
+ * @buf_size: buf size
+ * @data_index: indentify each share memory informaiton
+ */
+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 data_index);
+
+/**
+ * mtk_vcodec_dec_optee_invokd_cmd - send share memory data to optee .
+ * @optee_private: optee private context
+ * @hw_id: hardware index
+ * @data: normal world data used to init optee share memory
+ */
+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);
+
+/**
+ * mtk_vcodec_dec_get_shm_buffer_va - close the communication channels with TA.
+ * @optee_private: optee private context
+ * @hw_id: hardware index
+ * @@data_index: indentify each share memory informaiton
+ */
+void *mtk_vcodec_dec_get_shm_buffer_va(struct mtk_vdec_optee_private *optee_private,
+ enum mtk_vdec_hw_id hw_id,
+ enum mtk_vdec_optee_data_index data_index);
+
+/**
+ * mtk_vcodec_dec_get_shm_buffer_size - close the communication channels with TA.
+ * @optee_private: optee private context
+ * @hw_id: hardware index
+ * @@data_index: indentify each share memory informaiton
+ */
+int mtk_vcodec_dec_get_shm_buffer_size(struct mtk_vdec_optee_private *optee_private,
+ enum mtk_vdec_hw_id hw_id,
+ enum mtk_vdec_optee_data_index data_index);
+
#endif /* _MTK_VCODEC_FW_OPTEE_H_ */
--
2.25.1


2024-05-16 12:24:07

by Yunfei Dong (董云飞)

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

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 <[email protected]>
---
.../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 = &ca_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 = &optee_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_vdec_optee_ca_info *ca_info;
+ int i;

if (hw_id == MTK_VDEC_LAT0)
ca_info = &optee_private->lat_ca;
else
ca_info = &optee_private->core_ca;

+ for (i = 0; i < OPTEE_MAX_INDEX; i++)
+ mtk_vcodec_dec_optee_deinit_memref(ca_info, i);
+
tee_client_close_session(optee_private->tee_vdec_ctx, ca_info->vdec_session_id);
}

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
index 8b1dca49331e..24aa63af9887 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
@@ -18,16 +18,48 @@

#define MTK_OPTEE_MAX_TEE_PARAMS 4

+#define MTK_VDEC_OPTEE_MSG_SIZE 128
+#define MTK_VDEC_OPTEE_HW_SIZE (8 * SZ_1K)
+
+/**
+ * struct mtk_vdec_optee_shm_memref - share memory reference params
+ * @msg_shm: message shared with TA in TEE.
+ * @msg_shm_ca_buf: ca buffer.
+ *
+ * @msg_shm_size: share message size.
+ * @param_type: each tee param types.
+ * @copy_to_ta: need to copy data from ca to share memory.
+ */
+struct mtk_vdec_optee_shm_memref {
+ struct tee_shm *msg_shm;
+ u8 *msg_shm_ca_buf;
+
+ u32 msg_shm_size;
+ u64 param_type;
+ bool copy_to_ta;
+};
+
/**
* struct mtk_vdec_optee_ca_info - ca related param
* @vdec_session_id: optee TA session identifier.
* @hw_id: hardware index.
* @vdec_session_func: trusted application function id used specific to the TA.
+ * @shm_memref: share memory reference params.
*/
struct mtk_vdec_optee_ca_info {
u32 vdec_session_id;
enum mtk_vdec_hw_id hw_id;
u32 vdec_session_func;
+ struct mtk_vdec_optee_shm_memref shm_memref[MTK_OPTEE_MAX_TEE_PARAMS];
+};
+
+/*
+ * enum mtk_vdec_optee_data_index - used to indentify each share memory information
+ */
+enum mtk_vdec_optee_data_index {
+ OPTEE_MSG_INDEX = 0,
+ OPTEE_DATA_INDEX,
+ OPTEE_MAX_INDEX,
};

/**
--
2.25.1


2024-05-16 12:24:27

by Yunfei Dong (董云飞)

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

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 <[email protected]>
---
.../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 = &vpu->core_optee_info;
id = vpu->core_id;
- else
+ } else {
+ optee_data = &vpu->lat_optee_info;
id = vpu->id;
+ }
} else {
+ optee_data = &vpu->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 optee os directly for SVP mode,
+ * fw ipi interface is used for normal playback.
+ */
+ if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE &&
+ !vpu->ctx->is_secure_playback) {
err = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler,
vpu->core_id, vpu->handler,
"vdec", vpu->ctx->dev);
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.h b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.h
index 57ed9b1f5eaa..8e9d4c2cbb88 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.h
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.h
@@ -27,6 +27,8 @@ struct mtk_vcodec_dec_ctx;
* @codec_type : use codec type to separate different codecs
* @capture_type: used capture type to separate different capture format
* @fb_sz : frame buffer size of each plane
+ * @lat_optee_info : used to send msg to optee shm buffer
+ * @core_optee_info : used to send msg to optee shm buffer
*/
struct vdec_vpu_inst {
int id;
@@ -43,6 +45,8 @@ struct vdec_vpu_inst {
unsigned int codec_type;
unsigned int capture_type;
unsigned int fb_sz[2];
+ struct mtk_vdec_optee_data_to_shm lat_optee_info;
+ struct mtk_vdec_optee_data_to_shm core_optee_info;
};

/**
--
2.25.1


2024-05-16 12:24:37

by Yunfei Dong (董云飞)

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

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 <[email protected]>
---
.../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


2024-05-16 12:24:40

by Yunfei Dong (董云飞)

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

Need to call dma heap interface to allocate/free secure memory when playing
secure video.

Signed-off-by: Yunfei Dong <[email protected]>
---
.../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 <[email protected]>
*/

+#include <linux/dma-heap.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
+#include <uapi/linux/dma-heap.h>

#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 = &ctx->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;
+ mem->dma_addr = 0;
+ mem->size = 0;
+}
+
+int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem *mem)
+{
+ enum mtk_instance_type inst_type = *((unsigned int *)priv);
+ int ret;
+
+ if (inst_type == MTK_INST_DECODER) {
+ struct mtk_vcodec_dec_ctx *dec_ctx = priv;
+
+ if (dec_ctx->is_secure_playback) {
+ ret = mtk_vcodec_mem_alloc_sec(dec_ctx, mem);
+ goto alloc_end;
+ }
+ }
+
+ ret = mtk_vcodec_mem_alloc_nor(priv, mem);
+alloc_end:
+
+ return ret;
+}
+EXPORT_SYMBOL(mtk_vcodec_mem_alloc);
+
+void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem *mem)
+{
+ enum mtk_instance_type inst_type = *((unsigned int *)priv);
+
+ if (inst_type == MTK_INST_DECODER) {
+ struct mtk_vcodec_dec_ctx *dec_ctx = priv;
+
+ if (dec_ctx->is_secure_playback) {
+ mtk_vcodec_mem_free_sec(mem);
+ return;
+ }
+ }
+
+ mtk_vcodec_mem_free_nor(priv, mem);
+}
EXPORT_SYMBOL(mtk_vcodec_mem_free);

void *mtk_vcodec_get_hw_dev(struct mtk_vcodec_dec_dev *dev, int hw_idx)
@@ -171,3 +286,4 @@ EXPORT_SYMBOL(mtk_vcodec_get_curr_ctx);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Mediatek video codec driver");
+MODULE_IMPORT_NS(DMA_BUF);
diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h
index 85f615cdd4d3..22078e757ed0 100644
--- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h
+++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h
@@ -18,6 +18,9 @@ struct mtk_vcodec_mem {
size_t size;
void *va;
dma_addr_t dma_addr;
+
+ struct dma_buf_attachment *attach;
+ struct sg_table *sgt;
};

struct mtk_vcodec_fb {
--
2.25.1


2024-05-16 12:24:47

by Yunfei Dong (董云飞)

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

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 <[email protected]>
---
.../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 = &ctx->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


2024-05-16 12:24:46

by Yunfei Dong (董云飞)

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

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 <[email protected]>
---
.../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 000000000000..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 <[email protected]>
+ */
+
+#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(&vcodec_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(&vcodec_dev->optee_private->tee_active_cnt, 0);
+ mutex_init(&vcodec_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 = &optee_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, &mtk_vdec_lat_uuid);
+ session_func = MTK_VDEC_OPTEE_TA_LAT_SUBMIT_COMMAND;
+ ca_info = &optee_private->lat_ca;
+ break;
+ case MTK_VDEC_CORE:
+ export_uuid(session_arg.uuid, &mtk_vdec_core_uuid);
+ session_func = MTK_VDEC_OPTEE_TA_CORE_SUBMIT_COMMAND;
+ ca_info = &optee_private->core_ca;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ session_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
+ session_arg.num_params = 0;
+
+ err = tee_client_open_session(optee_private->tee_vdec_ctx, &session_arg, NULL);
+ if (err < 0 || session_arg.ret != 0) {
+ dev_err(dev, MTK_DBG_VCODEC_STR "open vdec tee session fail hw_id:%d err:%x.\n",
+ hardware_index, session_arg.ret);
+ return -EINVAL;
+ }
+ ca_info->vdec_session_id = session_arg.session;
+ ca_info->hw_id = hardware_index;
+ ca_info->vdec_session_func = session_func;
+
+ 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);
+
+ return err;
+}
+
+static void mtk_vcodec_dec_optee_deinit_hw_info(struct mtk_vdec_optee_private *optee_private,
+ enum mtk_vdec_hw_id hw_id)
+{
+ struct mtk_vdec_optee_ca_info *ca_info;
+
+ if (hw_id == MTK_VDEC_LAT0)
+ ca_info = &optee_private->lat_ca;
+ else
+ ca_info = &optee_private->core_ca;
+
+ tee_client_close_session(optee_private->tee_vdec_ctx, ca_info->vdec_session_id);
+}
+
+int mtk_vcodec_dec_optee_open(struct mtk_vdec_optee_private *optee_private)
+{
+ struct device *dev = &optee_private->vcodec_dev->plat_dev->dev;
+ int ret;
+
+ mutex_lock(&optee_private->tee_mutex);
+ if (atomic_inc_return(&optee_private->tee_active_cnt) > 1) {
+ mutex_unlock(&optee_private->tee_mutex);
+ dev_dbg(dev, MTK_DBG_VCODEC_STR "already init vdec optee private data!\n");
+ return 0;
+ }
+
+ /* Open context with TEE driver */
+ optee_private->tee_vdec_ctx = tee_client_open_context(NULL, mtk_vcodec_dec_optee_match,
+ NULL, NULL);
+ if (IS_ERR(optee_private->tee_vdec_ctx)) {
+ dev_err(dev, MTK_DBG_VCODEC_STR "optee vdec tee context failed.\n");
+ ret = PTR_ERR(optee_private->tee_vdec_ctx);
+ goto err_ctx_open;
+ }
+
+ ret = mtk_vcodec_dec_optee_init_hw_info(optee_private, MTK_VDEC_LAT0);
+ if (ret < 0)
+ goto err_lat_init;
+
+ if (IS_VDEC_LAT_ARCH(optee_private->vcodec_dev->vdec_pdata->hw_arch)) {
+ ret = mtk_vcodec_dec_optee_init_hw_info(optee_private, MTK_VDEC_CORE);
+ if (ret < 0)
+ goto err_core_init;
+ }
+
+ mutex_unlock(&optee_private->tee_mutex);
+ return 0;
+err_core_init:
+ mtk_vcodec_dec_optee_deinit_hw_info(optee_private, MTK_VDEC_LAT0);
+err_lat_init:
+ tee_client_close_context(optee_private->tee_vdec_ctx);
+err_ctx_open:
+
+ mutex_unlock(&optee_private->tee_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_open);
+
+void mtk_vcodec_dec_optee_release(struct mtk_vdec_optee_private *optee_private)
+{
+ mutex_lock(&optee_private->tee_mutex);
+ if (!atomic_dec_and_test(&optee_private->tee_active_cnt)) {
+ mutex_unlock(&optee_private->tee_mutex);
+ return;
+ }
+
+ mtk_vcodec_dec_optee_deinit_hw_info(optee_private, MTK_VDEC_LAT0);
+ if (IS_VDEC_LAT_ARCH(optee_private->vcodec_dev->vdec_pdata->hw_arch))
+ mtk_vcodec_dec_optee_deinit_hw_info(optee_private, MTK_VDEC_CORE);
+
+ tee_client_close_context(optee_private->tee_vdec_ctx);
+ mutex_unlock(&optee_private->tee_mutex);
+}
+EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_release);
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
new file mode 100644
index 000000000000..8b1dca49331e
--- /dev/null
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ * Author: Yunfei Dong <[email protected]>
+ */
+
+#ifndef _MTK_VCODEC_DEC_OPTEE_H_
+#define _MTK_VCODEC_DEC_OPTEE_H_
+
+#include <linux/tee_drv.h>
+#include <linux/uuid.h>
+
+#include "mtk_vcodec_dec_drv.h"
+
+/* The TA ID implemented in this TA */
+#define MTK_VDEC_OPTEE_TA_LAT_SUBMIT_COMMAND (0x10)
+#define MTK_VDEC_OPTEE_TA_CORE_SUBMIT_COMMAND (0x20)
+
+#define MTK_OPTEE_MAX_TEE_PARAMS 4
+
+/**
+ * struct mtk_vdec_optee_ca_info - ca related param
+ * @vdec_session_id: optee TA session identifier.
+ * @hw_id: hardware index.
+ * @vdec_session_func: trusted application function id used specific to the TA.
+ */
+struct mtk_vdec_optee_ca_info {
+ u32 vdec_session_id;
+ enum mtk_vdec_hw_id hw_id;
+ u32 vdec_session_func;
+};
+
+/**
+ * struct mtk_vdec_optee_private - optee private data
+ * @vcodec_dev: pointer to the mtk_vcodec_dev of the device
+ * @tee_vdec_ctx: decoder TEE context handler.
+ * @lat_ca: lat hardware information used to communicate with TA.
+ * @core_ca: core hardware information used to communicate with TA.
+ *
+ * @tee_active_cnt: used to mark whether need to init optee
+ * @tee_mutex: mutex lock used for optee
+ */
+struct mtk_vdec_optee_private {
+ struct mtk_vcodec_dec_dev *vcodec_dev;
+ struct tee_context *tee_vdec_ctx;
+
+ struct mtk_vdec_optee_ca_info lat_ca;
+ struct mtk_vdec_optee_ca_info core_ca;
+
+ atomic_t tee_active_cnt;
+ /* mutext used to lock optee open and release information. */
+ struct mutex tee_mutex;
+};
+
+/**
+ * mtk_vcodec_dec_optee_open - setup the communication channels with TA.
+ * @optee_private: optee private context
+ */
+int mtk_vcodec_dec_optee_open(struct mtk_vdec_optee_private *optee_private);
+
+/**
+ * mtk_vcodec_dec_optee_private_init - init optee parameters.
+ * @vcodec_dev: pointer to the mtk_vcodec_dev of the device
+ */
+int mtk_vcodec_dec_optee_private_init(struct mtk_vcodec_dec_dev *vcodec_dev);
+
+/**
+ * mtk_vcodec_dec_optee_release - close the communication channels with TA.
+ * @optee_private: optee private context
+ */
+void mtk_vcodec_dec_optee_release(struct mtk_vdec_optee_private *optee_private);
+
+#endif /* _MTK_VCODEC_FW_OPTEE_H_ */
--
2.25.1


2024-05-16 12:25:03

by Yunfei Dong (董云飞)

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

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 <[email protected]>
---
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_HI240 v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit dithered RGB */
--
2.25.1


2024-05-16 12:25:20

by Yunfei Dong (董云飞)

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

From: Jeffrey Kardatzke <[email protected]>

Adds documentation for V4L2_MEMORY_FLAG_RESTRICTED.

Signed-off-by: Jeffrey Kardatzke <[email protected]>
Signed-off-by: Yunfei Dong <[email protected]>
---
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 <mmap>` I/O and the
queue reports the :ref:`V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS
<V4L2-BUF-CAP-SUPPORTS-MMAP-CACHE-HINTS>` capability.
+ * .. _`V4L2-MEMORY-FLAG-RESTRICTED`:
+
+ - ``V4L2_MEMORY_FLAG_RESTRICTED``
+ - 0x00000002
+ - 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


2024-05-16 12:25:40

by Yunfei Dong (董云飞)

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

The hardware can parse syntax to get nal_info, needn't to use cpu.

Signed-off-by: Yunfei Dong <[email protected]>
---
.../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 = &inst->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(&inst->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(&src_buf_info->m2m_buf.vb, &lat_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, &bs->size,
+ vdec_h264_insert_startcode(inst->ctx->dev, bs->va, &bs->size,
&share_info->h264_slice_params.pps);

*res_chg = inst->resolution_changed;
--
2.25.1


2024-05-16 12:25:52

by Yunfei Dong (董云飞)

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

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 <[email protected]>
---
.../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 = &inst->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 (!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(ctx, "[h264-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.c.size = ctx->picinfo.fb_sz[1];
+
+ inst->vsi_core->dec.vdec_fb_va = (unsigned long)fb;
+ inst->vsi_core->dec.nal_info = share_info->nal_info;
+
+ inst->vsi_core->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
+ inst->vsi_core->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size;
+
+ inst->vsi_core->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr;
+ inst->vsi_core->err_map.size = lat_buf->wdma_err_addr.size;
+
+ inst->vsi_core->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr;
+ inst->vsi_core->slice_bc.size = lat_buf->slice_bc_addr.size;
+
+ inst->vsi_core->row_info.dma_addr = 0;
+ inst->vsi_core->row_info.size = 0;
+
+ inst->vsi_core->trans.dma_addr = share_info->trans_start;
+ inst->vsi_core->trans.dma_addr_end = share_info->trans_end;
+
+ for (i = 0; i < H264_MAX_MV_NUM; i++) {
+ mem = &inst->mv_buf[i];
+ inst->vsi_core->mv_buf_dma[i].dma_addr = mem->dma_addr;
+ inst->vsi_core->mv_buf_dma[i].size = mem->size;
+ }
+
+ vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, vb2_v4l2, true);
+
+ return 0;
+}
+
static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx *ctx)
{
struct vdec_h264_slice_inst *inst;
@@ -457,64 +571,22 @@ static void vdec_h264_slice_deinit(void *h_vdec)

static int vdec_h264_slice_core_decode(struct vdec_lat_buf *lat_buf)
{
- struct vdec_fb *fb;
- u64 vdec_fb_va;
- u64 y_fb_dma, c_fb_dma;
- int err, timeout, i;
+ int err, timeout;
struct mtk_vcodec_dec_ctx *ctx = lat_buf->ctx;
struct vdec_h264_slice_inst *inst = ctx->drv_handle;
- struct vb2_v4l2_buffer *vb2_v4l2;
struct vdec_h264_slice_share_info *share_info = lat_buf->private_data;
- struct mtk_vcodec_mem *mem;
struct vdec_vpu_inst *vpu = &inst->vpu;

mtk_vdec_debug(ctx, "[h264-core] vdec_h264 core decode");
memcpy(&inst->vsi_core->h264_slice_params, &share_info->h264_slice_params,
sizeof(share_info->h264_slice_params));

- fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx);
- if (!fb) {
- err = -EBUSY;
- mtk_vdec_err(ctx, "fb buffer is NULL");
+ err = vdec_h264_slice_setup_core_buffer(inst, share_info, lat_buf);
+ if (err)
goto vdec_dec_end;
- }
-
- vdec_fb_va = (unsigned long)fb;
- 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;
-
- mtk_vdec_debug(ctx, "[h264-core] y/c addr = 0x%llx 0x%llx", y_fb_dma, c_fb_dma);
-
- inst->vsi_core->dec.y_fb_dma = y_fb_dma;
- inst->vsi_core->dec.c_fb_dma = c_fb_dma;
- inst->vsi_core->dec.vdec_fb_va = vdec_fb_va;
- inst->vsi_core->dec.nal_info = share_info->nal_info;
- inst->vsi_core->wdma_start_addr =
- lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
- inst->vsi_core->wdma_end_addr =
- lat_buf->ctx->msg_queue.wdma_addr.dma_addr +
- lat_buf->ctx->msg_queue.wdma_addr.size;
- inst->vsi_core->wdma_err_addr = lat_buf->wdma_err_addr.dma_addr;
- inst->vsi_core->slice_bc_start_addr = lat_buf->slice_bc_addr.dma_addr;
- inst->vsi_core->slice_bc_end_addr = lat_buf->slice_bc_addr.dma_addr +
- lat_buf->slice_bc_addr.size;
- inst->vsi_core->trans_start = share_info->trans_start;
- inst->vsi_core->trans_end = share_info->trans_end;
- for (i = 0; i < H264_MAX_MV_NUM; i++) {
- mem = &inst->mv_buf[i];
- inst->vsi_core->mv_buf_dma[i] = mem->dma_addr;
- }
-
- vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
- v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, vb2_v4l2, true);

vdec_h264_slice_fill_decode_reflist(inst, &inst->vsi_core->h264_slice_params,
share_info);
-
err = vpu_dec_core(vpu);
if (err) {
mtk_vdec_err(ctx, "core decode err=%d", err);
@@ -573,12 +645,11 @@ 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 = &inst->vpu;
struct mtk_video_dec_buf *src_buf_info;
- int nal_start_idx, err, timeout = 0, i;
+ int nal_start_idx, err, timeout = 0;
unsigned int data[2];
struct vdec_lat_buf *lat_buf;
struct vdec_h264_slice_share_info *share_info;
unsigned char *buf;
- struct mtk_vcodec_mem *mem;

if (vdec_msg_queue_init(&inst->ctx->msg_queue, inst->ctx,
vdec_h264_slice_core_decode,
@@ -617,11 +688,9 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
if (err)
goto err_free_fb_out;

- vdec_h264_insert_startcode(inst->ctx->dev, buf, &bs->size,
- &share_info->h264_slice_params.pps);
-
- inst->vsi->dec.bs_buf_addr = (uint64_t)bs->dma_addr;
- inst->vsi->dec.bs_buf_size = bs->size;
+ if (!inst->ctx->is_secure_playback)
+ vdec_h264_insert_startcode(inst->ctx->dev, buf, &bs->size,
+ &share_info->h264_slice_params.pps);

*res_chg = inst->resolution_changed;
if (inst->resolution_changed) {
@@ -634,38 +703,27 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
}
inst->resolution_changed = false;
}
- for (i = 0; i < H264_MAX_MV_NUM; i++) {
- mem = &inst->mv_buf[i];
- inst->vsi->mv_buf_dma[i] = mem->dma_addr;
- }
- inst->vsi->wdma_start_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
- inst->vsi->wdma_end_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr +
- lat_buf->ctx->msg_queue.wdma_addr.size;
- inst->vsi->wdma_err_addr = lat_buf->wdma_err_addr.dma_addr;
- inst->vsi->slice_bc_start_addr = lat_buf->slice_bc_addr.dma_addr;
- inst->vsi->slice_bc_end_addr = lat_buf->slice_bc_addr.dma_addr +
- lat_buf->slice_bc_addr.size;
-
- inst->vsi->trans_end = inst->ctx->msg_queue.wdma_rptr_addr;
- inst->vsi->trans_start = inst->ctx->msg_queue.wdma_wptr_addr;
- mtk_vdec_debug(inst->ctx, "lat:trans(0x%llx 0x%llx) err:0x%llx",
- inst->vsi->wdma_start_addr,
- inst->vsi->wdma_end_addr,
- inst->vsi->wdma_err_addr);
-
- mtk_vdec_debug(inst->ctx, "slice(0x%llx 0x%llx) rprt((0x%llx 0x%llx))",
- inst->vsi->slice_bc_start_addr,
- inst->vsi->slice_bc_end_addr,
- inst->vsi->trans_start,
- inst->vsi->trans_end);
+
+ vdec_h264_slice_setup_lat_buffer(inst, bs, lat_buf);
+ mtk_vdec_debug(inst->ctx, "lat:trans(0x%llx 0x%lx) err:0x%llx",
+ inst->vsi->ube.dma_addr, (unsigned long)inst->vsi->ube.size,
+ inst->vsi->err_map.dma_addr);
+
+ mtk_vdec_debug(inst->ctx, "slice(0x%llx 0x%lx) rprt((0x%llx 0x%llx))",
+ inst->vsi->slice_bc.dma_addr, (unsigned long)inst->vsi->slice_bc.size,
+ inst->vsi->trans.dma_addr, inst->vsi->trans.dma_addr_end);
err = vpu_dec_start(vpu, data, 2);
if (err) {
mtk_vdec_debug(inst->ctx, "lat decode err: %d", err);
goto err_free_fb_out;
}

- share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
- inst->vsi->wdma_end_addr_offset;
+ if (inst->ctx->is_secure_playback)
+ share_info->trans_end = inst->vsi->dec.wdma_end_addr_offset;
+ else
+ share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
+ inst->vsi->dec.wdma_end_addr_offset;
+
share_info->trans_start = inst->ctx->msg_queue.wdma_wptr_addr;
share_info->nal_info = inst->vsi->dec.nal_info;

@@ -691,8 +749,11 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
return -EINVAL;
}

- share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
- inst->vsi->wdma_end_addr_offset;
+ if (inst->ctx->is_secure_playback)
+ share_info->trans_end = inst->vsi->dec.wdma_end_addr_offset;
+ else
+ share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
+ inst->vsi->dec.wdma_end_addr_offset;
vdec_msg_queue_update_ube_wptr(&lat_buf->ctx->msg_queue, share_info->trans_end);

if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
@@ -737,10 +798,10 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs
mtk_vdec_debug(inst->ctx, "[h264-dec] [%d] y_dma=%llx c_dma=%llx",
inst->ctx->decoded_frame_cnt, y_fb_dma, c_fb_dma);

- inst->vsi_ctx.dec.bs_buf_addr = (u64)bs->dma_addr;
- inst->vsi_ctx.dec.bs_buf_size = bs->size;
- inst->vsi_ctx.dec.y_fb_dma = y_fb_dma;
- inst->vsi_ctx.dec.c_fb_dma = c_fb_dma;
+ inst->vsi_ctx.bs.dma_addr = (u64)bs->dma_addr;
+ inst->vsi_ctx.bs.size = bs->size;
+ inst->vsi_ctx.fb.y.dma_addr = y_fb_dma;
+ inst->vsi_ctx.fb.c.dma_addr = c_fb_dma;
inst->vsi_ctx.dec.vdec_fb_va = (u64)(uintptr_t)fb;

v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb,
@@ -770,7 +831,7 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs

for (i = 0; i < H264_MAX_MV_NUM; i++) {
mem = &inst->mv_buf[i];
- inst->vsi_ctx.mv_buf_dma[i] = mem->dma_addr;
+ inst->vsi_ctx.mv_buf_dma[i].dma_addr = mem->dma_addr;
}
}

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c
index f283c4703dc6..c1310176ae05 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c
@@ -308,8 +308,13 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
msg_queue->wdma_addr.size = 0;
return -ENOMEM;
}
- msg_queue->wdma_rptr_addr = msg_queue->wdma_addr.dma_addr;
- msg_queue->wdma_wptr_addr = msg_queue->wdma_addr.dma_addr;
+ if (ctx->is_secure_playback) {
+ msg_queue->wdma_rptr_addr = 0;
+ msg_queue->wdma_wptr_addr = 0;
+ } else {
+ msg_queue->wdma_rptr_addr = msg_queue->wdma_addr.dma_addr;
+ msg_queue->wdma_wptr_addr = msg_queue->wdma_addr.dma_addr;
+ }

msg_queue->empty_lat_buf.ctx = ctx;
msg_queue->empty_lat_buf.core_decode = NULL;
--
2.25.1


2024-05-16 12:26:05

by Yunfei Dong (董云飞)

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

Initialize tee private data to support secure decoder.
Release tee related information for each instance when decoder
done.

Signed-off-by: Yunfei Dong <[email protected]>
---
.../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(&ctx->fh);
v4l2_ctrl_handler_free(&ctx->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(&ctx->list);
kfree(ctx);
@@ -466,6 +469,11 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
atomic_set(&dev->dec_active_cnt, 0);
memset(dev->vdec_racing_info, 0, sizeof(dev->vdec_racing_info));
mutex_init(&dev->dec_racing_info_mutex);
+ ret = mtk_vcodec_dec_optee_private_init(dev);
+ if (ret) {
+ dev_err(&pdev->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


2024-05-16 12:26:20

by Yunfei Dong (董云飞)

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

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 <[email protected]>
---
.../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);
- if (timeout)
- mtk_vdec_err(ctx, "core decode timeout: pic_%d", ctx->decoded_frame_cnt);
- inst->vsi_core->dec.timeout = !!timeout;
-
- vpu_dec_core_end(vpu);
+ if (!ctx->is_secure_playback) {
+ /* 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;
+
+ vpu_dec_core_end(vpu);
+ }
mtk_vdec_debug(ctx, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
ctx->decoded_frame_cnt,
inst->vsi_core->dec.crc[0], inst->vsi_core->dec.crc[1],
@@ -724,14 +726,16 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
}

- /* wait decoder done interrupt */
- timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
- WAIT_INTR_TIMEOUT_MS, MTK_VDEC_LAT0);
- if (timeout)
- mtk_vdec_err(inst->ctx, "lat decode timeout: pic_%d", inst->slice_dec_num);
- inst->vsi->dec.timeout = !!timeout;
+ if (!inst->ctx->is_secure_playback) {
+ /* wait decoder done interrupt */
+ timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
+ WAIT_INTR_TIMEOUT_MS, MTK_VDEC_LAT0);
+ if (timeout)
+ mtk_vdec_err(inst->ctx, "lat decode timeout: pic_%d", inst->slice_dec_num);
+ inst->vsi->dec.timeout = !!timeout;

- err = vpu_dec_end(vpu);
+ err = vpu_dec_end(vpu);
+ }
if (err == SLICE_HEADER_FULL || err == TRANS_BUFFER_FULL) {
if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability))
vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf);
@@ -831,16 +835,19 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs
if (err)
goto err_free_fb_out;

- /* wait decoder done interrupt */
- err = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
- WAIT_INTR_TIMEOUT_MS, MTK_VDEC_CORE);
- if (err)
- mtk_vdec_err(inst->ctx, "decode timeout: pic_%d", inst->ctx->decoded_frame_cnt);
-
- inst->vsi->dec.timeout = !!err;
- err = vpu_dec_end(vpu);
- if (err)
- goto err_free_fb_out;
+ if (!inst->ctx->is_secure_playback) {
+ /* wait decoder done interrupt */
+ err = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
+ WAIT_INTR_TIMEOUT_MS, MTK_VDEC_CORE);
+ if (err)
+ mtk_vdec_err(inst->ctx, "decode timeout: pic_%d",
+ inst->ctx->decoded_frame_cnt);
+
+ inst->vsi->dec.timeout = !!err;
+ err = vpu_dec_end(vpu);
+ if (err)
+ goto err_free_fb_out;
+ }

memcpy(&inst->vsi_ctx, inst->vpu.vsi, sizeof(inst->vsi_ctx));
mtk_vdec_debug(inst->ctx, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
--
2.25.1


2024-05-16 12:26:33

by Yunfei Dong (董云飞)

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

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 <[email protected]>
---
.../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 = &framebuf->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, &bs_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/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_common.c
@@ -79,15 +79,15 @@ void mtk_vdec_h264_fill_dpb_info(struct mtk_vcodec_dec_ctx *ctx,
vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
h264_dpb_info[index].field = vb2_v4l2->field;

- h264_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)
- h264_dpb_info[index].c_dma_addr =
- vb2_dma_contig_plane_dma_addr(vb, 1);
- else
- h264_dpb_info[index].c_dma_addr =
- h264_dpb_info[index].y_dma_addr +
- ctx->picinfo.fb_sz[0];
+ h264_dpb_info[index].y_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ if (!ctx->is_secure_playback) {
+ if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2)
+ h264_dpb_info[index].c_dma_addr =
+ vb2_dma_contig_plane_dma_addr(vb, 1);
+ else
+ h264_dpb_info[index].c_dma_addr =
+ h264_dpb_info[index].y_dma_addr + ctx->picinfo.fb_sz[0];
+ }
}
}

diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_drv_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec_drv_if.c
index d0b459b1603f..fb3e4f75ed93 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_drv_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_drv_if.c
@@ -73,14 +73,14 @@ int vdec_if_decode(struct mtk_vcodec_dec_ctx *ctx, struct mtk_vcodec_mem *bs,
{
int ret = 0;

- if (bs) {
+ if (bs && !ctx->is_secure_playback) {
if ((bs->dma_addr & 63) != 0) {
mtk_v4l2_vdec_err(ctx, "bs dma_addr should 64 byte align");
return -EINVAL;
}
}

- if (fb) {
+ if (fb && !ctx->is_secure_playback) {
if (((fb->base_y.dma_addr & 511) != 0) ||
((fb->base_c.dma_addr & 511) != 0)) {
mtk_v4l2_vdec_err(ctx, "frame buffer dma_addr should 512 byte align");
--
2.25.1


2024-05-16 12:26:43

by Yunfei Dong (董云飞)

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

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 <[email protected]>
---
.../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, &ctx->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, &ctx->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 {
- 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, pix_mp->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]);
+ if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ ret = mtk_vcodec_dec_init_pic_info(ctx, f->type);
}
- return 0;
+
+ return ret;
}

static int vidioc_enum_framesizes(struct file *file, void *priv,
@@ -722,7 +740,7 @@ int vb2ops_vdec_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
{
struct mtk_vcodec_dec_ctx *ctx = vb2_get_drv_priv(vq);
struct mtk_q_data *q_data;
- unsigned int i;
+ unsigned int i, ret;

q_data = mtk_vdec_get_q_data(ctx, vq->type);

@@ -731,6 +749,25 @@ int vb2ops_vdec_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
return -EINVAL;
}

+ if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (vq->restricted_mem && !ctx->is_secure_playback) {
+ ret = mtk_vcodec_dec_optee_open(ctx->dev->optee_private);
+ if (ret) {
+ mtk_v4l2_vdec_err(ctx, "Failed to open decoder optee os");
+ return ret;
+ }
+ ctx->is_secure_playback = vq->restricted_mem;
+ mtk_v4l2_vdec_dbg(1, ctx, "Getting secure decoder mode:%d",
+ ctx->is_secure_playback);
+ }
+
+ ret = mtk_vcodec_dec_init_pic_info(ctx, vq->type);
+ if (ret) {
+ mtk_v4l2_vdec_err(ctx, "Failed to init picture information");
+ return ret;
+ }
+ }
+
if (*nplanes) {
if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
if (*nplanes != q_data->fmt->num_planes)
@@ -980,6 +1017,7 @@ int mtk_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->lock = &ctx->dev->dev_mutex;
src_vq->dev = &ctx->dev->plat_dev->dev;
src_vq->allow_cache_hints = 1;
+ src_vq->allow_restricted_mem = 1;

ret = vb2_queue_init(src_vq);
if (ret) {
@@ -996,6 +1034,7 @@ int mtk_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->lock = &ctx->dev->dev_mutex;
dst_vq->dev = &ctx->dev->plat_dev->dev;
dst_vq->allow_cache_hints = 1;
+ dst_vq->allow_restricted_mem = 1;

ret = vb2_queue_init(dst_vq);
if (ret)
--
2.25.1


2024-05-16 12:28:10

by Yunfei Dong (董云飞)

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

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 <[email protected]>
---
.../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_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;

- vpu_dec_core_end(vpu);
- mtk_vdec_debug(ctx, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
- ctx->decoded_frame_cnt,
+ vpu_dec_core_end(vpu);
+ }
+ mtk_vdec_debug(ctx, "pic[%d] svp:%d crc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ ctx->decoded_frame_cnt, ctx->is_secure_playback,
inst->vsi_core->dec.crc[0], inst->vsi_core->dec.crc[1],
inst->vsi_core->dec.crc[2], inst->vsi_core->dec.crc[3],
inst->vsi_core->dec.crc[4], inst->vsi_core->dec.crc[5],
inst->vsi_core->dec.crc[6], inst->vsi_core->dec.crc[7]);
-
vdec_dec_end:
vdec_msg_queue_update_ube_rptr(&lat_buf->ctx->msg_queue, share_info->trans.dma_addr_end);
ctx->dev->vdec_pdata->cap_to_disp(ctx, !!err, lat_buf->src_buf_req);
@@ -1015,14 +1026,17 @@ static int vdec_hevc_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
}

- /* wait decoder done interrupt */
- timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
- WAIT_INTR_TIMEOUT_MS, MTK_VDEC_LAT0);
- if (timeout)
- mtk_vdec_err(inst->ctx, "lat decode timeout: pic_%d", inst->slice_dec_num);
- inst->vsi->dec.timeout = !!timeout;
+ if (!inst->ctx->is_secure_playback) {
+ /* wait decoder done interrupt */
+ timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
+ WAIT_INTR_TIMEOUT_MS, MTK_VDEC_LAT0);
+ if (timeout)
+ mtk_vdec_err(inst->ctx, "lat decode timeout: pic_%d", inst->slice_dec_num);
+ inst->vsi->dec.timeout = !!timeout;
+
+ err = vpu_dec_end(vpu);
+ }

- err = vpu_dec_end(vpu);
if (err == SLICE_HEADER_FULL || err == TRANS_BUFFER_FULL) {
if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability))
vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf);
@@ -1031,8 +1045,11 @@ static int vdec_hevc_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
return -EINVAL;
}

- share_info->trans.dma_addr_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
- inst->vsi->dec.wdma_end_addr_offset;
+ if (inst->ctx->is_secure_playback)
+ share_info->trans.dma_addr_end = inst->vsi->dec.wdma_end_addr_offset;
+ else
+ share_info->trans.dma_addr_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
+ inst->vsi->dec.wdma_end_addr_offset;
vdec_msg_queue_update_ube_wptr(&lat_buf->ctx->msg_queue, share_info->trans.dma_addr_end);

if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
@@ -1040,8 +1057,10 @@ static int vdec_hevc_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
sizeof(share_info->hevc_slice_params));
vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
}
- mtk_vdec_debug(inst->ctx, "dec num: %d lat crc: 0x%x 0x%x 0x%x", inst->slice_dec_num,
- inst->vsi->dec.crc[0], inst->vsi->dec.crc[1], inst->vsi->dec.crc[2]);
+
+ mtk_vdec_debug(inst->ctx, "dec num: %d lat crc: 0x%x 0x%x 0x%x 0x%x size:%d",
+ inst->slice_dec_num, inst->vsi->dec.crc[0], inst->vsi->dec.crc[1],
+ inst->vsi->dec.crc[2], inst->vsi->dec.crc[3], (unsigned int)bs->size);

inst->slice_dec_num++;
return 0;
--
2.25.1


2024-05-16 12:28:32

by Yunfei Dong (董云飞)

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

From: Yilong Zhou <[email protected]>

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 <[email protected]>
Signed-off-by: Yunfei Dong <[email protected]>
---
.../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 = &vsi->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, &instance->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,
if (ret)
goto err;

- vdec_vp9_slice_setup_seg_buffer(instance, vsi, &instance->seg[1]);
+ if (!instance->ctx->is_secure_playback)
+ vdec_vp9_slice_setup_seg_buffer(instance, vsi, &instance->seg[1]);

return 0;

@@ -1874,19 +1889,31 @@ static int vdec_vp9_slice_init(struct mtk_vcodec_dec_ctx *ctx)
goto error_vsi;
}
instance->init_vsi = vsi;
- instance->core_vsi = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
- (u32)vsi->core_vsi);
- if (!instance->core_vsi) {
- mtk_vdec_err(ctx, "failed to get VP9 core vsi\n");
- ret = -EINVAL;
- goto error_vsi;
- }

- instance->irq = 1;
+ if (ctx->is_secure_playback) {
+ instance->core_vsi =
+ mtk_vcodec_dec_get_shm_buffer_va(ctx->dev->optee_private, MTK_VDEC_CORE,
+ OPTEE_DATA_INDEX);
+ if (!instance->core_vsi) {
+ mtk_vdec_err(ctx, "failed to get VP9 svp core vsi\n");
+ ret = -EINVAL;
+ goto error_vsi;
+ }
+ instance->irq = 0;
+ } else {
+ instance->core_vsi = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
+ (u32)vsi->core_vsi);
+ if (!instance->core_vsi) {
+ mtk_vdec_err(ctx, "failed to get VP9 normal core vsi\n");
+ ret = -EINVAL;
+ goto error_vsi;
+ }
+ instance->irq = 1;

- ret = vdec_vp9_slice_init_default_frame_ctx(instance);
- if (ret)
- goto error_default_frame_ctx;
+ ret = vdec_vp9_slice_init_default_frame_ctx(instance);
+ if (ret)
+ goto error_default_frame_ctx;
+ }

ctx->drv_handle = instance;

@@ -2101,9 +2128,12 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
(unsigned long)pfc->vsi.trans.dma_addr,
(unsigned long)pfc->vsi.trans.dma_addr_end);

- vdec_msg_queue_update_ube_wptr(&ctx->msg_queue,
- vsi->trans.dma_addr_end +
- ctx->msg_queue.wdma_addr.dma_addr);
+ if (!instance->ctx->is_secure_playback) {
+ vsi->trans.dma_addr_end += ctx->msg_queue.wdma_addr.dma_addr;
+ mtk_vdec_debug(ctx, "core dma_addr_end 0x%lx\n",
+ (unsigned long)pfc->vsi.trans.dma_addr_end);
+ }
+ vdec_msg_queue_update_ube_wptr(&ctx->msg_queue, vsi->trans.dma_addr_end);
vdec_msg_queue_qbuf(&ctx->msg_queue.core_ctx, lat_buf);

return 0;
@@ -2183,9 +2213,6 @@ static int vdec_vp9_slice_core_decode(struct vdec_lat_buf *lat_buf)
goto err;
}

- pfc->vsi.trans.dma_addr_end += ctx->msg_queue.wdma_addr.dma_addr;
- mtk_vdec_debug(ctx, "core dma_addr_end 0x%lx\n",
- (unsigned long)pfc->vsi.trans.dma_addr_end);
vdec_msg_queue_update_ube_rptr(&ctx->msg_queue, pfc->vsi.trans.dma_addr_end);
ctx->dev->vdec_pdata->cap_to_disp(ctx, 0, lat_buf->src_buf_req);

--
2.25.1


2024-05-16 12:28:38

by Yunfei Dong (董云飞)

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

From: Xiaoyong Lu <[email protected]>

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 <[email protected]>
Signed-off-by: Yunfei Dong <[email protected]>
---
.../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, &instance->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, &instance->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, &instance->iq_table);
+ vsi->iq_table_size = AV1_IQ_TABLE_SIZE;
instance->iq_table.size = vsi->iq_table_size;

ret = mtk_vcodec_mem_alloc(ctx, &instance->iq_table);
if (ret)
return ret;

- memcpy(instance->iq_table.va, remote_iq_table, vsi->iq_table_size);
+ if (!instance->ctx->is_secure_playback) {
+ 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);
+ }

+ memcpy(instance->iq_table.va, remote_iq_table, vsi->iq_table_size);
+ }
return 0;
}

@@ -1388,7 +1398,7 @@ static int vdec_av1_slice_setup_tile_group(struct vdec_av1_slice_instance *insta
struct vdec_av1_slice_vsi *vsi)
{
struct v4l2_ctrl_av1_tile_group_entry *ctrl_tge;
- struct vdec_av1_slice_tile_group *tile_group = &instance->tile_group;
+ struct vdec_av1_slice_tile_group *tile_group = &vsi->tile_group;
struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh;
struct vdec_av1_slice_tile *tile = &uh->tile;
struct v4l2_ctrl *ctrl;
@@ -1629,7 +1639,9 @@ static void vdec_av1_slice_setup_lat_buffer(struct vdec_av1_slice_instance *inst

vsi->tile.buf = instance->tile.dma_addr;
vsi->tile.size = instance->tile.size;
- memcpy(lat_buf->tile_addr.va, instance->tile.va, 64 * instance->tile_group.num_tiles);
+ if (!instance->ctx->is_secure_playback)
+ memcpy(lat_buf->tile_addr.va, instance->tile.va,
+ 64 * vsi->tile_group.num_tiles);

vsi->cdf_table.buf = instance->cdf_table.dma_addr;
vsi->cdf_table.size = instance->cdf_table.size;
@@ -1646,7 +1658,7 @@ static void vdec_av1_slice_setup_seg_buffer(struct vdec_av1_slice_instance *inst
/* reset segment buffer */
if (uh->primary_ref_frame == AV1_PRIMARY_REF_NONE || !uh->seg.segmentation_enabled) {
mtk_vdec_debug(instance->ctx, "reset seg %d\n", vsi->slot_id);
- if (vsi->slot_id != AV1_INVALID_IDX) {
+ if (!instance->ctx->is_secure_playback && vsi->slot_id != AV1_INVALID_IDX) {
buf = &instance->seg[vsi->slot_id];
memset(buf->va, 0, buf->size);
}
@@ -1657,7 +1669,7 @@ static void vdec_av1_slice_setup_tile_buffer(struct vdec_av1_slice_instance *ins
struct vdec_av1_slice_vsi *vsi,
struct mtk_vcodec_mem *bs)
{
- struct vdec_av1_slice_tile_group *tile_group = &instance->tile_group;
+ struct vdec_av1_slice_tile_group *tile_group = &vsi->tile_group;
struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh;
struct vdec_av1_slice_tile *tile = &uh->tile;
u32 tile_num, tile_row, tile_col;
@@ -1740,7 +1752,9 @@ static int vdec_av1_slice_setup_lat(struct vdec_av1_slice_instance *instance,
return ret;

vdec_av1_slice_setup_seg_buffer(instance, vsi);
- vdec_av1_slice_setup_tile_buffer(instance, vsi, bs);
+ if (!instance->ctx->is_secure_playback)
+ vdec_av1_slice_setup_tile_buffer(instance, vsi, bs);
+
vdec_av1_slice_setup_lat_buffer(instance, vsi, bs, lat_buf);

return 0;
@@ -1803,10 +1817,15 @@ static int vdec_av1_slice_setup_core_buffer(struct vdec_av1_slice_instance *inst

/* frame buffer */
vsi->fb.y.dma_addr = fb->base_y.dma_addr;
- if (plane == 1)
- vsi->fb.c.dma_addr = fb->base_y.dma_addr + size;
- else
- vsi->fb.c.dma_addr = fb->base_c.dma_addr;
+
+ if (!instance->ctx->is_secure_playback) {
+ if (plane == 1)
+ vsi->fb.c.dma_addr = fb->base_y.dma_addr + size;
+ else
+ vsi->fb.c.dma_addr = fb->base_c.dma_addr;
+ }
+ vsi->fb.y.size = instance->ctx->picinfo.fb_sz[0];
+ vsi->fb.c.size = instance->ctx->picinfo.fb_sz[1];

/* reference buffers */
vq = v4l2_m2m_get_vq(instance->ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
@@ -1829,6 +1848,7 @@ static int vdec_av1_slice_setup_core_buffer(struct vdec_av1_slice_instance *inst
}

vref->y.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ vref->y.size = size;
if (plane == 1)
vref->c.dma_addr = vref->y.dma_addr + size;
else
@@ -1905,7 +1925,13 @@ static int vdec_av1_slice_init(struct mtk_vcodec_dec_ctx *ctx)
goto error_vsi;
}
instance->init_vsi = vsi;
- instance->core_vsi = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler, (u32)vsi->core_vsi);
+ if (ctx->is_secure_playback)
+ instance->core_vsi =
+ mtk_vcodec_dec_get_shm_buffer_va(ctx->dev->optee_private, MTK_VDEC_CORE,
+ OPTEE_DATA_INDEX);
+ else
+ instance->core_vsi = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
+ (u32)vsi->core_vsi);

if (!instance->core_vsi) {
mtk_vdec_err(ctx, "failed to get AV1 core vsi\n");
@@ -1917,11 +1943,12 @@ static int vdec_av1_slice_init(struct mtk_vcodec_dec_ctx *ctx)
mtk_vdec_err(ctx, "remote vsi size 0x%x mismatch! expected: 0x%zx\n",
vsi->vsi_size, sizeof(struct vdec_av1_slice_vsi));

- instance->irq_enabled = 1;
+ instance->irq_enabled = !ctx->is_secure_playback;
instance->inneracing_mode = IS_VDEC_INNER_RACING(instance->ctx->dev->dec_capability);

- mtk_vdec_debug(ctx, "vsi 0x%p core_vsi 0x%llx 0x%p, inneracing_mode %d\n",
- vsi, vsi->core_vsi, instance->core_vsi, instance->inneracing_mode);
+ mtk_vdec_debug(ctx, "secure %d:vsi 0x%p core_vsi 0x%llx 0x%p, inneracing_mode %d\n",
+ ctx->is_secure_playback, vsi, vsi->core_vsi, instance->core_vsi,
+ instance->inneracing_mode);

ret = vdec_av1_slice_init_cdf_table(instance);
if (ret)
@@ -2114,7 +2141,9 @@ static int vdec_av1_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf);
return -EBUSY;
}
- vsi->trans.dma_addr_end += ctx->msg_queue.wdma_addr.dma_addr;
+ if (!instance->ctx->is_secure_playback)
+ vsi->trans.dma_addr_end += ctx->msg_queue.wdma_addr.dma_addr;
+
mtk_vdec_debug(ctx, "lat dma 1 0x%pad 0x%pad\n",
&pfc->vsi.trans.dma_addr, &pfc->vsi.trans.dma_addr_end);

--
2.25.1


2024-05-17 09:54:00

by CK Hu (胡俊光)

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

Hi, Yunfei:

On Thu, 2024-05-16 at 20:20 +0800, Yunfei Dong wrote:
> 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 <[email protected]>
> ---
> .../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);
> - if (timeout)
> - mtk_vdec_err(ctx, "core decode timeout: pic_%d", ctx->decoded_frame_cnt);
> - inst->vsi_core->dec.timeout = !!timeout;
> -
> - vpu_dec_core_end(vpu);
> + if (!ctx->is_secure_playback) {
> + /* 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;
> +
> + vpu_dec_core_end(vpu);
> + }

In svp mode, optee driver would wait the irq, but why optee driver does not notify normal world driver? The normal world driver here does not wait anything and keep going, so it would get the frame
which has not been processed done and pass it to next module such as mdp? The normal world driver does not wait here, how does it make sure the frame is processed done?

Regards,

CK

> mtk_vdec_debug(ctx, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
> ctx->decoded_frame_cnt,
> inst->vsi_core->dec.crc[0], inst->vsi_core->dec.crc[1],
> @@ -724,14 +726,16 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
> vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf);
> }
>
> - /* wait decoder done interrupt */
> - timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
> - WAIT_INTR_TIMEOUT_MS, MTK_VDEC_LAT0);
> - if (timeout)
> - mtk_vdec_err(inst->ctx, "lat decode timeout: pic_%d", inst->slice_dec_num);
> - inst->vsi->dec.timeout = !!timeout;
> + if (!inst->ctx->is_secure_playback) {
> + /* wait decoder done interrupt */
> + timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
> + WAIT_INTR_TIMEOUT_MS, MTK_VDEC_LAT0);
> + if (timeout)
> + mtk_vdec_err(inst->ctx, "lat decode timeout: pic_%d", inst->slice_dec_num);
> + inst->vsi->dec.timeout = !!timeout;
>
> - err = vpu_dec_end(vpu);
> + err = vpu_dec_end(vpu);
> + }
> if (err == SLICE_HEADER_FULL || err == TRANS_BUFFER_FULL) {
> if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability))
> vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf);
> @@ -831,16 +835,19 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs
> if (err)
> goto err_free_fb_out;
>
> - /* wait decoder done interrupt */
> - err = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
> - WAIT_INTR_TIMEOUT_MS, MTK_VDEC_CORE);
> - if (err)
> - mtk_vdec_err(inst->ctx, "decode timeout: pic_%d", inst->ctx->decoded_frame_cnt);
> -
> - inst->vsi->dec.timeout = !!err;
> - err = vpu_dec_end(vpu);
> - if (err)
> - goto err_free_fb_out;
> + if (!inst->ctx->is_secure_playback) {
> + /* wait decoder done interrupt */
> + err = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
> + WAIT_INTR_TIMEOUT_MS, MTK_VDEC_CORE);
> + if (err)
> + mtk_vdec_err(inst->ctx, "decode timeout: pic_%d",
> + inst->ctx->decoded_frame_cnt);
> +
> + inst->vsi->dec.timeout = !!err;
> + err = vpu_dec_end(vpu);
> + if (err)
> + goto err_free_fb_out;
> + }
>
> memcpy(&inst->vsi_ctx, inst->vpu.vsi, sizeof(inst->vsi_ctx));
> mtk_vdec_debug(inst->ctx, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",

2024-05-22 11:16:42

by Laurent Pinchart

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

Hi Jefrey,

Thank you for the patch.

On Thu, May 16, 2024 at 08:20:42PM +0800, Yunfei Dong wrote:
> From: Jeffrey Kardatzke <[email protected]>
>
> Adds documentation for V4L2_MEMORY_FLAG_RESTRICTED.
>
> Signed-off-by: Jeffrey Kardatzke <[email protected]>
> Signed-off-by: Yunfei Dong <[email protected]>
> ---
> 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 <mmap>` I/O and the
> queue reports the :ref:`V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS
> <V4L2-BUF-CAP-SUPPORTS-MMAP-CACHE-HINTS>` capability.
> + * .. _`V4L2-MEMORY-FLAG-RESTRICTED`:
> +
> + - ``V4L2_MEMORY_FLAG_RESTRICTED``
> + - 0x00000002
> + - 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.

Why is this flag needed ? Given that the usage model requires the V4L2
device to be a dma buf importer, why would userspace set the
V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM flag and pass a non-restricted
buffer to the device ?

The V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM flag also needs to be
documented in the relevant section, I don't think that's done in this
series.

>
> .. raw:: latex
>

--
Regards,

Laurent Pinchart

2024-05-22 12:22:34

by Andrzej Pietrasiewicz

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

Hi Yunfei & Jeffrey,

W dniu 16.05.2024 o 14:20, Yunfei Dong pisze:
> From: Jeffrey Kardatzke <[email protected]>
>
> Validates the restricted memory flags when setting up a queue and
> ensures the queue has the proper capability.
>
> Signed-off-by: Jeffrey Kardatzke <[email protected]>
> Signed-off-by: Yunfei Dong <[email protected]>
> ---
> .../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;
> +

This condition is repeated in another place. If it is ever to be
changed, the person changing it must remember to look at both
places. Maybe:

static inline int restricted_mem_mismatch(bool restricted_mem,
struct vb2_queue *q, enum vb2_memory memory)
{
return restricted_mem &&
(!q->allow_restricted_mem || memory != VB2_MEMORY_DMABUF) ?
-1 : 0;
}

(you probably want to clean up line breaks)

and:

if (restricted_mem_mismatch(restricted_mem, q, memory))
return -EINVAL;

Regards,

Andrzej

> 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)
> + *caps |= V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM;
> if (max_num_bufs) {
> *max_num_bufs = q->max_num_buffers;
> *caps |= V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS;


2024-05-22 12:23:03

by Andrzej Pietrasiewicz

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

Hi Yunfei & Jeffrey,

W dniu 16.05.2024 o 14:20, Yunfei Dong pisze:
> Setting msg and vsi information to shared buffer, then call tee invoke
> function to send it to optee-os.
>
> Signed-off-by: Yunfei Dong <[email protected]>
> ---
> .../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(&optee_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 = &optee_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 = &optee_private->lat_ca;
> + else
> + ca_info = &optee_private->core_ca;

You seem to be using this in several places. Maybe create a helper?

static inline struct mtk_vdec_optee_ca_info *get_ca_info(
struct mtk_vdec_optee_private *optee_private,
enum mtk_vdec_hw_id hw_id)
{
return hw_id == MTK_VDEC_LAT0 ?
&optee_private->lat_ca : &optee_private->core_ca;
}

(you want to clean up the line breaks in this suggested function)

and then

ca_info = get_ca_info(optee_private, hw_id);

> +
> + memset(&trans_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 = &ca_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",

s/big/bigger ? Or s/big/greater ?

> + data->msg_buf_size[index], shm_memref->msg_shm_size);
> + return -EINVAL;
> + }
> +
> + ret = mtk_vcodec_dec_optee_fill_shm(&command_params[index], shm_memref,
> + data, index, dev);
> + if (ret)
> + return ret;

So if any of the iterations of this loop fails, then the data has been
potentially copied to several shm_memref->msg_shm_ca_buf and remains there until
next call to mtk_vcodec_dec_optee_fill_shm() for a corresponding ca_buf.
In other words, mtk_vcodec_dec_optee_fill_shm() has maybe filled several
ca_bufs, but if we return with error from this loop the tee function is not
invoked but the data prepared for its invocation remains in the buffers.
Don't know if this is a problem or not, but given we're dealing with restricted
aka secure memory you might want to think about it.

> + }
> +
> + ret = tee_client_invoke_func(optee_private->tee_vdec_ctx, &trans_args, command_params);
> + if (ret < 0 || trans_args.ret != 0) {
> + dev_err(dev, MTK_DBG_VCODEC_STR "tee submit command fail: 0x%x 0x%x.\n",
> + trans_args.ret, ret);
> + return (ret < 0) ? ret : trans_args.ret;
> + }
> +
> + /* clear all attrs, set all command param to unused */
> + for (index = 0; index < MTK_OPTEE_MAX_TEE_PARAMS; index++) {
> + data->msg_buf[index] = NULL;
> + data->msg_buf_size[index] = 0;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_invokd_cmd);
> +
> +void *mtk_vcodec_dec_get_shm_buffer_va(struct mtk_vdec_optee_private *optee_private,
> + enum mtk_vdec_hw_id hw_id,
> + enum mtk_vdec_optee_data_index data_index)
> +{
> + struct mtk_vdec_optee_ca_info *ca_info;
> +
> + if (hw_id == MTK_VDEC_LAT0)
> + ca_info = &optee_private->lat_ca;
> + else
> + ca_info = &optee_private->core_ca;
> +
> + return ca_info->shm_memref[data_index].msg_shm_ca_buf;
> +}
> +EXPORT_SYMBOL_GPL(mtk_vcodec_dec_get_shm_buffer_va);
> +
> +int mtk_vcodec_dec_get_shm_buffer_size(struct mtk_vdec_optee_private *optee_private,
> + enum mtk_vdec_hw_id hw_id,
> + enum mtk_vdec_optee_data_index data_index)
> +{
> + struct mtk_vdec_optee_ca_info *ca_info;
> +
> + if (hw_id == MTK_VDEC_LAT0)
> + ca_info = &optee_private->lat_ca;
> + else
> + ca_info = &optee_private->core_ca;
> +
> + return ca_info->shm_memref[data_index].msg_shm_size;
> +}
> +EXPORT_SYMBOL_GPL(mtk_vcodec_dec_get_shm_buffer_size);
> diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
> index 24aa63af9887..c24a567ec877 100644
> --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
> +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
> @@ -62,6 +62,16 @@ enum mtk_vdec_optee_data_index {
> OPTEE_MAX_INDEX,
> };
>
> +/**
> + * struct mtk_vdec_optee_data_to_shm - shm data used for TA
> + * @msg_buf: msg information to TA.
> + * @msg_buf_len: length of msg information.
> + */
> +struct mtk_vdec_optee_data_to_shm {
> + void *msg_buf[MTK_OPTEE_MAX_TEE_PARAMS];
> + int msg_buf_size[MTK_OPTEE_MAX_TEE_PARAMS];
> +};
> +
> /**
> * struct mtk_vdec_optee_private - optee private data
> * @vcodec_dev: pointer to the mtk_vcodec_dev of the device
> @@ -102,4 +112,45 @@ int mtk_vcodec_dec_optee_private_init(struct mtk_vcodec_dec_dev *vcodec_dev);
> */
> void mtk_vcodec_dec_optee_release(struct mtk_vdec_optee_private *optee_private);
>
> +/**
> + * mtk_vcodec_dec_optee_set_data - set buffer to share memref.
> + * @vcodec_dev: normal world data used to init optee share memory
> + * @buf: normal world buffer address
> + * @buf_size: buf size
> + * @data_index: indentify each share memory informaiton
> + */
> +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 data_index);
> +
> +/**
> + * mtk_vcodec_dec_optee_invokd_cmd - send share memory data to optee .
> + * @optee_private: optee private context
> + * @hw_id: hardware index
> + * @data: normal world data used to init optee share memory
> + */
> +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);
> +
> +/**
> + * mtk_vcodec_dec_get_shm_buffer_va - close the communication channels with TA.

This comment is most likely incorrect.

> + * @optee_private: optee private context
> + * @hw_id: hardware index
> + * @@data_index: indentify each share memory informaiton
> + */
> +void *mtk_vcodec_dec_get_shm_buffer_va(struct mtk_vdec_optee_private *optee_private,
> + enum mtk_vdec_hw_id hw_id,
> + enum mtk_vdec_optee_data_index data_index);
> +
> +/**
> + * mtk_vcodec_dec_get_shm_buffer_size - close the communication channels with TA.

And so is this one.

Regards,

Andrzej

> + * @optee_private: optee private context
> + * @hw_id: hardware index
> + * @@data_index: indentify each share memory informaiton
> + */
> +int mtk_vcodec_dec_get_shm_buffer_size(struct mtk_vdec_optee_private *optee_private,
> + enum mtk_vdec_hw_id hw_id,
> + enum mtk_vdec_optee_data_index data_index);
> +
> #endif /* _MTK_VCODEC_FW_OPTEE_H_ */


2024-05-22 12:24:13

by Andrzej Pietrasiewicz

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

Hi Yunfei,

W dniu 16.05.2024 o 14:20, Yunfei Dong pisze:
> 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 <[email protected]>
> ---
> .../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 = &ca_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;

Anything other than a zero possible here? In error-free exectution the return
value of zero is set far away from here. And then both error-free execution
and error recovery end in "return err;" which looks kind of weird to me.
Maybe that's just my personal preference, but I'd prefer "return 0;" here.
Alternatively, maybe rename "err" as "ret"? This applies to all patches.

I wouldn't mind a blank line here to visually separate the error recovery path
from error-free execution. This applies to all patches.

> +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 = &optee_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) {

Isn't i now equal to the index at which init memref failed?

> + for (j = 0; j < i; j++)
> + mtk_vcodec_dec_optee_deinit_memref(ca_info, j);
> + }

So instead of the above maybe:

--i;
while (i >= 0)
mtk_vcodec_dec_optee_deinit_memref(ca_info, i--);

after --i the i points to the last successfully initialized memref unless < 0.
This way you can eliminate the 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_vdec_optee_ca_info *ca_info;
> + int i;
>
> if (hw_id == MTK_VDEC_LAT0)
> ca_info = &optee_private->lat_ca;
> else
> ca_info = &optee_private->core_ca;
>
> + for (i = 0; i < OPTEE_MAX_INDEX; i++)
> + mtk_vcodec_dec_optee_deinit_memref(ca_info, i);
> +
> tee_client_close_session(optee_private->tee_vdec_ctx, ca_info->vdec_session_id);
> }
>
> diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
> index 8b1dca49331e..24aa63af9887 100644
> --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
> +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
> @@ -18,16 +18,48 @@
>
> #define MTK_OPTEE_MAX_TEE_PARAMS 4
>
> +#define MTK_VDEC_OPTEE_MSG_SIZE 128
> +#define MTK_VDEC_OPTEE_HW_SIZE (8 * SZ_1K)
> +
> +/**
> + * struct mtk_vdec_optee_shm_memref - share memory reference params

maybe s/share/shared ? Applies to other occurences as well.

Regards,

Andrzej

> + * @msg_shm: message shared with TA in TEE.
> + * @msg_shm_ca_buf: ca buffer.
> + *
> + * @msg_shm_size: share message size.
> + * @param_type: each tee param types.
> + * @copy_to_ta: need to copy data from ca to share memory.
> + */
> +struct mtk_vdec_optee_shm_memref {
> + struct tee_shm *msg_shm;
> + u8 *msg_shm_ca_buf;
> +
> + u32 msg_shm_size;
> + u64 param_type;
> + bool copy_to_ta;
> +};
> +
> /**
> * struct mtk_vdec_optee_ca_info - ca related param
> * @vdec_session_id: optee TA session identifier.
> * @hw_id: hardware index.
> * @vdec_session_func: trusted application function id used specific to the TA.
> + * @shm_memref: share memory reference params.
> */
> struct mtk_vdec_optee_ca_info {
> u32 vdec_session_id;
> enum mtk_vdec_hw_id hw_id;
> u32 vdec_session_func;
> + struct mtk_vdec_optee_shm_memref shm_memref[MTK_OPTEE_MAX_TEE_PARAMS];
> +};
> +
> +/*
> + * enum mtk_vdec_optee_data_index - used to indentify each share memory information
> + */
> +enum mtk_vdec_optee_data_index {
> + OPTEE_MSG_INDEX = 0,
> + OPTEE_DATA_INDEX,
> + OPTEE_MAX_INDEX,
> };
>
> /**


2024-05-22 12:25:56

by Andrzej Pietrasiewicz

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

Hi Yunfei,

W dniu 16.05.2024 o 14:20, Yunfei Dong pisze:
> Need to call dma heap interface to allocate/free secure memory when playing
> secure video.
>
> Signed-off-by: Yunfei Dong <[email protected]>
> ---
> .../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 <[email protected]>
> */
>
> +#include <linux/dma-heap.h>
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/regmap.h>
> +#include <uapi/linux/dma-heap.h>
>
> #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 = &ctx->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);

is (!mem->sgt) possible at all here?

In mtk_vcodec_mem_alloc_sec() "if (IS_ERR_OR_NULL(sgt))" triggers an
error recovery path and the allocation fails. Do you ever try to free_sec()
a failed allocation?

> + 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 = 0;
> + mem->size = 0;
> +}
> +
> +int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem *mem)
> +{
> + enum mtk_instance_type inst_type = *((unsigned int *)priv);
> + int ret;
> +
> + if (inst_type == MTK_INST_DECODER) {
> + struct mtk_vcodec_dec_ctx *dec_ctx = priv;
> +
> + if (dec_ctx->is_secure_playback) {
> + ret = mtk_vcodec_mem_alloc_sec(dec_ctx, mem);
> + goto alloc_end;
> + }
> + }
> +
> + ret = mtk_vcodec_mem_alloc_nor(priv, mem);
> +alloc_end:
> +

again maybe it's just my personal preference, but I'd have no goto
(not because goto is prohibited, but because maybe it's not really
justified here), fewer curly braces and no label:

int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem *mem)
{
struct mtk_vcodec_dec_ctx *dec_ctx = priv;

if (dec_ctx->inst_type == MTK_INST_DECODER && dec_ctx->is_secure_playback)
return mtk_vcodec_mem_alloc_sec(dec_ctx, mem);

return mtk_vcodec_mem_alloc_nor(priv, mem);
}

To me it makes no sense to cast priv to inst_type _and_ to dec_ctx
given that dec_ctx's first member _is_ inst_type.

> + return ret;
> +}
> +EXPORT_SYMBOL(mtk_vcodec_mem_alloc);
> +
> +void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem *mem)
> +{
> + enum mtk_instance_type inst_type = *((unsigned int *)priv);


ditto here.

Regards,

Andrzej

> +
> + if (inst_type == MTK_INST_DECODER) {
> + struct mtk_vcodec_dec_ctx *dec_ctx = priv;
> +
> + if (dec_ctx->is_secure_playback) {
> + mtk_vcodec_mem_free_sec(mem);
> + return;
> + }
> + }
> +
> + mtk_vcodec_mem_free_nor(priv, mem);
> +}
> EXPORT_SYMBOL(mtk_vcodec_mem_free);
>
> void *mtk_vcodec_get_hw_dev(struct mtk_vcodec_dec_dev *dev, int hw_idx)
> @@ -171,3 +286,4 @@ EXPORT_SYMBOL(mtk_vcodec_get_curr_ctx);
>
> MODULE_LICENSE("GPL v2");
> MODULE_DESCRIPTION("Mediatek video codec driver");
> +MODULE_IMPORT_NS(DMA_BUF);
> diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h
> index 85f615cdd4d3..22078e757ed0 100644
> --- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h
> +++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h
> @@ -18,6 +18,9 @@ struct mtk_vcodec_mem {
> size_t size;
> void *va;
> dma_addr_t dma_addr;
> +
> + struct dma_buf_attachment *attach;
> + struct sg_table *sgt;
> };
>
> struct mtk_vcodec_fb {


2024-05-22 12:26:37

by Andrzej Pietrasiewicz

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

Hi Yunfei,

W dniu 16.05.2024 o 14:20, Yunfei Dong pisze:
> 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 <[email protected]>
> ---
> 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

Maybe s/one/single ?

> + memory. Luma pixel in 16x32 tiles at the start, chroma pixel in 16x16

maybe the word "pixel" is reduntant here? What else than pixels could tile sizes mean?
Any padding between luma and chroma?

> + tiles at the end. The image height must be aligned with 32 and the image
> + width must be aligned with 16.

Maybe aligned to?

> .. 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;

s/One/Single ?

Regards,

Andrzej

> 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_HI240 v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit dithered RGB */


2024-05-22 12:30:16

by Andrzej Pietrasiewicz

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

Hi Yunfei & Jeffrey,

W dniu 16.05.2024 o 14:20, Yunfei Dong pisze:
> 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 <[email protected]>
> ---
> .../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 000000000000..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 <[email protected]>
> + */
> +
> +#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;

maybe:

return ver_data->impl_id == TEE_IMPL_ID_OPTEE;

> +}
> +
> +int mtk_vcodec_dec_optee_private_init(struct mtk_vcodec_dec_dev *vcodec_dev)
> +{
> + vcodec_dev->optee_private = devm_kzalloc(&vcodec_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(&vcodec_dev->optee_private->tee_active_cnt, 0);
> + mutex_init(&vcodec_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 = &optee_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, &mtk_vdec_lat_uuid);
> + session_func = MTK_VDEC_OPTEE_TA_LAT_SUBMIT_COMMAND;
> + ca_info = &optee_private->lat_ca;
> + break;
> + case MTK_VDEC_CORE:
> + export_uuid(session_arg.uuid, &mtk_vdec_core_uuid);
> + session_func = MTK_VDEC_OPTEE_TA_CORE_SUBMIT_COMMAND;
> + ca_info = &optee_private->core_ca;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + session_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
> + session_arg.num_params = 0;
> +
> + err = tee_client_open_session(optee_private->tee_vdec_ctx, &session_arg, NULL);
> + if (err < 0 || session_arg.ret != 0) {
> + dev_err(dev, MTK_DBG_VCODEC_STR "open vdec tee session fail hw_id:%d err:%x.\n",
> + hardware_index, session_arg.ret);
> + return -EINVAL;
> + }
> + ca_info->vdec_session_id = session_arg.session;
> + ca_info->hw_id = hardware_index;
> + ca_info->vdec_session_func = session_func;
> +
> + 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);
> +
> + return err;

Can it return anything other than a zero? I'm asking, because "return err;"
looks a bit as if it were some error recovery path. If only a zero is
possible here then maybe you want "return 0;" instead?

> +}
> +
> +static void mtk_vcodec_dec_optee_deinit_hw_info(struct mtk_vdec_optee_private *optee_private,
> + enum mtk_vdec_hw_id hw_id)
> +{
> + struct mtk_vdec_optee_ca_info *ca_info;
> +
> + if (hw_id == MTK_VDEC_LAT0)
> + ca_info = &optee_private->lat_ca;
> + else
> + ca_info = &optee_private->core_ca;
> +
> + tee_client_close_session(optee_private->tee_vdec_ctx, ca_info->vdec_session_id);
> +}
> +
> +int mtk_vcodec_dec_optee_open(struct mtk_vdec_optee_private *optee_private)
> +{
> + struct device *dev = &optee_private->vcodec_dev->plat_dev->dev;
> + int ret;
> +
> + mutex_lock(&optee_private->tee_mutex);
> + if (atomic_inc_return(&optee_private->tee_active_cnt) > 1) {
> + mutex_unlock(&optee_private->tee_mutex);
> + dev_dbg(dev, MTK_DBG_VCODEC_STR "already init vdec optee private data!\n");

maybe s/init/initialized ?

> + return 0;
> + }
> +
> + /* Open context with TEE driver */
> + optee_private->tee_vdec_ctx = tee_client_open_context(NULL, mtk_vcodec_dec_optee_match,
> + NULL, NULL);
> + if (IS_ERR(optee_private->tee_vdec_ctx)) {
> + dev_err(dev, MTK_DBG_VCODEC_STR "optee vdec tee context failed.\n");
> + ret = PTR_ERR(optee_private->tee_vdec_ctx);
> + goto err_ctx_open;
> + }
> +
> + ret = mtk_vcodec_dec_optee_init_hw_info(optee_private, MTK_VDEC_LAT0);
> + if (ret < 0)
> + goto err_lat_init;
> +
> + if (IS_VDEC_LAT_ARCH(optee_private->vcodec_dev->vdec_pdata->hw_arch)) {
> + ret = mtk_vcodec_dec_optee_init_hw_info(optee_private, MTK_VDEC_CORE);

Maybe it is ok (I'm not that much into vdec lat/core architecture), but it looks
suspicious, though. Few lines above this you initialize MTK_VDEC_LAT0, and here
you initialize MTK_VDEC_CORE but the condition asks if it is LAT. So reading
this I might conclude that if arch is not lat, then there's lat to be
initialized, but if arch is lat, then there's also core to be initialized.
Sounds confusing to me.

> + if (ret < 0)
> + goto err_core_init;
> + }
> +
> + mutex_unlock(&optee_private->tee_mutex);
> + return 0;

I wouldn't mind an empty line before and after this return 0.

> +err_core_init:
> + mtk_vcodec_dec_optee_deinit_hw_info(optee_private, MTK_VDEC_LAT0);
> +err_lat_init:
> + tee_client_close_context(optee_private->tee_vdec_ctx);
> +err_ctx_open:
> +
> + mutex_unlock(&optee_private->tee_mutex);

as well as here

> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_open);
> +
> +void mtk_vcodec_dec_optee_release(struct mtk_vdec_optee_private *optee_private)

to me a counterpart to an _open() would be _close()...

> +{
> + mutex_lock(&optee_private->tee_mutex);
> + if (!atomic_dec_and_test(&optee_private->tee_active_cnt)) {
> + mutex_unlock(&optee_private->tee_mutex);
> + return;
> + }
> +
> + mtk_vcodec_dec_optee_deinit_hw_info(optee_private, MTK_VDEC_LAT0);
> + if (IS_VDEC_LAT_ARCH(optee_private->vcodec_dev->vdec_pdata->hw_arch))
> + mtk_vcodec_dec_optee_deinit_hw_info(optee_private, MTK_VDEC_CORE);
> +
> + tee_client_close_context(optee_private->tee_vdec_ctx);

and indeed the context is being _closed_ here. Not a deal breaker, though.

Regards,

Andrzej

> + mutex_unlock(&optee_private->tee_mutex);
> +}
> +EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_release);
> diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
> new file mode 100644
> index 000000000000..8b1dca49331e
> --- /dev/null
> +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
> @@ -0,0 +1,73 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2023 MediaTek Inc.
> + * Author: Yunfei Dong <[email protected]>
> + */
> +
> +#ifndef _MTK_VCODEC_DEC_OPTEE_H_
> +#define _MTK_VCODEC_DEC_OPTEE_H_
> +
> +#include <linux/tee_drv.h>
> +#include <linux/uuid.h>
> +
> +#include "mtk_vcodec_dec_drv.h"
> +
> +/* The TA ID implemented in this TA */
> +#define MTK_VDEC_OPTEE_TA_LAT_SUBMIT_COMMAND (0x10)
> +#define MTK_VDEC_OPTEE_TA_CORE_SUBMIT_COMMAND (0x20)
> +
> +#define MTK_OPTEE_MAX_TEE_PARAMS 4
> +
> +/**
> + * struct mtk_vdec_optee_ca_info - ca related param
> + * @vdec_session_id: optee TA session identifier.
> + * @hw_id: hardware index.
> + * @vdec_session_func: trusted application function id used specific to the TA.
> + */
> +struct mtk_vdec_optee_ca_info {
> + u32 vdec_session_id;
> + enum mtk_vdec_hw_id hw_id;
> + u32 vdec_session_func;
> +};
> +
> +/**
> + * struct mtk_vdec_optee_private - optee private data
> + * @vcodec_dev: pointer to the mtk_vcodec_dev of the device
> + * @tee_vdec_ctx: decoder TEE context handler.
> + * @lat_ca: lat hardware information used to communicate with TA.
> + * @core_ca: core hardware information used to communicate with TA.
> + *
> + * @tee_active_cnt: used to mark whether need to init optee
> + * @tee_mutex: mutex lock used for optee
> + */
> +struct mtk_vdec_optee_private {
> + struct mtk_vcodec_dec_dev *vcodec_dev;
> + struct tee_context *tee_vdec_ctx;
> +
> + struct mtk_vdec_optee_ca_info lat_ca;
> + struct mtk_vdec_optee_ca_info core_ca;
> +
> + atomic_t tee_active_cnt;
> + /* mutext used to lock optee open and release information. */
> + struct mutex tee_mutex;
> +};
> +
> +/**
> + * mtk_vcodec_dec_optee_open - setup the communication channels with TA.
> + * @optee_private: optee private context
> + */
> +int mtk_vcodec_dec_optee_open(struct mtk_vdec_optee_private *optee_private);
> +
> +/**
> + * mtk_vcodec_dec_optee_private_init - init optee parameters.
> + * @vcodec_dev: pointer to the mtk_vcodec_dev of the device
> + */
> +int mtk_vcodec_dec_optee_private_init(struct mtk_vcodec_dec_dev *vcodec_dev);
> +
> +/**
> + * mtk_vcodec_dec_optee_release - close the communication channels with TA.
> + * @optee_private: optee private context
> + */
> +void mtk_vcodec_dec_optee_release(struct mtk_vdec_optee_private *optee_private);
> +
> +#endif /* _MTK_VCODEC_FW_OPTEE_H_ */


2024-05-22 12:33:14

by Andrzej Pietrasiewicz

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

Hi Yunfei & Jeffrey,

W dniu 16.05.2024 o 14:20, Yunfei Dong pisze:
> From: Jeffrey Kardatzke <[email protected]>
>
> Adds documentation for V4L2_MEMORY_FLAG_RESTRICTED.
>

Why not in the patch where the flag is actually being added?
From that commit until this commit it would be undocumented.

While at it...

> Signed-off-by: Jeffrey Kardatzke <[email protected]>
> Signed-off-by: Yunfei Dong <[email protected]>
> ---
> 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 <mmap>` I/O and the
> queue reports the :ref:`V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS
> <V4L2-BUF-CAP-SUPPORTS-MMAP-CACHE-HINTS>` capability.
> + * .. _`V4L2-MEMORY-FLAG-RESTRICTED`:
> +
> + - ``V4L2_MEMORY_FLAG_RESTRICTED``
> + - 0x00000002
> + - 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.

is V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM documented? Can it be referenced here
in a way similar to how V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS is?

Regards,

Andrzej

>
> .. raw:: latex
>


2024-05-23 10:16:08

by Andrzej Pietrasiewicz

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

Hi,

I'm having second thoughts, please see inline,

W dniu 22.05.2024 o 14:26, Andrzej Pietrasiewicz pisze:
> Hi Yunfei,
>
> W dniu 16.05.2024 o 14:20, Yunfei Dong pisze:
>> 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 <[email protected]>
>> ---
>>   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
>
> Maybe s/one/single ?
>
>> +        memory. Luma pixel in 16x32 tiles at the start, chroma pixel in 16x16
>
> maybe the word "pixel" is reduntant here? What else than pixels could tile sizes mean?
> Any padding between luma and chroma?
>
>> +        tiles at the end. The image height must be aligned with 32 and the image
>> +        width must be aligned with 16.
>
> Maybe aligned to?
>
>>   .. 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;
>
> s/One/Single ?
>

On the other hand "single" would be [in this case incorrectly] associated with
single-planar API, which would be totally confusing.

Still, the reality you are trying to model is complex: you use
MPLANE, yet there's a single plane in case of secure playback.

Regards,

Andrzej


> Regards,
>
> Andrzej
>
>>           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_HI240    v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit dithered RGB */
>


2024-05-23 10:36:29

by Chen-Yu Tsai

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

On Thu, May 23, 2024 at 6:14 PM Andrzej Pietrasiewicz
<[email protected]> wrote:
>
> Hi,
>
> I'm having second thoughts, please see inline,
>
> W dniu 22.05.2024 o 14:26, Andrzej Pietrasiewicz pisze:
> > Hi Yunfei,
> >
> > W dniu 16.05.2024 o 14:20, Yunfei Dong pisze:
> >> 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 <[email protected]>
> >> ---
> >> 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
> >
> > Maybe s/one/single ?
> >
> >> + memory. Luma pixel in 16x32 tiles at the start, chroma pixel in 16x16
> >
> > maybe the word "pixel" is reduntant here? What else than pixels could tile sizes mean?
> > Any padding between luma and chroma?
> >
> >> + tiles at the end. The image height must be aligned with 32 and the image
> >> + width must be aligned with 16.
> >
> > Maybe aligned to?
> >
> >> .. 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;
> >
> > s/One/Single ?
> >
>
> On the other hand "single" would be [in this case incorrectly] associated with
> single-planar API, which would be totally confusing.
>
> Still, the reality you are trying to model is complex: you use
> MPLANE, yet there's a single plane in case of secure playback.

I don't think that's a problem though. The NV12 format (seen above in
the diff context) has the same attributes: 1 contiguous memory plane
containing two component planes.

And it's perfectly fine for MPLANE drivers to support these formats,
Hantro being one of them that decodes to NV12. If a decoder can decode
into discontiguous buffers, it surely can decode into contiguous ones;
just set the second/third buffer address to the correct offset into
the first buffer based on the format layout.

In retrospect we probably should have named "MM21" as "MM21M" to denote
that it is multi-memory-plane, and this "MS21" would have been "MM21",
having a single contiguous memory plane.

And the MPLANE driver supporting "single memory plane" oddity gets
resolved if the API rework ever gets finished.


Regards,
ChenYu

> Regards,
>
> Andrzej
>
>
> > Regards,
> >
> > Andrzej
> >
> >> 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_HI240 v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit dithered RGB */
> >
>

2024-05-23 13:33:01

by Andrzej Pietrasiewicz

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

Hi Yunfei and Xiaoyong,

W dniu 16.05.2024 o 14:21, Yunfei Dong pisze:
> From: Xiaoyong Lu <[email protected]>
>
> 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 <[email protected]>
> Signed-off-by: Yunfei Dong <[email protected]>
> ---
> .../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, &instance->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, &instance->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);
> + }
>

In the original version mtk_vcodec_fw_map_dm_addr() is called before
mtk_vcodec_mem_alloc(), so if the former fails, the function terminates
early. After this patch is applied mtk_vcodec_mem_alloc() is called first and
when it is successful mtk_vcodec_fw_map_dm_addr() is called which may fail.
In case it fails maybe mtk_vcodec_mem_free() should be called before returning?

> 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, &instance->iq_table);
> + vsi->iq_table_size = AV1_IQ_TABLE_SIZE;
> instance->iq_table.size = vsi->iq_table_size;
>
> ret = mtk_vcodec_mem_alloc(ctx, &instance->iq_table);
> if (ret)
> return ret;
>
> - memcpy(instance->iq_table.va, remote_iq_table, vsi->iq_table_size);
> + if (!instance->ctx->is_secure_playback) {
> + 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);
> + }
>
> + memcpy(instance->iq_table.va, remote_iq_table, vsi->iq_table_size);
> + }

The same comment as above applies.

Regards,

Andrzej

> return 0;
> }
>
> @@ -1388,7 +1398,7 @@ static int vdec_av1_slice_setup_tile_group(struct vdec_av1_slice_instance *insta
> struct vdec_av1_slice_vsi *vsi)
> {
> struct v4l2_ctrl_av1_tile_group_entry *ctrl_tge;
> - struct vdec_av1_slice_tile_group *tile_group = &instance->tile_group;
> + struct vdec_av1_slice_tile_group *tile_group = &vsi->tile_group;
> struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh;
> struct vdec_av1_slice_tile *tile = &uh->tile;
> struct v4l2_ctrl *ctrl;
> @@ -1629,7 +1639,9 @@ static void vdec_av1_slice_setup_lat_buffer(struct vdec_av1_slice_instance *inst
>
> vsi->tile.buf = instance->tile.dma_addr;
> vsi->tile.size = instance->tile.size;
> - memcpy(lat_buf->tile_addr.va, instance->tile.va, 64 * instance->tile_group.num_tiles);
> + if (!instance->ctx->is_secure_playback)
> + memcpy(lat_buf->tile_addr.va, instance->tile.va,
> + 64 * vsi->tile_group.num_tiles);
>
> vsi->cdf_table.buf = instance->cdf_table.dma_addr;
> vsi->cdf_table.size = instance->cdf_table.size;
> @@ -1646,7 +1658,7 @@ static void vdec_av1_slice_setup_seg_buffer(struct vdec_av1_slice_instance *inst
> /* reset segment buffer */
> if (uh->primary_ref_frame == AV1_PRIMARY_REF_NONE || !uh->seg.segmentation_enabled) {
> mtk_vdec_debug(instance->ctx, "reset seg %d\n", vsi->slot_id);
> - if (vsi->slot_id != AV1_INVALID_IDX) {
> + if (!instance->ctx->is_secure_playback && vsi->slot_id != AV1_INVALID_IDX) {
> buf = &instance->seg[vsi->slot_id];
> memset(buf->va, 0, buf->size);
> }
> @@ -1657,7 +1669,7 @@ static void vdec_av1_slice_setup_tile_buffer(struct vdec_av1_slice_instance *ins
> struct vdec_av1_slice_vsi *vsi,
> struct mtk_vcodec_mem *bs)
> {
> - struct vdec_av1_slice_tile_group *tile_group = &instance->tile_group;
> + struct vdec_av1_slice_tile_group *tile_group = &vsi->tile_group;
> struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh;
> struct vdec_av1_slice_tile *tile = &uh->tile;
> u32 tile_num, tile_row, tile_col;
> @@ -1740,7 +1752,9 @@ static int vdec_av1_slice_setup_lat(struct vdec_av1_slice_instance *instance,
> return ret;
>
> vdec_av1_slice_setup_seg_buffer(instance, vsi);
> - vdec_av1_slice_setup_tile_buffer(instance, vsi, bs);
> + if (!instance->ctx->is_secure_playback)
> + vdec_av1_slice_setup_tile_buffer(instance, vsi, bs);
> +
> vdec_av1_slice_setup_lat_buffer(instance, vsi, bs, lat_buf);
>
> return 0;
> @@ -1803,10 +1817,15 @@ static int vdec_av1_slice_setup_core_buffer(struct vdec_av1_slice_instance *inst
>
> /* frame buffer */
> vsi->fb.y.dma_addr = fb->base_y.dma_addr;
> - if (plane == 1)
> - vsi->fb.c.dma_addr = fb->base_y.dma_addr + size;
> - else
> - vsi->fb.c.dma_addr = fb->base_c.dma_addr;
> +
> + if (!instance->ctx->is_secure_playback) {
> + if (plane == 1)
> + vsi->fb.c.dma_addr = fb->base_y.dma_addr + size;
> + else
> + vsi->fb.c.dma_addr = fb->base_c.dma_addr;
> + }
> + vsi->fb.y.size = instance->ctx->picinfo.fb_sz[0];
> + vsi->fb.c.size = instance->ctx->picinfo.fb_sz[1];
>
> /* reference buffers */
> vq = v4l2_m2m_get_vq(instance->ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
> @@ -1829,6 +1848,7 @@ static int vdec_av1_slice_setup_core_buffer(struct vdec_av1_slice_instance *inst
> }
>
> vref->y.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
> + vref->y.size = size;
> if (plane == 1)
> vref->c.dma_addr = vref->y.dma_addr + size;
> else
> @@ -1905,7 +1925,13 @@ static int vdec_av1_slice_init(struct mtk_vcodec_dec_ctx *ctx)
> goto error_vsi;
> }
> instance->init_vsi = vsi;
> - instance->core_vsi = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler, (u32)vsi->core_vsi);
> + if (ctx->is_secure_playback)
> + instance->core_vsi =
> + mtk_vcodec_dec_get_shm_buffer_va(ctx->dev->optee_private, MTK_VDEC_CORE,
> + OPTEE_DATA_INDEX);
> + else
> + instance->core_vsi = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
> + (u32)vsi->core_vsi);
>
> if (!instance->core_vsi) {
> mtk_vdec_err(ctx, "failed to get AV1 core vsi\n");
> @@ -1917,11 +1943,12 @@ static int vdec_av1_slice_init(struct mtk_vcodec_dec_ctx *ctx)
> mtk_vdec_err(ctx, "remote vsi size 0x%x mismatch! expected: 0x%zx\n",
> vsi->vsi_size, sizeof(struct vdec_av1_slice_vsi));
>
> - instance->irq_enabled = 1;
> + instance->irq_enabled = !ctx->is_secure_playback;
> instance->inneracing_mode = IS_VDEC_INNER_RACING(instance->ctx->dev->dec_capability);
>
> - mtk_vdec_debug(ctx, "vsi 0x%p core_vsi 0x%llx 0x%p, inneracing_mode %d\n",
> - vsi, vsi->core_vsi, instance->core_vsi, instance->inneracing_mode);
> + mtk_vdec_debug(ctx, "secure %d:vsi 0x%p core_vsi 0x%llx 0x%p, inneracing_mode %d\n",
> + ctx->is_secure_playback, vsi, vsi->core_vsi, instance->core_vsi,
> + instance->inneracing_mode);
>
> ret = vdec_av1_slice_init_cdf_table(instance);
> if (ret)
> @@ -2114,7 +2141,9 @@ static int vdec_av1_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
> vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf);
> return -EBUSY;
> }
> - vsi->trans.dma_addr_end += ctx->msg_queue.wdma_addr.dma_addr;
> + if (!instance->ctx->is_secure_playback)
> + vsi->trans.dma_addr_end += ctx->msg_queue.wdma_addr.dma_addr;
> +
> mtk_vdec_debug(ctx, "lat dma 1 0x%pad 0x%pad\n",
> &pfc->vsi.trans.dma_addr, &pfc->vsi.trans.dma_addr_end);
>


2024-05-27 05:59:25

by Chen-Yu Tsai

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

On Thu, May 16, 2024 at 8:21 PM Yunfei Dong <[email protected]> wrote:
>
> 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 <[email protected]>
> ---
> .../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;
> };

Hard NAK.

You are changing the interface with the firmware without any backward
compatibility. This breaks H.264 decoding on other platforms that use
this code path, including MT8192, MT8195, and MT8186. You cannot just
consider the current platform you are working on.

This is already showing in our downstream test results for Asurada / MT8192
on v6.1, same branch as MT8188, which has these patches applied.

The kernel needs to be able to run with older firmware. The firmware
needs to signal that it wants the new layout either with a version
number (which probably won't work with SCP here) or with capability
flags, like with 4K or AV1 or HEVC support we had before. The kernel
driver sees the capability flag and uses the new data structures.

Or you make changes to the layout in some backward compatible way, like
only expanding the data structure and keeping all the old fields, and
duplicating fields for new structures you add.


Regards
ChenYu

> @@ -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 = &inst->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 (!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(ctx, "[h264-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.c.size = ctx->picinfo.fb_sz[1];
> +
> + inst->vsi_core->dec.vdec_fb_va = (unsigned long)fb;
> + inst->vsi_core->dec.nal_info = share_info->nal_info;
> +
> + inst->vsi_core->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
> + inst->vsi_core->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size;
> +
> + inst->vsi_core->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr;
> + inst->vsi_core->err_map.size = lat_buf->wdma_err_addr.size;
> +
> + inst->vsi_core->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr;
> + inst->vsi_core->slice_bc.size = lat_buf->slice_bc_addr.size;
> +
> + inst->vsi_core->row_info.dma_addr = 0;
> + inst->vsi_core->row_info.size = 0;
> +
> + inst->vsi_core->trans.dma_addr = share_info->trans_start;
> + inst->vsi_core->trans.dma_addr_end = share_info->trans_end;
> +
> + for (i = 0; i < H264_MAX_MV_NUM; i++) {
> + mem = &inst->mv_buf[i];
> + inst->vsi_core->mv_buf_dma[i].dma_addr = mem->dma_addr;
> + inst->vsi_core->mv_buf_dma[i].size = mem->size;
> + }
> +
> + vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
> + v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, vb2_v4l2, true);
> +
> + return 0;
> +}
> +
> static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx *ctx)
> {
> struct vdec_h264_slice_inst *inst;
> @@ -457,64 +571,22 @@ static void vdec_h264_slice_deinit(void *h_vdec)
>
> static int vdec_h264_slice_core_decode(struct vdec_lat_buf *lat_buf)
> {
> - struct vdec_fb *fb;
> - u64 vdec_fb_va;
> - u64 y_fb_dma, c_fb_dma;
> - int err, timeout, i;
> + int err, timeout;
> struct mtk_vcodec_dec_ctx *ctx = lat_buf->ctx;
> struct vdec_h264_slice_inst *inst = ctx->drv_handle;
> - struct vb2_v4l2_buffer *vb2_v4l2;
> struct vdec_h264_slice_share_info *share_info = lat_buf->private_data;
> - struct mtk_vcodec_mem *mem;
> struct vdec_vpu_inst *vpu = &inst->vpu;
>
> mtk_vdec_debug(ctx, "[h264-core] vdec_h264 core decode");
> memcpy(&inst->vsi_core->h264_slice_params, &share_info->h264_slice_params,
> sizeof(share_info->h264_slice_params));
>
> - fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx);
> - if (!fb) {
> - err = -EBUSY;
> - mtk_vdec_err(ctx, "fb buffer is NULL");
> + err = vdec_h264_slice_setup_core_buffer(inst, share_info, lat_buf);
> + if (err)
> goto vdec_dec_end;
> - }
> -
> - vdec_fb_va = (unsigned long)fb;
> - 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;
> -
> - mtk_vdec_debug(ctx, "[h264-core] y/c addr = 0x%llx 0x%llx", y_fb_dma, c_fb_dma);
> -
> - inst->vsi_core->dec.y_fb_dma = y_fb_dma;
> - inst->vsi_core->dec.c_fb_dma = c_fb_dma;
> - inst->vsi_core->dec.vdec_fb_va = vdec_fb_va;
> - inst->vsi_core->dec.nal_info = share_info->nal_info;
> - inst->vsi_core->wdma_start_addr =
> - lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
> - inst->vsi_core->wdma_end_addr =
> - lat_buf->ctx->msg_queue.wdma_addr.dma_addr +
> - lat_buf->ctx->msg_queue.wdma_addr.size;
> - inst->vsi_core->wdma_err_addr = lat_buf->wdma_err_addr.dma_addr;
> - inst->vsi_core->slice_bc_start_addr = lat_buf->slice_bc_addr.dma_addr;
> - inst->vsi_core->slice_bc_end_addr = lat_buf->slice_bc_addr.dma_addr +
> - lat_buf->slice_bc_addr.size;
> - inst->vsi_core->trans_start = share_info->trans_start;
> - inst->vsi_core->trans_end = share_info->trans_end;
> - for (i = 0; i < H264_MAX_MV_NUM; i++) {
> - mem = &inst->mv_buf[i];
> - inst->vsi_core->mv_buf_dma[i] = mem->dma_addr;
> - }
> -
> - vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
> - v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, vb2_v4l2, true);
>
> vdec_h264_slice_fill_decode_reflist(inst, &inst->vsi_core->h264_slice_params,
> share_info);
> -
> err = vpu_dec_core(vpu);
> if (err) {
> mtk_vdec_err(ctx, "core decode err=%d", err);
> @@ -573,12 +645,11 @@ 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 = &inst->vpu;
> struct mtk_video_dec_buf *src_buf_info;
> - int nal_start_idx, err, timeout = 0, i;
> + int nal_start_idx, err, timeout = 0;
> unsigned int data[2];
> struct vdec_lat_buf *lat_buf;
> struct vdec_h264_slice_share_info *share_info;
> unsigned char *buf;
> - struct mtk_vcodec_mem *mem;
>
> if (vdec_msg_queue_init(&inst->ctx->msg_queue, inst->ctx,
> vdec_h264_slice_core_decode,
> @@ -617,11 +688,9 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
> if (err)
> goto err_free_fb_out;
>
> - vdec_h264_insert_startcode(inst->ctx->dev, buf, &bs->size,
> - &share_info->h264_slice_params.pps);
> -
> - inst->vsi->dec.bs_buf_addr = (uint64_t)bs->dma_addr;
> - inst->vsi->dec.bs_buf_size = bs->size;
> + if (!inst->ctx->is_secure_playback)
> + vdec_h264_insert_startcode(inst->ctx->dev, buf, &bs->size,
> + &share_info->h264_slice_paramspps);
>
> *res_chg = inst->resolution_changed;
> if (inst->resolution_changed) {
> @@ -634,38 +703,27 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
> }
> inst->resolution_changed = false;
> }
> - for (i = 0; i < H264_MAX_MV_NUM; i++) {
> - mem = &inst->mv_buf[i];
> - inst->vsi->mv_buf_dma[i] = mem->dma_addr;
> - }
> - inst->vsi->wdma_start_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
> - inst->vsi->wdma_end_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr +
> - lat_buf->ctx->msg_queue.wdma_addr.size;
> - inst->vsi->wdma_err_addr = lat_buf->wdma_err_addr.dma_addr;
> - inst->vsi->slice_bc_start_addr = lat_buf->slice_bc_addr.dma_addr;
> - inst->vsi->slice_bc_end_addr = lat_buf->slice_bc_addr.dma_addr +
> - lat_buf->slice_bc_addr.size;
> -
> - inst->vsi->trans_end = inst->ctx->msg_queue.wdma_rptr_addr;
> - inst->vsi->trans_start = inst->ctx->msg_queue.wdma_wptr_addr;
> - mtk_vdec_debug(inst->ctx, "lat:trans(0x%llx 0x%llx) err:0x%llx",
> - inst->vsi->wdma_start_addr,
> - inst->vsi->wdma_end_addr,
> - inst->vsi->wdma_err_addr);
> -
> - mtk_vdec_debug(inst->ctx, "slice(0x%llx 0x%llx) rprt((0x%llx 0x%llx))",
> - inst->vsi->slice_bc_start_addr,
> - inst->vsi->slice_bc_end_addr,
> - inst->vsi->trans_start,
> - inst->vsi->trans_end);
> +
> + vdec_h264_slice_setup_lat_buffer(inst, bs, lat_buf);
> + mtk_vdec_debug(inst->ctx, "lat:trans(0x%llx 0x%lx) err:0x%llx",
> + inst->vsi->ube.dma_addr, (unsigned long)inst->vsi->ube.size,
> + inst->vsi->err_map.dma_addr);
> +
> + mtk_vdec_debug(inst->ctx, "slice(0x%llx 0x%lx) rprt((0x%llx 0x%llx))",
> + inst->vsi->slice_bc.dma_addr, (unsigned long)inst->vsi->slice_bc.size,
> + inst->vsi->trans.dma_addr, inst->vsi->trans.dma_addr_end);
> err = vpu_dec_start(vpu, data, 2);
> if (err) {
> mtk_vdec_debug(inst->ctx, "lat decode err: %d", err);
> goto err_free_fb_out;
> }
>
> - share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
> - inst->vsi->wdma_end_addr_offset;
> + if (inst->ctx->is_secure_playback)
> + share_info->trans_end = inst->vsi->dec.wdma_end_addr_offset;
> + else
> + share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
> + inst->vsi->dec.wdma_end_addr_offset;
> +
> share_info->trans_start = inst->ctx->msg_queue.wdma_wptr_addr;
> share_info->nal_info = inst->vsi->dec.nal_info;
>
> @@ -691,8 +749,11 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
> return -EINVAL;
> }
>
> - share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
> - inst->vsi->wdma_end_addr_offset;
> + if (inst->ctx->is_secure_playback)
> + share_info->trans_end = inst->vsi->dec.wdma_end_addr_offset;
> + else
> + share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
> + inst->vsi->dec.wdma_end_addr_offset;
> vdec_msg_queue_update_ube_wptr(&lat_buf->ctx->msg_queue, share_info->trans_end);
>
> if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
> @@ -737,10 +798,10 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs
> mtk_vdec_debug(inst->ctx, "[h264-dec] [%d] y_dma=%llx c_dma=%llx",
> inst->ctx->decoded_frame_cnt, y_fb_dma, c_fb_dma);
>
> - inst->vsi_ctx.dec.bs_buf_addr = (u64)bs->dma_addr;
> - inst->vsi_ctx.dec.bs_buf_size = bs->size;
> - inst->vsi_ctx.dec.y_fb_dma = y_fb_dma;
> - inst->vsi_ctx.dec.c_fb_dma = c_fb_dma;
> + inst->vsi_ctx.bs.dma_addr = (u64)bs->dma_addr;
> + inst->vsi_ctx.bs.size = bs->size;
> + inst->vsi_ctx.fb.y.dma_addr = y_fb_dma;
> + inst->vsi_ctx.fb.c.dma_addr = c_fb_dma;
> inst->vsi_ctx.dec.vdec_fb_va = (u64)(uintptr_t)fb;
>
> v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb,
> @@ -770,7 +831,7 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs
>
> for (i = 0; i < H264_MAX_MV_NUM; i++) {
> mem = &inst->mv_buf[i];
> - inst->vsi_ctx.mv_buf_dma[i] = mem->dma_addr;
> + inst->vsi_ctx.mv_buf_dma[i].dma_addr = mem->dma_addr;
> }
> }
>
> diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c
> index f283c4703dc6..c1310176ae05 100644
> --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c
> +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c
> @@ -308,8 +308,13 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
> msg_queue->wdma_addr.size = 0;
> return -ENOMEM;
> }
> - msg_queue->wdma_rptr_addr = msg_queue->wdma_addr.dma_addr;
> - msg_queue->wdma_wptr_addr = msg_queue->wdma_addr.dma_addr;
> + if (ctx->is_secure_playback) {
> + msg_queue->wdma_rptr_addr = 0;
> + msg_queue->wdma_wptr_addr = 0;
> + } else {
> + msg_queue->wdma_rptr_addr = msg_queue->wdma_addr.dma_addr;
> + msg_queue->wdma_wptr_addr = msg_queue->wdma_addr.dma_addr;
> + }
>
> msg_queue->empty_lat_buf.ctx = ctx;
> msg_queue->empty_lat_buf.core_decode = NULL;
> --
> 2.25.1
>

2024-05-27 07:08:36

by Chen-Yu Tsai

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

Hi,

On Thu, May 16, 2024 at 8:21 PM Yunfei Dong <[email protected]> wrote:
>
> 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 <[email protected]>
> ---
> 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,

^
This is missing a '.' before 'pixel_enc', which breaks the build.

ChenYu

> + .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_HI240 v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit dithered RGB */
> --
> 2.25.1
>

2024-05-27 07:54:34

by Chen-Yu Tsai

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

On Thu, May 16, 2024 at 8:21 PM Yunfei Dong <[email protected]> wrote:
>
> From: Yilong Zhou <[email protected]>
>
> 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 <[email protected]>
> Signed-off-by: Yunfei Dong <[email protected]>
> ---
> .../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 = &vsi->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, &instance->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++) {

Starting in v6.10-rc1 with the introduction of REMOVE_BUFS, vq->num_buffers
was removed. There is now vq->max_num_buffers.

> + if (vb == vq->bufs[i]) {

This should probably use the helper "vb2_get_buffer(vq, i)".

ChenYu

> + 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,
> if (ret)
> goto err;
>
> - vdec_vp9_slice_setup_seg_buffer(instance, vsi, &instance->seg[1]);
> + if (!instance->ctx->is_secure_playback)
> + vdec_vp9_slice_setup_seg_buffer(instance, vsi, &instance->seg[1]);
>
> return 0;
>
> @@ -1874,19 +1889,31 @@ static int vdec_vp9_slice_init(struct mtk_vcodec_dec_ctx *ctx)
> goto error_vsi;
> }
> instance->init_vsi = vsi;
> - instance->core_vsi = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
> - (u32)vsi->core_vsi);
> - if (!instance->core_vsi) {
> - mtk_vdec_err(ctx, "failed to get VP9 core vsi\n");
> - ret = -EINVAL;
> - goto error_vsi;
> - }
>
> - instance->irq = 1;
> + if (ctx->is_secure_playback) {
> + instance->core_vsi =
> + mtk_vcodec_dec_get_shm_buffer_va(ctx->dev->optee_private, MTK_VDEC_CORE,
> + OPTEE_DATA_INDEX);
> + if (!instance->core_vsi) {
> + mtk_vdec_err(ctx, "failed to get VP9 svp core vsi\n");
> + ret = -EINVAL;
> + goto error_vsi;
> + }
> + instance->irq = 0;
> + } else {
> + instance->core_vsi = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler,
> + (u32)vsi->core_vsi);
> + if (!instance->core_vsi) {
> + mtk_vdec_err(ctx, "failed to get VP9 normal core vsi\n");
> + ret = -EINVAL;
> + goto error_vsi;
> + }
> + instance->irq = 1;
>
> - ret = vdec_vp9_slice_init_default_frame_ctx(instance);
> - if (ret)
> - goto error_default_frame_ctx;
> + ret = vdec_vp9_slice_init_default_frame_ctx(instance);
> + if (ret)
> + goto error_default_frame_ctx;
> + }
>
> ctx->drv_handle = instance;
>
> @@ -2101,9 +2128,12 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
> (unsigned long)pfc->vsi.trans.dma_addr,
> (unsigned long)pfc->vsi.trans.dma_addr_end);
>
> - vdec_msg_queue_update_ube_wptr(&ctx->msg_queue,
> - vsi->trans.dma_addr_end +
> - ctx->msg_queue.wdma_addr.dma_addr);
> + if (!instance->ctx->is_secure_playback) {
> + vsi->trans.dma_addr_end += ctx->msg_queue.wdma_addr.dma_addr;
> + mtk_vdec_debug(ctx, "core dma_addr_end 0x%lx\n",
> + (unsigned long)pfc->vsi.trans.dma_addr_end);
> + }
> + vdec_msg_queue_update_ube_wptr(&ctx->msg_queue, vsi->trans.dma_addr_end);
> vdec_msg_queue_qbuf(&ctx->msg_queue.core_ctx, lat_buf);
>
> return 0;
> @@ -2183,9 +2213,6 @@ static int vdec_vp9_slice_core_decode(struct vdec_lat_buf *lat_buf)
> goto err;
> }
>
> - pfc->vsi.trans.dma_addr_end += ctx->msg_queue.wdma_addr.dma_addr;
> - mtk_vdec_debug(ctx, "core dma_addr_end 0x%lx\n",
> - (unsigned long)pfc->vsi.trans.dma_addr_end);
> vdec_msg_queue_update_ube_rptr(&ctx->msg_queue, pfc->vsi.trans.dma_addr_end);
> ctx->dev->vdec_pdata->cap_to_disp(ctx, 0, lat_buf->src_buf_req);
>
> --
> 2.25.1
>

2024-05-27 08:19:47

by Chen-Yu Tsai

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

Hi,

On Thu, May 16, 2024 at 8:21 PM Yunfei Dong <[email protected]> wrote:
>
> 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 <[email protected]>
> ---
> .../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_drvh
> 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 000000000000..38d9c1c1785a
> --- /dev/null
> +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_opteec
> @@ -0,0 +1,165 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2023 MediaTek Inc.
> + * Author: Yunfei Dong <[email protected]>
> + */
> +
> +#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(&vcodec_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(&vcodec_dev->optee_private->tee_active_cnt, 0);
> + mutex_init(&vcodec_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 = &optee_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, &mtk_vdec_lat_uuid);
> + session_func = MTK_VDEC_OPTEE_TA_LAT_SUBMIT_COMMAND;
> + ca_info = &optee_private->lat_ca;
> + break;
> + case MTK_VDEC_CORE:
> + export_uuid(session_arg.uuid, &mtk_vdec_core_uuid);
> + session_func = MTK_VDEC_OPTEE_TA_CORE_SUBMIT_COMMAND;
> + ca_info = &optee_private->core_ca;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + session_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
> + session_arg.num_params = 0;
> +
> + err = tee_client_open_session(optee_private->tee_vdec_ctx, &session_arg, NULL);
> + if (err < 0 || session_arg.ret != 0) {
> + dev_err(dev, MTK_DBG_VCODEC_STR "open vdec tee session fail hw_id:%d err:%x.\n",
> + hardware_index, session_arg.ret);
> + return -EINVAL;
> + }
> + ca_info->vdec_session_id = session_arg.session;
> + ca_info->hw_id = hardware_index;
> + ca_info->vdec_session_func = session_func;
> +
> + 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);
> +
> + return err;
> +}
> +
> +static void mtk_vcodec_dec_optee_deinit_hw_info(struct mtk_vdec_optee_private *optee_private,
> + enum mtk_vdec_hw_id hw_id)
> +{
> + struct mtk_vdec_optee_ca_info *ca_info;
> +
> + if (hw_id == MTK_VDEC_LAT0)
> + ca_info = &optee_private->lat_ca;
> + else
> + ca_info = &optee_private->core_ca;
> +
> + tee_client_close_session(optee_private->tee_vdec_ctx, ca_info->vdec_session_id);

All the tee_* function calls make the driver depend on the TEE driver.
Either you need to make the whole vcodec driver depend on CONFIG_TEE
(which is probably not that good an idea), or isolate this OPTEE client
into a separate module, and make it depend on CONFIG_TEE. You then need
to add stub functions for the mtk_vcodec_dec_optee_* and
mtk_vcodec_dec_get_shm_* functions for when CONFIG_TEE=n and thus your
VIDEO_MEDIATEK_VCODEC_TEE=n.

Otherwise it's possible to build this driver with CONFIG_TEE=n, and the
kernel will fail to link together, or if built as a module, modpost will
fail.


ChenYu

> +}
> +
> +int mtk_vcodec_dec_optee_open(struct mtk_vdec_optee_private *optee_private)
> +{
> + struct device *dev = &optee_private->vcodec_dev->plat_dev->dev;
> + int ret;
> +
> + mutex_lock(&optee_private->tee_mutex);
> + if (atomic_inc_return(&optee_private->tee_active_cnt) > 1) {
> + mutex_unlock(&optee_private->tee_mutex);
> + dev_dbg(dev, MTK_DBG_VCODEC_STR "already init vdec optee private data!\n");
> + return 0;
> + }
> +
> + /* Open context with TEE driver */
> + optee_private->tee_vdec_ctx = tee_client_open_context(NULL, mtk_vcodec_dec_optee_match,
> + NULL, NULL);
> + if (IS_ERR(optee_private->tee_vdec_ctx)) {
> + dev_err(dev, MTK_DBG_VCODEC_STR "optee vdec tee context failed.\n");
> + ret = PTR_ERR(optee_private->tee_vdec_ctx);
> + goto err_ctx_open;
> + }
> +
> + ret = mtk_vcodec_dec_optee_init_hw_info(optee_private, MTK_VDEC_LAT0);
> + if (ret < 0)
> + goto err_lat_init;
> +
> + if (IS_VDEC_LAT_ARCH(optee_private->vcodec_dev->vdec_pdata->hw_arch)) {
> + ret = mtk_vcodec_dec_optee_init_hw_info(optee_private, MTK_VDEC_CORE);
> + if (ret < 0)
> + goto err_core_init;
> + }
> +
> + mutex_unlock(&optee_private->tee_mutex);
> + return 0;
> +err_core_init:
> + mtk_vcodec_dec_optee_deinit_hw_info(optee_private, MTK_VDEC_LAT0);
> +err_lat_init:
> + tee_client_close_context(optee_private->tee_vdec_ctx);
> +err_ctx_open:
> +
> + mutex_unlock(&optee_private->tee_mutex);
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_open);
> +
> +void mtk_vcodec_dec_optee_release(struct mtk_vdec_optee_private *optee_private)
> +{
> + mutex_lock(&optee_private->tee_mutex);
> + if (!atomic_dec_and_test(&optee_private->tee_active_cnt)) {
> + mutex_unlock(&optee_private->tee_mutex);
> + return;
> + }
> +
> + mtk_vcodec_dec_optee_deinit_hw_info(optee_private, MTK_VDEC_LAT0);
> + if (IS_VDEC_LAT_ARCH(optee_private->vcodec_dev->vdec_pdata->hw_arch))
> + mtk_vcodec_dec_optee_deinit_hw_info(optee_private, MTK_VDEC_CORE);
> +
> + tee_client_close_context(optee_private->tee_vdec_ctx);
> + mutex_unlock(&optee_private->tee_mutex);
> +}
> +EXPORT_SYMBOL_GPL(mtk_vcodec_dec_optee_release);
> diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_optee.h
> new file mode 100644
> index 000000000000..8b1dca49331e
> --- /dev/null
> +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_opteeh
> @@ -0,0 +1,73 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2023 MediaTek Inc.
> + * Author: Yunfei Dong <[email protected]>
> + */
> +
> +#ifndef _MTK_VCODEC_DEC_OPTEE_H_
> +#define _MTK_VCODEC_DEC_OPTEE_H_
> +
> +#include <linux/tee_drv.h>
> +#include <linux/uuid.h>
> +
> +#include "mtk_vcodec_dec_drv.h"
> +
> +/* The TA ID implemented in this TA */
> +#define MTK_VDEC_OPTEE_TA_LAT_SUBMIT_COMMAND (0x10)
> +#define MTK_VDEC_OPTEE_TA_CORE_SUBMIT_COMMAND (0x20)
> +
> +#define MTK_OPTEE_MAX_TEE_PARAMS 4
> +
> +/**
> + * struct mtk_vdec_optee_ca_info - ca related param
> + * @vdec_session_id: optee TA session identifier.
> + * @hw_id: hardware index.
> + * @vdec_session_func: trusted application function id used specific to the TA.
> + */
> +struct mtk_vdec_optee_ca_info {
> + u32 vdec_session_id;
> + enum mtk_vdec_hw_id hw_id;
> + u32 vdec_session_func;
> +};
> +
> +/**
> + * struct mtk_vdec_optee_private - optee private data
> + * @vcodec_dev: pointer to the mtk_vcodec_dev of the device
> + * @tee_vdec_ctx: decoder TEE context handler.
> + * @lat_ca: lat hardware information used to communicate with TA.
> + * @core_ca: core hardware information used to communicate with TA.
> + *
> + * @tee_active_cnt: used to mark whether need to init optee
> + * @tee_mutex: mutex lock used for optee
> + */
> +struct mtk_vdec_optee_private {
> + struct mtk_vcodec_dec_dev *vcodec_dev;
> + struct tee_context *tee_vdec_ctx;
> +
> + struct mtk_vdec_optee_ca_info lat_ca;
> + struct mtk_vdec_optee_ca_info core_ca;
> +
> + atomic_t tee_active_cnt;
> + /* mutext used to lock optee open and release information. */
> + struct mutex tee_mutex;
> +};
> +
> +/**
> + * mtk_vcodec_dec_optee_open - setup the communication channels with TA.
> + * @optee_private: optee private context
> + */
> +int mtk_vcodec_dec_optee_open(struct mtk_vdec_optee_private *optee_private);
> +
> +/**
> + * mtk_vcodec_dec_optee_private_init - init optee parameters.
> + * @vcodec_dev: pointer to the mtk_vcodec_dev of the device
> + */
> +int mtk_vcodec_dec_optee_private_init(struct mtk_vcodec_dec_dev *vcodec_dev);
> +
> +/**
> + * mtk_vcodec_dec_optee_release - close the communication channels with TA.
> + * @optee_private: optee private context
> + */
> +void mtk_vcodec_dec_optee_release(struct mtk_vdec_optee_private *optee_private);
> +
> +#endif /* _MTK_VCODEC_FW_OPTEE_H_ */
> --
> 2.25.1
>

2024-05-28 07:38:26

by Chen-Yu Tsai

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

On Mon, May 27, 2024 at 1:58 PM Chen-Yu Tsai <[email protected]> wrote:
>
> On Thu, May 16, 2024 at 8:21 PM Yunfei Dong <yunfei.dong@mediatekcom> wrote:
> >
> > 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 <[email protected]>
> > ---
> > .../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;
> > };
>
> Hard NAK.
>
> You are changing the interface with the firmware without any backward
> compatibility. This breaks H.264 decoding on other platforms that use
> this code path, including MT8192, MT8195, and MT8186. You cannot just
> consider the current platform you are working on.
>
> This is already showing in our downstream test results for Asurada / MT8192
> on v6.1, same branch as MT8188, which has these patches applied.

Also breaks MT8195 Cherry video decoding on v6.10-rc1 with all patches applied.

ChenYu

> The kernel needs to be able to run with older firmware. The firmware
> needs to signal that it wants the new layout either with a version
> number (which probably won't work with SCP here) or with capability
> flags, like with 4K or AV1 or HEVC support we had before. The kernel
> driver sees the capability flag and uses the new data structures.
>
> Or you make changes to the layout in some backward compatible way, like
> only expanding the data structure and keeping all the old fields, and
> duplicating fields for new structures you add.
>
>
> Regards
> ChenYu
>
> > @@ -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 = &inst->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 (!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(ctx, "[h264-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.c.size = ctx->picinfo.fb_sz[1];
> > +
> > + inst->vsi_core->dec.vdec_fb_va = (unsigned long)fb;
> > + inst->vsi_core->dec.nal_info = share_info->nal_info;
> > +
> > + inst->vsi_core->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
> > + inst->vsi_core->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size;
> > +
> > + inst->vsi_core->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr;
> > + inst->vsi_core->err_map.size = lat_buf->wdma_err_addr.size;
> > +
> > + inst->vsi_core->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr;
> > + inst->vsi_core->slice_bc.size = lat_buf->slice_bc_addr.size;
> > +
> > + inst->vsi_core->row_info.dma_addr = 0;
> > + inst->vsi_core->row_info.size = 0;
> > +
> > + inst->vsi_core->trans.dma_addr = share_info->trans_start;
> > + inst->vsi_core->trans.dma_addr_end = share_info->trans_end;
> > +
> > + for (i = 0; i < H264_MAX_MV_NUM; i++) {
> > + mem = &inst->mv_buf[i];
> > + inst->vsi_core->mv_buf_dma[i].dma_addr = mem->dma_addr;
> > + inst->vsi_core->mv_buf_dma[i].size = mem->size;
> > + }
> > +
> > + vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
> > + v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, vb2_v4l2, true);
> > +
> > + return 0;
> > +}
> > +
> > static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx *ctx)
> > {
> > struct vdec_h264_slice_inst *inst;
> > @@ -457,64 +571,22 @@ static void vdec_h264_slice_deinit(void *h_vdec)
> >
> > static int vdec_h264_slice_core_decode(struct vdec_lat_buf *lat_buf)
> > {
> > - struct vdec_fb *fb;
> > - u64 vdec_fb_va;
> > - u64 y_fb_dma, c_fb_dma;
> > - int err, timeout, i;
> > + int err, timeout;
> > struct mtk_vcodec_dec_ctx *ctx = lat_buf->ctx;
> > struct vdec_h264_slice_inst *inst = ctx->drv_handle;
> > - struct vb2_v4l2_buffer *vb2_v4l2;
> > struct vdec_h264_slice_share_info *share_info = lat_buf->private_data;
> > - struct mtk_vcodec_mem *mem;
> > struct vdec_vpu_inst *vpu = &inst->vpu;
> >
> > mtk_vdec_debug(ctx, "[h264-core] vdec_h264 core decode");
> > memcpy(&inst->vsi_core->h264_slice_params, &share_info->h264_slice_params,
> > sizeof(share_info->h264_slice_params));
> >
> > - fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx);
> > - if (!fb) {
> > - err = -EBUSY;
> > - mtk_vdec_err(ctx, "fb buffer is NULL");
> > + err = vdec_h264_slice_setup_core_buffer(inst, share_info, lat_buf);
> > + if (err)
> > goto vdec_dec_end;
> > - }
> > -
> > - vdec_fb_va = (unsigned long)fb;
> > - 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;
> > -
> > - mtk_vdec_debug(ctx, "[h264-core] y/c addr = 0x%llx 0x%llx", y_fb_dma, c_fb_dma);
> > -
> > - inst->vsi_core->dec.y_fb_dma = y_fb_dma;
> > - inst->vsi_core->dec.c_fb_dma = c_fb_dma;
> > - inst->vsi_core->dec.vdec_fb_va = vdec_fb_va;
> > - inst->vsi_core->dec.nal_info = share_info->nal_info;
> > - inst->vsi_core->wdma_start_addr =
> > - lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
> > - inst->vsi_core->wdma_end_addr =
> > - lat_buf->ctx->msg_queue.wdma_addr.dma_addr +
> > - lat_buf->ctx->msg_queue.wdma_addr.size;
> > - inst->vsi_core->wdma_err_addr = lat_buf->wdma_err_addr.dma_addr;
> > - inst->vsi_core->slice_bc_start_addr = lat_buf->slice_bc_addr.dma_addr;
> > - inst->vsi_core->slice_bc_end_addr = lat_buf->slice_bc_addr.dma_addr +
> > - lat_buf->slice_bc_addr.size;
> > - inst->vsi_core->trans_start = share_info->trans_start;
> > - inst->vsi_core->trans_end = share_info->trans_end;
> > - for (i = 0; i < H264_MAX_MV_NUM; i++) {
> > - mem = &inst->mv_buf[i];
> > - inst->vsi_core->mv_buf_dma[i] = mem->dma_addr;
> > - }
> > -
> > - vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
> > - v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, vb2_v4l2, true);
> >
> > vdec_h264_slice_fill_decode_reflist(inst, &inst->vsi_core->h264_slice_params,
> > share_info);
> > -
> > err = vpu_dec_core(vpu);
> > if (err) {
> > mtk_vdec_err(ctx, "core decode err=%d", err);
> > @@ -573,12 +645,11 @@ 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 = &inst->vpu;
> > struct mtk_video_dec_buf *src_buf_info;
> > - int nal_start_idx, err, timeout = 0, i;
> > + int nal_start_idx, err, timeout = 0;
> > unsigned int data[2];
> > struct vdec_lat_buf *lat_buf;
> > struct vdec_h264_slice_share_info *share_info;
> > unsigned char *buf;
> > - struct mtk_vcodec_mem *mem;
> >
> > if (vdec_msg_queue_init(&inst->ctx->msg_queue, inst->ctx,
> > vdec_h264_slice_core_decode,
> > @@ -617,11 +688,9 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
> > if (err)
> > goto err_free_fb_out;
> >
> > - vdec_h264_insert_startcode(inst->ctx->dev, buf, &bs->size,
> > - &share_info->h264_slice_params.pps);
> > -
> > - inst->vsi->dec.bs_buf_addr = (uint64_t)bs->dma_addr;
> > - inst->vsi->dec.bs_buf_size = bs->size;
> > + if (!inst->ctx->is_secure_playback)
> > + vdec_h264_insert_startcode(inst->ctx->dev, buf, &bs->size,
> > + &share_info->h264_slice_params.pps);
> >
> > *res_chg = inst->resolution_changed;
> > if (inst->resolution_changed) {
> > @@ -634,38 +703,27 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
> > }
> > inst->resolution_changed = false;
> > }
> > - for (i = 0; i < H264_MAX_MV_NUM; i++) {
> > - mem = &inst->mv_buf[i];
> > - inst->vsi->mv_buf_dma[i] = mem->dma_addr;
> > - }
> > - inst->vsi->wdma_start_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr;
> > - inst->vsi->wdma_end_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr +
> > - lat_buf->ctx->msg_queue.wdma_addr.size;
> > - inst->vsi->wdma_err_addr = lat_buf->wdma_err_addr.dma_addr;
> > - inst->vsi->slice_bc_start_addr = lat_buf->slice_bc_addr.dma_addr;
> > - inst->vsi->slice_bc_end_addr = lat_buf->slice_bc_addr.dma_addr +
> > - lat_buf->slice_bc_addr.size;
> > -
> > - inst->vsi->trans_end = inst->ctx->msg_queue.wdma_rptr_addr;
> > - inst->vsi->trans_start = inst->ctx->msg_queue.wdma_wptr_addr;
> > - mtk_vdec_debug(inst->ctx, "lat:trans(0x%llx 0x%llx) err:0x%llx",
> > - inst->vsi->wdma_start_addr,
> > - inst->vsi->wdma_end_addr,
> > - inst->vsi->wdma_err_addr);
> > -
> > - mtk_vdec_debug(inst->ctx, "slice(0x%llx 0x%llx) rprt((0x%llx 0x%llx))",
> > - inst->vsi->slice_bc_start_addr,
> > - inst->vsi->slice_bc_end_addr,
> > - inst->vsi->trans_start,
> > - inst->vsi->trans_end);
> > +
> > + vdec_h264_slice_setup_lat_buffer(inst, bs, lat_buf);
> > + mtk_vdec_debug(inst->ctx, "lat:trans(0x%llx 0x%lx) err:0x%llx",
> > + inst->vsi->ube.dma_addr, (unsigned long)inst->vsi->ube.size,
> > + inst->vsi->err_map.dma_addr);
> > +
> > + mtk_vdec_debug(inst->ctx, "slice(0x%llx 0x%lx) rprt((0x%llx 0x%llx))",
> > + inst->vsi->slice_bc.dma_addr, (unsigned long)inst->vsi->slice_bc.size,
> > + inst->vsi->trans.dma_addr, inst->vsi->trans.dma_addr_end);
> > err = vpu_dec_start(vpu, data, 2);
> > if (err) {
> > mtk_vdec_debug(inst->ctx, "lat decode err: %d", err);
> > goto err_free_fb_out;
> > }
> >
> > - share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
> > - inst->vsi->wdma_end_addr_offset;
> > + if (inst->ctx->is_secure_playback)
> > + share_info->trans_end = inst->vsi->dec.wdma_end_addr_offset;
> > + else
> > + share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
> > + inst->vsi->dec.wdma_end_addr_offset;
> > +
> > share_info->trans_start = inst->ctx->msg_queue.wdma_wptr_addr;
> > share_info->nal_info = inst->vsi->dec.nal_info;
> >
> > @@ -691,8 +749,11 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
> > return -EINVAL;
> > }
> >
> > - share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
> > - inst->vsi->wdma_end_addr_offset;
> > + if (inst->ctx->is_secure_playback)
> > + share_info->trans_end = inst->vsi->dec.wdma_end_addr_offset;
> > + else
> > + share_info->trans_end = inst->ctx->msg_queue.wdma_addr.dma_addr +
> > + inst->vsi->dec.wdma_end_addr_offset;
> > vdec_msg_queue_update_ube_wptr(&lat_buf->ctx->msg_queue, share_info->trans_end);
> >
> > if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) {
> > @@ -737,10 +798,10 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs
> > mtk_vdec_debug(inst->ctx, "[h264-dec] [%d] y_dma=%llx c_dma=%llx",
> > inst->ctx->decoded_frame_cnt, y_fb_dma, c_fb_dma);
> >
> > - inst->vsi_ctx.dec.bs_buf_addr = (u64)bs->dma_addr;
> > - inst->vsi_ctx.dec.bs_buf_size = bs->size;
> > - inst->vsi_ctx.dec.y_fb_dma = y_fb_dma;
> > - inst->vsi_ctx.dec.c_fb_dma = c_fb_dma;
> > + inst->vsi_ctx.bs.dma_addr = (u64)bs->dma_addr;
> > + inst->vsi_ctx.bs.size = bs->size;
> > + inst->vsi_ctx.fb.y.dma_addr = y_fb_dma;
> > + inst->vsi_ctx.fb.c.dma_addr = c_fb_dma;
> > inst->vsi_ctx.dec.vdec_fb_va = (u64)(uintptr_t)fb;
> >
> > v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb,
> > @@ -770,7 +831,7 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs
> >
> > for (i = 0; i < H264_MAX_MV_NUM; i++) {
> > mem = &inst->mv_buf[i];
> > - inst->vsi_ctx.mv_buf_dma[i] = mem->dma_addr;
> > + inst->vsi_ctx.mv_buf_dma[i].dma_addr = mem->dma_addr;
> > }
> > }
> >
> > diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c
> > index f283c4703dc6..c1310176ae05 100644
> > --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c
> > +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c
> > @@ -308,8 +308,13 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
> > msg_queue->wdma_addr.size = 0;
> > return -ENOMEM;
> > }
> > - msg_queue->wdma_rptr_addr = msg_queue->wdma_addr.dma_addr;
> > - msg_queue->wdma_wptr_addr = msg_queue->wdma_addr.dma_addr;
> > + if (ctx->is_secure_playback) {
> > + msg_queue->wdma_rptr_addr = 0;
> > + msg_queue->wdma_wptr_addr = 0;
> > + } else {
> > + msg_queue->wdma_rptr_addr = msg_queue->wdma_addr.dma_addr;
> > + msg_queue->wdma_wptr_addr = msg_queue->wdma_addr.dma_addr;
> > + }
> >
> > msg_queue->empty_lat_buf.ctx = ctx;
> > msg_queue->empty_lat_buf.core_decode = NULL;
> > --
> > 2.25.1
> >

2024-05-31 13:07:52

by Nicolas Dufresne

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

Hi,

Le jeudi 23 mai 2024 à 18:36 +0800, Chen-Yu Tsai a écrit :
> On Thu, May 23, 2024 at 6:14 PM Andrzej Pietrasiewicz
> <[email protected]> wrote:
> >
> > Hi,
> >
> > I'm having second thoughts, please see inline,
> >
> > W dniu 22.05.2024 o 14:26, Andrzej Pietrasiewicz pisze:
> > > Hi Yunfei,
> > >
> > > W dniu 16.05.2024 o 14:20, Yunfei Dong pisze:
> > > > 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 <[email protected]>
> > > > ---
> > > > 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
> > >
> > > Maybe s/one/single ?
> > >
> > > > + memory. Luma pixel in 16x32 tiles at the start, chroma pixel in 16x16
> > >
> > > maybe the word "pixel" is reduntant here? What else than pixels could tile sizes mean?
> > > Any padding between luma and chroma?
> > >
> > > > + tiles at the end. The image height must be aligned with 32 and the image
> > > > + width must be aligned with 16.
> > >
> > > Maybe aligned to?
> > >
> > > > .. 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;
> > >
> > > s/One/Single ?
> > >
> >
> > On the other hand "single" would be [in this case incorrectly] associated with
> > single-planar API, which would be totally confusing.
> >
> > Still, the reality you are trying to model is complex: you use
> > MPLANE, yet there's a single plane in case of secure playback.
>
> I don't think that's a problem though. The NV12 format (seen above in
> the diff context) has the same attributes: 1 contiguous memory plane
> containing two component planes.
>
> And it's perfectly fine for MPLANE drivers to support these formats,
> Hantro being one of them that decodes to NV12. If a decoder can decode
> into discontiguous buffers, it surely can decode into contiguous ones;
> just set the second/third buffer address to the correct offset into
> the first buffer based on the format layout.

There is some complexity and limitations not disclose here, but in 99% of the
cases I agree.

>
> In retrospect we probably should have named "MM21" as "MM21M" to denote
> that it is multi-memory-plane, and this "MS21" would have been "MM21",
> having a single contiguous memory plane.
>
> And the MPLANE driver supporting "single memory plane" oddity gets
> resolved if the API rework ever gets finished.

Not clear what you are proposing here, since its too late to rename MM21. I
agree with you there is no problem adding single allocation version of MM21 to
save on secure zones, and this is intented to be support by the MPLANE API too.

Though, on the other side, I'm thinking its an internal limitation that we must
have multiple allocation when using planar formats. We could certainly export
twice the same dmabuf, in that capture case, data_offset would be used with its
original design (driver provided). In fact, if we remove this internal
limitation, we could stop the proliferation of duplicated pixel formats in V4L2
which is quite a bad design error in my opinion.

Nicolas

>
>
> Regards,
> ChenYu
>
> > Regards,
> >
> > Andrzej
> >
> >
> > > Regards,
> > >
> > > Andrzej
> > >
> > > > 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_HI240 v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit dithered RGB */
> > >
> >


2024-05-31 13:08:50

by Nicolas Dufresne

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

Le jeudi 16 mai 2024 à 20:20 +0800, Yunfei Dong a écrit :
> 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.

Please, replace "one plane" with "single allocation". This should disambiguate
the message a little bit, since MS21 remains a semi-planar format with 2 planes.

Nicolas

>
> Signed-off-by: Yunfei Dong <[email protected]>
> ---
> .../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 = &ctx->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++;
> }


2024-06-12 04:32:56

by Tomasz Figa

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

On Thu, May 16, 2024 at 08:20:41PM +0800, Yunfei Dong wrote:
> From: Jeffrey Kardatzke <[email protected]>
>
> 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 <[email protected]>
> Signed-off-by: Yunfei Dong <[email protected]>
> ---
> 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.
> + */

Kernel coding style [1] defines multi-line comments to start with an empty
line.

[1] https://www.kernel.org/doc/html/latest/process/coding-style.html#commenting

> + if (buf->vb->vb2_queue->restricted_mem && !sg_dma_is_restricted(sgt->sgl)) {
> + pr_err("restricted queue requires restricted dma_buf");
> + return -EINVAL;

This would leak the mapping. We need to unmap the attachment here.

> + }
> +
> /* 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.
> + */

Ditto.

> + if (buf->vb->vb2_queue->restricted_mem && !sg_dma_is_restricted(sgt->sgl)) {
> + pr_err("restricted queue requires restricted dma_buf");
> + return -EINVAL;

Ditto.

Best regards,
Tomasz

> + }
> +
> buf->dma_sgt = sgt;
> buf->vaddr = NULL;
>
> --
> 2.25.1
>

2024-06-12 04:38:05

by Tomasz Figa

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

On Wed, May 22, 2024 at 02:16:22PM +0300, Laurent Pinchart wrote:
> Hi Jefrey,
>
> Thank you for the patch.
>
> On Thu, May 16, 2024 at 08:20:42PM +0800, Yunfei Dong wrote:
> > From: Jeffrey Kardatzke <[email protected]>
> >
> > Adds documentation for V4L2_MEMORY_FLAG_RESTRICTED.
> >
> > Signed-off-by: Jeffrey Kardatzke <[email protected]>
> > Signed-off-by: Yunfei Dong <[email protected]>
> > ---
> > 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 <mmap>` I/O and the
> > queue reports the :ref:`V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS
> > <V4L2-BUF-CAP-SUPPORTS-MMAP-CACHE-HINTS>` capability.
> > + * .. _`V4L2-MEMORY-FLAG-RESTRICTED`:
> > +
> > + - ``V4L2_MEMORY_FLAG_RESTRICTED``
> > + - 0x00000002
> > + - 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.
>
> Why is this flag needed ? Given that the usage model requires the V4L2
> device to be a dma buf importer, why would userspace set the
> V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM flag and pass a non-restricted
> buffer to the device ?

Given that the flag is specified at REQBUF / CREATE_BUFS time, it's
actually useful to tell the driver the queue is operating in restricted
(aka secure) mode.

I suppose we could handle that at the time of a first QBUF, but that
would make the driver initialization and validation quite a bit of pain.
So I'd say that the design being proposed here makes things simpler and
more clear, even if it doesn't add any extra functionality.

>
> The V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM flag also needs to be
> documented in the relevant section, I don't think that's done in this
> series.
>

+1

Best regards,
Tomasz

> >
> > .. raw:: latex
> >
>
> --
> Regards,
>
> Laurent Pinchart

2024-06-12 05:24:00

by Tomasz Figa

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

On Thu, May 16, 2024 at 08:20:50PM +0800, Yunfei Dong wrote:
> Need to call dma heap interface to allocate/free secure memory when playing
> secure video.
>
> Signed-off-by: Yunfei Dong <[email protected]>
> ---
> .../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 <[email protected]>
> */
>
> +#include <linux/dma-heap.h>
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/regmap.h>
> +#include <uapi/linux/dma-heap.h>
>
> #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 = &ctx->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;
> + }

How is the heap name determined here? My recollection is that the heap
name comes from the heap node in the DT, so it may vary depending on the
board.

Is the heap name documented anywhere in the DT bindings?

Shouldn't we rather query DT for a phandle to the right heap?

> +
> + 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);

This will be incorrect if NULL was returned, because the function will
return 0. Does dma_heap_buffer_alloc() actually return NULL?

> + }
> +
> + 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);

Ditto.

> + 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);

Ditto.

> + goto err_sgt;
> + }
> +
> + mem->va = dma_buffer;

Isn't this field supposed to point to the kernel mapping of the buffer
itself? If we need to store the dma_buf pointer, we should probably add
a separate field to avoid (potentially serious) bugs.

> + mem->dma_addr = (dma_addr_t)sg_dma_address((sgt)->sgl);

Why is this type cast necessary here?

> +
> + if (!mem->va || !mem->dma_addr) {

I don't think any of these 2 conditions are possible, since we already
checked for successful completion of the functions above. Also 0 is a
valid DMA address, so it shouldn't be considered an error.

> + 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:

Please name the labels according to the clean-up step they perform
first, because it will make it much easier to validate at the goto point
whether it jumps to the right place.

> + 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;
> + mem->dma_addr = 0;
> + mem->size = 0;
> +}
> +
> +int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem *mem)
> +{
> + enum mtk_instance_type inst_type = *((unsigned int *)priv);
> + int ret;
> +
> + if (inst_type == MTK_INST_DECODER) {
> + struct mtk_vcodec_dec_ctx *dec_ctx = priv;
> +
> + if (dec_ctx->is_secure_playback) {
> + ret = mtk_vcodec_mem_alloc_sec(dec_ctx, mem);
> + goto alloc_end;

Why not just return here directly?

Best regards,
Tomasz

> + }
> + }
> +
> + ret = mtk_vcodec_mem_alloc_nor(priv, mem);
> +alloc_end:
> +
> + return ret;
> +}
> +EXPORT_SYMBOL(mtk_vcodec_mem_alloc);
> +
> +void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem *mem)
> +{
> + enum mtk_instance_type inst_type = *((unsigned int *)priv);
> +
> + if (inst_type == MTK_INST_DECODER) {
> + struct mtk_vcodec_dec_ctx *dec_ctx = priv;
> +
> + if (dec_ctx->is_secure_playback) {
> + mtk_vcodec_mem_free_sec(mem);
> + return;
> + }
> + }
> +
> + mtk_vcodec_mem_free_nor(priv, mem);
> +}
> EXPORT_SYMBOL(mtk_vcodec_mem_free);
>
> void *mtk_vcodec_get_hw_dev(struct mtk_vcodec_dec_dev *dev, int hw_idx)
> @@ -171,3 +286,4 @@ EXPORT_SYMBOL(mtk_vcodec_get_curr_ctx);
>
> MODULE_LICENSE("GPL v2");
> MODULE_DESCRIPTION("Mediatek video codec driver");
> +MODULE_IMPORT_NS(DMA_BUF);
> diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h
> index 85f615cdd4d3..22078e757ed0 100644
> --- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h
> +++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h
> @@ -18,6 +18,9 @@ struct mtk_vcodec_mem {
> size_t size;
> void *va;
> dma_addr_t dma_addr;
> +
> + struct dma_buf_attachment *attach;
> + struct sg_table *sgt;
> };
>
> struct mtk_vcodec_fb {
> --
> 2.25.1
>

2024-06-12 19:44:18

by Nicolas Dufresne

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

Hi,

Le mercredi 12 juin 2024 à 13:37 +0900, Tomasz Figa a écrit :
> > Why is this flag needed ? Given that the usage model requires the V4L2
> > device to be a dma buf importer, why would userspace set the
> > V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM flag and pass a non-restricted
> > buffer to the device ?
>
> Given that the flag is specified at REQBUF / CREATE_BUFS time, it's
> actually useful to tell the driver the queue is operating in restricted
> (aka secure) mode.
>
> I suppose we could handle that at the time of a first QBUF, but that
> would make the driver initialization and validation quite a bit of pain.
> So I'd say that the design being proposed here makes things simpler and
> more clear, even if it doesn't add any extra functionality.

There is few more reasons I notice in previous series (haven't read the latest):

- The driver needs to communicate through the OPTEE rather then SCP and some
communication are needed just to figure-out things like supported profile/level
resolutions etc.
- The driver needs to allocate auxiliary buffers in secure heap too, allocation
at runtime are not the best

Note that the discussion around this flag already took place in the very first
iteration of the serie, it was originally using a CID and that was a proposed
replacement from Hans.

regards,
Nicolas

2024-06-12 20:33:19

by Laurent Pinchart

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

On Wed, Jun 12, 2024 at 03:43:58PM -0400, Nicolas Dufresne wrote:
> Le mercredi 12 juin 2024 à 13:37 +0900, Tomasz Figa a écrit :
> > > Why is this flag needed ? Given that the usage model requires the V4L2
> > > device to be a dma buf importer, why would userspace set the
> > > V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM flag and pass a non-restricted
> > > buffer to the device ?
> >
> > Given that the flag is specified at REQBUF / CREATE_BUFS time, it's
> > actually useful to tell the driver the queue is operating in restricted
> > (aka secure) mode.
> >
> > I suppose we could handle that at the time of a first QBUF, but that
> > would make the driver initialization and validation quite a bit of pain.
> > So I'd say that the design being proposed here makes things simpler and
> > more clear, even if it doesn't add any extra functionality.
>
> There is few more reasons I notice in previous series (haven't read the latest):
>
> - The driver needs to communicate through the OPTEE rather then SCP and some
> communication are needed just to figure-out things like supported profile/level
> resolutions etc.
> - The driver needs to allocate auxiliary buffers in secure heap too, allocation
> at runtime are not the best

Will the same driver support both modes on the same system ?

> Note that the discussion around this flag already took place in the very first
> iteration of the serie, it was originally using a CID and that was a proposed
> replacement from Hans.

--
Regards,

Laurent Pinchart

2024-06-12 20:59:18

by Nicolas Dufresne

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

Hi,

Le mercredi 12 juin 2024 à 23:25 +0300, Laurent Pinchart a écrit :
> On Wed, Jun 12, 2024 at 03:43:58PM -0400, Nicolas Dufresne wrote:
> > Le mercredi 12 juin 2024 à 13:37 +0900, Tomasz Figa a écrit :
> > > > Why is this flag needed ? Given that the usage model requires the V4L2
> > > > device to be a dma buf importer, why would userspace set the
> > > > V4L2_BUF_CAP_SUPPORTS_RESTRICTED_MEM flag and pass a non-restricted
> > > > buffer to the device ?
> > >
> > > Given that the flag is specified at REQBUF / CREATE_BUFS time, it's
> > > actually useful to tell the driver the queue is operating in restricted
> > > (aka secure) mode.
> > >
> > > I suppose we could handle that at the time of a first QBUF, but that
> > > would make the driver initialization and validation quite a bit of pain.
> > > So I'd say that the design being proposed here makes things simpler and
> > > more clear, even if it doesn't add any extra functionality.
> >
> > There is few more reasons I notice in previous series (haven't read the latest):
> >
> > - The driver needs to communicate through the OPTEE rather then SCP and some
> > communication are needed just to figure-out things like supported profile/level
> > resolutions etc.
> > - The driver needs to allocate auxiliary buffers in secure heap too, allocation
> > at runtime are not the best
>
> Will the same driver support both modes on the same system ?

Yes, as per this implementation, it seems you can flip from one mode to another
even on the same instance.

Nicolas

>
> > Note that the discussion around this flag already took place in the very first
> > iteration of the serie, it was originally using a CID and that was a proposed
> > replacement from Hans.
>