18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * i.MX6 Video Data Order Adapter (VDOA)
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2014 Philipp Zabel
68c2ecf20Sopenharmony_ci * Copyright (C) 2016 Pengutronix, Michael Tretter <kernel@pengutronix.de>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/clk.h>
108c2ecf20Sopenharmony_ci#include <linux/device.h>
118c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
128c2ecf20Sopenharmony_ci#include <linux/module.h>
138c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h>
148c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
158c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
168c2ecf20Sopenharmony_ci#include <linux/videodev2.h>
178c2ecf20Sopenharmony_ci#include <linux/slab.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include "imx-vdoa.h"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#define VDOA_NAME "imx-vdoa"
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define VDOAC		0x00
248c2ecf20Sopenharmony_ci#define VDOASRR		0x04
258c2ecf20Sopenharmony_ci#define VDOAIE		0x08
268c2ecf20Sopenharmony_ci#define VDOAIST		0x0c
278c2ecf20Sopenharmony_ci#define VDOAFP		0x10
288c2ecf20Sopenharmony_ci#define VDOAIEBA00	0x14
298c2ecf20Sopenharmony_ci#define VDOAIEBA01	0x18
308c2ecf20Sopenharmony_ci#define VDOAIEBA02	0x1c
318c2ecf20Sopenharmony_ci#define VDOAIEBA10	0x20
328c2ecf20Sopenharmony_ci#define VDOAIEBA11	0x24
338c2ecf20Sopenharmony_ci#define VDOAIEBA12	0x28
348c2ecf20Sopenharmony_ci#define VDOASL		0x2c
358c2ecf20Sopenharmony_ci#define VDOAIUBO	0x30
368c2ecf20Sopenharmony_ci#define VDOAVEBA0	0x34
378c2ecf20Sopenharmony_ci#define VDOAVEBA1	0x38
388c2ecf20Sopenharmony_ci#define VDOAVEBA2	0x3c
398c2ecf20Sopenharmony_ci#define VDOAVUBO	0x40
408c2ecf20Sopenharmony_ci#define VDOASR		0x44
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#define VDOAC_ISEL		BIT(6)
438c2ecf20Sopenharmony_ci#define VDOAC_PFS		BIT(5)
448c2ecf20Sopenharmony_ci#define VDOAC_SO		BIT(4)
458c2ecf20Sopenharmony_ci#define VDOAC_SYNC		BIT(3)
468c2ecf20Sopenharmony_ci#define VDOAC_NF		BIT(2)
478c2ecf20Sopenharmony_ci#define VDOAC_BNDM_MASK		0x3
488c2ecf20Sopenharmony_ci#define VDOAC_BAND_HEIGHT_8	0x0
498c2ecf20Sopenharmony_ci#define VDOAC_BAND_HEIGHT_16	0x1
508c2ecf20Sopenharmony_ci#define VDOAC_BAND_HEIGHT_32	0x2
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#define VDOASRR_START		BIT(1)
538c2ecf20Sopenharmony_ci#define VDOASRR_SWRST		BIT(0)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define VDOAIE_EITERR		BIT(1)
568c2ecf20Sopenharmony_ci#define VDOAIE_EIEOT		BIT(0)
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci#define VDOAIST_TERR		BIT(1)
598c2ecf20Sopenharmony_ci#define VDOAIST_EOT		BIT(0)
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#define VDOAFP_FH_MASK		(0x1fff << 16)
628c2ecf20Sopenharmony_ci#define VDOAFP_FW_MASK		(0x3fff)
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci#define VDOASL_VSLY_MASK	(0x3fff << 16)
658c2ecf20Sopenharmony_ci#define VDOASL_ISLY_MASK	(0x7fff)
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#define VDOASR_ERRW		BIT(4)
688c2ecf20Sopenharmony_ci#define VDOASR_EOB		BIT(3)
698c2ecf20Sopenharmony_ci#define VDOASR_CURRENT_FRAME	(0x3 << 1)
708c2ecf20Sopenharmony_ci#define VDOASR_CURRENT_BUFFER	BIT(1)
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cienum {
738c2ecf20Sopenharmony_ci	V4L2_M2M_SRC = 0,
748c2ecf20Sopenharmony_ci	V4L2_M2M_DST = 1,
758c2ecf20Sopenharmony_ci};
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistruct vdoa_data {
788c2ecf20Sopenharmony_ci	struct vdoa_ctx		*curr_ctx;
798c2ecf20Sopenharmony_ci	struct device		*dev;
808c2ecf20Sopenharmony_ci	struct clk		*vdoa_clk;
818c2ecf20Sopenharmony_ci	void __iomem		*regs;
828c2ecf20Sopenharmony_ci};
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistruct vdoa_q_data {
858c2ecf20Sopenharmony_ci	unsigned int	width;
868c2ecf20Sopenharmony_ci	unsigned int	height;
878c2ecf20Sopenharmony_ci	unsigned int	bytesperline;
888c2ecf20Sopenharmony_ci	unsigned int	sizeimage;
898c2ecf20Sopenharmony_ci	u32		pixelformat;
908c2ecf20Sopenharmony_ci};
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistruct vdoa_ctx {
938c2ecf20Sopenharmony_ci	struct vdoa_data	*vdoa;
948c2ecf20Sopenharmony_ci	struct completion	completion;
958c2ecf20Sopenharmony_ci	struct vdoa_q_data	q_data[2];
968c2ecf20Sopenharmony_ci	unsigned int		submitted_job;
978c2ecf20Sopenharmony_ci	unsigned int		completed_job;
988c2ecf20Sopenharmony_ci};
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_cistatic irqreturn_t vdoa_irq_handler(int irq, void *data)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	struct vdoa_data *vdoa = data;
1038c2ecf20Sopenharmony_ci	struct vdoa_ctx *curr_ctx;
1048c2ecf20Sopenharmony_ci	u32 val;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	/* Disable interrupts */
1078c2ecf20Sopenharmony_ci	writel(0, vdoa->regs + VDOAIE);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	curr_ctx = vdoa->curr_ctx;
1108c2ecf20Sopenharmony_ci	if (!curr_ctx) {
1118c2ecf20Sopenharmony_ci		dev_warn(vdoa->dev,
1128c2ecf20Sopenharmony_ci			"Instance released before the end of transaction\n");
1138c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
1148c2ecf20Sopenharmony_ci	}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	val = readl(vdoa->regs + VDOAIST);
1178c2ecf20Sopenharmony_ci	writel(val, vdoa->regs + VDOAIST);
1188c2ecf20Sopenharmony_ci	if (val & VDOAIST_TERR) {
1198c2ecf20Sopenharmony_ci		val = readl(vdoa->regs + VDOASR) & VDOASR_ERRW;
1208c2ecf20Sopenharmony_ci		dev_err(vdoa->dev, "AXI %s error\n", val ? "write" : "read");
1218c2ecf20Sopenharmony_ci	} else if (!(val & VDOAIST_EOT)) {
1228c2ecf20Sopenharmony_ci		dev_warn(vdoa->dev, "Spurious interrupt\n");
1238c2ecf20Sopenharmony_ci	}
1248c2ecf20Sopenharmony_ci	curr_ctx->completed_job++;
1258c2ecf20Sopenharmony_ci	complete(&curr_ctx->completion);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ciint vdoa_wait_for_completion(struct vdoa_ctx *ctx)
1318c2ecf20Sopenharmony_ci{
1328c2ecf20Sopenharmony_ci	struct vdoa_data *vdoa = ctx->vdoa;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	if (ctx->submitted_job == ctx->completed_job)
1358c2ecf20Sopenharmony_ci		return 0;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	if (!wait_for_completion_timeout(&ctx->completion,
1388c2ecf20Sopenharmony_ci					 msecs_to_jiffies(300))) {
1398c2ecf20Sopenharmony_ci		dev_err(vdoa->dev,
1408c2ecf20Sopenharmony_ci			"Timeout waiting for transfer result\n");
1418c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
1428c2ecf20Sopenharmony_ci	}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	return 0;
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vdoa_wait_for_completion);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_civoid vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	struct vdoa_q_data *src_q_data, *dst_q_data;
1518c2ecf20Sopenharmony_ci	struct vdoa_data *vdoa = ctx->vdoa;
1528c2ecf20Sopenharmony_ci	u32 val;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	if (vdoa->curr_ctx)
1558c2ecf20Sopenharmony_ci		vdoa_wait_for_completion(vdoa->curr_ctx);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	vdoa->curr_ctx = ctx;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	reinit_completion(&ctx->completion);
1608c2ecf20Sopenharmony_ci	ctx->submitted_job++;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	src_q_data = &ctx->q_data[V4L2_M2M_SRC];
1638c2ecf20Sopenharmony_ci	dst_q_data = &ctx->q_data[V4L2_M2M_DST];
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	/* Progressive, no sync, 1 frame per run */
1668c2ecf20Sopenharmony_ci	if (dst_q_data->pixelformat == V4L2_PIX_FMT_YUYV)
1678c2ecf20Sopenharmony_ci		val = VDOAC_PFS;
1688c2ecf20Sopenharmony_ci	else
1698c2ecf20Sopenharmony_ci		val = 0;
1708c2ecf20Sopenharmony_ci	writel(val, vdoa->regs + VDOAC);
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	writel(dst_q_data->height << 16 | dst_q_data->width,
1738c2ecf20Sopenharmony_ci	       vdoa->regs + VDOAFP);
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	val = dst;
1768c2ecf20Sopenharmony_ci	writel(val, vdoa->regs + VDOAIEBA00);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	writel(src_q_data->bytesperline << 16 | dst_q_data->bytesperline,
1798c2ecf20Sopenharmony_ci	       vdoa->regs + VDOASL);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	if (dst_q_data->pixelformat == V4L2_PIX_FMT_NV12 ||
1828c2ecf20Sopenharmony_ci	    dst_q_data->pixelformat == V4L2_PIX_FMT_NV21)
1838c2ecf20Sopenharmony_ci		val = dst_q_data->bytesperline * dst_q_data->height;
1848c2ecf20Sopenharmony_ci	else
1858c2ecf20Sopenharmony_ci		val = 0;
1868c2ecf20Sopenharmony_ci	writel(val, vdoa->regs + VDOAIUBO);
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	val = src;
1898c2ecf20Sopenharmony_ci	writel(val, vdoa->regs + VDOAVEBA0);
1908c2ecf20Sopenharmony_ci	val = round_up(src_q_data->bytesperline * src_q_data->height, 4096);
1918c2ecf20Sopenharmony_ci	writel(val, vdoa->regs + VDOAVUBO);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	/* Enable interrupts and start transfer */
1948c2ecf20Sopenharmony_ci	writel(VDOAIE_EITERR | VDOAIE_EIEOT, vdoa->regs + VDOAIE);
1958c2ecf20Sopenharmony_ci	writel(VDOASRR_START, vdoa->regs + VDOASRR);
1968c2ecf20Sopenharmony_ci}
1978c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vdoa_device_run);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cistruct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	struct vdoa_ctx *ctx;
2028c2ecf20Sopenharmony_ci	int err;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
2058c2ecf20Sopenharmony_ci	if (!ctx)
2068c2ecf20Sopenharmony_ci		return NULL;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	err = clk_prepare_enable(vdoa->vdoa_clk);
2098c2ecf20Sopenharmony_ci	if (err) {
2108c2ecf20Sopenharmony_ci		kfree(ctx);
2118c2ecf20Sopenharmony_ci		return NULL;
2128c2ecf20Sopenharmony_ci	}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	init_completion(&ctx->completion);
2158c2ecf20Sopenharmony_ci	ctx->vdoa = vdoa;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	return ctx;
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vdoa_context_create);
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_civoid vdoa_context_destroy(struct vdoa_ctx *ctx)
2228c2ecf20Sopenharmony_ci{
2238c2ecf20Sopenharmony_ci	struct vdoa_data *vdoa = ctx->vdoa;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	if (vdoa->curr_ctx == ctx) {
2268c2ecf20Sopenharmony_ci		vdoa_wait_for_completion(vdoa->curr_ctx);
2278c2ecf20Sopenharmony_ci		vdoa->curr_ctx = NULL;
2288c2ecf20Sopenharmony_ci	}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	clk_disable_unprepare(vdoa->vdoa_clk);
2318c2ecf20Sopenharmony_ci	kfree(ctx);
2328c2ecf20Sopenharmony_ci}
2338c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vdoa_context_destroy);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ciint vdoa_context_configure(struct vdoa_ctx *ctx,
2368c2ecf20Sopenharmony_ci			   unsigned int width, unsigned int height,
2378c2ecf20Sopenharmony_ci			   u32 pixelformat)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	struct vdoa_q_data *src_q_data;
2408c2ecf20Sopenharmony_ci	struct vdoa_q_data *dst_q_data;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	if (width < 16 || width  > 8192 || width % 16 != 0 ||
2438c2ecf20Sopenharmony_ci	    height < 16 || height > 4096 || height % 16 != 0)
2448c2ecf20Sopenharmony_ci		return -EINVAL;
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	if (pixelformat != V4L2_PIX_FMT_YUYV &&
2478c2ecf20Sopenharmony_ci	    pixelformat != V4L2_PIX_FMT_NV12)
2488c2ecf20Sopenharmony_ci		return -EINVAL;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	/* If no context is passed, only check if the format is valid */
2518c2ecf20Sopenharmony_ci	if (!ctx)
2528c2ecf20Sopenharmony_ci		return 0;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	src_q_data = &ctx->q_data[V4L2_M2M_SRC];
2558c2ecf20Sopenharmony_ci	dst_q_data = &ctx->q_data[V4L2_M2M_DST];
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	src_q_data->width = width;
2588c2ecf20Sopenharmony_ci	src_q_data->height = height;
2598c2ecf20Sopenharmony_ci	src_q_data->bytesperline = width;
2608c2ecf20Sopenharmony_ci	src_q_data->sizeimage =
2618c2ecf20Sopenharmony_ci		round_up(src_q_data->bytesperline * height, 4096) +
2628c2ecf20Sopenharmony_ci		src_q_data->bytesperline * height / 2;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	dst_q_data->width = width;
2658c2ecf20Sopenharmony_ci	dst_q_data->height = height;
2668c2ecf20Sopenharmony_ci	dst_q_data->pixelformat = pixelformat;
2678c2ecf20Sopenharmony_ci	switch (pixelformat) {
2688c2ecf20Sopenharmony_ci	case V4L2_PIX_FMT_YUYV:
2698c2ecf20Sopenharmony_ci		dst_q_data->bytesperline = width * 2;
2708c2ecf20Sopenharmony_ci		dst_q_data->sizeimage = dst_q_data->bytesperline * height;
2718c2ecf20Sopenharmony_ci		break;
2728c2ecf20Sopenharmony_ci	case V4L2_PIX_FMT_NV12:
2738c2ecf20Sopenharmony_ci	default:
2748c2ecf20Sopenharmony_ci		dst_q_data->bytesperline = width;
2758c2ecf20Sopenharmony_ci		dst_q_data->sizeimage =
2768c2ecf20Sopenharmony_ci			dst_q_data->bytesperline * height * 3 / 2;
2778c2ecf20Sopenharmony_ci		break;
2788c2ecf20Sopenharmony_ci	}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	return 0;
2818c2ecf20Sopenharmony_ci}
2828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vdoa_context_configure);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_cistatic int vdoa_probe(struct platform_device *pdev)
2858c2ecf20Sopenharmony_ci{
2868c2ecf20Sopenharmony_ci	struct vdoa_data *vdoa;
2878c2ecf20Sopenharmony_ci	struct resource *res;
2888c2ecf20Sopenharmony_ci	int ret;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
2918c2ecf20Sopenharmony_ci	if (ret) {
2928c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "DMA enable failed\n");
2938c2ecf20Sopenharmony_ci		return ret;
2948c2ecf20Sopenharmony_ci	}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	vdoa = devm_kzalloc(&pdev->dev, sizeof(*vdoa), GFP_KERNEL);
2978c2ecf20Sopenharmony_ci	if (!vdoa)
2988c2ecf20Sopenharmony_ci		return -ENOMEM;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	vdoa->dev = &pdev->dev;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	vdoa->vdoa_clk = devm_clk_get(vdoa->dev, NULL);
3038c2ecf20Sopenharmony_ci	if (IS_ERR(vdoa->vdoa_clk)) {
3048c2ecf20Sopenharmony_ci		dev_err(vdoa->dev, "Failed to get clock\n");
3058c2ecf20Sopenharmony_ci		return PTR_ERR(vdoa->vdoa_clk);
3068c2ecf20Sopenharmony_ci	}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3098c2ecf20Sopenharmony_ci	vdoa->regs = devm_ioremap_resource(vdoa->dev, res);
3108c2ecf20Sopenharmony_ci	if (IS_ERR(vdoa->regs))
3118c2ecf20Sopenharmony_ci		return PTR_ERR(vdoa->regs);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
3148c2ecf20Sopenharmony_ci	if (!res)
3158c2ecf20Sopenharmony_ci		return -EINVAL;
3168c2ecf20Sopenharmony_ci	ret = devm_request_threaded_irq(&pdev->dev, res->start, NULL,
3178c2ecf20Sopenharmony_ci					vdoa_irq_handler, IRQF_ONESHOT,
3188c2ecf20Sopenharmony_ci					"vdoa", vdoa);
3198c2ecf20Sopenharmony_ci	if (ret < 0) {
3208c2ecf20Sopenharmony_ci		dev_err(vdoa->dev, "Failed to get irq\n");
3218c2ecf20Sopenharmony_ci		return ret;
3228c2ecf20Sopenharmony_ci	}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, vdoa);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	return 0;
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic int vdoa_remove(struct platform_device *pdev)
3308c2ecf20Sopenharmony_ci{
3318c2ecf20Sopenharmony_ci	return 0;
3328c2ecf20Sopenharmony_ci}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_cistatic const struct of_device_id vdoa_dt_ids[] = {
3358c2ecf20Sopenharmony_ci	{ .compatible = "fsl,imx6q-vdoa" },
3368c2ecf20Sopenharmony_ci	{}
3378c2ecf20Sopenharmony_ci};
3388c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, vdoa_dt_ids);
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_cistatic struct platform_driver vdoa_driver = {
3418c2ecf20Sopenharmony_ci	.probe		= vdoa_probe,
3428c2ecf20Sopenharmony_ci	.remove		= vdoa_remove,
3438c2ecf20Sopenharmony_ci	.driver		= {
3448c2ecf20Sopenharmony_ci		.name	= VDOA_NAME,
3458c2ecf20Sopenharmony_ci		.of_match_table = vdoa_dt_ids,
3468c2ecf20Sopenharmony_ci	},
3478c2ecf20Sopenharmony_ci};
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_cimodule_platform_driver(vdoa_driver);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Video Data Order Adapter");
3528c2ecf20Sopenharmony_ciMODULE_AUTHOR("Philipp Zabel <philipp.zabel@gmail.com>");
3538c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:imx-vdoa");
3548c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
355