Commit bf1d556a authored by Yunfei Dong's avatar Yunfei Dong Committed by Mauro Carvalho Chehab
Browse files

media: mtk-vcodec: abstract firmware interface



MT8183's codec firmware is run by a different remote processor from
MT8173. While the firmware interface is basically the same, the way to
invoke it differs. Abstract all firmware calls under a layer that will
allow us to handle both firmware types transparently.

[acourbot: refactor, cleanup and split]
[pihsun: fix error path and add mtk_vcodec_fw_release]
[hverkuil: fixed some checkpatch alignment warnings]
[hverkuil: fixed merge conflicts]

Signed-off-by: default avatarYunfei Dong <yunfei.dong@mediatek.com>
Co-developed-by: default avatarAlexandre Courbot <acourbot@chromium.org>
Signed-off-by: default avatarAlexandre Courbot <acourbot@chromium.org>
Signed-off-by: default avatarPi-Hsun Shih <pihsun@chromium.org>
Reviewed-by: default avatarTiffany Lin <tiffany.lin@mediatek.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent cbd2dca7
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -13,7 +13,6 @@ mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
		mtk_vcodec_dec.o \
		mtk_vcodec_dec_pm.o \


mtk-vcodec-enc-y := venc/venc_vp8_if.o \
		venc/venc_h264_if.o \
		mtk_vcodec_enc.o \
@@ -25,5 +24,4 @@ mtk-vcodec-enc-y := venc/venc_vp8_if.o \

mtk-vcodec-common-y := mtk_vcodec_intr.o \
		mtk_vcodec_util.o \

ccflags-y += -I$(srctree)/drivers/media/platform/mtk-vpu
		mtk_vcodec_fw.o
+20 −29
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@
#include "mtk_vcodec_dec_pm.h"
#include "mtk_vcodec_intr.h"
#include "mtk_vcodec_util.h"
#include "mtk_vpu.h"
#include "mtk_vcodec_fw.h"

#define VDEC_HW_ACTIVE	0x10
#define VDEC_IRQ_CFG	0x11
@@ -77,22 +77,6 @@ static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void *priv)
	return IRQ_HANDLED;
}

static void mtk_vcodec_dec_reset_handler(void *priv)
{
	struct mtk_vcodec_dev *dev = priv;
	struct mtk_vcodec_ctx *ctx;

	mtk_v4l2_err("Watchdog timeout!!");

	mutex_lock(&dev->dev_mutex);
	list_for_each_entry(ctx, &dev->ctx_list, list) {
		ctx->state = MTK_STATE_ABORT;
		mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ERROR",
				ctx->id);
	}
	mutex_unlock(&dev->dev_mutex);
}

static int fops_vcodec_open(struct file *file)
{
	struct mtk_vcodec_dev *dev = video_drvdata(file);
@@ -144,21 +128,20 @@ static int fops_vcodec_open(struct file *file)
	if (v4l2_fh_is_singular(&ctx->fh)) {
		mtk_vcodec_dec_pw_on(&dev->pm);
		/*
		 * vpu_load_firmware checks if it was loaded already and
		 * does nothing in that case
		 * Does nothing if firmware was already loaded.
		 */
		ret = vpu_load_firmware(dev->vpu_plat_dev);
		ret = mtk_vcodec_fw_load_firmware(dev->fw_handler);
		if (ret < 0) {
			/*
			 * Return 0 if downloading firmware successfully,
			 * otherwise it is failed
			 */
			mtk_v4l2_err("vpu_load_firmware failed!");
			mtk_v4l2_err("failed to load firmware!");
			goto err_load_fw;
		}

		dev->dec_capability =
			vpu_get_vdec_hw_capa(dev->vpu_plat_dev);
			mtk_vcodec_fw_get_vdec_capa(dev->fw_handler);
		mtk_v4l2_debug(0, "decoder capability %x", dev->dec_capability);
	}

@@ -228,6 +211,8 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
	struct mtk_vcodec_dev *dev;
	struct video_device *vfd_dec;
	struct resource *res;
	phandle rproc_phandle;
	enum mtk_vcodec_fw_type fw_type;
	int i, ret;

	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
@@ -237,10 +222,12 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
	INIT_LIST_HEAD(&dev->ctx_list);
	dev->plat_dev = pdev;

	dev->vpu_plat_dev = vpu_get_plat_device(dev->plat_dev);
	if (dev->vpu_plat_dev == NULL) {
		mtk_v4l2_err("[VPU] vpu device in not ready");
		return -EPROBE_DEFER;
	if (!of_property_read_u32(pdev->dev.of_node, "mediatek,vpu",
				  &rproc_phandle)) {
		fw_type = VPU;
	} else {
		mtk_v4l2_err("Could not get vdec IPI device");
		return -ENODEV;
	}
	if (!pdev->dev.dma_parms) {
		pdev->dev.dma_parms = devm_kzalloc(&pdev->dev,
@@ -251,13 +238,14 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
	}
	dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));

	vpu_wdt_reg_handler(dev->vpu_plat_dev, mtk_vcodec_dec_reset_handler,
			dev, VPU_RST_DEC);
	dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, VPU_RST_DEC);
	if (IS_ERR(dev->fw_handler))
		return PTR_ERR(dev->fw_handler);

	ret = mtk_vcodec_init_dec_pm(dev);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to get mt vcodec clock source");
		return ret;
		goto err_dec_pm;
	}

	for (i = 0; i < NUM_MAX_VDEC_REG_BASE; i++) {
@@ -360,6 +348,8 @@ err_dec_alloc:
	v4l2_device_unregister(&dev->v4l2_dev);
err_res:
	mtk_vcodec_release_dec_pm(dev);
err_dec_pm:
	mtk_vcodec_fw_release(dev->fw_handler);
	return ret;
}

@@ -384,6 +374,7 @@ static int mtk_vcodec_dec_remove(struct platform_device *pdev)

	v4l2_device_unregister(&dev->v4l2_dev);
	mtk_vcodec_release_dec_pm(dev);
	mtk_vcodec_fw_release(dev->fw_handler);
	return 0;
}

+0 −1
Original line number Diff line number Diff line
@@ -12,7 +12,6 @@

#include "mtk_vcodec_dec_pm.h"
#include "mtk_vcodec_util.h"
#include "mtk_vpu.h"

int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
{
+3 −2
Original line number Diff line number Diff line
@@ -309,13 +309,13 @@ struct mtk_vcodec_ctx {
 * @m2m_dev_dec: m2m device for decoder
 * @m2m_dev_enc: m2m device for encoder.
 * @plat_dev: platform device
 * @vpu_plat_dev: mtk vpu platform device
 * @ctx_list: list of struct mtk_vcodec_ctx
 * @irqlock: protect data access by irq handler and work thread
 * @curr_ctx: The context that is waiting for codec hardware
 *
 * @reg_base: Mapped address of MTK Vcodec registers.
 *
 * @fw_handler: used to communicate with the firmware.
 * @id_counter: used to identify current opened instance
 *
 * @encode_workqueue: encode work queue
@@ -344,12 +344,13 @@ struct mtk_vcodec_dev {
	struct v4l2_m2m_dev *m2m_dev_dec;
	struct v4l2_m2m_dev *m2m_dev_enc;
	struct platform_device *plat_dev;
	struct platform_device *vpu_plat_dev;
	struct list_head ctx_list;
	spinlock_t irqlock;
	struct mtk_vcodec_ctx *curr_ctx;
	void __iomem *reg_base[NUM_MAX_VCODEC_REG_BASE];

	struct mtk_vcodec_fw *fw_handler;

	unsigned long id_counter;

	struct workqueue_struct *decode_workqueue;
+19 −27
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@
#include "mtk_vcodec_enc_pm.h"
#include "mtk_vcodec_intr.h"
#include "mtk_vcodec_util.h"
#include "mtk_vpu.h"
#include "mtk_vcodec_fw.h"

module_param(mtk_v4l2_dbg_level, int, S_IRUGO | S_IWUSR);
module_param(mtk_vcodec_dbg, bool, S_IRUGO | S_IWUSR);
@@ -101,22 +101,6 @@ static irqreturn_t mtk_vcodec_enc_lt_irq_handler(int irq, void *priv)
	return IRQ_HANDLED;
}

static void mtk_vcodec_enc_reset_handler(void *priv)
{
	struct mtk_vcodec_dev *dev = priv;
	struct mtk_vcodec_ctx *ctx;

	mtk_v4l2_debug(0, "Watchdog timeout!!");

	mutex_lock(&dev->dev_mutex);
	list_for_each_entry(ctx, &dev->ctx_list, list) {
		ctx->state = MTK_STATE_ABORT;
		mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ABORT",
				ctx->id);
	}
	mutex_unlock(&dev->dev_mutex);
}

static int fops_vcodec_open(struct file *file)
{
	struct mtk_vcodec_dev *dev = video_drvdata(file);
@@ -159,10 +143,10 @@ static int fops_vcodec_open(struct file *file)

	if (v4l2_fh_is_singular(&ctx->fh)) {
		/*
		 * vpu_load_firmware checks if it was loaded already and
		 * load fireware to checks if it was loaded already and
		 * does nothing in that case
		 */
		ret = vpu_load_firmware(dev->vpu_plat_dev);
		ret = mtk_vcodec_fw_load_firmware(dev->fw_handler);
		if (ret < 0) {
			/*
			 * Return 0 if downloading firmware successfully,
@@ -173,7 +157,7 @@ static int fops_vcodec_open(struct file *file)
		}

		dev->enc_capability =
			vpu_get_venc_hw_capa(dev->vpu_plat_dev);
			mtk_vcodec_fw_get_venc_capa(dev->fw_handler);
		mtk_v4l2_debug(0, "encoder capability %x", dev->enc_capability);
	}

@@ -235,6 +219,8 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
	struct mtk_vcodec_dev *dev;
	struct video_device *vfd_enc;
	struct resource *res;
	phandle rproc_phandle;
	enum mtk_vcodec_fw_type fw_type;
	int i, j, ret;

	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
@@ -244,10 +230,12 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
	INIT_LIST_HEAD(&dev->ctx_list);
	dev->plat_dev = pdev;

	dev->vpu_plat_dev = vpu_get_plat_device(dev->plat_dev);
	if (dev->vpu_plat_dev == NULL) {
		mtk_v4l2_err("[VPU] vpu device in not ready");
		return -EPROBE_DEFER;
	if (!of_property_read_u32(pdev->dev.of_node, "mediatek,vpu",
				  &rproc_phandle)) {
		fw_type = VPU;
	} else {
		mtk_v4l2_err("Could not get venc IPI device");
		return -ENODEV;
	}
	if (!pdev->dev.dma_parms) {
		pdev->dev.dma_parms = devm_kzalloc(&pdev->dev,
@@ -258,13 +246,14 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
	}
	dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));

	vpu_wdt_reg_handler(dev->vpu_plat_dev, mtk_vcodec_enc_reset_handler,
				dev, VPU_RST_ENC);
	dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, VPU_RST_ENC);
	if (IS_ERR(dev->fw_handler))
		return PTR_ERR(dev->fw_handler);

	ret = mtk_vcodec_init_enc_pm(dev);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to get mt vcodec clock source!");
		return ret;
		goto err_enc_pm;
	}

	for (i = VENC_SYS, j = 0; i < NUM_MAX_VCODEC_REG_BASE; i++, j++) {
@@ -385,6 +374,8 @@ err_enc_alloc:
	v4l2_device_unregister(&dev->v4l2_dev);
err_res:
	mtk_vcodec_release_enc_pm(dev);
err_enc_pm:
	mtk_vcodec_fw_release(dev->fw_handler);
	return ret;
}

@@ -409,6 +400,7 @@ static int mtk_vcodec_enc_remove(struct platform_device *pdev)

	v4l2_device_unregister(&dev->v4l2_dev);
	mtk_vcodec_release_enc_pm(dev);
	mtk_vcodec_fw_release(dev->fw_handler);
	return 0;
}

Loading