// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2021 MediaTek Inc.
 * Author: Yunfei Dong <yunfei.dong@mediatek.com>
 */

#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>

#include "mtk_vcodec_drv.h"
#include "mtk_vcodec_dec.h"
#include "mtk_vcodec_dec_hw.h"
#include "mtk_vcodec_dec_pm.h"
#include "mtk_vcodec_intr.h"
#include "mtk_vcodec_util.h"

static const struct of_device_id mtk_vdec_hw_match[] = {
	{
		.compatible = "mediatek,mtk-vcodec-lat",
		.data = (void *)MTK_VDEC_LAT0,
	},
	{
		.compatible = "mediatek,mtk-vcodec-core",
		.data = (void *)MTK_VDEC_CORE,
	},
	{
		.compatible = "mediatek,mtk-vcodec-lat-soc",
		.data = (void *)MTK_VDEC_LAT_SOC,
	},
	{},
};
MODULE_DEVICE_TABLE(of, mtk_vdec_hw_match);

static int mtk_vdec_hw_prob_done(struct mtk_vcodec_dev *vdec_dev)
{
	struct platform_device *pdev = vdec_dev->plat_dev;
	struct device_node *subdev_node;
	enum mtk_vdec_hw_id hw_idx;
	const struct of_device_id *of_id;
	int i;

	for (i = 0; i < ARRAY_SIZE(mtk_vdec_hw_match); i++) {
		of_id = &mtk_vdec_hw_match[i];
		subdev_node = of_find_compatible_node(NULL, NULL,
						      of_id->compatible);
		if (!subdev_node)
			continue;

		of_node_put(subdev_node);

		hw_idx = (enum mtk_vdec_hw_id)(uintptr_t)of_id->data;
		if (!test_bit(hw_idx, vdec_dev->subdev_bitmap)) {
			dev_err(&pdev->dev, "vdec %d is not ready", hw_idx);
			return -EAGAIN;
		}
	}

	return 0;
}

static irqreturn_t mtk_vdec_hw_irq_handler(int irq, void *priv)
{
	struct mtk_vdec_hw_dev *dev = priv;
	struct mtk_vcodec_ctx *ctx;
	u32 cg_status;
	unsigned int dec_done_status;
	void __iomem *vdec_misc_addr = dev->reg_base[VDEC_HW_MISC] +
					VDEC_IRQ_CFG_REG;

	ctx = mtk_vcodec_get_curr_ctx(dev->main_dev, dev->hw_idx);

	/* check if HW active or not */
	cg_status = readl(dev->reg_base[VDEC_HW_SYS]);
	if (cg_status & VDEC_HW_ACTIVE) {
		mtk_v4l2_err("vdec active is not 0x0 (0x%08x)",
			     cg_status);
		return IRQ_HANDLED;
	}

	dec_done_status = readl(vdec_misc_addr);
	if ((dec_done_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) !=
	    MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
		return IRQ_HANDLED;

	/* clear interrupt */
	writel(dec_done_status | VDEC_IRQ_CFG, vdec_misc_addr);
	writel(dec_done_status & ~VDEC_IRQ_CLR, vdec_misc_addr);

	wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED, dev->hw_idx);

	mtk_v4l2_debug(3, "wake up ctx %d, dec_done_status=%x",
		       ctx->id, dec_done_status);

	return IRQ_HANDLED;
}

static int mtk_vdec_hw_init_irq(struct mtk_vdec_hw_dev *dev)
{
	struct platform_device *pdev = dev->plat_dev;
	int ret;

	dev->dec_irq = platform_get_irq(pdev, 0);
	if (dev->dec_irq < 0)
		return dev->dec_irq;

	irq_set_status_flags(dev->dec_irq, IRQ_NOAUTOEN);
	ret = devm_request_irq(&pdev->dev, dev->dec_irq,
			       mtk_vdec_hw_irq_handler, 0, pdev->name, dev);
	if (ret) {
		dev_err(&pdev->dev, "Failed to install dev->dec_irq %d (%d)",
			dev->dec_irq, ret);
		return ret;
	}

	return 0;
}

static int mtk_vdec_hw_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct mtk_vdec_hw_dev *subdev_dev;
	struct mtk_vcodec_dev *main_dev;
	const struct of_device_id *of_id;
	int hw_idx;
	int ret;

	if (!dev->parent) {
		dev_err(dev, "no parent for hardware devices.\n");
		return -ENODEV;
	}

	main_dev = dev_get_drvdata(dev->parent);
	if (!main_dev) {
		dev_err(dev, "failed to get parent driver data");
		return -EINVAL;
	}

	subdev_dev = devm_kzalloc(dev, sizeof(*subdev_dev), GFP_KERNEL);
	if (!subdev_dev)
		return -ENOMEM;

	subdev_dev->plat_dev = pdev;
	ret = mtk_vcodec_init_dec_clk(pdev, &subdev_dev->pm);
	if (ret)
		return ret;
	pm_runtime_enable(&pdev->dev);

	of_id = of_match_device(mtk_vdec_hw_match, dev);
	if (!of_id) {
		dev_err(dev, "Can't get vdec subdev id.\n");
		ret = -EINVAL;
		goto err;
	}

	hw_idx = (enum mtk_vdec_hw_id)(uintptr_t)of_id->data;
	if (hw_idx >= MTK_VDEC_HW_MAX) {
		dev_err(dev, "Hardware index %d not correct.\n", hw_idx);
		ret = -EINVAL;
		goto err;
	}

	main_dev->subdev_dev[hw_idx] = subdev_dev;
	subdev_dev->hw_idx = hw_idx;
	subdev_dev->main_dev = main_dev;
	subdev_dev->reg_base[VDEC_HW_SYS] = main_dev->reg_base[VDEC_HW_SYS];
	set_bit(subdev_dev->hw_idx, main_dev->subdev_bitmap);

	if (IS_SUPPORT_VDEC_HW_IRQ(hw_idx)) {
		ret = mtk_vdec_hw_init_irq(subdev_dev);
		if (ret)
			goto err;
	}

	subdev_dev->reg_base[VDEC_HW_MISC] =
		devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR((__force void *)subdev_dev->reg_base[VDEC_HW_MISC])) {
		ret = PTR_ERR((__force void *)subdev_dev->reg_base[VDEC_HW_MISC]);
		goto err;
	}

	if (!main_dev->subdev_prob_done)
		main_dev->subdev_prob_done = mtk_vdec_hw_prob_done;

	platform_set_drvdata(pdev, subdev_dev);
	return 0;
err:
	pm_runtime_disable(subdev_dev->pm.dev);
	return ret;
}

static struct platform_driver mtk_vdec_driver = {
	.probe	= mtk_vdec_hw_probe,
	.driver	= {
		.name	= "mtk-vdec-comp",
		.of_match_table = mtk_vdec_hw_match,
	},
};
module_platform_driver(mtk_vdec_driver);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Mediatek video decoder hardware driver");
