[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-arm-kernel mailing list