[PATCH v7 12/28] media: mediatek: vcodec: add interface to allocate/free secure memory
Yunfei Dong
yunfei.dong at mediatek.com
Sat Jul 20 00:15:50 PDT 2024
Calling dma heap interface to allocate/free secure memory when
playing secure video.
Signed-off-by: Yunfei Dong <yunfei.dong at mediatek.com>
---
.../media/platform/mediatek/vcodec/Kconfig | 1 +
.../mediatek/vcodec/common/mtk_vcodec_util.c | 117 +++++++++++++++++-
.../mediatek/vcodec/common/mtk_vcodec_util.h | 8 +-
3 files changed, 122 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/mediatek/vcodec/Kconfig b/drivers/media/platform/mediatek/vcodec/Kconfig
index ce63e1fa6118..f4c105b1d39b 100644
--- a/drivers/media/platform/mediatek/vcodec/Kconfig
+++ b/drivers/media/platform/mediatek/vcodec/Kconfig
@@ -37,6 +37,7 @@ config VIDEO_MEDIATEK_VCODEC
config VIDEO_MEDIATEK_VCODEC_TEE
bool "MediaTek Video Codec TEE driver"
+ depends on DMABUF_HEAPS
depends on OPTEE
depends on TEE
select VIDEO_MEDIATEK_VCODEC
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 fc4e34c29192..a77832f8cf46 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 <tiffany.lin at mediatek.com>
*/
+#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;
@@ -76,9 +78,71 @@ int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem *mem)
return 0;
}
-EXPORT_SYMBOL(mtk_vcodec_mem_alloc);
-void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem *mem)
+static int mtk_vcodec_mem_alloc_sec(struct mtk_vcodec_dec_ctx *ctx, struct mtk_vcodec_mem *mem)
+{
+#if IS_ENABLED(CONFIG_DMABUF_HEAPS)
+ struct device *dev = &ctx->dev->plat_dev->dev;
+ struct dma_buf *dma_buffer;
+ struct dma_heap *dma_heap;
+ struct dma_buf_attachment *attach;
+ struct sg_table *sgt;
+ unsigned long size = mem->size;
+
+ if (!size)
+ return -EINVAL;
+
+ dma_heap = dma_heap_find("restricted_mtk_cma");
+ if (!dma_heap) {
+ mtk_v4l2_vdec_err(ctx, "dma heap find failed!");
+ goto err_alloc_mem;
+ }
+
+ dma_buffer = dma_heap_buffer_alloc(dma_heap, size, DMA_HEAP_VALID_FD_FLAGS,
+ DMA_HEAP_VALID_HEAP_FLAGS);
+ if (IS_ERR(dma_buffer)) {
+ mtk_v4l2_vdec_err(ctx, "dma heap alloc size=0x%lx failed!", size);
+ dma_heap_put(dma_heap);
+ goto err_alloc_mem;
+ }
+ dma_heap_put(dma_heap);
+
+ attach = dma_buf_attach(dma_buffer, dev);
+ if (IS_ERR(attach)) {
+ mtk_v4l2_vdec_err(ctx, "dma attach size=0x%lx failed!", size);
+ dma_buf_put(dma_buffer);
+ goto err_alloc_mem;
+ }
+
+ sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+ if (IS_ERR(sgt)) {
+ mtk_v4l2_vdec_err(ctx, "dma map attach size=0x%lx failed!", size);
+ dma_buf_detach(dma_buffer, attach);
+ dma_buf_put(dma_buffer);
+ goto err_alloc_mem;
+ }
+
+ mem->dma_addr = sg_dma_address(sgt->sgl);
+ mem->dma_buf = dma_buffer;
+ mem->attach = attach;
+ mem->sgt = sgt;
+
+ return 0;
+
+err_alloc_mem:
+ mem->attach = NULL;
+ mem->dma_buf = NULL;
+ mem->sgt = NULL;
+ mem->dma_addr = 0;
+ mem->size = 0;
+
+ return -ENOMEM;
+#else
+ return -EOPNOTSUPP;
+#endif
+}
+
+static void mtk_vcodec_mem_free_nor(void *priv, struct mtk_vcodec_mem *mem)
{
enum mtk_instance_type inst_type = *((unsigned int *)priv);
struct platform_device *plat_dev;
@@ -111,6 +175,52 @@ 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 IS_ENABLED(CONFIG_DMABUF_HEAPS)
+ dma_buf_unmap_attachment(mem->attach, mem->sgt, DMA_BIDIRECTIONAL);
+ dma_buf_detach(mem->dma_buf, mem->attach);
+ dma_buf_put(mem->dma_buf);
+
+ mem->attach = NULL;
+ mem->dma_buf = NULL;
+ mem->sgt = NULL;
+ mem->dma_addr = 0;
+ mem->size = 0;
+#endif
+}
+
+int mtk_vcodec_mem_alloc(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)
+ return mtk_vcodec_mem_alloc_sec(dec_ctx, mem);
+ }
+
+ return mtk_vcodec_mem_alloc_nor(priv, mem);
+}
+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)
@@ -172,3 +282,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..0a264e4f52bf 100644
--- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h
+++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.h
@@ -16,8 +16,14 @@
struct mtk_vcodec_mem {
size_t size;
- void *va;
+ union {
+ void *va;
+ struct dma_buf *dma_buf;
+ };
dma_addr_t dma_addr;
+
+ struct dma_buf_attachment *attach;
+ struct sg_table *sgt;
};
struct mtk_vcodec_fb {
--
2.18.0
More information about the Linux-mediatek
mailing list