// SPDX-License-Identifier: GPL-2.0-only
/*
 * i.MX6 Video Data Order Adapter (VDOA)
 *
 * Copyright (C) 2014 Philipp Zabel
 * Copyright (C) 2016 Pengutronix, Michael Tretter <kernel@pengutronix.de>
 */

#include <linux/clk.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/videodev2.h>
#include <linux/slab.h>

#include "imx-vdoa.h"

#define VDOA_NAME "imx-vdoa"

#define VDOAC		0x00
#define VDOASRR		0x04
#define VDOAIE		0x08
#define VDOAIST		0x0c
#define VDOAFP		0x10
#define VDOAIEBA00	0x14
#define VDOAIEBA01	0x18
#define VDOAIEBA02	0x1c
#define VDOAIEBA10	0x20
#define VDOAIEBA11	0x24
#define VDOAIEBA12	0x28
#define VDOASL		0x2c
#define VDOAIUBO	0x30
#define VDOAVEBA0	0x34
#define VDOAVEBA1	0x38
#define VDOAVEBA2	0x3c
#define VDOAVUBO	0x40
#define VDOASR		0x44

#define VDOAC_ISEL		BIT(6)
#define VDOAC_PFS		BIT(5)
#define VDOAC_SO		BIT(4)
#define VDOAC_SYNC		BIT(3)
#define VDOAC_NF		BIT(2)
#define VDOAC_BNDM_MASK		0x3
#define VDOAC_BAND_HEIGHT_8	0x0
#define VDOAC_BAND_HEIGHT_16	0x1
#define VDOAC_BAND_HEIGHT_32	0x2

#define VDOASRR_START		BIT(1)
#define VDOASRR_SWRST		BIT(0)

#define VDOAIE_EITERR		BIT(1)
#define VDOAIE_EIEOT		BIT(0)

#define VDOAIST_TERR		BIT(1)
#define VDOAIST_EOT		BIT(0)

#define VDOAFP_FH_MASK		(0x1fff << 16)
#define VDOAFP_FW_MASK		(0x3fff)

#define VDOASL_VSLY_MASK	(0x3fff << 16)
#define VDOASL_ISLY_MASK	(0x7fff)

#define VDOASR_ERRW		BIT(4)
#define VDOASR_EOB		BIT(3)
#define VDOASR_CURRENT_FRAME	(0x3 << 1)
#define VDOASR_CURRENT_BUFFER	BIT(1)

enum {
	V4L2_M2M_SRC = 0,
	V4L2_M2M_DST = 1,
};

struct vdoa_data {
	struct vdoa_ctx		*curr_ctx;
	struct device		*dev;
	struct clk		*vdoa_clk;
	void __iomem		*regs;
};

struct vdoa_q_data {
	unsigned int	width;
	unsigned int	height;
	unsigned int	bytesperline;
	unsigned int	sizeimage;
	u32		pixelformat;
};

struct vdoa_ctx {
	struct vdoa_data	*vdoa;
	struct completion	completion;
	struct vdoa_q_data	q_data[2];
	unsigned int		submitted_job;
	unsigned int		completed_job;
};

static irqreturn_t vdoa_irq_handler(int irq, void *data)
{
	struct vdoa_data *vdoa = data;
	struct vdoa_ctx *curr_ctx;
	u32 val;

	/* Disable interrupts */
	writel(0, vdoa->regs + VDOAIE);

	curr_ctx = vdoa->curr_ctx;
	if (!curr_ctx) {
		dev_warn(vdoa->dev,
			"Instance released before the end of transaction\n");
		return IRQ_HANDLED;
	}

	val = readl(vdoa->regs + VDOAIST);
	writel(val, vdoa->regs + VDOAIST);
	if (val & VDOAIST_TERR) {
		val = readl(vdoa->regs + VDOASR) & VDOASR_ERRW;
		dev_err(vdoa->dev, "AXI %s error\n", val ? "write" : "read");
	} else if (!(val & VDOAIST_EOT)) {
		dev_warn(vdoa->dev, "Spurious interrupt\n");
	}
	curr_ctx->completed_job++;
	complete(&curr_ctx->completion);

	return IRQ_HANDLED;
}

int vdoa_wait_for_completion(struct vdoa_ctx *ctx)
{
	struct vdoa_data *vdoa = ctx->vdoa;

	if (ctx->submitted_job == ctx->completed_job)
		return 0;

	if (!wait_for_completion_timeout(&ctx->completion,
					 msecs_to_jiffies(300))) {
		dev_err(vdoa->dev,
			"Timeout waiting for transfer result\n");
		return -ETIMEDOUT;
	}

	return 0;
}
EXPORT_SYMBOL(vdoa_wait_for_completion);

void vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src)
{
	struct vdoa_q_data *src_q_data, *dst_q_data;
	struct vdoa_data *vdoa = ctx->vdoa;
	u32 val;

	if (vdoa->curr_ctx)
		vdoa_wait_for_completion(vdoa->curr_ctx);

	vdoa->curr_ctx = ctx;

	reinit_completion(&ctx->completion);
	ctx->submitted_job++;

	src_q_data = &ctx->q_data[V4L2_M2M_SRC];
	dst_q_data = &ctx->q_data[V4L2_M2M_DST];

	/* Progressive, no sync, 1 frame per run */
	if (dst_q_data->pixelformat == V4L2_PIX_FMT_YUYV)
		val = VDOAC_PFS;
	else
		val = 0;
	writel(val, vdoa->regs + VDOAC);

	writel(dst_q_data->height << 16 | dst_q_data->width,
	       vdoa->regs + VDOAFP);

	val = dst;
	writel(val, vdoa->regs + VDOAIEBA00);

	writel(src_q_data->bytesperline << 16 | dst_q_data->bytesperline,
	       vdoa->regs + VDOASL);

	if (dst_q_data->pixelformat == V4L2_PIX_FMT_NV12 ||
	    dst_q_data->pixelformat == V4L2_PIX_FMT_NV21)
		val = dst_q_data->bytesperline * dst_q_data->height;
	else
		val = 0;
	writel(val, vdoa->regs + VDOAIUBO);

	val = src;
	writel(val, vdoa->regs + VDOAVEBA0);
	val = round_up(src_q_data->bytesperline * src_q_data->height, 4096);
	writel(val, vdoa->regs + VDOAVUBO);

	/* Enable interrupts and start transfer */
	writel(VDOAIE_EITERR | VDOAIE_EIEOT, vdoa->regs + VDOAIE);
	writel(VDOASRR_START, vdoa->regs + VDOASRR);
}
EXPORT_SYMBOL(vdoa_device_run);

struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa)
{
	struct vdoa_ctx *ctx;
	int err;

	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
	if (!ctx)
		return NULL;

	err = clk_prepare_enable(vdoa->vdoa_clk);
	if (err) {
		kfree(ctx);
		return NULL;
	}

	init_completion(&ctx->completion);
	ctx->vdoa = vdoa;

	return ctx;
}
EXPORT_SYMBOL(vdoa_context_create);

void vdoa_context_destroy(struct vdoa_ctx *ctx)
{
	struct vdoa_data *vdoa = ctx->vdoa;

	if (vdoa->curr_ctx == ctx) {
		vdoa_wait_for_completion(vdoa->curr_ctx);
		vdoa->curr_ctx = NULL;
	}

	clk_disable_unprepare(vdoa->vdoa_clk);
	kfree(ctx);
}
EXPORT_SYMBOL(vdoa_context_destroy);

int vdoa_context_configure(struct vdoa_ctx *ctx,
			   unsigned int width, unsigned int height,
			   u32 pixelformat)
{
	struct vdoa_q_data *src_q_data;
	struct vdoa_q_data *dst_q_data;

	if (width < 16 || width  > 8192 || width % 16 != 0 ||
	    height < 16 || height > 4096 || height % 16 != 0)
		return -EINVAL;

	if (pixelformat != V4L2_PIX_FMT_YUYV &&
	    pixelformat != V4L2_PIX_FMT_NV12)
		return -EINVAL;

	/* If no context is passed, only check if the format is valid */
	if (!ctx)
		return 0;

	src_q_data = &ctx->q_data[V4L2_M2M_SRC];
	dst_q_data = &ctx->q_data[V4L2_M2M_DST];

	src_q_data->width = width;
	src_q_data->height = height;
	src_q_data->bytesperline = width;
	src_q_data->sizeimage =
		round_up(src_q_data->bytesperline * height, 4096) +
		src_q_data->bytesperline * height / 2;

	dst_q_data->width = width;
	dst_q_data->height = height;
	dst_q_data->pixelformat = pixelformat;
	switch (pixelformat) {
	case V4L2_PIX_FMT_YUYV:
		dst_q_data->bytesperline = width * 2;
		dst_q_data->sizeimage = dst_q_data->bytesperline * height;
		break;
	case V4L2_PIX_FMT_NV12:
	default:
		dst_q_data->bytesperline = width;
		dst_q_data->sizeimage =
			dst_q_data->bytesperline * height * 3 / 2;
		break;
	}

	return 0;
}
EXPORT_SYMBOL(vdoa_context_configure);

static int vdoa_probe(struct platform_device *pdev)
{
	struct vdoa_data *vdoa;
	int ret;

	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
	if (ret) {
		dev_err(&pdev->dev, "DMA enable failed\n");
		return ret;
	}

	vdoa = devm_kzalloc(&pdev->dev, sizeof(*vdoa), GFP_KERNEL);
	if (!vdoa)
		return -ENOMEM;

	vdoa->dev = &pdev->dev;

	vdoa->vdoa_clk = devm_clk_get(vdoa->dev, NULL);
	if (IS_ERR(vdoa->vdoa_clk)) {
		dev_err(vdoa->dev, "Failed to get clock\n");
		return PTR_ERR(vdoa->vdoa_clk);
	}

	vdoa->regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(vdoa->regs))
		return PTR_ERR(vdoa->regs);

	ret = platform_get_irq(pdev, 0);
	if (ret < 0)
		return ret;
	ret = devm_request_threaded_irq(&pdev->dev, ret, NULL,
					vdoa_irq_handler, IRQF_ONESHOT,
					"vdoa", vdoa);
	if (ret < 0) {
		dev_err(vdoa->dev, "Failed to get irq\n");
		return ret;
	}

	platform_set_drvdata(pdev, vdoa);

	return 0;
}

static const struct of_device_id vdoa_dt_ids[] = {
	{ .compatible = "fsl,imx6q-vdoa" },
	{}
};
MODULE_DEVICE_TABLE(of, vdoa_dt_ids);

static struct platform_driver vdoa_driver = {
	.probe		= vdoa_probe,
	.driver		= {
		.name	= VDOA_NAME,
		.of_match_table = vdoa_dt_ids,
	},
};

module_platform_driver(vdoa_driver);

MODULE_DESCRIPTION("Video Data Order Adapter");
MODULE_AUTHOR("Philipp Zabel <philipp.zabel@gmail.com>");
MODULE_ALIAS("platform:imx-vdoa");
MODULE_LICENSE("GPL");
