@@ -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
@@ -8,6 +8,8 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
+#include <linux/dma-heap.h>
+#include <uapi/linux/dma-heap.h>
#include "../decoder/mtk_vcodec_dec_drv.h"
#include "../encoder/mtk_vcodec_enc_drv.h"
@@ -45,11 +47,11 @@ int mtk_vcodec_write_vdecsys(struct mtk_vcodec_dec_ctx *ctx, unsigned int reg,
}
EXPORT_SYMBOL(mtk_vcodec_write_vdecsys);
-static int mtk_vcodec_mem_dec_alloc(void *priv, struct mtk_vcodec_mem *mem)
+static int mtk_vcodec_mem_dec_alloc_nor(struct mtk_vcodec_dec_ctx *ctx,
+ struct mtk_vcodec_mem *mem)
{
- unsigned long size = mem->size;
- struct mtk_vcodec_dec_ctx *ctx = priv;
struct device *dev = &ctx->dev->plat_dev->dev;
+ unsigned long size = mem->size;
mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL);
if (!mem->va) {
@@ -57,12 +59,89 @@ static int mtk_vcodec_mem_dec_alloc(void *priv, struct mtk_vcodec_mem *mem)
return -ENOMEM;
}
+ return 0;
+}
+
+static int mtk_vcodec_mem_dec_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("mtk_svp");
+ if (!vdec_heap) {
+ mtk_v4l2_vdec_err(ctx, "dma heap find failed!");
+ return -EPERM;
+ }
+
+ dma_buffer = dma_heap_buffer_alloc(vdec_heap, size, DMA_HEAP_VALID_FD_FLAGS,
+ DMA_HEAP_VALID_HEAP_FLAGS);
+ if (IS_ERR_OR_NULL(dma_buffer)) {
+ mtk_v4l2_vdec_err(ctx, "dma heap alloc size=0x%lx failed!", size);
+ return PTR_ERR(dma_buffer);
+ }
+
+ attach = dma_buf_attach(dma_buffer, dev);
+ if (IS_ERR_OR_NULL(attach)) {
+ mtk_v4l2_vdec_err(ctx, "dma attach size=0x%lx failed!", size);
+ ret = PTR_ERR(attach);
+ goto err_attach;
+ }
+
+ sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+ if (IS_ERR_OR_NULL(sgt)) {
+ mtk_v4l2_vdec_err(ctx, "dma map attach size=0x%lx failed!", size);
+ ret = PTR_ERR(sgt);
+ goto err_sgt;
+ }
+
+ mem->va = dma_buffer;
+ mem->dma_addr = (dma_addr_t)sg_dma_address((sgt)->sgl);
+
+ if (!mem->va || !mem->dma_addr) {
+ mtk_v4l2_vdec_err(ctx, "dma buffer size=0x%lx failed!", size);
+ ret = -EPERM;
+ goto err_addr;
+ }
+
+ mem->attach = attach;
+ mem->sgt = sgt;
+
+ return 0;
+err_addr:
+ dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+err_sgt:
+ dma_buf_detach(dma_buffer, attach);
+err_attach:
+ dma_buf_put(dma_buffer);
+
+ return ret;
+}
+
+static int mtk_vcodec_mem_dec_alloc(void *priv, struct mtk_vcodec_mem *mem)
+{
+ struct mtk_vcodec_dec_ctx *ctx = priv;
+ int ret;
+
+ if (ctx->is_svp_mode)
+ ret = mtk_vcodec_mem_dec_alloc_sec(ctx, mem);
+ else
+ ret = mtk_vcodec_mem_dec_alloc_nor(ctx, mem);
+
mtk_v4l2_vdec_dbg(3, ctx, "[%d] - va = %p", ctx->id, mem->va);
mtk_v4l2_vdec_dbg(3, ctx, "[%d] - dma = 0x%lx", ctx->id,
(unsigned long)mem->dma_addr);
- mtk_v4l2_vdec_dbg(3, ctx, "[%d] size = 0x%lx", ctx->id, size);
+ mtk_v4l2_vdec_dbg(3, ctx, "[%d] size = 0x%lx", ctx->id, (unsigned long)mem->size);
- return 0;
+ return ret;
}
static int mtk_vcodec_mem_enc_alloc(void *priv, struct mtk_vcodec_mem *mem)
@@ -96,6 +175,31 @@ int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem *mem)
}
EXPORT_SYMBOL(mtk_vcodec_mem_alloc);
+static void mtk_vcodec_mem_dec_free_nor(struct mtk_vcodec_dec_ctx *ctx,
+ struct mtk_vcodec_mem *mem)
+{
+ struct device *dev = &ctx->dev->plat_dev->dev;
+
+ dma_free_coherent(dev, mem->size, mem->va, mem->dma_addr);
+
+ mem->va = NULL;
+ mem->dma_addr = 0;
+ mem->size = 0;
+}
+
+static void mtk_vcodec_mem_dec_free_sec(struct mtk_vcodec_mem *mem)
+{
+ 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;
+}
+
static void mtk_vcodec_mem_dec_free(void *priv, struct mtk_vcodec_mem *mem)
{
unsigned long size = mem->size;
@@ -112,10 +216,10 @@ static void mtk_vcodec_mem_dec_free(void *priv, struct mtk_vcodec_mem *mem)
(unsigned long)mem->dma_addr);
mtk_v4l2_vdec_dbg(3, ctx, "[%d] size = 0x%lx", ctx->id, size);
- dma_free_coherent(dev, size, mem->va, mem->dma_addr);
- mem->va = NULL;
- mem->dma_addr = 0;
- mem->size = 0;
+ if (ctx->is_svp_mode)
+ mtk_vcodec_mem_dec_free_sec(mem);
+ else
+ mtk_vcodec_mem_dec_free_nor(ctx, mem);
}
static void mtk_vcodec_mem_enc_free(void *priv, struct mtk_vcodec_mem *mem)
@@ -210,3 +314,4 @@ EXPORT_SYMBOL(mtk_vcodec_get_curr_ctx);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Mediatek video codec driver");
+MODULE_IMPORT_NS(DMA_BUF);
@@ -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 {
Need to call dma heap interface to allocate/free secure memory when playing secure video. Signed-off-by: Yunfei Dong <yunfei.dong@mediatek.com> --- .../media/platform/mediatek/vcodec/Kconfig | 1 + .../mediatek/vcodec/common/mtk_vcodec_util.c | 123 ++++++++++++++++-- .../mediatek/vcodec/common/mtk_vcodec_util.h | 3 + 3 files changed, 118 insertions(+), 9 deletions(-)