All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] ipu-v3/imx-drm PRG/PRE extension
@ 2017-02-17 18:28 Lucas Stach
       [not found] ` <20170217182830.32618-1-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  0 siblings, 1 reply; 19+ messages in thread
From: Lucas Stach @ 2017-02-17 18:28 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Rob Herring, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

Hi all,

this is the first round of patches to enable the Prefetch Resolve Gasket
and the Prefetch Resolve Engine as found on the i.MX6 QuadPlus. Basically
those units are external extensions to the IPUv3 that are able to prefetch
display data from DRAM to an internal SRAM region, transforming the
periodic realtime requests from the display FIFOs into larger bursts of
normal memory requests, which do mix better with other DRAM traffic in the
system.

The PRE can do a number of transformations on the fly, like changing
component and plane ordering, as well resolving the Vivante GPU tiling
format into linear scanlines. None of those transformations are used
right now.

This initial patchset uses the PRG/PRE units as linear prefetchers only.
It does however hook up most of the interactions between imx-drm, IPUv3
and PRG/PRE, so that adding those transformations should be an
incremental change over that. Also the devicetree binding fully describe
the devices, so that no further changes should be necessary.

Regards,
Lucas

Lucas Stach (9):
  gpu: ipu-v3: remove AXI ID setting for IC channel
  gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine
  gpu: ipu-v3: add driver for Prefetch Resolve Engine
  gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket
  gpu: ipu-v3: add driver for Prefetch Resolve Gasket
  gpu: ipu-v3: extend the IPUv3 DT binding for i.MX6 QuadPlus
  gpu: ipu-v3: hook up PRG unit
  drm/imx: enable/disable PRG on CRTC enable/disable
  drm/imx: use PRG/PRE when possible

 .../bindings/display/imx/fsl-imx-drm.txt           |  53 +++
 drivers/gpu/drm/imx/imx-drm-core.c                 |   5 +
 drivers/gpu/drm/imx/imx-drm.h                      |   3 +
 drivers/gpu/drm/imx/ipuv3-crtc.c                   |   2 +
 drivers/gpu/drm/imx/ipuv3-plane.c                  | 122 +++++-
 drivers/gpu/ipu-v3/Makefile                        |   2 +-
 drivers/gpu/ipu-v3/ipu-common.c                    |   7 +
 drivers/gpu/ipu-v3/ipu-image-convert.c             |   2 -
 drivers/gpu/ipu-v3/ipu-pre.c                       | 290 +++++++++++++++
 drivers/gpu/ipu-v3/ipu-prg.c                       | 413 +++++++++++++++++++++
 drivers/gpu/ipu-v3/ipu-prv.h                       |  15 +
 include/video/imx-ipu-v3.h                         |  15 +
 12 files changed, 923 insertions(+), 6 deletions(-)
 create mode 100644 drivers/gpu/ipu-v3/ipu-pre.c
 create mode 100644 drivers/gpu/ipu-v3/ipu-prg.c

-- 
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	[flat|nested] 19+ messages in thread

* [PATCH 1/9] gpu: ipu-v3: remove AXI ID setting for IC channel
       [not found] ` <20170217182830.32618-1-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2017-02-17 18:28   ` Lucas Stach
  2017-02-20 13:04     ` Philipp Zabel
  2017-02-17 18:28   ` [PATCH 2/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine Lucas Stach
                     ` (7 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Lucas Stach @ 2017-02-17 18:28 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Rob Herring, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

This is a pretty minor optimization for the IC channel to get
out-of-order AXI returns, but clashes with the AXI ID assignment
that needs to be done for the display channels on QuadPlus.

Signed-off-by: Lucas Stach <l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 drivers/gpu/ipu-v3/ipu-image-convert.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-image-convert.c b/drivers/gpu/ipu-v3/ipu-image-convert.c
index 805b6fa7b5f4..5e3cc6bd98fc 100644
--- a/drivers/gpu/ipu-v3/ipu-image-convert.c
+++ b/drivers/gpu/ipu-v3/ipu-image-convert.c
@@ -671,8 +671,6 @@ 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);
-
 	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] 19+ messages in thread

* [PATCH 2/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine
       [not found] ` <20170217182830.32618-1-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  2017-02-17 18:28   ` [PATCH 1/9] gpu: ipu-v3: remove AXI ID setting for IC channel Lucas Stach
@ 2017-02-17 18:28   ` Lucas Stach
       [not found]     ` <20170217182830.32618-3-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  2017-02-17 18:28   ` [PATCH 3/9] gpu: ipu-v3: add driver for " Lucas Stach
                     ` (6 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Lucas Stach @ 2017-02-17 18:28 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Rob Herring, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

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>
---
 .../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 971c3eedb1c7..1bd777d7c37d 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,ocram: phandle pointing to the mmio-sram device node, that should be
+  used for the PRE SRAM double buffer.
+
+example:
+
+pre@021c8000 {
+	compatible = "fsl,imx6qp-pre";
+	reg = <0x021c8000 0x1000>;
+	interrupts = <GIC_SPI 90 IRQ_TYPE_EDGE_RISING>;
+	clocks = <&clks IMX6QDL_CLK_PRE0>;
+	clock-names = "axi";
+	fsl,ocram = <&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] 19+ messages in thread

* [PATCH 3/9] gpu: ipu-v3: add driver for Prefetch Resolve Engine
       [not found] ` <20170217182830.32618-1-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  2017-02-17 18:28   ` [PATCH 1/9] gpu: ipu-v3: remove AXI ID setting for IC channel Lucas Stach
  2017-02-17 18:28   ` [PATCH 2/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine Lucas Stach
@ 2017-02-17 18:28   ` Lucas Stach
       [not found]     ` <20170217182830.32618-4-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  2017-02-17 18:28   ` [PATCH 4/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket Lucas Stach
                     ` (5 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Lucas Stach @ 2017-02-17 18:28 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Rob Herring, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

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>
---
 drivers/gpu/ipu-v3/Makefile  |   2 +-
 drivers/gpu/ipu-v3/ipu-pre.c | 290 +++++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/ipu-v3/ipu-prv.h |  11 ++
 3 files changed, 302 insertions(+), 1 deletion(-)
 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 5f961416c4ee..8ae90de46b4d 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-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c
new file mode 100644
index 000000000000..febe0cb8b094
--- /dev/null
+++ b/drivers/gpu/ipu-v3/ipu-pre.c
@@ -0,0 +1,290 @@
+/*
+ * 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		*ocram;
+
+	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_get_by_prg_device(struct device *dev, int index)
+{
+	struct device_node *pre_node = of_parse_phandle(dev->of_node,
+							"fsl,pres", 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->ocram = of_gen_pool_get(dev->of_node, "fsl,ocram", 0);
+	if (!pre->ocram)
+		return -EPROBE_DEFER;
+
+	/*
+	 * Allocate OCRAM buffer with maximum size. This could be made dynamic,
+	 * but as there is no other user of this OCRAM region and we can fit all
+	 * max sized buffers into it, there is no need yet.
+	 */
+	pre->buffer_virt = gen_pool_dma_alloc(pre->ocram, 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->ocram, (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 */ },
+};
+
+static 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,
+	},
+};
+module_platform_driver(ipu_pre_drv);
diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h
index 22e47b68b14a..536a156a5eb6 100644
--- a/drivers/gpu/ipu-v3/ipu-prv.h
+++ b/drivers/gpu/ipu-v3/ipu-prv.h
@@ -168,6 +168,7 @@ struct ipu_ic_priv;
 struct ipu_vdi;
 struct ipu_image_convert_priv;
 struct ipu_smfc_priv;
+struct ipu_pre;
 
 struct ipu_devtype;
 
@@ -259,4 +260,14 @@ 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_get_by_prg_device(struct device *dev, 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);
+
 #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] 19+ messages in thread

* [PATCH 4/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket
       [not found] ` <20170217182830.32618-1-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
                     ` (2 preceding siblings ...)
  2017-02-17 18:28   ` [PATCH 3/9] gpu: ipu-v3: add driver for " Lucas Stach
@ 2017-02-17 18:28   ` Lucas Stach
  2017-02-27 17:02     ` Rob Herring
  2017-02-17 18:28   ` [PATCH 5/9] gpu: ipu-v3: add driver for " Lucas Stach
                     ` (4 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Lucas Stach @ 2017-02-17 18:28 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Rob Herring, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

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>
---
 .../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 1bd777d7c37d..5e4b8b13b9f8 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@021c8000 {
 	fsl,ocram = <&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@021cc000 {
+	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] 19+ messages in thread

* [PATCH 5/9] gpu: ipu-v3: add driver for Prefetch Resolve Gasket
       [not found] ` <20170217182830.32618-1-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
                     ` (3 preceding siblings ...)
  2017-02-17 18:28   ` [PATCH 4/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket Lucas Stach
@ 2017-02-17 18:28   ` Lucas Stach
  2017-02-20 15:31     ` Philipp Zabel
  2017-02-17 18:28   ` [PATCH 6/9] gpu: ipu-v3: extend the IPUv3 DT binding for i.MX6 QuadPlus Lucas Stach
                     ` (3 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Lucas Stach @ 2017-02-17 18:28 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Rob Herring, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

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>
---
 drivers/gpu/ipu-v3/Makefile  |   2 +-
 drivers/gpu/ipu-v3/ipu-prg.c | 413 +++++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/ipu-v3/ipu-prv.h |   3 +
 include/video/imx-ipu-v3.h   |  15 ++
 4 files changed, 432 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 8ae90de46b4d..1ab9bceee755 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-prg.c b/drivers/gpu/ipu-v3/ipu-prg.c
new file mode 100644
index 000000000000..c1e1ab0ec5c5
--- /dev/null
+++ b/drivers/gpu/ipu-v3/ipu-prg.c
@@ -0,0 +1,413 @@
+/*
+ * 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_get_by_ipu_device(struct device *dev)
+{
+	struct device_node *prg_node = of_parse_phandle(dev->of_node,
+							"fsl,prg", 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 = of_alias_get_id(dev->of_node, "ipu");
+			return prg;
+		}
+	}
+	mutex_unlock(&ipu_prg_list_mutex);
+
+	return NULL;
+}
+
+int ipu_prg_max_active_channels(void)
+{
+	return ipu_pre_get_available_count();
+}
+
+bool ipu_prg_present(struct ipu_soc *ipu)
+{
+	if (ipu->prg_priv)
+		return true;
+
+	return false;
+}
+
+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;
+}
+
+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;
+}
+
+void ipu_prg_disable(struct ipu_soc *ipu)
+{
+	struct ipu_prg *prg = ipu->prg_priv;
+
+	if (!prg)
+		return;
+
+	clk_disable_unprepare(prg->clk_axi);
+}
+
+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;
+}
+
+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;
+}
+
+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_get_by_prg_device(dev, 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 */ },
+};
+
+static 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,
+	},
+};
+module_platform_driver(ipu_prg_drv);
diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h
index 536a156a5eb6..0d1d2d667f3b 100644
--- a/drivers/gpu/ipu-v3/ipu-prv.h
+++ b/drivers/gpu/ipu-v3/ipu-prv.h
@@ -169,6 +169,7 @@ struct ipu_vdi;
 struct ipu_image_convert_priv;
 struct ipu_smfc_priv;
 struct ipu_pre;
+struct ipu_prg;
 
 struct ipu_devtype;
 
@@ -270,4 +271,6 @@ 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_get_by_ipu_device(struct device *dev);
+
 #endif				/* __IPU_PRV_H__ */
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 228e32082097..3902323f8769 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] 19+ messages in thread

* [PATCH 6/9] gpu: ipu-v3: extend the IPUv3 DT binding for i.MX6 QuadPlus
       [not found] ` <20170217182830.32618-1-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
                     ` (4 preceding siblings ...)
  2017-02-17 18:28   ` [PATCH 5/9] gpu: ipu-v3: add driver for " Lucas Stach
@ 2017-02-17 18:28   ` Lucas Stach
  2017-02-27 17:04     ` Rob Herring
  2017-02-17 18:28   ` [PATCH 7/9] gpu: ipu-v3: hook up PRG unit Lucas Stach
                     ` (2 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Lucas Stach @ 2017-02-17 18:28 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Rob Herring, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

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>
---
 Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
index 5e4b8b13b9f8..c8c7a7b3951f 100644
--- a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
+++ b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
@@ -28,6 +28,8 @@ Required properties:
   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] 19+ messages in thread

* [PATCH 7/9] gpu: ipu-v3: hook up PRG unit
       [not found] ` <20170217182830.32618-1-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
                     ` (5 preceding siblings ...)
  2017-02-17 18:28   ` [PATCH 6/9] gpu: ipu-v3: extend the IPUv3 DT binding for i.MX6 QuadPlus Lucas Stach
@ 2017-02-17 18:28   ` Lucas Stach
  2017-02-17 18:28   ` [PATCH 8/9] drm/imx: enable/disable PRG on CRTC enable/disable Lucas Stach
  2017-02-17 18:28   ` [PATCH 9/9] drm/imx: use PRG/PRE when possible Lucas Stach
  8 siblings, 0 replies; 19+ messages in thread
From: Lucas Stach @ 2017-02-17 18:28 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Rob Herring, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

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-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 drivers/gpu/ipu-v3/ipu-common.c | 7 +++++++
 drivers/gpu/ipu-v3/ipu-prv.h    | 1 +
 2 files changed, 8 insertions(+)

diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index d0694ef95f28..37426dd94408 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -937,6 +937,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);
@@ -1402,6 +1403,12 @@ static int ipu_probe(struct platform_device *pdev)
 	if (!ipu)
 		return -ENODEV;
 
+	if (of_device_is_compatible(np, "fsl,imx6qp-ipu")) {
+		ipu->prg_priv = ipu_prg_get_by_ipu_device(&pdev->dev);
+		if (!ipu->prg_priv)
+			return -EPROBE_DEFER;
+	}
+
 	for (i = 0; i < 64; i++)
 		ipu->channel[i].ipu = ipu;
 	ipu->devtype = devtype;
diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h
index 0d1d2d667f3b..0d32a4f3a76a 100644
--- a/drivers/gpu/ipu-v3/ipu-prv.h
+++ b/drivers/gpu/ipu-v3/ipu-prv.h
@@ -204,6 +204,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

--
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] 19+ messages in thread

* [PATCH 8/9] drm/imx: enable/disable PRG on CRTC enable/disable
       [not found] ` <20170217182830.32618-1-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
                     ` (6 preceding siblings ...)
  2017-02-17 18:28   ` [PATCH 7/9] gpu: ipu-v3: hook up PRG unit Lucas Stach
@ 2017-02-17 18:28   ` Lucas Stach
  2017-02-17 18:28   ` [PATCH 9/9] drm/imx: use PRG/PRE when possible Lucas Stach
  8 siblings, 0 replies; 19+ messages in thread
From: Lucas Stach @ 2017-02-17 18:28 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Rob Herring, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

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>
---
 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 6be515a9fb69..4299c7d07d80 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);
@@ -75,6 +76,7 @@ static void ipu_crtc_atomic_disable(struct drm_crtc *crtc,
 	 */
 	drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false);
 	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] 19+ messages in thread

* [PATCH 9/9] drm/imx: use PRG/PRE when possible
       [not found] ` <20170217182830.32618-1-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
                     ` (7 preceding siblings ...)
  2017-02-17 18:28   ` [PATCH 8/9] drm/imx: enable/disable PRG on CRTC enable/disable Lucas Stach
@ 2017-02-17 18:28   ` Lucas Stach
  8 siblings, 0 replies; 19+ messages in thread
From: Lucas Stach @ 2017-02-17 18:28 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: David Airlie, Rob Herring, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

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-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
 drivers/gpu/drm/imx/imx-drm-core.c |   5 ++
 drivers/gpu/drm/imx/imx-drm.h      |   3 +
 drivers/gpu/drm/imx/ipuv3-plane.c  | 122 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 127 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index bef76cb0d05d..f3fd94046e3e 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -147,6 +147,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 5a91cb16c8fa..485df472fd34 100644
--- a/drivers/gpu/drm/imx/imx-drm.h
+++ b/drivers/gpu/drm/imx/imx-drm.h
@@ -52,4 +52,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 57130352db3b..6867cd7f2da3 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);
@@ -225,6 +236,8 @@ static int ipu_disable_plane(struct drm_plane *plane)
 	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);
 
 	return 0;
 }
@@ -239,13 +252,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,
@@ -458,14 +514,30 @@ static void ipu_plane_atomic_disable(struct drm_plane *plane,
 	ipu_disable_plane(plane);
 }
 
+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 int axi_id = ipu_chan_assign_axi_id(ipu_plane->dma);
 	unsigned long eba, ubo, vbo;
 	unsigned long alpha_eba = 0;
 	enum ipu_color_space ics;
@@ -476,7 +548,22 @@ 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) {
+		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->pixel_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);
@@ -535,6 +622,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->pixel_format) {
 	case DRM_FORMAT_YUV420:
 	case DRM_FORMAT_YVU420:
@@ -610,6 +698,34 @@ 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->pixel_format,
+					     plane_state->fb->modifier)) {
+			ipu_state->use_pre = true;
+			available_pres--;
+		} else {
+			ipu_state->use_pre = false;
+		}
+	}
+
+	return 0;
+}
+
 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

--
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] 19+ messages in thread

* Re: [PATCH 1/9] gpu: ipu-v3: remove AXI ID setting for IC channel
  2017-02-17 18:28   ` [PATCH 1/9] gpu: ipu-v3: remove AXI ID setting for IC channel Lucas Stach
@ 2017-02-20 13:04     ` Philipp Zabel
  0 siblings, 0 replies; 19+ messages in thread
From: Philipp Zabel @ 2017-02-20 13:04 UTC (permalink / raw)
  To: Lucas Stach
  Cc: Mark Rutland, devicetree, dri-devel, patchwork-lst, Rob Herring, kernel

On Fri, 2017-02-17 at 19:28 +0100, Lucas Stach wrote:
> This is a pretty minor optimization for the IC channel to get
> out-of-order AXI returns, but clashes with the AXI ID assignment
> that needs to be done for the display channels on QuadPlus.
> 
> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
> ---
>  drivers/gpu/ipu-v3/ipu-image-convert.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/gpu/ipu-v3/ipu-image-convert.c b/drivers/gpu/ipu-v3/ipu-image-convert.c
> index 805b6fa7b5f4..5e3cc6bd98fc 100644
> --- a/drivers/gpu/ipu-v3/ipu-image-convert.c
> +++ b/drivers/gpu/ipu-v3/ipu-image-convert.c
> @@ -671,8 +671,6 @@ 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);
> -

The IC IDMAC channels were set to AXI ID 1 to avoid starving the scanout
channels. AXI ID 0 is set to the highest QoS priority in imx6q_axi_init,
AXI ID 1 is set slightly lower for that reason. This should be kept for
all the non-plus models.

>  	ipu_idmac_set_double_buffer(channel, ctx->double_buffering);
>  }
>  

regards
Philipp

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

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

* Re: [PATCH 2/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine
       [not found]     ` <20170217182830.32618-3-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2017-02-20 15:01       ` Philipp Zabel
  2017-02-27 17:00       ` Rob Herring
  1 sibling, 0 replies; 19+ messages in thread
From: Philipp Zabel @ 2017-02-20 15:01 UTC (permalink / raw)
  To: Lucas Stach
  Cc: David Airlie, Rob Herring, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

On Fri, 2017-02-17 at 19:28 +0100, Lucas Stach wrote:
> 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>
> ---
>  .../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 971c3eedb1c7..1bd777d7c37d 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,ocram: phandle pointing to the mmio-sram device node, that should be
> +  used for the PRE SRAM double buffer.
> +
> +example:
> +
> +pre@021c8000 {
> +	compatible = "fsl,imx6qp-pre";
> +	reg = <0x021c8000 0x1000>;
> +	interrupts = <GIC_SPI 90 IRQ_TYPE_EDGE_RISING>;
> +	clocks = <&clks IMX6QDL_CLK_PRE0>;
> +	clock-names = "axi";
> +	fsl,ocram = <&ocram2>;

Nitpick: the CODA property for this is called iram. Should we do the
same here in case the PRE is later used on other SoCs that call their
on-chip SRAM differently?
There is no mention of OCRAM in the PRE chapter in the i.MX6QP reference
manual, but Figures 38-1 and 38-5 mention an "IRAM Double Buffer".

> +};
> +
>  Parallel display support
>  ========================
>  

regards
Philipp

--
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	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/9] gpu: ipu-v3: add driver for Prefetch Resolve Engine
       [not found]     ` <20170217182830.32618-4-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
@ 2017-02-20 15:20       ` Philipp Zabel
  2017-03-03 18:25         ` Lucas Stach
  0 siblings, 1 reply; 19+ messages in thread
From: Philipp Zabel @ 2017-02-20 15:20 UTC (permalink / raw)
  To: Lucas Stach
  Cc: David Airlie, Rob Herring, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

On Fri, 2017-02-17 at 19:28 +0100, Lucas Stach wrote:
> 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>
> ---
>  drivers/gpu/ipu-v3/Makefile  |   2 +-
>  drivers/gpu/ipu-v3/ipu-pre.c | 290 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/ipu-v3/ipu-prv.h |  11 ++
>  3 files changed, 302 insertions(+), 1 deletion(-)
>  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 5f961416c4ee..8ae90de46b4d 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-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c
> new file mode 100644
> index 000000000000..febe0cb8b094
> --- /dev/null
> +++ b/drivers/gpu/ipu-v3/ipu-pre.c
> @@ -0,0 +1,290 @@
> +/*
> + * 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)

Single bit fields could use BIT(0) etc.

> +#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		*ocram;
> +
> +	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_get_by_prg_device(struct device *dev, int index)

I'd call this ipu_pre_lookup_by_phandle and pass the device_node and
property name string parameter.
That way the name is better separated from ipu_pre_get ...

> +{
> +	struct device_node *pre_node = of_parse_phandle(dev->of_node,
> +							"fsl,pres", index);

... and the PRG specific "fsl,pres" string could move into the PRG
driver.

> +	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;

This could race for in_use ...

> +	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;

... until here.

> +	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->ocram = of_gen_pool_get(dev->of_node, "fsl,ocram", 0);
> +	if (!pre->ocram)
> +		return -EPROBE_DEFER;

I'd call this iram, from the point of view of the PRE.

> +
> +	/*
> +	 * Allocate OCRAM buffer with maximum size. This could be made dynamic,
> +	 * but as there is no other user of this OCRAM region and we can fit all
> +	 * max sized buffers into it, there is no need yet.
> +	 */
> +	pre->buffer_virt = gen_pool_dma_alloc(pre->ocram, 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->ocram, (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 */ },
> +};
> +
> +static 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,
> +	},
> +};
> +module_platform_driver(ipu_pre_drv);
> diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h
> index 22e47b68b14a..536a156a5eb6 100644
> --- a/drivers/gpu/ipu-v3/ipu-prv.h
> +++ b/drivers/gpu/ipu-v3/ipu-prv.h
> @@ -168,6 +168,7 @@ struct ipu_ic_priv;
>  struct ipu_vdi;
>  struct ipu_image_convert_priv;
>  struct ipu_smfc_priv;
> +struct ipu_pre;
>  
>  struct ipu_devtype;
>  
> @@ -259,4 +260,14 @@ 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_get_by_prg_device(struct device *dev, 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);
> +
>  #endif				/* __IPU_PRV_H__ */

regards
Philipp

--
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	[flat|nested] 19+ messages in thread

* Re: [PATCH 5/9] gpu: ipu-v3: add driver for Prefetch Resolve Gasket
  2017-02-17 18:28   ` [PATCH 5/9] gpu: ipu-v3: add driver for " Lucas Stach
@ 2017-02-20 15:31     ` Philipp Zabel
  0 siblings, 0 replies; 19+ messages in thread
From: Philipp Zabel @ 2017-02-20 15:31 UTC (permalink / raw)
  To: Lucas Stach
  Cc: Mark Rutland, devicetree, dri-devel, patchwork-lst, Rob Herring, kernel

On Fri, 2017-02-17 at 19:28 +0100, Lucas Stach wrote:
> 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@pengutronix.de>
> ---
>  drivers/gpu/ipu-v3/Makefile  |   2 +-
>  drivers/gpu/ipu-v3/ipu-prg.c | 413 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/ipu-v3/ipu-prv.h |   3 +
>  include/video/imx-ipu-v3.h   |  15 ++
>  4 files changed, 432 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 8ae90de46b4d..1ab9bceee755 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-prg.c b/drivers/gpu/ipu-v3/ipu-prg.c
> new file mode 100644
> index 000000000000..c1e1ab0ec5c5
> --- /dev/null
> +++ b/drivers/gpu/ipu-v3/ipu-prg.c
> @@ -0,0 +1,413 @@
> +/*
> + * 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_get_by_ipu_device(struct device *dev)

Same as for the PRE, I'd prefer this to be called "lookup" instead of
"get", and to pass the "fsl,prg" string from the IPU driver, to whose DT
binding it belongs.

> +{
> +	struct device_node *prg_node = of_parse_phandle(dev->of_node,
> +							"fsl,prg", 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 = of_alias_get_id(dev->of_node, "ipu");
> +			return prg;
> +		}
> +	}
> +	mutex_unlock(&ipu_prg_list_mutex);
> +
> +	return NULL;
> +}
> +
> +int ipu_prg_max_active_channels(void)
> +{
> +	return ipu_pre_get_available_count();
> +}
> +
> +bool ipu_prg_present(struct ipu_soc *ipu)
> +{
> +	if (ipu->prg_priv)
> +		return true;
> +
> +	return false;
> +}
> +
> +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;
> +}
> +
> +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;
> +}
> +
> +void ipu_prg_disable(struct ipu_soc *ipu)
> +{
> +	struct ipu_prg *prg = ipu->prg_priv;
> +
> +	if (!prg)
> +		return;
> +
> +	clk_disable_unprepare(prg->clk_axi);
> +}
> +
> +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;
> +}
> +
> +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;
> +}
> +
> +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);
> +
> +

So much whitespace.

> +	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_get_by_prg_device(dev, 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 */ },
> +};
> +
> +static 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,
> +	},
> +};
> +module_platform_driver(ipu_prg_drv);
> diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h
> index 536a156a5eb6..0d1d2d667f3b 100644
> --- a/drivers/gpu/ipu-v3/ipu-prv.h
> +++ b/drivers/gpu/ipu-v3/ipu-prv.h
> @@ -169,6 +169,7 @@ struct ipu_vdi;
>  struct ipu_image_convert_priv;
>  struct ipu_smfc_priv;
>  struct ipu_pre;
> +struct ipu_prg;
>  
>  struct ipu_devtype;
>  
> @@ -270,4 +271,6 @@ 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_get_by_ipu_device(struct device *dev);
> +
>  #endif				/* __IPU_PRV_H__ */
> diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
> index 228e32082097..3902323f8769 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;

regards
Philipp

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

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

* Re: [PATCH 2/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine
       [not found]     ` <20170217182830.32618-3-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
  2017-02-20 15:01       ` Philipp Zabel
@ 2017-02-27 17:00       ` Rob Herring
  1 sibling, 0 replies; 19+ messages in thread
From: Rob Herring @ 2017-02-27 17:00 UTC (permalink / raw)
  To: Lucas Stach
  Cc: Philipp Zabel, David Airlie, Mark Rutland,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	patchwork-lst-bIcnvbaLZ9MEGnE8C9+IrQ

On Fri, Feb 17, 2017 at 07:28:23PM +0100, Lucas Stach wrote:
> 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>
> ---
>  .../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 971c3eedb1c7..1bd777d7c37d 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,ocram: phandle pointing to the mmio-sram device node, that should be
> +  used for the PRE SRAM double buffer.
> +
> +example:
> +
> +pre@021c8000 {

Drop the leading 0.

> +	compatible = "fsl,imx6qp-pre";
> +	reg = <0x021c8000 0x1000>;
> +	interrupts = <GIC_SPI 90 IRQ_TYPE_EDGE_RISING>;
> +	clocks = <&clks IMX6QDL_CLK_PRE0>;
> +	clock-names = "axi";
> +	fsl,ocram = <&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	[flat|nested] 19+ messages in thread

* Re: [PATCH 4/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket
  2017-02-17 18:28   ` [PATCH 4/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket Lucas Stach
@ 2017-02-27 17:02     ` Rob Herring
  0 siblings, 0 replies; 19+ messages in thread
From: Rob Herring @ 2017-02-27 17:02 UTC (permalink / raw)
  To: Lucas Stach; +Cc: Mark Rutland, devicetree, dri-devel, patchwork-lst, kernel

On Fri, Feb 17, 2017 at 07:28:25PM +0100, Lucas Stach wrote:
> 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@pengutronix.de>
> ---
>  .../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 1bd777d7c37d..5e4b8b13b9f8 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@021c8000 {
>  	fsl,ocram = <&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@021cc000 {

Drop the leading 0. With that,

Acked-by: Rob Herring <robh@kernel.org>

> +	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@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 6/9] gpu: ipu-v3: extend the IPUv3 DT binding for i.MX6 QuadPlus
  2017-02-17 18:28   ` [PATCH 6/9] gpu: ipu-v3: extend the IPUv3 DT binding for i.MX6 QuadPlus Lucas Stach
@ 2017-02-27 17:04     ` Rob Herring
  0 siblings, 0 replies; 19+ messages in thread
From: Rob Herring @ 2017-02-27 17:04 UTC (permalink / raw)
  To: Lucas Stach; +Cc: Mark Rutland, devicetree, dri-devel, patchwork-lst, kernel

On Fri, Feb 17, 2017 at 07:28:27PM +0100, Lucas Stach wrote:
> 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.

Is there already a new compatible string? If not, add one. If so, then 
the subject should be more specific.

> 
> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
> ---
>  Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
> index 5e4b8b13b9f8..c8c7a7b3951f 100644
> --- a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
> +++ b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt
> @@ -28,6 +28,8 @@ Required properties:
>    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
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 3/9] gpu: ipu-v3: add driver for Prefetch Resolve Engine
  2017-02-20 15:20       ` Philipp Zabel
@ 2017-03-03 18:25         ` Lucas Stach
  2017-03-06  8:42           ` Philipp Zabel
  0 siblings, 1 reply; 19+ messages in thread
From: Lucas Stach @ 2017-03-03 18:25 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: Mark Rutland, devicetree, dri-devel, patchwork-lst, Rob Herring, kernel

Am Montag, den 20.02.2017, 16:20 +0100 schrieb Philipp Zabel:
> On Fri, 2017-02-17 at 19:28 +0100, Lucas Stach wrote:
> > 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@pengutronix.de>
> > ---
> >  drivers/gpu/ipu-v3/Makefile  |   2 +-
> >  drivers/gpu/ipu-v3/ipu-pre.c | 290
> > +++++++++++++++++++++++++++++++++++++++++++
> >  drivers/gpu/ipu-v3/ipu-prv.h |  11 ++
> >  3 files changed, 302 insertions(+), 1 deletion(-)
> >  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 5f961416c4ee..8ae90de46b4d 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-pre.c b/drivers/gpu/ipu-v3/ipu-
> > pre.c
> > new file mode 100644
> > index 000000000000..febe0cb8b094
> > --- /dev/null
> > +++ b/drivers/gpu/ipu-v3/ipu-pre.c
> > @@ -0,0 +1,290 @@
> > +/*
> > + * 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)
> 
> Single bit fields could use BIT(0) etc.
> 
> > +#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					0x0
> > 30
> > +
> > +#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			0x0
> > a0
> > +#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				0x11
> > 0
> > +#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				0x13
> > 0
> > +#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				0x1
> > 40
> > +#define  IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(v)		((v &
> > 0xffff) << 0)
> > +
> > +#define IPU_PRE_STORE_ENG_ADDR				0x15
> > 0
> > +
> > +struct ipu_pre {
> > +	struct list_head	list;
> > +	struct device		*dev;
> > +
> > +	void __iomem		*regs;
> > +	struct clk		*clk_axi;
> > +	struct gen_pool		*ocram;
> > +
> > +	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_get_by_prg_device(struct device *dev, int index)
> 
> I'd call this ipu_pre_lookup_by_phandle and pass the device_node and
> property name string parameter.
> That way the name is better separated from ipu_pre_get ...
> 
> > +{
> > +	struct device_node *pre_node = of_parse_phandle(dev-
> > >of_node,
> > +							"fsl,pres"
> > , index);
> 
> ... and the PRG specific "fsl,pres" string could move into the PRG
> driver.

Good point, will do.

> 
> > +	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;
> 
> This could race for in_use ...

All the PRE/PRG configuration functions are thread unsafe, with the
premise that they are only used during an atomic commit, which is
inherently single threaded. I would rather like to avoid introducing
unnecessary thread safety here.

> 
> > +	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;
> 
> ... until here.
> 
> > +	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->ocram = of_gen_pool_get(dev->of_node, "fsl,ocram",
> > 0);
> > +	if (!pre->ocram)
> > +		return -EPROBE_DEFER;
> 
> I'd call this iram, from the point of view of the PRE.
> 
> > +
> > +	/*
> > +	 * Allocate OCRAM buffer with maximum size. This could be
> > made dynamic,
> > +	 * but as there is no other user of this OCRAM region and
> > we can fit all
> > +	 * max sized buffers into it, there is no need yet.
> > +	 */
> > +	pre->buffer_virt = gen_pool_dma_alloc(pre->ocram,
> > IPU_PRE_MAX_WIDTH *
> > +					      IPU_PRE_NUM_SCANLINE
> > S * 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->ocram, (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 */ },
> > +};
> > +
> > +static 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,
> > +	},
> > +};
> > +module_platform_driver(ipu_pre_drv);
> > diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-
> > prv.h
> > index 22e47b68b14a..536a156a5eb6 100644
> > --- a/drivers/gpu/ipu-v3/ipu-prv.h
> > +++ b/drivers/gpu/ipu-v3/ipu-prv.h
> > @@ -168,6 +168,7 @@ struct ipu_ic_priv;
> >  struct ipu_vdi;
> >  struct ipu_image_convert_priv;
> >  struct ipu_smfc_priv;
> > +struct ipu_pre;
> >  
> >  struct ipu_devtype;
> >  
> > @@ -259,4 +260,14 @@ 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_get_by_prg_device(struct device *dev, 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);
> > +
> >  #endif				/* __IPU_PRV_H__ */
> 
> regards
> Philipp
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 3/9] gpu: ipu-v3: add driver for Prefetch Resolve Engine
  2017-03-03 18:25         ` Lucas Stach
@ 2017-03-06  8:42           ` Philipp Zabel
  0 siblings, 0 replies; 19+ messages in thread
From: Philipp Zabel @ 2017-03-06  8:42 UTC (permalink / raw)
  To: Lucas Stach
  Cc: Mark Rutland, devicetree, dri-devel, patchwork-lst, Rob Herring, kernel

On Fri, 2017-03-03 at 19:25 +0100, Lucas Stach wrote:
[...]
> > > +int ipu_pre_get(struct ipu_pre *pre)
> > > +{
> > > +	u32 val;
> > > +
> > > +	if (pre->in_use)
> > > +		return -EBUSY;
> > 
> > This could race for in_use ...
> 
> All the PRE/PRG configuration functions are thread unsafe, with the
> premise that they are only used during an atomic commit, [...]

Oh, okay. It would be nice to point this out in a comment.

regards
Philipp

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

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

end of thread, other threads:[~2017-03-06  8:42 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-17 18:28 [PATCH 0/9] ipu-v3/imx-drm PRG/PRE extension Lucas Stach
     [not found] ` <20170217182830.32618-1-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2017-02-17 18:28   ` [PATCH 1/9] gpu: ipu-v3: remove AXI ID setting for IC channel Lucas Stach
2017-02-20 13:04     ` Philipp Zabel
2017-02-17 18:28   ` [PATCH 2/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Engine Lucas Stach
     [not found]     ` <20170217182830.32618-3-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2017-02-20 15:01       ` Philipp Zabel
2017-02-27 17:00       ` Rob Herring
2017-02-17 18:28   ` [PATCH 3/9] gpu: ipu-v3: add driver for " Lucas Stach
     [not found]     ` <20170217182830.32618-4-l.stach-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2017-02-20 15:20       ` Philipp Zabel
2017-03-03 18:25         ` Lucas Stach
2017-03-06  8:42           ` Philipp Zabel
2017-02-17 18:28   ` [PATCH 4/9] gpu: ipu-v3: add DT binding for the Prefetch Resolve Gasket Lucas Stach
2017-02-27 17:02     ` Rob Herring
2017-02-17 18:28   ` [PATCH 5/9] gpu: ipu-v3: add driver for " Lucas Stach
2017-02-20 15:31     ` Philipp Zabel
2017-02-17 18:28   ` [PATCH 6/9] gpu: ipu-v3: extend the IPUv3 DT binding for i.MX6 QuadPlus Lucas Stach
2017-02-27 17:04     ` Rob Herring
2017-02-17 18:28   ` [PATCH 7/9] gpu: ipu-v3: hook up PRG unit Lucas Stach
2017-02-17 18:28   ` [PATCH 8/9] drm/imx: enable/disable PRG on CRTC enable/disable Lucas Stach
2017-02-17 18:28   ` [PATCH 9/9] drm/imx: use PRG/PRE when possible Lucas Stach

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.