linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/9] ARM: dts: imx6qdl: Add VDOA compatible and clocks properties
@ 2016-12-08 15:24 Michael Tretter
  2016-12-08 15:24 ` [PATCH 2/9] [media] coda: add i.MX6 VDOA driver Michael Tretter
                   ` (7 more replies)
  0 siblings, 8 replies; 13+ messages in thread
From: Michael Tretter @ 2016-12-08 15:24 UTC (permalink / raw)
  To: linux-media; +Cc: p.zabel, Philipp Zabel, Michael Tretter

From: Philipp Zabel <philipp.zabel@gmail.com>

This adds a compatible property and the correct clock for the
i.MX6Q Video Data Order Adapter.

Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
---
 arch/arm/boot/dts/imx6qdl.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index b13b0b2..69e3668 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -1153,8 +1153,10 @@
 			};
 
 			vdoa@021e4000 {
+				compatible = "fsl,imx6q-vdoa";
 				reg = <0x021e4000 0x4000>;
 				interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6QDL_CLK_VDOA>;
 			};
 
 			uart2: serial@021e8000 {
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/9] [media] coda: add i.MX6 VDOA driver
  2016-12-08 15:24 [PATCH 1/9] ARM: dts: imx6qdl: Add VDOA compatible and clocks properties Michael Tretter
@ 2016-12-08 15:24 ` Michael Tretter
  2016-12-08 15:24 ` [PATCH 3/9] ARM: dts: imx6qdl: Add VDOA phandle to CODA node Michael Tretter
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Michael Tretter @ 2016-12-08 15:24 UTC (permalink / raw)
  To: linux-media; +Cc: p.zabel, Philipp Zabel, Michael Tretter

From: Philipp Zabel <philipp.zabel@gmail.com>

The i.MX6 Video Data Order Adapter's (VDOA) sole purpose is to convert
from a custom macroblock tiled format produced by the CODA960 decoder
into linear formats that can be used for scanout.

Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
---
 drivers/media/platform/Kconfig         |   3 +
 drivers/media/platform/coda/Makefile   |   1 +
 drivers/media/platform/coda/imx-vdoa.c | 331 +++++++++++++++++++++++++++++++++
 drivers/media/platform/coda/imx-vdoa.h |  58 ++++++
 4 files changed, 393 insertions(+)
 create mode 100644 drivers/media/platform/coda/imx-vdoa.c
 create mode 100644 drivers/media/platform/coda/imx-vdoa.h

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index ce4a96f..41e007f 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -162,6 +162,9 @@ config VIDEO_CODA
 	   Coda is a range of video codec IPs that supports
 	   H.264, MPEG-4, and other video formats.
 
+config VIDEO_IMX_VDOA
+	def_tristate VIDEO_CODA if SOC_IMX6Q || COMPILE_TEST
+
 config VIDEO_MEDIATEK_VPU
 	tristate "Mediatek Video Processor Unit"
 	depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA
diff --git a/drivers/media/platform/coda/Makefile b/drivers/media/platform/coda/Makefile
index 9342ac5..8582843 100644
--- a/drivers/media/platform/coda/Makefile
+++ b/drivers/media/platform/coda/Makefile
@@ -3,3 +3,4 @@ ccflags-y += -I$(src)
 coda-objs := coda-common.o coda-bit.o coda-gdi.o coda-h264.o coda-jpeg.o
 
 obj-$(CONFIG_VIDEO_CODA) += coda.o
+obj-$(CONFIG_VIDEO_IMX_VDOA) += imx-vdoa.o
diff --git a/drivers/media/platform/coda/imx-vdoa.c b/drivers/media/platform/coda/imx-vdoa.c
new file mode 100644
index 0000000..9b4ae07
--- /dev/null
+++ b/drivers/media/platform/coda/imx-vdoa.c
@@ -0,0 +1,331 @@
+/*
+ * i.MX6 Video Data Order Adapter (VDOA)
+ *
+ * Copyright (C) 2014 Philipp Zabel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/module.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;
+	int			irq;
+};
+
+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];
+};
+
+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_dbg(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");
+	}
+	complete(&curr_ctx->completion);
+
+	return IRQ_HANDLED;
+}
+
+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;
+
+	vdoa->curr_ctx = ctx;
+
+	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 = src_q_data->bytesperline * src_q_data->height;
+	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);
+
+int vdoa_wait_for_completion(struct vdoa_ctx *ctx)
+{
+	struct vdoa_data *vdoa = ctx->vdoa;
+
+	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);
+
+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;
+
+	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;
+
+	src_q_data = &ctx->q_data[V4L2_M2M_SRC];
+	dst_q_data = &ctx->q_data[V4L2_M2M_DST];
+
+	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;
+
+	src_q_data->width = width;
+	src_q_data->height = height;
+	src_q_data->bytesperline = width;
+	src_q_data->sizeimage = src_q_data->bytesperline * height * 3 / 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;
+	struct resource *res;
+
+	dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+
+	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);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	vdoa->regs = devm_ioremap_resource(vdoa->dev, res);
+	if (IS_ERR(vdoa->regs))
+		return PTR_ERR(vdoa->regs);
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	vdoa->irq = devm_request_threaded_irq(&pdev->dev, res->start, NULL,
+					vdoa_irq_handler, IRQF_ONESHOT,
+					"vdoa", vdoa);
+	if (vdoa->irq < 0) {
+		dev_err(vdoa->dev, "Failed to get irq\n");
+		return vdoa->irq;
+	}
+
+	platform_set_drvdata(pdev, vdoa);
+
+	return 0;
+}
+
+static int vdoa_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static 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,
+	.remove		= vdoa_remove,
+	.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");
diff --git a/drivers/media/platform/coda/imx-vdoa.h b/drivers/media/platform/coda/imx-vdoa.h
new file mode 100644
index 0000000..967576b
--- /dev/null
+++ b/drivers/media/platform/coda/imx-vdoa.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef IMX_VDOA_H
+#define IMX_VDOA_H
+
+struct vdoa_data;
+struct vdoa_ctx;
+
+#if (defined CONFIG_VIDEO_IMX_VDOA || defined CONFIG_VIDEO_IMX_VDOA_MODULE)
+
+struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa);
+int vdoa_context_configure(struct vdoa_ctx *ctx,
+			   unsigned int width, unsigned int height,
+			   u32 pixelformat);
+void vdoa_context_destroy(struct vdoa_ctx *ctx);
+
+void vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src);
+int vdoa_wait_for_completion(struct vdoa_ctx *ctx);
+
+#else
+
+static inline struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa)
+{
+	return NULL;
+}
+
+static inline int vdoa_context_configure(struct vdoa_ctx *ctx,
+					 unsigned int width,
+					 unsigned int height,
+					 u32 pixelformat)
+{
+	return 0;
+}
+
+static inline void vdoa_context_destroy(struct vdoa_ctx *ctx) { };
+
+static inline void vdoa_device_run(struct vdoa_ctx *ctx,
+				   dma_addr_t dst, dma_addr_t src) { };
+
+static inline int vdoa_wait_for_completion(struct vdoa_ctx *ctx)
+{
+	return 0;
+};
+
+#endif
+
+#endif /* IMX_VDOA_H */
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/9] ARM: dts: imx6qdl: Add VDOA phandle to CODA node
  2016-12-08 15:24 [PATCH 1/9] ARM: dts: imx6qdl: Add VDOA compatible and clocks properties Michael Tretter
  2016-12-08 15:24 ` [PATCH 2/9] [media] coda: add i.MX6 VDOA driver Michael Tretter
@ 2016-12-08 15:24 ` Michael Tretter
  2016-12-08 15:24 ` [PATCH 4/9] [media] coda: correctly set capture compose rectangle Michael Tretter
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Michael Tretter @ 2016-12-08 15:24 UTC (permalink / raw)
  To: linux-media; +Cc: p.zabel, Michael Tretter

The CODA driver should use the VDOA to transform the tiled format to
raster-ordered format, if the platform has a VDOA. Link the CODA and
VDOA nodes to tell the CODA driver that it can use the VDOA.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
---
 Documentation/devicetree/bindings/media/coda.txt | 2 ++
 arch/arm/boot/dts/imx6qdl.dtsi                   | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/media/coda.txt b/Documentation/devicetree/bindings/media/coda.txt
index 2865d04..7900788 100644
--- a/Documentation/devicetree/bindings/media/coda.txt
+++ b/Documentation/devicetree/bindings/media/coda.txt
@@ -17,6 +17,7 @@ Required properties:
   determined by the clock-names property.
 - clock-names : Should be "ahb", "per"
 - iram : phandle pointing to the SRAM device node
+- vdoa : phandle pointing to the VDOA device node
 
 Example:
 
@@ -27,4 +28,5 @@ vpu: vpu@63ff4000 {
 	clocks = <&clks 63>, <&clks 63>;
 	clock-names = "ahb", "per";
 	iram = <&ocram>;
+	vdoa = <&vdoa>;
 };
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 69e3668..7bf3429 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -427,6 +427,7 @@
 				power-domains = <&gpc 1>;
 				resets = <&src 1>;
 				iram = <&ocram>;
+				vdoa = <&vdoa>;
 			};
 
 			aipstz@0207c000 { /* AIPSTZ1 */
@@ -1152,7 +1153,7 @@
 				};
 			};
 
-			vdoa@021e4000 {
+			vdoa: vdoa@021e4000 {
 				compatible = "fsl,imx6q-vdoa";
 				reg = <0x021e4000 0x4000>;
 				interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 4/9] [media] coda: correctly set capture compose rectangle
  2016-12-08 15:24 [PATCH 1/9] ARM: dts: imx6qdl: Add VDOA compatible and clocks properties Michael Tretter
  2016-12-08 15:24 ` [PATCH 2/9] [media] coda: add i.MX6 VDOA driver Michael Tretter
  2016-12-08 15:24 ` [PATCH 3/9] ARM: dts: imx6qdl: Add VDOA phandle to CODA node Michael Tretter
@ 2016-12-08 15:24 ` Michael Tretter
  2016-12-08 15:24 ` [PATCH 5/9] [media] coda: get VDOA device using dt phandle Michael Tretter
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Michael Tretter @ 2016-12-08 15:24 UTC (permalink / raw)
  To: linux-media; +Cc: p.zabel, Michael Tretter

From: Philipp Zabel <p.zabel@pengutronix.de>

Correctly store the rectangle of valid video data in the destination
q_data before rounding up to macroblock size. This fixes the output
of VIDIOC_G_SELECTION for the capture side compose rectangle.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
---
 drivers/media/platform/coda/coda-common.c | 37 ++++++++++++++++++++++++-------
 1 file changed, 29 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index c39718a..e0184194 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -566,7 +566,8 @@ static int coda_try_fmt_vid_out(struct file *file, void *priv,
 	return coda_try_fmt(ctx, codec, f);
 }
 
-static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f)
+static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f,
+		      struct v4l2_rect *r)
 {
 	struct coda_q_data *q_data;
 	struct vb2_queue *vq;
@@ -589,10 +590,14 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f)
 	q_data->height = f->fmt.pix.height;
 	q_data->bytesperline = f->fmt.pix.bytesperline;
 	q_data->sizeimage = f->fmt.pix.sizeimage;
-	q_data->rect.left = 0;
-	q_data->rect.top = 0;
-	q_data->rect.width = f->fmt.pix.width;
-	q_data->rect.height = f->fmt.pix.height;
+	if (r) {
+		q_data->rect = *r;
+	} else {
+		q_data->rect.left = 0;
+		q_data->rect.top = 0;
+		q_data->rect.width = f->fmt.pix.width;
+		q_data->rect.height = f->fmt.pix.height;
+	}
 
 	switch (f->fmt.pix.pixelformat) {
 	case V4L2_PIX_FMT_NV12:
@@ -621,27 +626,37 @@ static int coda_s_fmt_vid_cap(struct file *file, void *priv,
 			      struct v4l2_format *f)
 {
 	struct coda_ctx *ctx = fh_to_ctx(priv);
+	struct coda_q_data *q_data_src;
+	struct v4l2_rect r;
 	int ret;
 
 	ret = coda_try_fmt_vid_cap(file, priv, f);
 	if (ret)
 		return ret;
 
-	return coda_s_fmt(ctx, f);
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	r.left = 0;
+	r.top = 0;
+	r.width = q_data_src->width;
+	r.height = q_data_src->height;
+
+	return coda_s_fmt(ctx, f, &r);
 }
 
 static int coda_s_fmt_vid_out(struct file *file, void *priv,
 			      struct v4l2_format *f)
 {
 	struct coda_ctx *ctx = fh_to_ctx(priv);
+	struct coda_q_data *q_data_src;
 	struct v4l2_format f_cap;
+	struct v4l2_rect r;
 	int ret;
 
 	ret = coda_try_fmt_vid_out(file, priv, f);
 	if (ret)
 		return ret;
 
-	ret = coda_s_fmt(ctx, f);
+	ret = coda_s_fmt(ctx, f, NULL);
 	if (ret)
 		return ret;
 
@@ -657,7 +672,13 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv,
 	if (ret)
 		return ret;
 
-	return coda_s_fmt(ctx, &f_cap);
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	r.left = 0;
+	r.top = 0;
+	r.width = q_data_src->width;
+	r.height = q_data_src->height;
+
+	return coda_s_fmt(ctx, &f_cap, &r);
 }
 
 static int coda_reqbufs(struct file *file, void *priv,
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 5/9] [media] coda: get VDOA device using dt phandle
  2016-12-08 15:24 [PATCH 1/9] ARM: dts: imx6qdl: Add VDOA compatible and clocks properties Michael Tretter
                   ` (2 preceding siblings ...)
  2016-12-08 15:24 ` [PATCH 4/9] [media] coda: correctly set capture compose rectangle Michael Tretter
@ 2016-12-08 15:24 ` Michael Tretter
  2016-12-08 15:50   ` Philipp Zabel
  2016-12-08 15:24 ` [PATCH 6/9] [media] coda: add debug output about tiling Michael Tretter
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 13+ messages in thread
From: Michael Tretter @ 2016-12-08 15:24 UTC (permalink / raw)
  To: linux-media; +Cc: p.zabel, Michael Tretter

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
---
 drivers/media/platform/coda/coda-common.c | 43 +++++++++++++++++++++++++++++++
 drivers/media/platform/coda/coda.h        |  1 +
 2 files changed, 44 insertions(+)

diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index e0184194..1adb6f3 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -41,6 +41,7 @@
 #include <media/videobuf2-vmalloc.h>
 
 #include "coda.h"
+#include "imx-vdoa.h"
 
 #define CODA_NAME		"coda"
 
@@ -66,6 +67,10 @@ static int disable_tiling;
 module_param(disable_tiling, int, 0644);
 MODULE_PARM_DESC(disable_tiling, "Disable tiled frame buffers");
 
+static int disable_vdoa;
+module_param(disable_vdoa, int, 0644);
+MODULE_PARM_DESC(disable_vdoa, "Disable Video Data Order Adapter tiled to raster-scan conversion");
+
 void coda_write(struct coda_dev *dev, u32 data, u32 reg)
 {
 	v4l2_dbg(2, coda_debug, &dev->v4l2_dev,
@@ -325,6 +330,34 @@ const char *coda_product_name(int product)
 	}
 }
 
+static struct vdoa_data *coda_get_vdoa_data(struct device_node *np,
+					    const char *name)
+{
+	struct device_node *vdoa_node;
+	struct platform_device *vdoa_pdev;
+	struct vdoa_data *vdoa_data;
+
+	vdoa_node = of_parse_phandle(np, name, 0);
+	if (!vdoa_node)
+		return NULL;
+
+	vdoa_pdev = of_find_device_by_node(vdoa_node);
+	if (!vdoa_pdev) {
+		vdoa_data = NULL;
+		goto out;
+	}
+
+	vdoa_data = platform_get_drvdata(vdoa_pdev);
+	if (!vdoa_data)
+		vdoa_data = ERR_PTR(-EPROBE_DEFER);
+
+out:
+	if (vdoa_node)
+		of_node_put(vdoa_node);
+
+	return vdoa_data;
+}
+
 /*
  * V4L2 ioctl() operations.
  */
@@ -2256,6 +2289,16 @@ static int coda_probe(struct platform_device *pdev)
 	}
 	dev->iram_pool = pool;
 
+	/* Get VDOA from device tree if available */
+	if (!disable_tiling && !disable_vdoa) {
+		dev->vdoa = coda_get_vdoa_data(np, "vdoa");
+		if (PTR_ERR(dev->vdoa) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		if (!dev->vdoa)
+			dev_info(&pdev->dev,
+				 "vdoa not available; not using tiled intermediate format");
+	}
+
 	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
 	if (ret)
 		return ret;
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index 53f9666..ae202dc 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -75,6 +75,7 @@ struct coda_dev {
 	struct platform_device	*plat_dev;
 	const struct coda_devtype *devtype;
 	int			firmware;
+	struct vdoa_data	*vdoa;
 
 	void __iomem		*regs_base;
 	struct clk		*clk_per;
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 6/9] [media] coda: add debug output about tiling
  2016-12-08 15:24 [PATCH 1/9] ARM: dts: imx6qdl: Add VDOA compatible and clocks properties Michael Tretter
                   ` (3 preceding siblings ...)
  2016-12-08 15:24 ` [PATCH 5/9] [media] coda: get VDOA device using dt phandle Michael Tretter
@ 2016-12-08 15:24 ` Michael Tretter
  2016-12-08 15:24 ` [PATCH 7/9] [media] coda: fix frame index to returned error Michael Tretter
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Michael Tretter @ 2016-12-08 15:24 UTC (permalink / raw)
  To: linux-media; +Cc: p.zabel, Michael Tretter

From: Philipp Zabel <p.zabel@pengutronix.de>

In order to make the VDOA work correctly, the CODA must produce frames
in tiled format. Print this information in the debug output.

Also print the color format in fourcc instead of the numeric value.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
---
 drivers/media/platform/coda/coda-common.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 1adb6f3..3a21000 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -649,8 +649,10 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f,
 	}
 
 	v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
-		"Setting format for type %d, wxh: %dx%d, fmt: %d\n",
-		f->type, q_data->width, q_data->height, q_data->fourcc);
+		"Setting format for type %d, wxh: %dx%d, fmt: %4.4s %c\n",
+		f->type, q_data->width, q_data->height,
+		(char *)&q_data->fourcc,
+		(ctx->tiled_map_type == GDI_LINEAR_FRAME_MAP) ? 'L' : 'T');
 
 	return 0;
 }
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 7/9] [media] coda: fix frame index to returned error
  2016-12-08 15:24 [PATCH 1/9] ARM: dts: imx6qdl: Add VDOA compatible and clocks properties Michael Tretter
                   ` (4 preceding siblings ...)
  2016-12-08 15:24 ` [PATCH 6/9] [media] coda: add debug output about tiling Michael Tretter
@ 2016-12-08 15:24 ` Michael Tretter
  2016-12-08 15:53   ` Philipp Zabel
  2016-12-08 15:24 ` [PATCH 8/9] [media] coda: use VDOA for un-tiling custom macroblock format Michael Tretter
  2016-12-08 15:24 ` [PATCH 9/9] [media] coda: support YUYV output if VDOA is used Michael Tretter
  7 siblings, 1 reply; 13+ messages in thread
From: Michael Tretter @ 2016-12-08 15:24 UTC (permalink / raw)
  To: linux-media; +Cc: p.zabel, Michael Tretter

display_idx refers to the frame that will be returned in the next round.
The currently processed frame is ctx->display_idx and errors should be
reported for this frame.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
---
 drivers/media/platform/coda/coda-bit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index b662504..309eb4e 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -2057,7 +2057,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
 		}
 		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);
 
-		coda_m2m_buf_done(ctx, dst_buf, ctx->frame_errors[display_idx] ?
+		coda_m2m_buf_done(ctx, dst_buf, ctx->frame_errors[ctx->display_idx] ?
 				  VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
 
 		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 8/9] [media] coda: use VDOA for un-tiling custom macroblock format
  2016-12-08 15:24 [PATCH 1/9] ARM: dts: imx6qdl: Add VDOA compatible and clocks properties Michael Tretter
                   ` (5 preceding siblings ...)
  2016-12-08 15:24 ` [PATCH 7/9] [media] coda: fix frame index to returned error Michael Tretter
@ 2016-12-08 15:24 ` Michael Tretter
  2016-12-08 15:58   ` Philipp Zabel
  2016-12-08 15:24 ` [PATCH 9/9] [media] coda: support YUYV output if VDOA is used Michael Tretter
  7 siblings, 1 reply; 13+ messages in thread
From: Michael Tretter @ 2016-12-08 15:24 UTC (permalink / raw)
  To: linux-media; +Cc: p.zabel, Michael Tretter

If the CODA driver is configured to produce NV12 output and the VDOA is
available, the VDOA can be used to transform the custom macroblock tiled
format to a raster-ordered format for scanout.

In this case, set the output format of the CODA to the custom macroblock
tiled format, disable the rotator, and use the VDOA to write to the v4l2
buffer. The VDOA is synchronized with the CODA to always un-tile the
frame that the CODA finished in the previous run.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
---
 drivers/media/platform/coda/coda-bit.c    | 77 +++++++++++++++++++++----------
 drivers/media/platform/coda/coda-common.c | 55 ++++++++++++++++++++--
 drivers/media/platform/coda/coda.h        |  2 +
 3 files changed, 104 insertions(+), 30 deletions(-)

diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index 309eb4e..3e2f830 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -30,6 +30,7 @@
 #include <media/videobuf2-vmalloc.h>
 
 #include "coda.h"
+#include "imx-vdoa.h"
 #define CREATE_TRACE_POINTS
 #include "trace.h"
 
@@ -1517,6 +1518,10 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
 	u32 val;
 	int ret;
 
+	v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+		 "Video Data Order Adapter: %s\n",
+		 ctx->use_vdoa ? "Enabled" : "Disabled");
+
 	/* Start decoding */
 	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
@@ -1535,7 +1540,8 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
 	if (dst_fourcc == V4L2_PIX_FMT_NV12)
 		ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
 	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
-		ctx->frame_mem_ctrl |= (0x3 << 9) | CODA9_FRAME_TILED2LINEAR;
+		ctx->frame_mem_ctrl |= (0x3 << 9) |
+			((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR);
 	coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL);
 
 	ctx->display_idx = -1;
@@ -1724,6 +1730,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
 	struct coda_q_data *q_data_dst;
 	struct coda_buffer_meta *meta;
 	unsigned long flags;
+	u32 rot_mode = 0;
 	u32 reg_addr, reg_stride;
 
 	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
@@ -1759,27 +1766,40 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
 	if (dev->devtype->product == CODA_960)
 		coda_set_gdi_regs(ctx);
 
-	if (dev->devtype->product == CODA_960) {
-		/*
-		 * The CODA960 seems to have an internal list of buffers with
-		 * 64 entries that includes the registered frame buffers as
-		 * well as the rotator buffer output.
-		 * ROT_INDEX needs to be < 0x40, but > ctx->num_internal_frames.
-		 */
-		coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf->vb2_buf.index,
-				CODA9_CMD_DEC_PIC_ROT_INDEX);
-
-		reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y;
-		reg_stride = CODA9_CMD_DEC_PIC_ROT_STRIDE;
+	if (ctx->use_vdoa &&
+	    ctx->display_idx >= 0 &&
+	    ctx->display_idx < ctx->num_internal_frames) {
+		vdoa_device_run(ctx->vdoa,
+				vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0),
+				ctx->internal_frames[ctx->display_idx].paddr);
 	} else {
-		reg_addr = CODA_CMD_DEC_PIC_ROT_ADDR_Y;
-		reg_stride = CODA_CMD_DEC_PIC_ROT_STRIDE;
+		if (dev->devtype->product == CODA_960) {
+			/*
+			 * The CODA960 seems to have an internal list of
+			 * buffers with 64 entries that includes the
+			 * registered frame buffers as well as the rotator
+			 * buffer output.
+			 *
+			 * ROT_INDEX needs to be < 0x40, but >
+			 * ctx->num_internal_frames.
+			 */
+			coda_write(dev,
+				   CODA_MAX_FRAMEBUFFERS + dst_buf->vb2_buf.index,
+				   CODA9_CMD_DEC_PIC_ROT_INDEX);
+
+			reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y;
+			reg_stride = CODA9_CMD_DEC_PIC_ROT_STRIDE;
+		} else {
+			reg_addr = CODA_CMD_DEC_PIC_ROT_ADDR_Y;
+			reg_stride = CODA_CMD_DEC_PIC_ROT_STRIDE;
+		}
+		coda_write_base(ctx, q_data_dst, dst_buf, reg_addr);
+		coda_write(dev, q_data_dst->bytesperline, reg_stride);
+
+		rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode;
 	}
-	coda_write_base(ctx, q_data_dst, dst_buf, reg_addr);
-	coda_write(dev, q_data_dst->bytesperline, reg_stride);
 
-	coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
-			CODA_CMD_DEC_PIC_ROT_MODE);
+	coda_write(dev, rot_mode, CODA_CMD_DEC_PIC_ROT_MODE);
 
 	switch (dev->devtype->product) {
 	case CODA_DX6:
@@ -1851,6 +1871,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
 	u32 src_fourcc;
 	int success;
 	u32 err_mb;
+	int err_vdoa = 0;
 	u32 val;
 
 	/* Update kfifo out pointer from coda bitstream read pointer */
@@ -1934,13 +1955,17 @@ static void coda_finish_decode(struct coda_ctx *ctx)
 		}
 	}
 
+	/* Wait until the VDOA finished writing the previous display frame */
+	if (ctx->use_vdoa &&
+	    ctx->display_idx >= 0 &&
+	    ctx->display_idx < ctx->num_internal_frames) {
+		err_vdoa = vdoa_wait_for_completion(ctx->vdoa);
+	}
+
 	ctx->frm_dis_flg = coda_read(dev,
 				     CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
 
-	/*
-	 * The previous display frame was copied out by the rotator,
-	 * now it can be overwritten again
-	 */
+	/* The previous display frame was copied out and can be overwritten */
 	if (ctx->display_idx >= 0 &&
 	    ctx->display_idx < ctx->num_internal_frames) {
 		ctx->frm_dis_flg &= ~(1 << ctx->display_idx);
@@ -2057,8 +2082,10 @@ static void coda_finish_decode(struct coda_ctx *ctx)
 		}
 		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);
 
-		coda_m2m_buf_done(ctx, dst_buf, ctx->frame_errors[ctx->display_idx] ?
-				  VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+		if (ctx->frame_errors[ctx->display_idx] || err_vdoa)
+			coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_ERROR);
+		else
+			coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_DONE);
 
 		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
 			"job finished: decoding frame (%d) (%s)\n",
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 3a21000..8b23ea4 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -450,6 +450,30 @@ static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f)
 	return 0;
 }
 
+static int coda_try_vdoa(struct coda_ctx *ctx, struct v4l2_format *f)
+{
+	int err;
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (!ctx->vdoa) {
+		ctx->use_vdoa = false;
+		return 0;
+	}
+
+	err = vdoa_context_configure(ctx->vdoa, f->fmt.pix.width,
+				     f->fmt.pix.height, f->fmt.pix.pixelformat);
+	if (err) {
+		ctx->use_vdoa = false;
+		return 0;
+	}
+
+	ctx->use_vdoa = true;
+
+	return 0;
+}
+
 static unsigned int coda_estimate_sizeimage(struct coda_ctx *ctx, u32 sizeimage,
 					    u32 width, u32 height)
 {
@@ -564,6 +588,10 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
 		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
 		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
 				       f->fmt.pix.height * 3 / 2;
+
+		ret = coda_try_vdoa(ctx, f);
+		if (ret < 0)
+			return ret;
 	}
 
 	return 0;
@@ -632,13 +660,20 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f,
 		q_data->rect.height = f->fmt.pix.height;
 	}
 
+	/*
+	 * It would be nice to set use_vdoa in coda_s_fmt instead of
+	 * coda_try_vdoa() to have a single location where this is changed.
+	 * Unfortunately, if the capture format is V4L2_PIX_FMT_NV12, we
+	 * cannot be sure if the VDOA should be used, without storing the
+	 * result of coda_try_vdoa() or calling vdoa_context_configure()
+	 * again. Therefore, set use_vdoa in coda_try_vdoa.
+	 */
+
 	switch (f->fmt.pix.pixelformat) {
 	case V4L2_PIX_FMT_NV12:
-		if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-			ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
-			if (!disable_tiling)
-				break;
-		}
+		ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
+		if (!disable_tiling)
+			break;
 		/* else fall through */
 	case V4L2_PIX_FMT_YUV420:
 	case V4L2_PIX_FMT_YVU420:
@@ -1764,6 +1799,13 @@ static int coda_open(struct file *file)
 	default:
 		ctx->reg_idx = idx;
 	}
+	if (ctx->dev->vdoa) {
+		ctx->vdoa = vdoa_context_create(dev->vdoa);
+		if (!ctx->vdoa)
+			v4l2_warn(&dev->v4l2_dev,
+				  "Failed to create vdoa context: not using vdoa");
+	}
+	ctx->use_vdoa = false;
 
 	/* Power up and upload firmware if necessary */
 	ret = pm_runtime_get_sync(&dev->plat_dev->dev);
@@ -1839,6 +1881,9 @@ static int coda_release(struct file *file)
 	v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n",
 		 ctx);
 
+	if (ctx->vdoa)
+		vdoa_context_destroy(ctx->vdoa);
+
 	if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit)
 		coda_bit_stream_end_flag(ctx);
 
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index ae202dc..7ed79eb 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -237,6 +237,8 @@ struct coda_ctx {
 	int				display_idx;
 	struct dentry			*debugfs_entry;
 	bool				use_bit;
+	bool				use_vdoa;
+	struct vdoa_ctx			*vdoa;
 };
 
 extern int coda_debug;
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 9/9] [media] coda: support YUYV output if VDOA is used
  2016-12-08 15:24 [PATCH 1/9] ARM: dts: imx6qdl: Add VDOA compatible and clocks properties Michael Tretter
                   ` (6 preceding siblings ...)
  2016-12-08 15:24 ` [PATCH 8/9] [media] coda: use VDOA for un-tiling custom macroblock format Michael Tretter
@ 2016-12-08 15:24 ` Michael Tretter
  2016-12-08 16:00   ` Philipp Zabel
  7 siblings, 1 reply; 13+ messages in thread
From: Michael Tretter @ 2016-12-08 15:24 UTC (permalink / raw)
  To: linux-media; +Cc: p.zabel, Michael Tretter

The VDOA is able to transform the NV12 custom macroblock tiled format of
the CODA to YUYV format. If and only if the VDOA is available, the
driver can also provide YUYV support.

While the driver is configured to produce YUYV output, the CODA must be
configured to produce NV12 macroblock tiled frames and the VDOA must
transform the intermediate result into the final YUYV output.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
---
 drivers/media/platform/coda/coda-bit.c    |  7 +++++--
 drivers/media/platform/coda/coda-common.c | 30 ++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index 3e2f830..b94ba62 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -759,7 +759,7 @@ static void coda9_set_frame_cache(struct coda_ctx *ctx, u32 fourcc)
 		cache_config = 1 << CODA9_CACHE_PAGEMERGE_OFFSET;
 	}
 	coda_write(ctx->dev, cache_size, CODA9_CMD_SET_FRAME_CACHE_SIZE);
-	if (fourcc == V4L2_PIX_FMT_NV12) {
+	if (fourcc == V4L2_PIX_FMT_NV12 || fourcc == V4L2_PIX_FMT_YUYV) {
 		cache_config |= 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
 				16 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET |
 				0 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET;
@@ -1537,7 +1537,7 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
 
 	ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) |
 				 CODA9_FRAME_TILED2LINEAR);
-	if (dst_fourcc == V4L2_PIX_FMT_NV12)
+	if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV)
 		ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
 	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
 		ctx->frame_mem_ctrl |= (0x3 << 9) |
@@ -2070,6 +2070,9 @@ static void coda_finish_decode(struct coda_ctx *ctx)
 		trace_coda_dec_rot_done(ctx, dst_buf, meta);
 
 		switch (q_data_dst->fourcc) {
+		case V4L2_PIX_FMT_YUYV:
+			payload = width * height * 2;
+			break;
 		case V4L2_PIX_FMT_YUV420:
 		case V4L2_PIX_FMT_YVU420:
 		case V4L2_PIX_FMT_NV12:
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 8b23ea4..1a809b2 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -95,6 +95,8 @@ void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
 	u32 base_cb, base_cr;
 
 	switch (q_data->fourcc) {
+	case V4L2_PIX_FMT_YUYV:
+		/* Fallthrough: IN -H264-> CODA -NV12 MB-> VDOA -YUYV-> OUT */
 	case V4L2_PIX_FMT_NV12:
 	case V4L2_PIX_FMT_YUV420:
 	default:
@@ -201,6 +203,11 @@ static const struct coda_video_device coda_bit_decoder = {
 		V4L2_PIX_FMT_NV12,
 		V4L2_PIX_FMT_YUV420,
 		V4L2_PIX_FMT_YVU420,
+		/*
+		 * If V4L2_PIX_FMT_YUYV should be default,
+		 * set_default_params() must be adjusted.
+		 */
+		V4L2_PIX_FMT_YUYV,
 	},
 };
 
@@ -246,6 +253,7 @@ static u32 coda_format_normalize_yuv(u32 fourcc)
 	case V4L2_PIX_FMT_YUV420:
 	case V4L2_PIX_FMT_YVU420:
 	case V4L2_PIX_FMT_YUV422P:
+	case V4L2_PIX_FMT_YUYV:
 		return V4L2_PIX_FMT_YUV420;
 	default:
 		return fourcc;
@@ -437,6 +445,11 @@ static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f)
 		return -EINVAL;
 
 	for (i = 0; i < CODA_MAX_FORMATS; i++) {
+		/* Skip YUYV if the vdoa is not available */
+		if (!ctx->vdoa && f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+		    formats[i] == V4L2_PIX_FMT_YUYV)
+			continue;
+
 		if (formats[i] == f->fmt.pix.pixelformat) {
 			f->fmt.pix.pixelformat = formats[i];
 			return 0;
@@ -520,6 +533,11 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
 		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
 					f->fmt.pix.height * 3 / 2;
 		break;
+	case V4L2_PIX_FMT_YUYV:
+		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16) * 2;
+		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+					f->fmt.pix.height;
+		break;
 	case V4L2_PIX_FMT_YUV422P:
 		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
 		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
@@ -592,6 +610,15 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
 		ret = coda_try_vdoa(ctx, f);
 		if (ret < 0)
 			return ret;
+
+		if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
+			if (!ctx->use_vdoa)
+				return -EINVAL;
+
+			f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16) * 2;
+			f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+				f->fmt.pix.height;
+		}
 	}
 
 	return 0;
@@ -670,6 +697,9 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f,
 	 */
 
 	switch (f->fmt.pix.pixelformat) {
+	case V4L2_PIX_FMT_YUYV:
+		ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
+		break;
 	case V4L2_PIX_FMT_NV12:
 		ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
 		if (!disable_tiling)
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 5/9] [media] coda: get VDOA device using dt phandle
  2016-12-08 15:24 ` [PATCH 5/9] [media] coda: get VDOA device using dt phandle Michael Tretter
@ 2016-12-08 15:50   ` Philipp Zabel
  0 siblings, 0 replies; 13+ messages in thread
From: Philipp Zabel @ 2016-12-08 15:50 UTC (permalink / raw)
  To: Michael Tretter; +Cc: linux-media

Am Donnerstag, den 08.12.2016, 16:24 +0100 schrieb Michael Tretter:
> Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
> ---
>  drivers/media/platform/coda/coda-common.c | 43 +++++++++++++++++++++++++++++++
>  drivers/media/platform/coda/coda.h        |  1 +
>  2 files changed, 44 insertions(+)
> 
> diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
> index e0184194..1adb6f3 100644
> --- a/drivers/media/platform/coda/coda-common.c
> +++ b/drivers/media/platform/coda/coda-common.c
> @@ -41,6 +41,7 @@
>  #include <media/videobuf2-vmalloc.h>
>  
>  #include "coda.h"
> +#include "imx-vdoa.h"
>  
>  #define CODA_NAME		"coda"
>  
> @@ -66,6 +67,10 @@ static int disable_tiling;
>  module_param(disable_tiling, int, 0644);
>  MODULE_PARM_DESC(disable_tiling, "Disable tiled frame buffers");
>  
> +static int disable_vdoa;
> +module_param(disable_vdoa, int, 0644);
> +MODULE_PARM_DESC(disable_vdoa, "Disable Video Data Order Adapter tiled to raster-scan conversion");
> +
>  void coda_write(struct coda_dev *dev, u32 data, u32 reg)
>  {
>  	v4l2_dbg(2, coda_debug, &dev->v4l2_dev,
> @@ -325,6 +330,34 @@ const char *coda_product_name(int product)
>  	}
>  }
>  
> +static struct vdoa_data *coda_get_vdoa_data(struct device_node *np,
> +					    const char *name)

I'd drop the name parameter, there's only one possible phandle name.

> +{
> +	struct device_node *vdoa_node;
> +	struct platform_device *vdoa_pdev;
> +	struct vdoa_data *vdoa_data;
> +
> +	vdoa_node = of_parse_phandle(np, name, 0);

	vdoa_node = of_parse_phandle(np, "vdoa", 0);

> +	if (!vdoa_node)
> +		return NULL;
> +
> +	vdoa_pdev = of_find_device_by_node(vdoa_node);
> +	if (!vdoa_pdev) {
> +		vdoa_data = NULL;
> +		goto out;
> +	}
> +
> +	vdoa_data = platform_get_drvdata(vdoa_pdev);
> +	if (!vdoa_data)
> +		vdoa_data = ERR_PTR(-EPROBE_DEFER);
> +
> +out:
> +	if (vdoa_node)
> +		of_node_put(vdoa_node);
> +
> +	return vdoa_data;
> +}
> +
>  /*
>   * V4L2 ioctl() operations.
>   */
> @@ -2256,6 +2289,16 @@ static int coda_probe(struct platform_device *pdev)
>  	}
>  	dev->iram_pool = pool;
>  
> +	/* Get VDOA from device tree if available */
> +	if (!disable_tiling && !disable_vdoa) {

disable_tiling/disable_vdoa could be changed after the module is loaded.
Better always call coda_get_vdoa_data.

> +		dev->vdoa = coda_get_vdoa_data(np, "vdoa");

		dev->vdoa = coda_get_vdoa_data(np);

> +		if (PTR_ERR(dev->vdoa) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +		if (!dev->vdoa)
> +			dev_info(&pdev->dev,
> +				 "vdoa not available; not using tiled intermediate format");

This message is not useful on i.MX53, maybe use
	if (dev_type == CODA_960)

> +	}
> +
>  	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
>  	if (ret)
>  		return ret;
> diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
> index 53f9666..ae202dc 100644
> --- a/drivers/media/platform/coda/coda.h
> +++ b/drivers/media/platform/coda/coda.h
> @@ -75,6 +75,7 @@ struct coda_dev {
>  	struct platform_device	*plat_dev;
>  	const struct coda_devtype *devtype;
>  	int			firmware;
> +	struct vdoa_data	*vdoa;
>  
>  	void __iomem		*regs_base;
>  	struct clk		*clk_per;

regards
Philipp


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 7/9] [media] coda: fix frame index to returned error
  2016-12-08 15:24 ` [PATCH 7/9] [media] coda: fix frame index to returned error Michael Tretter
@ 2016-12-08 15:53   ` Philipp Zabel
  0 siblings, 0 replies; 13+ messages in thread
From: Philipp Zabel @ 2016-12-08 15:53 UTC (permalink / raw)
  To: Michael Tretter; +Cc: linux-media

Am Donnerstag, den 08.12.2016, 16:24 +0100 schrieb Michael Tretter:
> display_idx refers to the frame that will be returned in the next round.
> The currently processed frame is ctx->display_idx and errors should be
> reported for this frame.
> 
> Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
> ---
>  drivers/media/platform/coda/coda-bit.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
> index b662504..309eb4e 100644
> --- a/drivers/media/platform/coda/coda-bit.c
> +++ b/drivers/media/platform/coda/coda-bit.c
> @@ -2057,7 +2057,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
>  		}
>  		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);
>  
> -		coda_m2m_buf_done(ctx, dst_buf, ctx->frame_errors[display_idx] ?
> +		coda_m2m_buf_done(ctx, dst_buf, ctx->frame_errors[ctx->display_idx] ?
>  				  VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
>  
>  		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,

Acked-by: Philipp Zabel <p.zabel@pengutronix.de>

regards
Philipp


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 8/9] [media] coda: use VDOA for un-tiling custom macroblock format
  2016-12-08 15:24 ` [PATCH 8/9] [media] coda: use VDOA for un-tiling custom macroblock format Michael Tretter
@ 2016-12-08 15:58   ` Philipp Zabel
  0 siblings, 0 replies; 13+ messages in thread
From: Philipp Zabel @ 2016-12-08 15:58 UTC (permalink / raw)
  To: Michael Tretter; +Cc: linux-media

Am Donnerstag, den 08.12.2016, 16:24 +0100 schrieb Michael Tretter:
> If the CODA driver is configured to produce NV12 output and the VDOA is
> available, the VDOA can be used to transform the custom macroblock tiled
> format to a raster-ordered format for scanout.
> 
> In this case, set the output format of the CODA to the custom macroblock
> tiled format, disable the rotator, and use the VDOA to write to the v4l2
> buffer. The VDOA is synchronized with the CODA to always un-tile the
> frame that the CODA finished in the previous run.
> 
> Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
> ---
>  drivers/media/platform/coda/coda-bit.c    | 77 +++++++++++++++++++++----------
>  drivers/media/platform/coda/coda-common.c | 55 ++++++++++++++++++++--
>  drivers/media/platform/coda/coda.h        |  2 +
>  3 files changed, 104 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
> index 309eb4e..3e2f830 100644
> --- a/drivers/media/platform/coda/coda-bit.c
> +++ b/drivers/media/platform/coda/coda-bit.c
> @@ -30,6 +30,7 @@
>  #include <media/videobuf2-vmalloc.h>
>  
>  #include "coda.h"
> +#include "imx-vdoa.h"
>  #define CREATE_TRACE_POINTS
>  #include "trace.h"
>  
> @@ -1517,6 +1518,10 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
>  	u32 val;
>  	int ret;
>  
> +	v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> +		 "Video Data Order Adapter: %s\n",
> +		 ctx->use_vdoa ? "Enabled" : "Disabled");
> +
>  	/* Start decoding */
>  	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
>  	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> @@ -1535,7 +1540,8 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
>  	if (dst_fourcc == V4L2_PIX_FMT_NV12)
>  		ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
>  	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
> -		ctx->frame_mem_ctrl |= (0x3 << 9) | CODA9_FRAME_TILED2LINEAR;
> +		ctx->frame_mem_ctrl |= (0x3 << 9) |
> +			((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR);
>  	coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL);
>  
>  	ctx->display_idx = -1;
> @@ -1724,6 +1730,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
>  	struct coda_q_data *q_data_dst;
>  	struct coda_buffer_meta *meta;
>  	unsigned long flags;
> +	u32 rot_mode = 0;
>  	u32 reg_addr, reg_stride;
>  
>  	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> @@ -1759,27 +1766,40 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
>  	if (dev->devtype->product == CODA_960)
>  		coda_set_gdi_regs(ctx);
>  
> -	if (dev->devtype->product == CODA_960) {
> -		/*
> -		 * The CODA960 seems to have an internal list of buffers with
> -		 * 64 entries that includes the registered frame buffers as
> -		 * well as the rotator buffer output.
> -		 * ROT_INDEX needs to be < 0x40, but > ctx->num_internal_frames.
> -		 */
> -		coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf->vb2_buf.index,
> -				CODA9_CMD_DEC_PIC_ROT_INDEX);
> -
> -		reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y;
> -		reg_stride = CODA9_CMD_DEC_PIC_ROT_STRIDE;
> +	if (ctx->use_vdoa &&
> +	    ctx->display_idx >= 0 &&
> +	    ctx->display_idx < ctx->num_internal_frames) {
> +		vdoa_device_run(ctx->vdoa,
> +				vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0),
> +				ctx->internal_frames[ctx->display_idx].paddr);
>  	} else {
> -		reg_addr = CODA_CMD_DEC_PIC_ROT_ADDR_Y;
> -		reg_stride = CODA_CMD_DEC_PIC_ROT_STRIDE;
> +		if (dev->devtype->product == CODA_960) {
> +			/*
> +			 * The CODA960 seems to have an internal list of
> +			 * buffers with 64 entries that includes the
> +			 * registered frame buffers as well as the rotator
> +			 * buffer output.
> +			 *
> +			 * ROT_INDEX needs to be < 0x40, but >
> +			 * ctx->num_internal_frames.
> +			 */
> +			coda_write(dev,
> +				   CODA_MAX_FRAMEBUFFERS + dst_buf->vb2_buf.index,
> +				   CODA9_CMD_DEC_PIC_ROT_INDEX);
> +
> +			reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y;
> +			reg_stride = CODA9_CMD_DEC_PIC_ROT_STRIDE;
> +		} else {
> +			reg_addr = CODA_CMD_DEC_PIC_ROT_ADDR_Y;
> +			reg_stride = CODA_CMD_DEC_PIC_ROT_STRIDE;
> +		}
> +		coda_write_base(ctx, q_data_dst, dst_buf, reg_addr);
> +		coda_write(dev, q_data_dst->bytesperline, reg_stride);
> +
> +		rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode;
>  	}
> -	coda_write_base(ctx, q_data_dst, dst_buf, reg_addr);
> -	coda_write(dev, q_data_dst->bytesperline, reg_stride);
>  
> -	coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
> -			CODA_CMD_DEC_PIC_ROT_MODE);
> +	coda_write(dev, rot_mode, CODA_CMD_DEC_PIC_ROT_MODE);
>  
>  	switch (dev->devtype->product) {
>  	case CODA_DX6:
> @@ -1851,6 +1871,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
>  	u32 src_fourcc;
>  	int success;
>  	u32 err_mb;
> +	int err_vdoa = 0;
>  	u32 val;
>  
>  	/* Update kfifo out pointer from coda bitstream read pointer */
> @@ -1934,13 +1955,17 @@ static void coda_finish_decode(struct coda_ctx *ctx)
>  		}
>  	}
>  
> +	/* Wait until the VDOA finished writing the previous display frame */
> +	if (ctx->use_vdoa &&
> +	    ctx->display_idx >= 0 &&
> +	    ctx->display_idx < ctx->num_internal_frames) {
> +		err_vdoa = vdoa_wait_for_completion(ctx->vdoa);
> +	}
> +
>  	ctx->frm_dis_flg = coda_read(dev,
>  				     CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
>  
> -	/*
> -	 * The previous display frame was copied out by the rotator,
> -	 * now it can be overwritten again
> -	 */
> +	/* The previous display frame was copied out and can be overwritten */
>  	if (ctx->display_idx >= 0 &&
>  	    ctx->display_idx < ctx->num_internal_frames) {
>  		ctx->frm_dis_flg &= ~(1 << ctx->display_idx);
> @@ -2057,8 +2082,10 @@ static void coda_finish_decode(struct coda_ctx *ctx)
>  		}
>  		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);
>  
> -		coda_m2m_buf_done(ctx, dst_buf, ctx->frame_errors[ctx->display_idx] ?
> -				  VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
> +		if (ctx->frame_errors[ctx->display_idx] || err_vdoa)
> +			coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_ERROR);
> +		else
> +			coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_DONE);
>  
>  		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
>  			"job finished: decoding frame (%d) (%s)\n",
> diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
> index 3a21000..8b23ea4 100644
> --- a/drivers/media/platform/coda/coda-common.c
> +++ b/drivers/media/platform/coda/coda-common.c
> @@ -450,6 +450,30 @@ static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f)
>  	return 0;
>  }
>  
> +static int coda_try_vdoa(struct coda_ctx *ctx, struct v4l2_format *f)

This should probably be called coda_try_fmt_vdoa and add an additional
bool *use_vdoa return value ...

> +{
> +	int err;
> +
> +	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +		return -EINVAL;
> +
> +	if (!ctx->vdoa) {
> +		ctx->use_vdoa = false;
> +		return 0;
> +	}
> +
> +	err = vdoa_context_configure(ctx->vdoa, f->fmt.pix.width,
> +				     f->fmt.pix.height, f->fmt.pix.pixelformat);
> +	if (err) {
> +		ctx->use_vdoa = false;
> +		return 0;
> +	}
> +
> +	ctx->use_vdoa = true;

... to avoid changing context state when called from TRY_FMT.

> +
> +	return 0;
> +}
> +
>  static unsigned int coda_estimate_sizeimage(struct coda_ctx *ctx, u32 sizeimage,
>  					    u32 width, u32 height)
>  {
> @@ -564,6 +588,10 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
>  		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
>  		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
>  				       f->fmt.pix.height * 3 / 2;
> +
> +		ret = coda_try_vdoa(ctx, f);
> +		if (ret < 0)
> +			return ret;
>  	}
>  
>  	return 0;
> @@ -632,13 +660,20 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f,
>  		q_data->rect.height = f->fmt.pix.height;
>  	}
>  
> +	/*
> +	 * It would be nice to set use_vdoa in coda_s_fmt instead of
> +	 * coda_try_vdoa() to have a single location where this is changed.
> +	 * Unfortunately, if the capture format is V4L2_PIX_FMT_NV12, we
> +	 * cannot be sure if the VDOA should be used, without storing the
> +	 * result of coda_try_vdoa() or calling vdoa_context_configure()
> +	 * again. Therefore, set use_vdoa in coda_try_vdoa.
> +	 */
> +

See above. ctx->use_vdoa should only be set in SET_FMT.

>  	switch (f->fmt.pix.pixelformat) {
>  	case V4L2_PIX_FMT_NV12:
> -		if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
> -			ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
> -			if (!disable_tiling)
> -				break;
> -		}
> +		ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
> +		if (!disable_tiling)
> +			break;
>  		/* else fall through */
>  	case V4L2_PIX_FMT_YUV420:
>  	case V4L2_PIX_FMT_YVU420:
> @@ -1764,6 +1799,13 @@ static int coda_open(struct file *file)
>  	default:
>  		ctx->reg_idx = idx;
>  	}
> +	if (ctx->dev->vdoa) {

	if (ctx->dev->vdoa && !disable_vdoa) {

> +		ctx->vdoa = vdoa_context_create(dev->vdoa);
> +		if (!ctx->vdoa)
> +			v4l2_warn(&dev->v4l2_dev,
> +				  "Failed to create vdoa context: not using vdoa");
> +	}
> +	ctx->use_vdoa = false;
>  
>  	/* Power up and upload firmware if necessary */
>  	ret = pm_runtime_get_sync(&dev->plat_dev->dev);
> @@ -1839,6 +1881,9 @@ static int coda_release(struct file *file)
>  	v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n",
>  		 ctx);
>  
> +	if (ctx->vdoa)
> +		vdoa_context_destroy(ctx->vdoa);
> +
>  	if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit)
>  		coda_bit_stream_end_flag(ctx);
>  
> diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
> index ae202dc..7ed79eb 100644
> --- a/drivers/media/platform/coda/coda.h
> +++ b/drivers/media/platform/coda/coda.h
> @@ -237,6 +237,8 @@ struct coda_ctx {
>  	int				display_idx;
>  	struct dentry			*debugfs_entry;
>  	bool				use_bit;
> +	bool				use_vdoa;
> +	struct vdoa_ctx			*vdoa;
>  };
>  
>  extern int coda_debug;

regards
Philipp


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 9/9] [media] coda: support YUYV output if VDOA is used
  2016-12-08 15:24 ` [PATCH 9/9] [media] coda: support YUYV output if VDOA is used Michael Tretter
@ 2016-12-08 16:00   ` Philipp Zabel
  0 siblings, 0 replies; 13+ messages in thread
From: Philipp Zabel @ 2016-12-08 16:00 UTC (permalink / raw)
  To: Michael Tretter; +Cc: linux-media

Am Donnerstag, den 08.12.2016, 16:24 +0100 schrieb Michael Tretter:
> The VDOA is able to transform the NV12 custom macroblock tiled format of
> the CODA to YUYV format. If and only if the VDOA is available, the
> driver can also provide YUYV support.
> 
> While the driver is configured to produce YUYV output, the CODA must be
> configured to produce NV12 macroblock tiled frames and the VDOA must
> transform the intermediate result into the final YUYV output.
> 
> Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>

Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>

> ---
>  drivers/media/platform/coda/coda-bit.c    |  7 +++++--
>  drivers/media/platform/coda/coda-common.c | 30 ++++++++++++++++++++++++++++++
>  2 files changed, 35 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
> index 3e2f830..b94ba62 100644
> --- a/drivers/media/platform/coda/coda-bit.c
> +++ b/drivers/media/platform/coda/coda-bit.c
> @@ -759,7 +759,7 @@ static void coda9_set_frame_cache(struct coda_ctx *ctx, u32 fourcc)
>  		cache_config = 1 << CODA9_CACHE_PAGEMERGE_OFFSET;
>  	}
>  	coda_write(ctx->dev, cache_size, CODA9_CMD_SET_FRAME_CACHE_SIZE);
> -	if (fourcc == V4L2_PIX_FMT_NV12) {
> +	if (fourcc == V4L2_PIX_FMT_NV12 || fourcc == V4L2_PIX_FMT_YUYV) {
>  		cache_config |= 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
>  				16 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET |
>  				0 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET;
> @@ -1537,7 +1537,7 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
>  
>  	ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) |
>  				 CODA9_FRAME_TILED2LINEAR);
> -	if (dst_fourcc == V4L2_PIX_FMT_NV12)
> +	if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV)
>  		ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
>  	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
>  		ctx->frame_mem_ctrl |= (0x3 << 9) |
> @@ -2070,6 +2070,9 @@ static void coda_finish_decode(struct coda_ctx *ctx)
>  		trace_coda_dec_rot_done(ctx, dst_buf, meta);
>  
>  		switch (q_data_dst->fourcc) {
> +		case V4L2_PIX_FMT_YUYV:
> +			payload = width * height * 2;
> +			break;
>  		case V4L2_PIX_FMT_YUV420:
>  		case V4L2_PIX_FMT_YVU420:
>  		case V4L2_PIX_FMT_NV12:
> diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
> index 8b23ea4..1a809b2 100644
> --- a/drivers/media/platform/coda/coda-common.c
> +++ b/drivers/media/platform/coda/coda-common.c
> @@ -95,6 +95,8 @@ void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
>  	u32 base_cb, base_cr;
>  
>  	switch (q_data->fourcc) {
> +	case V4L2_PIX_FMT_YUYV:
> +		/* Fallthrough: IN -H264-> CODA -NV12 MB-> VDOA -YUYV-> OUT */
>  	case V4L2_PIX_FMT_NV12:
>  	case V4L2_PIX_FMT_YUV420:
>  	default:
> @@ -201,6 +203,11 @@ static const struct coda_video_device coda_bit_decoder = {
>  		V4L2_PIX_FMT_NV12,
>  		V4L2_PIX_FMT_YUV420,
>  		V4L2_PIX_FMT_YVU420,
> +		/*
> +		 * If V4L2_PIX_FMT_YUYV should be default,
> +		 * set_default_params() must be adjusted.
> +		 */
> +		V4L2_PIX_FMT_YUYV,
>  	},
>  };
>  
> @@ -246,6 +253,7 @@ static u32 coda_format_normalize_yuv(u32 fourcc)
>  	case V4L2_PIX_FMT_YUV420:
>  	case V4L2_PIX_FMT_YVU420:
>  	case V4L2_PIX_FMT_YUV422P:
> +	case V4L2_PIX_FMT_YUYV:
>  		return V4L2_PIX_FMT_YUV420;
>  	default:
>  		return fourcc;
> @@ -437,6 +445,11 @@ static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f)
>  		return -EINVAL;
>  
>  	for (i = 0; i < CODA_MAX_FORMATS; i++) {
> +		/* Skip YUYV if the vdoa is not available */
> +		if (!ctx->vdoa && f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
> +		    formats[i] == V4L2_PIX_FMT_YUYV)
> +			continue;
> +
>  		if (formats[i] == f->fmt.pix.pixelformat) {
>  			f->fmt.pix.pixelformat = formats[i];
>  			return 0;
> @@ -520,6 +533,11 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
>  		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
>  					f->fmt.pix.height * 3 / 2;
>  		break;
> +	case V4L2_PIX_FMT_YUYV:
> +		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16) * 2;
> +		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
> +					f->fmt.pix.height;
> +		break;
>  	case V4L2_PIX_FMT_YUV422P:
>  		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
>  		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
> @@ -592,6 +610,15 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
>  		ret = coda_try_vdoa(ctx, f);
>  		if (ret < 0)
>  			return ret;
> +
> +		if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
> +			if (!ctx->use_vdoa)
> +				return -EINVAL;
> +
> +			f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16) * 2;
> +			f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
> +				f->fmt.pix.height;
> +		}
>  	}
>  
>  	return 0;
> @@ -670,6 +697,9 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f,
>  	 */
>  
>  	switch (f->fmt.pix.pixelformat) {
> +	case V4L2_PIX_FMT_YUYV:
> +		ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
> +		break;
>  	case V4L2_PIX_FMT_NV12:
>  		ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
>  		if (!disable_tiling)



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2016-12-08 16:00 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-12-08 15:24 [PATCH 1/9] ARM: dts: imx6qdl: Add VDOA compatible and clocks properties Michael Tretter
2016-12-08 15:24 ` [PATCH 2/9] [media] coda: add i.MX6 VDOA driver Michael Tretter
2016-12-08 15:24 ` [PATCH 3/9] ARM: dts: imx6qdl: Add VDOA phandle to CODA node Michael Tretter
2016-12-08 15:24 ` [PATCH 4/9] [media] coda: correctly set capture compose rectangle Michael Tretter
2016-12-08 15:24 ` [PATCH 5/9] [media] coda: get VDOA device using dt phandle Michael Tretter
2016-12-08 15:50   ` Philipp Zabel
2016-12-08 15:24 ` [PATCH 6/9] [media] coda: add debug output about tiling Michael Tretter
2016-12-08 15:24 ` [PATCH 7/9] [media] coda: fix frame index to returned error Michael Tretter
2016-12-08 15:53   ` Philipp Zabel
2016-12-08 15:24 ` [PATCH 8/9] [media] coda: use VDOA for un-tiling custom macroblock format Michael Tretter
2016-12-08 15:58   ` Philipp Zabel
2016-12-08 15:24 ` [PATCH 9/9] [media] coda: support YUYV output if VDOA is used Michael Tretter
2016-12-08 16:00   ` Philipp Zabel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).