10934d375SYunfei Dong // SPDX-License-Identifier: GPL-2.0
20934d375SYunfei Dong /*
30934d375SYunfei Dong * Copyright (c) 2016 MediaTek Inc.
40934d375SYunfei Dong * Author: PC Chen <pc.chen@mediatek.com>
50934d375SYunfei Dong *	Tiffany Lin <tiffany.lin@mediatek.com>
60934d375SYunfei Dong */
70934d375SYunfei Dong 
80934d375SYunfei Dong #include <linux/module.h>
90934d375SYunfei Dong #include <linux/of.h>
100934d375SYunfei Dong #include <linux/regmap.h>
110934d375SYunfei Dong 
120934d375SYunfei Dong #include "../decoder/mtk_vcodec_dec_drv.h"
130934d375SYunfei Dong #include "../encoder/mtk_vcodec_enc_drv.h"
140934d375SYunfei Dong #include "../decoder/mtk_vcodec_dec_hw.h"
150934d375SYunfei Dong 
160934d375SYunfei Dong #if defined(CONFIG_DEBUG_FS)
170934d375SYunfei Dong int mtk_vcodec_dbg;
180934d375SYunfei Dong EXPORT_SYMBOL(mtk_vcodec_dbg);
190934d375SYunfei Dong 
200934d375SYunfei Dong int mtk_v4l2_dbg_level;
210934d375SYunfei Dong EXPORT_SYMBOL(mtk_v4l2_dbg_level);
220934d375SYunfei Dong #endif
230934d375SYunfei Dong 
mtk_vcodec_get_reg_addr(void __iomem ** reg_base,unsigned int reg_idx)240934d375SYunfei Dong void __iomem *mtk_vcodec_get_reg_addr(void __iomem **reg_base, unsigned int reg_idx)
250934d375SYunfei Dong {
260934d375SYunfei Dong 	if (reg_idx >= NUM_MAX_VCODEC_REG_BASE) {
270934d375SYunfei Dong 		pr_err(MTK_DBG_V4L2_STR "Invalid arguments, reg_idx=%d", reg_idx);
280934d375SYunfei Dong 		return NULL;
290934d375SYunfei Dong 	}
300934d375SYunfei Dong 	return reg_base[reg_idx];
310934d375SYunfei Dong }
320934d375SYunfei Dong EXPORT_SYMBOL(mtk_vcodec_get_reg_addr);
330934d375SYunfei Dong 
mtk_vcodec_write_vdecsys(struct mtk_vcodec_dec_ctx * ctx,unsigned int reg,unsigned int val)340934d375SYunfei Dong int mtk_vcodec_write_vdecsys(struct mtk_vcodec_dec_ctx *ctx, unsigned int reg,
350934d375SYunfei Dong 			     unsigned int val)
360934d375SYunfei Dong {
370934d375SYunfei Dong 	struct mtk_vcodec_dec_dev *dev = ctx->dev;
380934d375SYunfei Dong 
390934d375SYunfei Dong 	if (dev->vdecsys_regmap)
400934d375SYunfei Dong 		return regmap_write(dev->vdecsys_regmap, reg, val);
410934d375SYunfei Dong 
420934d375SYunfei Dong 	writel(val, dev->reg_base[VDEC_SYS] + reg);
430934d375SYunfei Dong 
440934d375SYunfei Dong 	return 0;
450934d375SYunfei Dong }
460934d375SYunfei Dong EXPORT_SYMBOL(mtk_vcodec_write_vdecsys);
470934d375SYunfei Dong 
mtk_vcodec_mem_alloc(void * priv,struct mtk_vcodec_mem * mem)480934d375SYunfei Dong int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem *mem)
490934d375SYunfei Dong {
50*8bdaa92bSYunfei Dong 	enum mtk_instance_type inst_type = *((unsigned int *)priv);
51*8bdaa92bSYunfei Dong 	struct platform_device *plat_dev;
520934d375SYunfei Dong 	unsigned long size = mem->size;
53*8bdaa92bSYunfei Dong 	int id;
540934d375SYunfei Dong 
55*8bdaa92bSYunfei Dong 	if (inst_type == MTK_INST_ENCODER) {
56*8bdaa92bSYunfei Dong 		struct mtk_vcodec_enc_ctx *enc_ctx = priv;
57*8bdaa92bSYunfei Dong 
58*8bdaa92bSYunfei Dong 		plat_dev = enc_ctx->dev->plat_dev;
59*8bdaa92bSYunfei Dong 		id = enc_ctx->id;
60*8bdaa92bSYunfei Dong 	} else {
61*8bdaa92bSYunfei Dong 		struct mtk_vcodec_dec_ctx *dec_ctx = priv;
62*8bdaa92bSYunfei Dong 
63*8bdaa92bSYunfei Dong 		plat_dev = dec_ctx->dev->plat_dev;
64*8bdaa92bSYunfei Dong 		id = dec_ctx->id;
65*8bdaa92bSYunfei Dong 	}
66*8bdaa92bSYunfei Dong 
67*8bdaa92bSYunfei Dong 	mem->va = dma_alloc_coherent(&plat_dev->dev, size, &mem->dma_addr, GFP_KERNEL);
680934d375SYunfei Dong 	if (!mem->va) {
69*8bdaa92bSYunfei Dong 		mtk_v4l2_err(plat_dev, "%s dma_alloc size=%ld failed!",
70*8bdaa92bSYunfei Dong 			     dev_name(&plat_dev->dev), size);
710934d375SYunfei Dong 		return -ENOMEM;
720934d375SYunfei Dong 	}
730934d375SYunfei Dong 
74*8bdaa92bSYunfei Dong 	mtk_v4l2_debug(plat_dev, 3, "[%d] - va = %p dma = 0x%lx size = 0x%lx", id, mem->va,
75*8bdaa92bSYunfei Dong 		       (unsigned long)mem->dma_addr, size);
760934d375SYunfei Dong 
770934d375SYunfei Dong 	return 0;
780934d375SYunfei Dong }
790934d375SYunfei Dong EXPORT_SYMBOL(mtk_vcodec_mem_alloc);
800934d375SYunfei Dong 
mtk_vcodec_mem_free(void * priv,struct mtk_vcodec_mem * mem)810934d375SYunfei Dong void mtk_vcodec_mem_free(void *priv, struct mtk_vcodec_mem *mem)
820934d375SYunfei Dong {
83*8bdaa92bSYunfei Dong 	enum mtk_instance_type inst_type = *((unsigned int *)priv);
84*8bdaa92bSYunfei Dong 	struct platform_device *plat_dev;
850934d375SYunfei Dong 	unsigned long size = mem->size;
86*8bdaa92bSYunfei Dong 	int id;
87*8bdaa92bSYunfei Dong 
88*8bdaa92bSYunfei Dong 	if (inst_type == MTK_INST_ENCODER) {
89*8bdaa92bSYunfei Dong 		struct mtk_vcodec_enc_ctx *enc_ctx = priv;
90*8bdaa92bSYunfei Dong 
91*8bdaa92bSYunfei Dong 		plat_dev = enc_ctx->dev->plat_dev;
92*8bdaa92bSYunfei Dong 		id = enc_ctx->id;
93*8bdaa92bSYunfei Dong 	} else {
94*8bdaa92bSYunfei Dong 		struct mtk_vcodec_dec_ctx *dec_ctx = priv;
95*8bdaa92bSYunfei Dong 
96*8bdaa92bSYunfei Dong 		plat_dev = dec_ctx->dev->plat_dev;
97*8bdaa92bSYunfei Dong 		id = dec_ctx->id;
98*8bdaa92bSYunfei Dong 	}
990934d375SYunfei Dong 
1000934d375SYunfei Dong 	if (!mem->va) {
101*8bdaa92bSYunfei Dong 		mtk_v4l2_err(plat_dev, "%s dma_free size=%ld failed!",
102*8bdaa92bSYunfei Dong 			     dev_name(&plat_dev->dev), size);
1030934d375SYunfei Dong 		return;
1040934d375SYunfei Dong 	}
1050934d375SYunfei Dong 
106*8bdaa92bSYunfei Dong 	mtk_v4l2_debug(plat_dev, 3, "[%d] - va = %p dma = 0x%lx size = 0x%lx", id, mem->va,
107*8bdaa92bSYunfei Dong 		       (unsigned long)mem->dma_addr, size);
1080934d375SYunfei Dong 
109*8bdaa92bSYunfei Dong 	dma_free_coherent(&plat_dev->dev, size, mem->va, mem->dma_addr);
1100934d375SYunfei Dong 	mem->va = NULL;
1110934d375SYunfei Dong 	mem->dma_addr = 0;
1120934d375SYunfei Dong 	mem->size = 0;
1130934d375SYunfei Dong }
1140934d375SYunfei Dong EXPORT_SYMBOL(mtk_vcodec_mem_free);
1150934d375SYunfei Dong 
mtk_vcodec_get_hw_dev(struct mtk_vcodec_dec_dev * dev,int hw_idx)1160934d375SYunfei Dong void *mtk_vcodec_get_hw_dev(struct mtk_vcodec_dec_dev *dev, int hw_idx)
1170934d375SYunfei Dong {
1180934d375SYunfei Dong 	if (hw_idx >= MTK_VDEC_HW_MAX || hw_idx < 0 || !dev->subdev_dev[hw_idx]) {
1190934d375SYunfei Dong 		dev_err(&dev->plat_dev->dev, "hw idx is out of range:%d", hw_idx);
1200934d375SYunfei Dong 		return NULL;
1210934d375SYunfei Dong 	}
1220934d375SYunfei Dong 
1230934d375SYunfei Dong 	return dev->subdev_dev[hw_idx];
1240934d375SYunfei Dong }
1250934d375SYunfei Dong EXPORT_SYMBOL(mtk_vcodec_get_hw_dev);
1260934d375SYunfei Dong 
mtk_vcodec_set_curr_ctx(struct mtk_vcodec_dec_dev * vdec_dev,struct mtk_vcodec_dec_ctx * ctx,int hw_idx)1270934d375SYunfei Dong void mtk_vcodec_set_curr_ctx(struct mtk_vcodec_dec_dev *vdec_dev,
1280934d375SYunfei Dong 			     struct mtk_vcodec_dec_ctx *ctx, int hw_idx)
1290934d375SYunfei Dong {
1300934d375SYunfei Dong 	unsigned long flags;
1310934d375SYunfei Dong 	struct mtk_vdec_hw_dev *subdev_dev;
1320934d375SYunfei Dong 
1330934d375SYunfei Dong 	spin_lock_irqsave(&vdec_dev->irqlock, flags);
1340934d375SYunfei Dong 	if (vdec_dev->vdec_pdata->is_subdev_supported) {
1350934d375SYunfei Dong 		subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx);
1360934d375SYunfei Dong 		if (!subdev_dev) {
1370934d375SYunfei Dong 			dev_err(&vdec_dev->plat_dev->dev, "Failed to get hw dev");
1380934d375SYunfei Dong 			spin_unlock_irqrestore(&vdec_dev->irqlock, flags);
1390934d375SYunfei Dong 			return;
1400934d375SYunfei Dong 		}
1410934d375SYunfei Dong 		subdev_dev->curr_ctx = ctx;
1420934d375SYunfei Dong 	} else {
1430934d375SYunfei Dong 		vdec_dev->curr_ctx = ctx;
1440934d375SYunfei Dong 	}
1450934d375SYunfei Dong 	spin_unlock_irqrestore(&vdec_dev->irqlock, flags);
1460934d375SYunfei Dong }
1470934d375SYunfei Dong EXPORT_SYMBOL(mtk_vcodec_set_curr_ctx);
1480934d375SYunfei Dong 
mtk_vcodec_get_curr_ctx(struct mtk_vcodec_dec_dev * vdec_dev,unsigned int hw_idx)1490934d375SYunfei Dong struct mtk_vcodec_dec_ctx *mtk_vcodec_get_curr_ctx(struct mtk_vcodec_dec_dev *vdec_dev,
1500934d375SYunfei Dong 						   unsigned int hw_idx)
1510934d375SYunfei Dong {
1520934d375SYunfei Dong 	unsigned long flags;
1530934d375SYunfei Dong 	struct mtk_vcodec_dec_ctx *ctx;
1540934d375SYunfei Dong 	struct mtk_vdec_hw_dev *subdev_dev;
1550934d375SYunfei Dong 
1560934d375SYunfei Dong 	spin_lock_irqsave(&vdec_dev->irqlock, flags);
1570934d375SYunfei Dong 	if (vdec_dev->vdec_pdata->is_subdev_supported) {
1580934d375SYunfei Dong 		subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx);
1590934d375SYunfei Dong 		if (!subdev_dev) {
1600934d375SYunfei Dong 			dev_err(&vdec_dev->plat_dev->dev, "Failed to get hw dev");
1610934d375SYunfei Dong 			spin_unlock_irqrestore(&vdec_dev->irqlock, flags);
1620934d375SYunfei Dong 			return NULL;
1630934d375SYunfei Dong 		}
1640934d375SYunfei Dong 		ctx = subdev_dev->curr_ctx;
1650934d375SYunfei Dong 	} else {
1660934d375SYunfei Dong 		ctx = vdec_dev->curr_ctx;
1670934d375SYunfei Dong 	}
1680934d375SYunfei Dong 	spin_unlock_irqrestore(&vdec_dev->irqlock, flags);
1690934d375SYunfei Dong 	return ctx;
1700934d375SYunfei Dong }
1710934d375SYunfei Dong EXPORT_SYMBOL(mtk_vcodec_get_curr_ctx);
1720934d375SYunfei Dong 
1730934d375SYunfei Dong MODULE_LICENSE("GPL v2");
1740934d375SYunfei Dong MODULE_DESCRIPTION("Mediatek video codec driver");
175