devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 1/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine
@ 2017-03-14 10:38 Philipp Zabel
  2017-03-14 10:38 ` [PATCH v3 6/9] gpu: ipu-v3: hook up PRG unit Philipp Zabel
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Philipp Zabel @ 2017-03-14 10:38 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Lucas Stach, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ, Philipp Zabel

From: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

The Prefetch Resolve Engine is a prefetch and tile resolve engine
which prefetches display data from DRAM to an internal SRAM region.
It has a single clock for configuration register access and the
functional units. A single shared interrupt is used for status and
error signaling.

The only external dependency is the SRAM region to use for the
prefetch double buffer.

Signed-off-by: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Signed-off-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 .../bindings/display/imx/fsl-imx-drm.txt           | 26 ++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
index 971c3eedb1c7b..70ae5335d1e30 100644
--- a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
+++ b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
@@ -53,6 +53,32 @@ ipu: ipu@18000000 {
 	};
 };
 
+Freescale i.MX PRE (Prefetch Resolve Engine)
+============================================
+
+Required properties:
+- compatible: should be "fsl,imx6qp-pre"
+- reg: should be register base and length as documented in the
+  datasheet
+- clocks : phandle to the PRE axi clock input, as described
+  in Documentation/devicetree/bindings/clock/clock-bindings.txt and
+  Documentation/devicetree/bindings/clock/imx6q-clock.txt.
+- clock-names: should be "axi"
+- interrupts: should contain the PRE interrupt
+- fsl,iram: phandle pointing to the mmio-sram device node, that should be
+  used for the PRE SRAM double buffer.
+
+example:
+
+pre@21c8000 {
+	compatible = "fsl,imx6qp-pre";
+	reg = <0x021c8000 0x1000>;
+	interrupts = <GIC_SPI 90 IRQ_TYPE_EDGE_RISING>;
+	clocks = <&clks IMX6QDL_CLK_PRE0>;
+	clock-names = "axi";
+	fsl,iram = <&ocram2>;
+};
+
 Parallel display support
 ========================
 
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 2/9] gpu: ipu-v3: add driver for Prefetch Resolve Engine
       [not found] ` <1489487928-26083-1-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2017-03-14 10:38   ` Philipp Zabel
  2017-03-14 10:38   ` [PATCH v3 3/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket Philipp Zabel
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Philipp Zabel @ 2017-03-14 10:38 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Lucas Stach, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ, Philipp Zabel

From: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

This adds support for the i.MX6 QuadPlus PRE units. Currently only
linear prefetch into SRAM is supported, other modes of operation
like the tiled-to-linear conversion will be added later.

Signed-off-by: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Signed-off-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
v3: Fix modular build (drop duplicate module_platform_driver)
---
 drivers/gpu/ipu-v3/Makefile     |   2 +-
 drivers/gpu/ipu-v3/ipu-common.c |  17 ++-
 drivers/gpu/ipu-v3/ipu-pre.c    | 289 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/ipu-v3/ipu-prv.h    |  14 ++
 4 files changed, 320 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/ipu-v3/ipu-pre.c

diff --git a/drivers/gpu/ipu-v3/Makefile b/drivers/gpu/ipu-v3/Makefile
index 5f961416c4eeb..8ae90de46b4dd 100644
--- a/drivers/gpu/ipu-v3/Makefile
+++ b/drivers/gpu/ipu-v3/Makefile
@@ -2,4 +2,4 @@ obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
 
 imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
 		ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-image-convert.o \
-		ipu-smfc.o ipu-vdi.o
+		ipu-pre.o ipu-smfc.o ipu-vdi.o
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 448043c051e94..7ae1b9739a7ff 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -1528,7 +1528,22 @@ static struct platform_driver imx_ipu_driver = {
 	.remove = ipu_remove,
 };
 
-module_platform_driver(imx_ipu_driver);
+static struct platform_driver * const drivers[] = {
+	&ipu_pre_drv,
+	&imx_ipu_driver,
+};
+
+static int __init imx_ipu_init(void)
+{
+	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
+}
+module_init(imx_ipu_init);
+
+static void __exit imx_ipu_exit(void)
+{
+	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
+}
+module_exit(imx_ipu_exit);
 
 MODULE_ALIAS("platform:imx-ipuv3");
 MODULE_DESCRIPTION("i.MX IPU v3 driver");
diff --git a/drivers/gpu/ipu-v3/ipu-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c
new file mode 100644
index 0000000000000..c55563379e2e3
--- /dev/null
+++ b/drivers/gpu/ipu-v3/ipu-pre.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2017 Lucas Stach, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <drm/drm_fourcc.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/genalloc.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <video/imx-ipu-v3.h>
+
+#include "ipu-prv.h"
+
+#define IPU_PRE_MAX_WIDTH	2048
+#define IPU_PRE_NUM_SCANLINES	8
+
+#define IPU_PRE_CTRL					0x000
+#define IPU_PRE_CTRL_SET				0x004
+#define  IPU_PRE_CTRL_ENABLE				(1 << 0)
+#define  IPU_PRE_CTRL_BLOCK_EN				(1 << 1)
+#define  IPU_PRE_CTRL_BLOCK_16				(1 << 2)
+#define  IPU_PRE_CTRL_SDW_UPDATE			(1 << 4)
+#define  IPU_PRE_CTRL_VFLIP				(1 << 5)
+#define  IPU_PRE_CTRL_SO				(1 << 6)
+#define  IPU_PRE_CTRL_INTERLACED_FIELD			(1 << 7)
+#define  IPU_PRE_CTRL_HANDSHAKE_EN			(1 << 8)
+#define  IPU_PRE_CTRL_HANDSHAKE_LINE_NUM(v)		((v & 0x3) << 9)
+#define  IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN		(1 << 11)
+#define  IPU_PRE_CTRL_EN_REPEAT				(1 << 28)
+#define  IPU_PRE_CTRL_TPR_REST_SEL			(1 << 29)
+#define  IPU_PRE_CTRL_CLKGATE				(1 << 30)
+#define  IPU_PRE_CTRL_SFTRST				(1 << 31)
+
+#define IPU_PRE_CUR_BUF					0x030
+
+#define IPU_PRE_NEXT_BUF				0x040
+
+#define IPU_PRE_TPR_CTRL				0x070
+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT(v)		((v & 0xff) << 0)
+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK		0xff
+
+#define IPU_PRE_PREFETCH_ENG_CTRL			0x080
+#define  IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN		(1 << 0)
+#define  IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(v)		((v & 0x7) << 1)
+#define  IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(v)	((v & 0x3) << 4)
+#define  IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(v)	((v & 0x7) << 8)
+#define  IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS		(1 << 11)
+#define  IPU_PRE_PREF_ENG_CTRL_FIELD_INVERSE		(1 << 12)
+#define  IPU_PRE_PREF_ENG_CTRL_PARTIAL_UV_SWAP		(1 << 14)
+#define  IPU_PRE_PREF_ENG_CTRL_TPR_COOR_OFFSET_EN	(1 << 15)
+
+#define IPU_PRE_PREFETCH_ENG_INPUT_SIZE			0x0a0
+#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(v)	((v & 0xffff) << 0)
+#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(v)	((v & 0xffff) << 16)
+
+#define IPU_PRE_PREFETCH_ENG_PITCH			0x0d0
+#define  IPU_PRE_PREFETCH_ENG_PITCH_Y(v)		((v & 0xffff) << 0)
+#define  IPU_PRE_PREFETCH_ENG_PITCH_UV(v)		((v & 0xffff) << 16)
+
+#define IPU_PRE_STORE_ENG_CTRL				0x110
+#define  IPU_PRE_STORE_ENG_CTRL_STORE_EN		(1 << 0)
+#define  IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(v)		((v & 0x7) << 1)
+#define  IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(v)	((v & 0x3) << 4)
+
+#define IPU_PRE_STORE_ENG_SIZE				0x130
+#define  IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(v)		((v & 0xffff) << 0)
+#define  IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(v)		((v & 0xffff) << 16)
+
+#define IPU_PRE_STORE_ENG_PITCH				0x140
+#define  IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(v)		((v & 0xffff) << 0)
+
+#define IPU_PRE_STORE_ENG_ADDR				0x150
+
+struct ipu_pre {
+	struct list_head	list;
+	struct device		*dev;
+
+	void __iomem		*regs;
+	struct clk		*clk_axi;
+	struct gen_pool		*iram;
+
+	dma_addr_t		buffer_paddr;
+	void			*buffer_virt;
+	bool			in_use;
+};
+
+static DEFINE_MUTEX(ipu_pre_list_mutex);
+static LIST_HEAD(ipu_pre_list);
+static int available_pres;
+
+int ipu_pre_get_available_count(void)
+{
+	return available_pres;
+}
+
+struct ipu_pre *
+ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index)
+{
+	struct device_node *pre_node = of_parse_phandle(dev->of_node,
+							name, index);
+	struct ipu_pre *pre;
+
+	mutex_lock(&ipu_pre_list_mutex);
+	list_for_each_entry(pre, &ipu_pre_list, list) {
+		if (pre_node == pre->dev->of_node) {
+			mutex_unlock(&ipu_pre_list_mutex);
+			device_link_add(dev, pre->dev, DL_FLAG_AUTOREMOVE);
+			return pre;
+		}
+	}
+	mutex_unlock(&ipu_pre_list_mutex);
+
+	return NULL;
+}
+
+int ipu_pre_get(struct ipu_pre *pre)
+{
+	u32 val;
+
+	if (pre->in_use)
+		return -EBUSY;
+
+	clk_prepare_enable(pre->clk_axi);
+
+	/* first get the engine out of reset and remove clock gating */
+	writel(0, pre->regs + IPU_PRE_CTRL);
+
+	/* init defaults that should be applied to all streams */
+	val = IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN |
+	      IPU_PRE_CTRL_HANDSHAKE_EN |
+	      IPU_PRE_CTRL_TPR_REST_SEL |
+	      IPU_PRE_CTRL_BLOCK_16 | IPU_PRE_CTRL_SDW_UPDATE;
+	writel(val, pre->regs + IPU_PRE_CTRL);
+
+	pre->in_use = true;
+	return 0;
+}
+
+void ipu_pre_put(struct ipu_pre *pre)
+{
+	u32 val;
+
+	val = IPU_PRE_CTRL_SFTRST | IPU_PRE_CTRL_CLKGATE;
+	writel(val, pre->regs + IPU_PRE_CTRL);
+
+	clk_disable_unprepare(pre->clk_axi);
+
+	pre->in_use = false;
+}
+
+void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
+		       unsigned int height, unsigned int stride, u32 format,
+		       unsigned int bufaddr)
+{
+	const struct drm_format_info *info = drm_format_info(format);
+	u32 active_bpp = info->cpp[0] >> 1;
+	u32 val;
+
+	writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
+	writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
+
+	val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
+	      IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
+	      IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(4) |
+	      IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS |
+	      IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN;
+	writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_CTRL);
+
+	val = IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(width) |
+	      IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(height);
+	writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_INPUT_SIZE);
+
+	val = IPU_PRE_PREFETCH_ENG_PITCH_Y(stride);
+	writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_PITCH);
+
+	val = IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(active_bpp) |
+	      IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(4) |
+	      IPU_PRE_STORE_ENG_CTRL_STORE_EN;
+	writel(val, pre->regs + IPU_PRE_STORE_ENG_CTRL);
+
+	val = IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(width) |
+	      IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(height);
+	writel(val, pre->regs + IPU_PRE_STORE_ENG_SIZE);
+
+	val = IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(stride);
+	writel(val, pre->regs + IPU_PRE_STORE_ENG_PITCH);
+
+	writel(pre->buffer_paddr, pre->regs + IPU_PRE_STORE_ENG_ADDR);
+
+	val = readl(pre->regs + IPU_PRE_CTRL);
+	val |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE |
+	       IPU_PRE_CTRL_SDW_UPDATE;
+	writel(val, pre->regs + IPU_PRE_CTRL);
+}
+
+void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
+{
+	writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
+	writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET);
+}
+
+u32 ipu_pre_get_baddr(struct ipu_pre *pre)
+{
+	return (u32)pre->buffer_paddr;
+}
+
+static int ipu_pre_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct ipu_pre *pre;
+
+	pre = devm_kzalloc(dev, sizeof(*pre), GFP_KERNEL);
+	if (!pre)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pre->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pre->regs))
+		return PTR_ERR(pre->regs);
+
+	pre->clk_axi = devm_clk_get(dev, "axi");
+	if (IS_ERR(pre->clk_axi))
+		return PTR_ERR(pre->clk_axi);
+
+	pre->iram = of_gen_pool_get(dev->of_node, "fsl,iram", 0);
+	if (!pre->iram)
+		return -EPROBE_DEFER;
+
+	/*
+	 * Allocate IRAM buffer with maximum size. This could be made dynamic,
+	 * but as there is no other user of this IRAM region and we can fit all
+	 * max sized buffers into it, there is no need yet.
+	 */
+	pre->buffer_virt = gen_pool_dma_alloc(pre->iram, IPU_PRE_MAX_WIDTH *
+					      IPU_PRE_NUM_SCANLINES * 4,
+					      &pre->buffer_paddr);
+	if (!pre->buffer_virt)
+		return -ENOMEM;
+
+	pre->dev = dev;
+	platform_set_drvdata(pdev, pre);
+	mutex_lock(&ipu_pre_list_mutex);
+	list_add(&pre->list, &ipu_pre_list);
+	available_pres++;
+	mutex_unlock(&ipu_pre_list_mutex);
+
+	return 0;
+}
+
+static int ipu_pre_remove(struct platform_device *pdev)
+{
+	struct ipu_pre *pre = platform_get_drvdata(pdev);
+
+	mutex_lock(&ipu_pre_list_mutex);
+	list_del(&pre->list);
+	available_pres--;
+	mutex_unlock(&ipu_pre_list_mutex);
+
+	if (pre->buffer_virt)
+		gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,
+			      IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4);
+	return 0;
+}
+
+static const struct of_device_id ipu_pre_dt_ids[] = {
+	{ .compatible = "fsl,imx6qp-pre", },
+	{ /* sentinel */ },
+};
+
+struct platform_driver ipu_pre_drv = {
+	.probe		= ipu_pre_probe,
+	.remove		= ipu_pre_remove,
+	.driver		= {
+		.name	= "imx-ipu-pre",
+		.of_match_table = ipu_pre_dt_ids,
+	},
+};
diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h
index 285595702ee0f..262efdff1dbaa 100644
--- a/drivers/gpu/ipu-v3/ipu-prv.h
+++ b/drivers/gpu/ipu-v3/ipu-prv.h
@@ -173,6 +173,7 @@ struct ipu_ic_priv;
 struct ipu_vdi;
 struct ipu_image_convert_priv;
 struct ipu_smfc_priv;
+struct ipu_pre;
 
 struct ipu_devtype;
 
@@ -264,4 +265,17 @@ void ipu_cpmem_exit(struct ipu_soc *ipu);
 int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
 void ipu_smfc_exit(struct ipu_soc *ipu);
 
+struct ipu_pre *ipu_pre_lookup_by_phandle(struct device *dev, const char *name,
+					  int index);
+int ipu_pre_get_available_count(void);
+int ipu_pre_get(struct ipu_pre *pre);
+void ipu_pre_put(struct ipu_pre *pre);
+u32 ipu_pre_get_baddr(struct ipu_pre *pre);
+void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
+		       unsigned int height,
+		       unsigned int stride, u32 format, unsigned int bufaddr);
+void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
+
+extern struct platform_driver ipu_pre_drv;
+
 #endif				/* __IPU_PRV_H__ */
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 3/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket
       [not found] ` <1489487928-26083-1-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  2017-03-14 10:38   ` [PATCH v3 2/9] gpu: ipu-v3: add driver for Prefetch Resolve Engine Philipp Zabel
@ 2017-03-14 10:38   ` Philipp Zabel
  2017-03-14 10:38   ` [PATCH v3 4/9] gpu: ipu-v3: add driver for " Philipp Zabel
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Philipp Zabel @ 2017-03-14 10:38 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Lucas Stach, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ, Philipp Zabel

From: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

This adds the the devicetree binding for the Prefetch Resolve Gasket,
as found on i.MX6 QuadPlus.
The PRG is fairly simple in that it only has a configuration register
range and two clocks, one for the AHB slave port and one for the AXI
ports and the functional units.

The PRE connections need to be described in the DT, as the PRE<->PRG
assignment is a mix between fixed and muxable connections.

Signed-off-by: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 .../bindings/display/imx/fsl-imx-drm.txt           | 25 ++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
index 70ae5335d1e30..62eb637630b5a 100644
--- a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
+++ b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
@@ -79,6 +79,31 @@ pre@21c8000 {
 	fsl,iram = <&ocram2>;
 };
 
+Freescale i.MX PRG (Prefetch Resolve Gasket)
+============================================
+
+Required properties:
+- compatible: should be "fsl,imx6qp-prg"
+- reg: should be register base and length as documented in the
+  datasheet
+- clocks : phandles to the PRG ipg and axi clock inputs, as described
+  in Documentation/devicetree/bindings/clock/clock-bindings.txt and
+  Documentation/devicetree/bindings/clock/imx6q-clock.txt.
+- clock-names: should be "ipg" and "axi"
+- fsl,pres: phandles to the PRE units attached to this PRG, with the fixed
+  PRE as the first entry and the muxable PREs following.
+
+example:
+
+prg@21cc000 {
+	compatible = "fsl,imx6qp-prg";
+	reg = <0x021cc000 0x1000>;
+	clocks = <&clks IMX6QDL_CLK_PRG0_APB>,
+		 <&clks IMX6QDL_CLK_PRG0_AXI>;
+	clock-names = "ipg", "axi";
+	fsl,pres = <&pre1>, <&pre2>, <&pre3>;
+};
+
 Parallel display support
 ========================
 
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 4/9] gpu: ipu-v3: add driver for Prefetch Resolve Gasket
       [not found] ` <1489487928-26083-1-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  2017-03-14 10:38   ` [PATCH v3 2/9] gpu: ipu-v3: add driver for Prefetch Resolve Engine Philipp Zabel
  2017-03-14 10:38   ` [PATCH v3 3/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket Philipp Zabel
@ 2017-03-14 10:38   ` Philipp Zabel
  2017-03-14 10:38   ` [PATCH v3 5/9] gpu: ipu-v3: document valid IPUv3 compatibles and extend for i.MX6 QuadPlus Philipp Zabel
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Philipp Zabel @ 2017-03-14 10:38 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Lucas Stach, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ, Philipp Zabel

From: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

This adds support for the i.MX6 QUadPlus PRG unit. It glues together the
IPU and the PRE units.

Signed-off-by: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Signed-off-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
v3: Fix modular build (drop duplicate module_platform_driver, export symbols)
---
 drivers/gpu/ipu-v3/Makefile     |   2 +-
 drivers/gpu/ipu-v3/ipu-common.c |   1 +
 drivers/gpu/ipu-v3/ipu-prg.c    | 424 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/ipu-v3/ipu-prv.h    |   5 +
 include/video/imx-ipu-v3.h      |  15 ++
 5 files changed, 446 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/ipu-v3/ipu-prg.c

diff --git a/drivers/gpu/ipu-v3/Makefile b/drivers/gpu/ipu-v3/Makefile
index 8ae90de46b4dd..1ab9bceee755f 100644
--- a/drivers/gpu/ipu-v3/Makefile
+++ b/drivers/gpu/ipu-v3/Makefile
@@ -2,4 +2,4 @@ obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
 
 imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
 		ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-image-convert.o \
-		ipu-pre.o ipu-smfc.o ipu-vdi.o
+		ipu-pre.o ipu-prg.o ipu-smfc.o ipu-vdi.o
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 7ae1b9739a7ff..4c84539897467 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -1530,6 +1530,7 @@ static struct platform_driver imx_ipu_driver = {
 
 static struct platform_driver * const drivers[] = {
 	&ipu_pre_drv,
+	&ipu_prg_drv,
 	&imx_ipu_driver,
 };
 
diff --git a/drivers/gpu/ipu-v3/ipu-prg.c b/drivers/gpu/ipu-v3/ipu-prg.c
new file mode 100644
index 0000000000000..caca57febbd6d
--- /dev/null
+++ b/drivers/gpu/ipu-v3/ipu-prg.c
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <drm/drm_fourcc.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <video/imx-ipu-v3.h>
+
+#include "ipu-prv.h"
+
+#define IPU_PRG_CTL				0x00
+#define  IPU_PRG_CTL_BYPASS(i)			(1 << (0 + i))
+#define  IPU_PRG_CTL_SOFT_ARID_MASK		0x3
+#define  IPU_PRG_CTL_SOFT_ARID_SHIFT(i)		(8 + i * 2)
+#define  IPU_PRG_CTL_SOFT_ARID(i, v)		((v & 0x3) << (8 + 2 * i))
+#define  IPU_PRG_CTL_SO(i)			(1 << (16 + i))
+#define  IPU_PRG_CTL_VFLIP(i)			(1 << (19 + i))
+#define  IPU_PRG_CTL_BLOCK_MODE(i)		(1 << (22 + i))
+#define  IPU_PRG_CTL_CNT_LOAD_EN(i)		(1 << (25 + i))
+#define  IPU_PRG_CTL_SOFTRST			(1 << 30)
+#define  IPU_PRG_CTL_SHADOW_EN			(1 << 31)
+
+#define IPU_PRG_STATUS				0x04
+#define  IPU_PRG_STATUS_BUFFER0_READY(i)	(1 << (0 + i * 2))
+#define  IPU_PRG_STATUS_BUFFER1_READY(i)	(1 << (1 + i * 2))
+
+#define IPU_PRG_QOS				0x08
+#define  IPU_PRG_QOS_ARID_MASK			0xf
+#define  IPU_PRG_QOS_ARID_SHIFT(i)		(0 + i * 4)
+
+#define IPU_PRG_REG_UPDATE			0x0c
+#define  IPU_PRG_REG_UPDATE_REG_UPDATE		(1 << 0)
+
+#define IPU_PRG_STRIDE(i)			(0x10 + i * 0x4)
+#define  IPU_PRG_STRIDE_STRIDE_MASK		0x3fff
+
+#define IPU_PRG_CROP_LINE			0x1c
+
+#define IPU_PRG_THD				0x20
+
+#define IPU_PRG_BADDR(i)			(0x24 + i * 0x4)
+
+#define IPU_PRG_OFFSET(i)			(0x30 + i * 0x4)
+
+#define IPU_PRG_ILO(i)				(0x3c + i * 0x4)
+
+#define IPU_PRG_HEIGHT(i)			(0x48 + i * 0x4)
+#define  IPU_PRG_HEIGHT_PRE_HEIGHT_MASK		0xfff
+#define  IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT	0
+#define  IPU_PRG_HEIGHT_IPU_HEIGHT_MASK		0xfff
+#define  IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT	16
+
+struct ipu_prg_channel {
+	bool			enabled;
+	int			used_pre;
+};
+
+struct ipu_prg {
+	struct list_head	list;
+	struct device		*dev;
+	int			id;
+
+	void __iomem		*regs;
+	struct clk		*clk_ipg, *clk_axi;
+	struct regmap		*iomuxc_gpr;
+	struct ipu_pre		*pres[3];
+
+	struct ipu_prg_channel	chan[3];
+};
+
+static DEFINE_MUTEX(ipu_prg_list_mutex);
+static LIST_HEAD(ipu_prg_list);
+
+struct ipu_prg *
+ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id)
+{
+	struct device_node *prg_node = of_parse_phandle(dev->of_node,
+							name, 0);
+	struct ipu_prg *prg;
+
+	mutex_lock(&ipu_prg_list_mutex);
+	list_for_each_entry(prg, &ipu_prg_list, list) {
+		if (prg_node == prg->dev->of_node) {
+			mutex_unlock(&ipu_prg_list_mutex);
+			device_link_add(dev, prg->dev, DL_FLAG_AUTOREMOVE);
+			prg->id = ipu_id;
+			return prg;
+		}
+	}
+	mutex_unlock(&ipu_prg_list_mutex);
+
+	return NULL;
+}
+
+int ipu_prg_max_active_channels(void)
+{
+	return ipu_pre_get_available_count();
+}
+EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels);
+
+bool ipu_prg_present(struct ipu_soc *ipu)
+{
+	if (ipu->prg_priv)
+		return true;
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(ipu_prg_present);
+
+bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
+			      uint64_t modifier)
+{
+	const struct drm_format_info *info = drm_format_info(format);
+
+	if (info->num_planes != 1)
+		return false;
+
+	return true;
+}
+EXPORT_SYMBOL_GPL(ipu_prg_format_supported);
+
+int ipu_prg_enable(struct ipu_soc *ipu)
+{
+	struct ipu_prg *prg = ipu->prg_priv;
+	int ret;
+
+	if (!prg)
+		return 0;
+
+	ret = clk_prepare_enable(prg->clk_axi);
+	if (ret)
+		goto fail_disable_ipg;
+
+	return 0;
+
+fail_disable_ipg:
+	clk_disable_unprepare(prg->clk_ipg);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ipu_prg_enable);
+
+void ipu_prg_disable(struct ipu_soc *ipu)
+{
+	struct ipu_prg *prg = ipu->prg_priv;
+
+	if (!prg)
+		return;
+
+	clk_disable_unprepare(prg->clk_axi);
+}
+EXPORT_SYMBOL_GPL(ipu_prg_disable);
+
+/*
+ * The channel configuartion functions below are not thread safe, as they
+ * must be only called from the atomic commit path in the DRM driver, which
+ * is properly serialized.
+ */
+static int ipu_prg_ipu_to_prg_chan(int ipu_chan)
+{
+	/*
+	 * This isn't clearly documented in the RM, but IPU to PRG channel
+	 * assignment is fixed, as only with this mapping the control signals
+	 * match up.
+	 */
+	switch (ipu_chan) {
+	case IPUV3_CHANNEL_MEM_BG_SYNC:
+		return 0;
+	case IPUV3_CHANNEL_MEM_FG_SYNC:
+		return 1;
+	case IPUV3_CHANNEL_MEM_DC_SYNC:
+		return 2;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan)
+{
+	int i, ret;
+
+	/* channel 0 is special as it is hardwired to one of the PREs */
+	if (prg_chan == 0) {
+		ret = ipu_pre_get(prg->pres[0]);
+		if (ret)
+			goto fail;
+		prg->chan[prg_chan].used_pre = 0;
+		return 0;
+	}
+
+	for (i = 1; i < 3; i++) {
+		ret = ipu_pre_get(prg->pres[i]);
+		if (!ret) {
+			u32 val, mux;
+			int shift;
+
+			prg->chan[prg_chan].used_pre = i;
+
+			/* configure the PRE to PRG channel mux */
+			shift = (i == 1) ? 12 : 14;
+			mux = (prg->id << 1) | (prg_chan - 1);
+			regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
+					   0x3 << shift, mux << shift);
+
+			/* check other mux, must not point to same channel */
+			shift = (i == 1) ? 14 : 12;
+			regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val);
+			if (((val >> shift) & 0x3) == mux) {
+				regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
+						   0x3 << shift,
+						   (mux ^ 0x1) << shift);
+			}
+
+			return 0;
+		}
+	}
+
+fail:
+	dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan);
+	return ret;
+}
+
+static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan)
+{
+	struct ipu_prg_channel *chan = &prg->chan[prg_chan];
+
+	ipu_pre_put(prg->pres[chan->used_pre]);
+	chan->used_pre = -1;
+}
+
+void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan)
+{
+	int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
+	struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
+	struct ipu_prg_channel *chan = &prg->chan[prg_chan];
+	u32 val;
+
+	if (!chan->enabled || prg_chan < 0)
+		return;
+
+	clk_prepare_enable(prg->clk_ipg);
+
+	val = readl(prg->regs + IPU_PRG_CTL);
+	val |= IPU_PRG_CTL_BYPASS(prg_chan);
+	writel(val, prg->regs + IPU_PRG_CTL);
+
+	val = IPU_PRG_REG_UPDATE_REG_UPDATE;
+	writel(val, prg->regs + IPU_PRG_REG_UPDATE);
+
+	clk_disable_unprepare(prg->clk_ipg);
+
+	ipu_prg_put_pre(prg, prg_chan);
+
+	chan->enabled = false;
+}
+EXPORT_SYMBOL_GPL(ipu_prg_channel_disable);
+
+int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
+			      unsigned int axi_id, unsigned int width,
+			      unsigned int height, unsigned int stride,
+			      u32 format, unsigned long *eba)
+{
+	int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
+	struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
+	struct ipu_prg_channel *chan = &prg->chan[prg_chan];
+	u32 val;
+	int ret;
+
+	if (prg_chan < 0)
+		return prg_chan;
+
+	if (chan->enabled) {
+		ipu_pre_update(prg->pres[chan->used_pre], *eba);
+		return 0;
+	}
+
+	ret = ipu_prg_get_pre(prg, prg_chan);
+	if (ret)
+		return ret;
+
+	ipu_pre_configure(prg->pres[chan->used_pre],
+			  width, height, stride, format, *eba);
+
+
+	ret = clk_prepare_enable(prg->clk_ipg);
+	if (ret) {
+		ipu_prg_put_pre(prg, prg_chan);
+		return ret;
+	}
+
+	val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK;
+	writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan));
+
+	val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) <<
+	       IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) |
+	      ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) <<
+	       IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT);
+	writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan));
+
+	val = ipu_pre_get_baddr(prg->pres[chan->used_pre]);
+	*eba = val;
+	writel(val, prg->regs + IPU_PRG_BADDR(prg_chan));
+
+	val = readl(prg->regs + IPU_PRG_CTL);
+	/* counter load enable */
+	val |= IPU_PRG_CTL_CNT_LOAD_EN(prg_chan);
+	/* config AXI ID */
+	val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK <<
+		 IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan));
+	val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id);
+	/* enable channel */
+	val &= ~IPU_PRG_CTL_BYPASS(prg_chan);
+	writel(val, prg->regs + IPU_PRG_CTL);
+
+	val = IPU_PRG_REG_UPDATE_REG_UPDATE;
+	writel(val, prg->regs + IPU_PRG_REG_UPDATE);
+
+	clk_disable_unprepare(prg->clk_ipg);
+
+	chan->enabled = true;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_prg_channel_configure);
+
+static int ipu_prg_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct ipu_prg *prg;
+	u32 val;
+	int i, ret;
+
+	prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL);
+	if (!prg)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	prg->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(prg->regs))
+		return PTR_ERR(prg->regs);
+
+
+	prg->clk_ipg = devm_clk_get(dev, "ipg");
+	if (IS_ERR(prg->clk_ipg))
+		return PTR_ERR(prg->clk_ipg);
+
+	prg->clk_axi = devm_clk_get(dev, "axi");
+	if (IS_ERR(prg->clk_axi))
+		return PTR_ERR(prg->clk_axi);
+
+	prg->iomuxc_gpr =
+		syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+	if (IS_ERR(prg->iomuxc_gpr))
+		return PTR_ERR(prg->iomuxc_gpr);
+
+	for (i = 0; i < 3; i++) {
+		prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i);
+		if (!prg->pres[i])
+			return -EPROBE_DEFER;
+	}
+
+	ret = clk_prepare_enable(prg->clk_ipg);
+	if (ret)
+		return ret;
+
+	/* init to free running mode */
+	val = readl(prg->regs + IPU_PRG_CTL);
+	val |= IPU_PRG_CTL_SHADOW_EN;
+	writel(val, prg->regs + IPU_PRG_CTL);
+
+	/* disable address threshold */
+	writel(0xffffffff, prg->regs + IPU_PRG_THD);
+
+	clk_disable_unprepare(prg->clk_ipg);
+
+	prg->dev = dev;
+	platform_set_drvdata(pdev, prg);
+	mutex_lock(&ipu_prg_list_mutex);
+	list_add(&prg->list, &ipu_prg_list);
+	mutex_unlock(&ipu_prg_list_mutex);
+
+	return 0;
+}
+
+static int ipu_prg_remove(struct platform_device *pdev)
+{
+	struct ipu_prg *prg = platform_get_drvdata(pdev);
+
+	mutex_lock(&ipu_prg_list_mutex);
+	list_del(&prg->list);
+	mutex_unlock(&ipu_prg_list_mutex);
+
+	return 0;
+}
+
+static const struct of_device_id ipu_prg_dt_ids[] = {
+	{ .compatible = "fsl,imx6qp-prg", },
+	{ /* sentinel */ },
+};
+
+struct platform_driver ipu_prg_drv = {
+	.probe		= ipu_prg_probe,
+	.remove		= ipu_prg_remove,
+	.driver		= {
+		.name	= "imx-ipu-prg",
+		.of_match_table = ipu_prg_dt_ids,
+	},
+};
diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h
index 262efdff1dbaa..7e9c47efcb1e0 100644
--- a/drivers/gpu/ipu-v3/ipu-prv.h
+++ b/drivers/gpu/ipu-v3/ipu-prv.h
@@ -174,6 +174,7 @@ struct ipu_vdi;
 struct ipu_image_convert_priv;
 struct ipu_smfc_priv;
 struct ipu_pre;
+struct ipu_prg;
 
 struct ipu_devtype;
 
@@ -276,6 +277,10 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
 		       unsigned int stride, u32 format, unsigned int bufaddr);
 void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
 
+struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,
+					  int ipu_id);
+
 extern struct platform_driver ipu_pre_drv;
+extern struct platform_driver ipu_prg_drv;
 
 #endif				/* __IPU_PRV_H__ */
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 6af74f0cf161f..8cb07680fb416 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -331,6 +331,21 @@ int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha,
 		bool bg_chan);
 
 /*
+ * IPU Prefetch Resolve Gasket (prg) functions
+ */
+int ipu_prg_max_active_channels(void);
+bool ipu_prg_present(struct ipu_soc *ipu);
+bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
+			      uint64_t modifier);
+int ipu_prg_enable(struct ipu_soc *ipu);
+void ipu_prg_disable(struct ipu_soc *ipu);
+void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan);
+int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
+			      unsigned int axi_id,  unsigned int width,
+			      unsigned int height, unsigned int stride,
+			      u32 format, unsigned long *eba);
+
+/*
  * IPU CMOS Sensor Interface (csi) functions
  */
 struct ipu_csi;
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 5/9] gpu: ipu-v3: document valid IPUv3 compatibles and extend for i.MX6 QuadPlus
       [not found] ` <1489487928-26083-1-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
                     ` (2 preceding siblings ...)
  2017-03-14 10:38   ` [PATCH v3 4/9] gpu: ipu-v3: add driver for " Philipp Zabel
@ 2017-03-14 10:38   ` Philipp Zabel
  2017-03-20 22:12     ` Rob Herring
  2017-03-14 10:38   ` [PATCH v3 7/9] gpu: ipu-v3: only set non-zero AXI ID for IC when PRG is absent Philipp Zabel
  2017-03-14 10:38   ` [PATCH v3 8/9] drm/imx: enable/disable PRG on CRTC enable/disable Philipp Zabel
  5 siblings, 1 reply; 10+ messages in thread
From: Philipp Zabel @ 2017-03-14 10:38 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Lucas Stach, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ, Philipp Zabel

From: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Document the valid compatible strings for the IPUv3.

On i.MX6 QuadPlus the IPU needs to know which PRG has to be
used for this IPU instance. Add a "fsl,prg" property containing
a phandle pointing to the correct PRG device.

Signed-off-by: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Signed-off-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
index 62eb637630b5a..fa01db7eb66c5 100644
--- a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
+++ b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
@@ -21,13 +21,19 @@ Freescale i.MX IPUv3
 ====================
 
 Required properties:
-- compatible: Should be "fsl,<chip>-ipu"
+- compatible: Should be "fsl,<chip>-ipu" where <chip> is one of
+  - imx51
+  - imx53
+  - imx6q
+  - imx6qp
 - reg: should be register base and length as documented in the
   datasheet
 - interrupts: Should contain sync interrupt and error interrupt,
   in this order.
 - resets: phandle pointing to the system reset controller and
           reset line index, see reset/fsl,imx-src.txt for details
+Additional required properties for fsl,imx6qp-ipu:
+- fsl,prg: phandle to prg node associated with this IPU instance
 Optional properties:
 - port@[0-3]: Port nodes with endpoint definitions as defined in
   Documentation/devicetree/bindings/media/video-interfaces.txt.
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 6/9] gpu: ipu-v3: hook up PRG unit
  2017-03-14 10:38 [PATCH v3 1/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine Philipp Zabel
@ 2017-03-14 10:38 ` Philipp Zabel
       [not found] ` <1489487928-26083-1-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  2017-03-14 10:38 ` [PATCH v3 9/9] drm/imx: use PRG/PRE when possible Philipp Zabel
  2 siblings, 0 replies; 10+ messages in thread
From: Philipp Zabel @ 2017-03-14 10:38 UTC (permalink / raw)
  To: dri-devel; +Cc: Mark Rutland, devicetree, patchwork-lst, Rob Herring, kernel

From: Lucas Stach <l.stach@pengutronix.de>

The i.MX6 QuadPlus IPU needs to PRG unit to gain access to the
data bus. Make sure it is present and available to be used.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/gpu/ipu-v3/ipu-common.c | 11 ++++++++++-
 drivers/gpu/ipu-v3/ipu-prv.h    |  1 +
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 4c84539897467..7aefccec31b1e 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -939,6 +939,7 @@ static const struct of_device_id imx_ipu_dt_ids[] = {
 	{ .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, },
 	{ .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, },
 	{ .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, },
+	{ .compatible = "fsl,imx6qp-ipu", .data = &ipu_type_imx6q, },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids);
@@ -1398,11 +1399,19 @@ static int ipu_probe(struct platform_device *pdev)
 	if (!ipu)
 		return -ENODEV;
 
+	ipu->id = of_alias_get_id(np, "ipu");
+
+	if (of_device_is_compatible(np, "fsl,imx6qp-ipu")) {
+		ipu->prg_priv = ipu_prg_lookup_by_phandle(&pdev->dev,
+							  "fsl,prg", ipu->id);
+		if (!ipu->prg_priv)
+			return -EPROBE_DEFER;
+	}
+
 	for (i = 0; i < 64; i++)
 		ipu->channel[i].ipu = ipu;
 	ipu->devtype = devtype;
 	ipu->ipu_type = devtype->type;
-	ipu->id = of_alias_get_id(np, "ipu");
 
 	spin_lock_init(&ipu->lock);
 	mutex_init(&ipu->channel_lock);
diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h
index 7e9c47efcb1e0..ca2a223a0d1e0 100644
--- a/drivers/gpu/ipu-v3/ipu-prv.h
+++ b/drivers/gpu/ipu-v3/ipu-prv.h
@@ -209,6 +209,7 @@ struct ipu_soc {
 	struct ipu_vdi          *vdi_priv;
 	struct ipu_image_convert_priv *image_convert_priv;
 	struct ipu_smfc_priv	*smfc_priv;
+	struct ipu_prg		*prg_priv;
 };
 
 static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v3 7/9] gpu: ipu-v3: only set non-zero AXI ID for IC when PRG is absent
       [not found] ` <1489487928-26083-1-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
                     ` (3 preceding siblings ...)
  2017-03-14 10:38   ` [PATCH v3 5/9] gpu: ipu-v3: document valid IPUv3 compatibles and extend for i.MX6 QuadPlus Philipp Zabel
@ 2017-03-14 10:38   ` Philipp Zabel
  2017-03-14 10:38   ` [PATCH v3 8/9] drm/imx: enable/disable PRG on CRTC enable/disable Philipp Zabel
  5 siblings, 0 replies; 10+ messages in thread
From: Philipp Zabel @ 2017-03-14 10:38 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Lucas Stach, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ, Philipp Zabel

From: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Using non-zero AXI IDs for anything other than the display channels
collides with the PRG AXI snooping, so only do this if there is no
PRG present.

Signed-off-by: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Signed-off-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 drivers/gpu/ipu-v3/ipu-image-convert.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/ipu-v3/ipu-image-convert.c b/drivers/gpu/ipu-v3/ipu-image-convert.c
index 805b6fa7b5f4c..524a717ab28e4 100644
--- a/drivers/gpu/ipu-v3/ipu-image-convert.c
+++ b/drivers/gpu/ipu-v3/ipu-image-convert.c
@@ -671,7 +671,12 @@ static void init_idmac_channel(struct ipu_image_convert_ctx *ctx,
 	ipu_ic_task_idma_init(chan->ic, channel, width, height,
 			      burst_size, rot_mode);
 
-	ipu_cpmem_set_axi_id(channel, 1);
+	/*
+	 * Setting a non-zero AXI ID collides with the PRG AXI snooping, so
+	 * only do this when there is no PRG present.
+	 */
+	if (!channel->ipu->prg_priv)
+		ipu_cpmem_set_axi_id(channel, 1);
 
 	ipu_idmac_set_double_buffer(channel, ctx->double_buffering);
 }
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 8/9] drm/imx: enable/disable PRG on CRTC enable/disable
       [not found] ` <1489487928-26083-1-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
                     ` (4 preceding siblings ...)
  2017-03-14 10:38   ` [PATCH v3 7/9] gpu: ipu-v3: only set non-zero AXI ID for IC when PRG is absent Philipp Zabel
@ 2017-03-14 10:38   ` Philipp Zabel
  5 siblings, 0 replies; 10+ messages in thread
From: Philipp Zabel @ 2017-03-14 10:38 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Lucas Stach, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ, Philipp Zabel

From: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

On i.MX6 QuadPlus the PRG needs to be clocked in order to pass
through the data access requests from the IDMAC. This call is a
no-op for other all other SoCs.

Signed-off-by: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Signed-off-by: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 drivers/gpu/drm/imx/ipuv3-crtc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
index 82772b8d63216..dab9d50ffd8c1 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -55,6 +55,7 @@ static void ipu_crtc_enable(struct drm_crtc *crtc)
 	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
 	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
 
+	ipu_prg_enable(ipu);
 	ipu_dc_enable(ipu);
 	ipu_dc_enable_channel(ipu_crtc->dc);
 	ipu_di_enable(ipu_crtc->di);
@@ -95,6 +96,7 @@ static void ipu_crtc_atomic_disable(struct drm_crtc *crtc,
 	 */
 	ipu_crtc_disable_planes(ipu_crtc, old_crtc_state);
 	ipu_dc_disable(ipu);
+	ipu_prg_disable(ipu);
 
 	spin_lock_irq(&crtc->dev->event_lock);
 	if (crtc->state->event) {
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 9/9] drm/imx: use PRG/PRE when possible
  2017-03-14 10:38 [PATCH v3 1/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine Philipp Zabel
  2017-03-14 10:38 ` [PATCH v3 6/9] gpu: ipu-v3: hook up PRG unit Philipp Zabel
       [not found] ` <1489487928-26083-1-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2017-03-14 10:38 ` Philipp Zabel
  2 siblings, 0 replies; 10+ messages in thread
From: Philipp Zabel @ 2017-03-14 10:38 UTC (permalink / raw)
  To: dri-devel; +Cc: Mark Rutland, devicetree, patchwork-lst, Rob Herring, kernel

From: Lucas Stach <l.stach@pengutronix.de>

Allow the planes to use the PRG/PRE units as linear prefetchers when
possible. This improves DRAM efficiency a bit and reduces the chance
for display underflow when the memory subsystem is under load.

This does not yet support scanning out tiled buffers directly, as this
needs more work, but it already wires up the basic interaction between
imx-drm, the IPUv3 driver and the PRG and PRE drivers.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
v3: Fix modular build (export ipu_planes_assign_pre symbol)
---
 drivers/gpu/drm/imx/imx-drm-core.c |   5 ++
 drivers/gpu/drm/imx/imx-drm.h      |   3 +
 drivers/gpu/drm/imx/ipuv3-plane.c  | 124 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 129 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index a8f09d38bddb4..9e7310e09d020 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -110,6 +110,11 @@ static int imx_drm_atomic_check(struct drm_device *dev,
 	if (ret)
 		return ret;
 
+	/* Assign PRG/PRE channels and check if all constrains are satisfied. */
+	ret = ipu_planes_assign_pre(dev, state);
+	if (ret)
+		return ret;
+
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h
index cc003334505dc..295434b199db9 100644
--- a/drivers/gpu/drm/imx/imx-drm.h
+++ b/drivers/gpu/drm/imx/imx-drm.h
@@ -39,4 +39,7 @@ int imx_drm_encoder_parse_of(struct drm_device *drm,
 void imx_drm_connector_destroy(struct drm_connector *connector);
 void imx_drm_encoder_destroy(struct drm_encoder *encoder);
 
+int ipu_planes_assign_pre(struct drm_device *dev,
+			  struct drm_atomic_state *state);
+
 #endif /* _IMX_DRM_H_ */
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index cecb8eba5c320..d63e853a03006 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -23,6 +23,17 @@
 #include "video/imx-ipu-v3.h"
 #include "ipuv3-plane.h"
 
+struct ipu_plane_state {
+	struct drm_plane_state base;
+	bool use_pre;
+};
+
+static inline struct ipu_plane_state *
+to_ipu_plane_state(struct drm_plane_state *p)
+{
+	return container_of(p, struct ipu_plane_state, base);
+}
+
 static inline struct ipu_plane *to_ipu_plane(struct drm_plane *p)
 {
 	return container_of(p, struct ipu_plane, base);
@@ -223,6 +234,8 @@ void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel)
 	ipu_dmfc_disable_channel(ipu_plane->dmfc);
 	if (ipu_plane->dp)
 		ipu_dp_disable(ipu_plane->ipu);
+	if (ipu_prg_present(ipu_plane->ipu))
+		ipu_prg_channel_disable(ipu_plane->ipu_ch);
 }
 
 void ipu_plane_disable_deferred(struct drm_plane *plane)
@@ -246,13 +259,56 @@ static void ipu_plane_destroy(struct drm_plane *plane)
 	kfree(ipu_plane);
 }
 
+void ipu_plane_state_reset(struct drm_plane *plane)
+{
+	struct ipu_plane_state *ipu_state;
+
+	if (plane->state) {
+		ipu_state = to_ipu_plane_state(plane->state);
+		__drm_atomic_helper_plane_destroy_state(plane->state);
+		kfree(ipu_state);
+	}
+
+	ipu_state = kzalloc(sizeof(*ipu_state), GFP_KERNEL);
+
+	if (ipu_state) {
+		ipu_state->base.plane = plane;
+		ipu_state->base.rotation = DRM_ROTATE_0;
+	}
+
+	plane->state = &ipu_state->base;
+}
+
+struct drm_plane_state *ipu_plane_duplicate_state(struct drm_plane *plane)
+{
+	struct ipu_plane_state *state;
+
+	if (WARN_ON(!plane->state))
+		return NULL;
+
+	state = kmalloc(sizeof(*state), GFP_KERNEL);
+	if (state)
+		__drm_atomic_helper_plane_duplicate_state(plane, &state->base);
+
+	return &state->base;
+}
+
+void ipu_plane_destroy_state(struct drm_plane *plane,
+			     struct drm_plane_state *state)
+{
+	struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
+
+	__drm_atomic_helper_plane_destroy_state(state);
+	kfree(ipu_state);
+}
+
 static const struct drm_plane_funcs ipu_plane_funcs = {
 	.update_plane	= drm_atomic_helper_update_plane,
 	.disable_plane	= drm_atomic_helper_disable_plane,
 	.destroy	= ipu_plane_destroy,
-	.reset		= drm_atomic_helper_plane_reset,
-	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
-	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+	.reset		= ipu_plane_state_reset,
+	.atomic_duplicate_state	= ipu_plane_duplicate_state,
+	.atomic_destroy_state	= ipu_plane_destroy_state,
 };
 
 static int ipu_plane_atomic_check(struct drm_plane *plane,
@@ -426,17 +482,33 @@ static void ipu_plane_atomic_disable(struct drm_plane *plane,
 	ipu_plane->disabling = true;
 }
 
+static int ipu_chan_assign_axi_id(int ipu_chan)
+{
+	switch (ipu_chan) {
+	case IPUV3_CHANNEL_MEM_BG_SYNC:
+		return 1;
+	case IPUV3_CHANNEL_MEM_FG_SYNC:
+		return 2;
+	case IPUV3_CHANNEL_MEM_DC_SYNC:
+		return 3;
+	default:
+		return 0;
+	}
+}
+
 static void ipu_plane_atomic_update(struct drm_plane *plane,
 				    struct drm_plane_state *old_state)
 {
 	struct ipu_plane *ipu_plane = to_ipu_plane(plane);
 	struct drm_plane_state *state = plane->state;
+	struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
 	struct drm_crtc_state *crtc_state = state->crtc->state;
 	struct drm_framebuffer *fb = state->fb;
 	struct drm_rect *dst = &state->dst;
 	unsigned long eba, ubo, vbo;
 	unsigned long alpha_eba = 0;
 	enum ipu_color_space ics;
+	unsigned int axi_id = 0;
 	int active;
 
 	if (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_FG)
@@ -444,7 +516,23 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
 
 	eba = drm_plane_state_to_eba(state, 0);
 
+	/*
+	 * Configure PRG channel and attached PRE, this changes the EBA to an
+	 * internal SRAM location.
+	 */
+	if (ipu_state->use_pre) {
+		axi_id = ipu_chan_assign_axi_id(ipu_plane->dma);
+		ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id,
+					  drm_rect_width(&state->src) >> 16,
+					  drm_rect_height(&state->src) >> 16,
+					  state->fb->pitches[0],
+					  state->fb->format->format, &eba);
+	}
+
 	if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
+		/* nothing to do if PRE is used */
+		if (ipu_state->use_pre)
+			return;
 		active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
 		ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
 		ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
@@ -503,6 +591,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
 	ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
 	ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
 	ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]);
+	ipu_cpmem_set_axi_id(ipu_plane->ipu_ch, axi_id);
 	switch (fb->format->format) {
 	case DRM_FORMAT_YUV420:
 	case DRM_FORMAT_YVU420:
@@ -578,6 +667,35 @@ static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
 	.atomic_update = ipu_plane_atomic_update,
 };
 
+int ipu_planes_assign_pre(struct drm_device *dev,
+			  struct drm_atomic_state *state)
+{
+	struct drm_plane_state *plane_state;
+	struct drm_plane *plane;
+	int available_pres = ipu_prg_max_active_channels();
+	int i;
+
+	for_each_plane_in_state(state, plane, plane_state, i) {
+		struct ipu_plane_state *ipu_state =
+				to_ipu_plane_state(plane_state);
+		struct ipu_plane *ipu_plane = to_ipu_plane(plane);
+
+		if (ipu_prg_present(ipu_plane->ipu) && available_pres &&
+		    plane_state->fb &&
+		    ipu_prg_format_supported(ipu_plane->ipu,
+					     plane_state->fb->format->format,
+					     plane_state->fb->modifier)) {
+			ipu_state->use_pre = true;
+			available_pres--;
+		} else {
+			ipu_state->use_pre = false;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_planes_assign_pre);
+
 struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
 				 int dma, int dp, unsigned int possible_crtcs,
 				 enum drm_plane_type type)
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 5/9] gpu: ipu-v3: document valid IPUv3 compatibles and extend for i.MX6 QuadPlus
  2017-03-14 10:38   ` [PATCH v3 5/9] gpu: ipu-v3: document valid IPUv3 compatibles and extend for i.MX6 QuadPlus Philipp Zabel
@ 2017-03-20 22:12     ` Rob Herring
  0 siblings, 0 replies; 10+ messages in thread
From: Rob Herring @ 2017-03-20 22:12 UTC (permalink / raw)
  To: Philipp Zabel; +Cc: Mark Rutland, devicetree, dri-devel, patchwork-lst, kernel

On Tue, Mar 14, 2017 at 11:38:44AM +0100, Philipp Zabel wrote:
> From: Lucas Stach <l.stach@pengutronix.de>
> 
> Document the valid compatible strings for the IPUv3.
> 
> On i.MX6 QuadPlus the IPU needs to know which PRG has to be
> used for this IPU instance. Add a "fsl,prg" property containing
> a phandle pointing to the correct PRG device.
> 
> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> ---
>  Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)

Acked-by: Rob Herring <robh@kernel.org>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2017-03-20 22:12 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-03-14 10:38 [PATCH v3 1/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine Philipp Zabel
2017-03-14 10:38 ` [PATCH v3 6/9] gpu: ipu-v3: hook up PRG unit Philipp Zabel
     [not found] ` <1489487928-26083-1-git-send-email-p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2017-03-14 10:38   ` [PATCH v3 2/9] gpu: ipu-v3: add driver for Prefetch Resolve Engine Philipp Zabel
2017-03-14 10:38   ` [PATCH v3 3/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket Philipp Zabel
2017-03-14 10:38   ` [PATCH v3 4/9] gpu: ipu-v3: add driver for " Philipp Zabel
2017-03-14 10:38   ` [PATCH v3 5/9] gpu: ipu-v3: document valid IPUv3 compatibles and extend for i.MX6 QuadPlus Philipp Zabel
2017-03-20 22:12     ` Rob Herring
2017-03-14 10:38   ` [PATCH v3 7/9] gpu: ipu-v3: only set non-zero AXI ID for IC when PRG is absent Philipp Zabel
2017-03-14 10:38   ` [PATCH v3 8/9] drm/imx: enable/disable PRG on CRTC enable/disable Philipp Zabel
2017-03-14 10:38 ` [PATCH v3 9/9] drm/imx: use PRG/PRE when possible 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).