From mboxrd@z Thu Jan  1 00:00:00 1970
From: rmk+kernel@arm.linux.org.uk (Russell King)
Date: Sun, 06 Oct 2013 23:11:56 +0100
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Message-ID: <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/armada/Kconfig      |    9 +++++++
 drivers/gpu/drm/armada/armada_drv.c |   42 +++++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
index c7a0a94..87e62dd 100644
--- a/drivers/gpu/drm/armada/Kconfig
+++ b/drivers/gpu/drm/armada/Kconfig
@@ -13,3 +13,12 @@ config DRM_ARMADA
 	  This driver provides no built-in acceleration; acceleration is
 	  performed by other IP found on the SoC.  This driver provides
 	  kernel mode setting and buffer management to userspace.
+
+config DRM_ARMADA_TDA1998X
+	bool "Support TDA1998X HDMI output"
+	depends on DRM_ARMADA != n
+	depends on I2C && DRM_I2C_NXP_TDA998X = y
+	default y
+	help
+	  Support the TDA1998x HDMI output device found on the Solid-Run
+	  CuBox.
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index db62f1b..69517cf 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -16,6 +16,42 @@
 #include <drm/armada_drm.h>
 #include "armada_ioctlP.h"
 
+#ifdef CONFIG_DRM_ARMADA_TDA1998X
+#include <drm/i2c/tda998x.h>
+#include "armada_slave.h"
+
+static struct tda998x_encoder_params params = {
+	/* With 0x24, there is no translation between vp_out and int_vp
+	FB	LCD out	Pins	VIP	Int Vp
+	R:23:16	R:7:0	VPC7:0	7:0	7:0[R]
+	G:15:8	G:15:8	VPB7:0	23:16	23:16[G]
+	B:7:0	B:23:16	VPA7:0	15:8	15:8[B]
+	*/
+	.swap_a = 2,
+	.swap_b = 3,
+	.swap_c = 4,
+	.swap_d = 5,
+	.swap_e = 0,
+	.swap_f = 1,
+	.audio_cfg = BIT(2),
+	.audio_frame[1] = 1,
+	.audio_format = AFMT_SPDIF,
+	.audio_sample_rate = 44100,
+};
+
+static const struct armada_drm_slave_config tda19988_config = {
+	.i2c_adapter_id = 0,
+	.crtcs = 1 << 0, /* Only LCD0@the moment */
+	.polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT,
+	.interlace_allowed = true,
+	.info = {
+		.type = "tda998x",
+		.addr = 0x70,
+		.platform_data = &params,
+	},
+};
+#endif
+
 static void armada_drm_unref_work(struct work_struct *work)
 {
 	struct armada_private *priv =
@@ -134,6 +170,12 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
 			goto err_kms;
 	}
 
+#ifdef CONFIG_DRM_ARMADA_TDA1998X
+	ret = armada_drm_connector_slave_create(dev, &tda19988_config);
+	if (ret)
+		goto err_kms;
+#endif
+
 	ret = drm_vblank_init(dev, n);
 	if (ret)
 		goto err_kms;
-- 
1.7.4.4

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Sun, 6 Oct 2013 23:07:29 +0100
Subject: [PATCH 0/5] Armada DRM stuff
Message-ID: <20131006220728.GG12758@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

The Armada DRM drivers again, along with the TDA998x HDMI output support,
and an illustration to show how to add Armada 610 support (and others.)

Rob has looked at this a couple of times since its last posting, and
has provided additional useful feedback which has been incorporated.
I believe all the major issues have been addressed now.

 drivers/gpu/drm/Kconfig                 |    2 +
 drivers/gpu/drm/Makefile                |    1 +
 drivers/gpu/drm/armada/Kconfig          |   24 +
 drivers/gpu/drm/armada/Makefile         |    8 +
 drivers/gpu/drm/armada/armada_510.c     |   87 +++
 drivers/gpu/drm/armada/armada_610.c     |   49 ++
 drivers/gpu/drm/armada/armada_crtc.c    | 1099 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_crtc.h    |   83 +++
 drivers/gpu/drm/armada/armada_debugfs.c |  183 +++++
 drivers/gpu/drm/armada/armada_drm.h     |  114 ++++
 drivers/gpu/drm/armada/armada_drv.c     |  428 ++++++++++++
 drivers/gpu/drm/armada/armada_fb.c      |  170 +++++
 drivers/gpu/drm/armada/armada_fb.h      |   24 +
 drivers/gpu/drm/armada/armada_fbdev.c   |  202 ++++++
 drivers/gpu/drm/armada/armada_gem.c     |  616 +++++++++++++++++
 drivers/gpu/drm/armada/armada_gem.h     |   52 ++
 drivers/gpu/drm/armada/armada_hw.h      |  326 +++++++++
 drivers/gpu/drm/armada/armada_ioctlP.h  |   18 +
 drivers/gpu/drm/armada/armada_output.c  |  158 +++++
 drivers/gpu/drm/armada/armada_output.h  |   39 ++
 drivers/gpu/drm/armada/armada_overlay.c |  477 ++++++++++++++
 drivers/gpu/drm/armada/armada_slave.c   |  139 ++++
 drivers/gpu/drm/armada/armada_slave.h   |   26 +
 drivers/gpu/drm/i2c/tda998x_drv.c       |    2 +
 include/drm/drm_crtc.h                  |   17 +
 include/uapi/drm/armada_drm.h           |   45 ++
 26 files changed, 4389 insertions(+), 0 deletions(-)

From mboxrd@z Thu Jan  1 00:00:00 1970
From: rmk+kernel@arm.linux.org.uk (Russell King)
Date: Sun, 06 Oct 2013 23:07:55 +0100
Subject: [PATCH 1/5] drm/i2c: tda998x: set VIF for full range, underscanned
 display
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Message-ID: <E1VSwUV-0000hl-Rw@rmk-PC.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/i2c/tda998x_drv.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 60e8404..704040b5 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -549,6 +549,8 @@ tda998x_write_avi(struct drm_encoder *encoder, struct drm_display_mode *mode)
 	buf[HB(0)] = 0x82;
 	buf[HB(1)] = 0x02;
 	buf[HB(2)] = 13;
+	buf[PB(1)] = 2; /* underscanned display */
+	buf[PB(3)] = 2 << 2; /* full range */
 	buf[PB(4)] = drm_match_cea_mode(mode);
 
 	tda998x_write_if(encoder, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf,
-- 
1.7.4.4

From mboxrd@z Thu Jan  1 00:00:00 1970
From: rmk+kernel@arm.linux.org.uk (Russell King)
Date: Sun, 06 Oct 2013 23:10:56 +0100
Subject: [PATCH 4/5] DRM: Armada: start of MMP2/MMP3 support
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Message-ID: <E1VSwXQ-0000iL-8N@rmk-PC.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/armada/Makefile      |    1 +
 drivers/gpu/drm/armada/armada_610.c  |   49 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_crtc.c |    1 +
 drivers/gpu/drm/armada/armada_drm.h  |    1 +
 drivers/gpu/drm/armada/armada_drv.c  |    6 ++++
 drivers/gpu/drm/armada/armada_hw.h   |    8 +++++
 6 files changed, 66 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/armada/armada_610.c

diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile
index d6f43e0..088db4a 100644
--- a/drivers/gpu/drm/armada/Makefile
+++ b/drivers/gpu/drm/armada/Makefile
@@ -2,6 +2,7 @@ armada-y	:= armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
 		   armada_gem.o armada_output.o armada_overlay.o \
 		   armada_slave.o
 armada-y	+= armada_510.o
+armada-y	+= armada_610.o
 armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
 
 obj-$(CONFIG_DRM_ARMADA) := armada.o
diff --git a/drivers/gpu/drm/armada/armada_610.c b/drivers/gpu/drm/armada/armada_610.c
new file mode 100644
index 0000000..36a10e3
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_610.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Armada 610/MMP2/MMP3 variant support
+ */
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_hw.h"
+
+static int mmp23_init(struct armada_private *priv, struct device *dev)
+{
+	priv->extclk[0] = devm_clk_get(dev, NULL);
+
+	if (IS_ERR(priv->extclk[0]) && PTR_ERR(priv->extclk[0]) == -ENOENT)
+		priv->extclk[0] = ERR_PTR(-EPROBE_DEFER);
+
+	return PTR_RET(priv->extclk[0]);
+}
+
+/*
+ * This gets called with sclk = NULL to test whether the mode is
+ * supportable, and again with sclk != NULL to set the clocks up for
+ * that.  The former can return an error, but the latter is expected
+ * not to.
+ */
+static int mmp23_crtc_compute_clock(struct armada_crtc *dcrtc,
+	const struct drm_display_mode *mode, uint32_t *sclk)
+{
+	/*
+	 * on MMP3 bits 31:29 select the clock, OLPC wants 0x1 here, LCD clock 1
+	 * on MMP2 bits 31:30 select the clock, OLPC wants 0x1 here, LCD clock 1
+	 */
+	*sclk = 0x20001100; // FIXME hardcoded mmp3 value
+
+	return 0;
+}
+
+const struct armada_variant mmp23_ops = {
+	.init = mmp23_init,
+	.crtc_compute_clock = mmp23_crtc_compute_clock,
+};
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index e8605bf..b5877ee 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1054,6 +1054,7 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
 	dcrtc->clk = ERR_PTR(-EINVAL);
 	dcrtc->csc_yuv_mode = CSC_AUTO;
 	dcrtc->csc_rgb_mode = CSC_AUTO;
+	/* FIXME: MMP2/MMP3: OLPC panel is RGB666 */
 	dcrtc->cfg_dumb_ctrl = DUMB24_RGB888_0;
 	dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
 	spin_lock_init(&dcrtc->irq_lock);
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index eef09ec..f52fccb 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -70,6 +70,7 @@ struct armada_variant {
 
 /* Variant ops */
 extern const struct armada_variant armada510_ops;
+extern const struct armada_variant mmp23_ops;
 
 struct armada_private {
 	const struct armada_variant *variant;
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 7bfab9a..db62f1b 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -344,6 +344,12 @@ static const struct platform_device_id armada_drm_platform_ids[] = {
 		.name		= "armada-drm",
 		.driver_data	= (unsigned long)&armada510_ops,
 	}, {
+		.name		= "armada-610-drm", /* aka MMP2 */
+		.driver_data	= (unsigned long)&mmp23_ops,
+	}, {
+		.name		= "mmp3-drm",
+		.driver_data	= (unsigned long)&mmp23_ops,
+	}, {
 		.name		= "armada-510-drm",
 		.driver_data	= (unsigned long)&armada510_ops,
 	},
diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
index 27319a8..1688716 100644
--- a/drivers/gpu/drm/armada/armada_hw.h
+++ b/drivers/gpu/drm/armada/armada_hw.h
@@ -74,6 +74,7 @@ enum {
 	LCD_SPU_IOPAD_CONTROL		= 0x01bc,
 	LCD_SPU_IRQ_ENA			= 0x01c0,
 	LCD_SPU_IRQ_ISR			= 0x01c4,
+	LCD_MISC_CNTL			= 0x01c8,	/* Armada 168 */
 };
 
 /* For LCD_SPU_ADV_REG */
@@ -211,6 +212,13 @@ enum {
 	SCLK_16X_PLL		= 0x8 << 28,
 	SCLK_16X_FRAC_DIV_MASK	= 0xfff << 16,
 	SCLK_16X_INT_DIV_MASK	= 0xffff << 0,
+
+	/* PXA910 / MMP2 (Armada 610) / MMP3 / PXA988 */
+	SCLK_MMP_SRC_SEL	= 1 << 31,
+	SCLK_MMP_DISABLE	= 1 << 28,
+	SCLK_MMP_FRAC_DIV_MASK	= 0xfff << 16,
+	SCLK_MMP_DSI_DIV_MASK	= 0xf << 8,
+	SCLK_MMP_INT_DIV_MASK	= 0xff << 0,
 };
 
 /* For LCD_SPU_DUMB_CTRL */
-- 
1.7.4.4

From mboxrd@z Thu Jan  1 00:00:00 1970
From: rmk+kernel@arm.linux.org.uk (Russell King)
Date: Sun, 06 Oct 2013 23:09:56 +0100
Subject: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Message-ID: <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

This patch adds ARGB hardware cursor support to the DRM driver for the
Marvell Armada SoCs.  ARGB cursors are supported at either 32x64 or
64x32 resolutions.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/armada/armada_510.c  |    1 +
 drivers/gpu/drm/armada/armada_crtc.c |  245 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/armada/armada_crtc.h |    9 ++
 drivers/gpu/drm/armada/armada_drm.h  |    1 +
 drivers/gpu/drm/armada/armada_hw.h   |    6 +-
 5 files changed, 256 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_510.c b/drivers/gpu/drm/armada/armada_510.c
index a016888..59948ef 100644
--- a/drivers/gpu/drm/armada/armada_510.c
+++ b/drivers/gpu/drm/armada/armada_510.c
@@ -80,6 +80,7 @@ static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
 
 const struct armada_variant armada510_ops = {
 	.has_spu_adv_reg = true,
+	.spu_adv_reg = ADV_HWC32ENABLE | ADV_HWC32ARGB | ADV_HWC32BLEND,
 	.init = armada510_init,
 	.crtc_init = armada510_crtc_init,
 	.crtc_compute_clock = armada510_crtc_compute_clock,
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 7b379fd..e8605bf 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -381,8 +381,21 @@ void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
 		val = readl_relaxed(base + LCD_SPU_ADV_REG);
 		val &= ~(ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF | ADV_VSYNCOFFEN);
 		val |= dcrtc->v[i].spu_adv_reg;
-		writel_relaxed(val, dcrtc->base + LCD_SPU_ADV_REG);
+		writel_relaxed(val, base + LCD_SPU_ADV_REG);
 	}
+
+	if (stat & DUMB_FRAMEDONE && dcrtc->cursor_update) {
+		writel_relaxed(dcrtc->cursor_hw_pos,
+			       base + LCD_SPU_HWC_OVSA_HPXL_VLN);
+		writel_relaxed(dcrtc->cursor_hw_sz,
+			       base + LCD_SPU_HWC_HPXL_VLN);
+		armada_updatel(CFG_HWC_ENA,
+			       CFG_HWC_ENA | CFG_HWC_1BITMOD | CFG_HWC_1BITENA,
+			       base + LCD_SPU_DMA_CTRL0);
+		dcrtc->cursor_update = false;
+		armada_drm_crtc_disable_irq(dcrtc, DUMB_FRAMEDONE_ENA);
+	}
+
 	spin_unlock(&dcrtc->irq_lock);
 
 	if (stat & GRA_FRAME_IRQ) {
@@ -522,7 +535,8 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
 				    adj->crtc_htotal;
 	dcrtc->v[1].spu_v_porch = tm << 16 | bm;
 	val = adj->crtc_hsync_start;
-	dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN;
+	dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
+		priv->variant->spu_adv_reg;
 
 	if (interlaced) {
 		/* Odd interlaced frame */
@@ -530,7 +544,8 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
 						(1 << 16);
 		dcrtc->v[0].spu_v_porch = dcrtc->v[1].spu_v_porch + 1;
 		val = adj->crtc_hsync_start - adj->crtc_htotal / 2;
-		dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN;
+		dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
+			priv->variant->spu_adv_reg;
 	} else {
 		dcrtc->v[0] = dcrtc->v[1];
 	}
@@ -545,10 +560,11 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
 	armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total,
 			   LCD_SPUT_V_H_TOTAL);
 
-	if (priv->variant->has_spu_adv_reg)
+	if (priv->variant->has_spu_adv_reg) {
 		armada_reg_queue_mod(regs, i, dcrtc->v[0].spu_adv_reg,
 				     ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF |
 				     ADV_VSYNCOFFEN, LCD_SPU_ADV_REG);
+	}
 
 	val = CFG_GRA_ENA | CFG_GRA_HSMOOTH;
 	val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.fb)->fmt);
@@ -640,11 +656,230 @@ static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = {
 	.disable	= armada_drm_crtc_disable,
 };
 
+static void armada_load_cursor_argb(void __iomem *base, uint32_t *pix,
+	unsigned stride, unsigned width, unsigned height)
+{
+	uint32_t addr;
+	unsigned y;
+
+	addr = SRAM_HWC32_RAM1;
+	for (y = 0; y < height; y++) {
+		uint32_t *p = &pix[y * stride];
+		unsigned x;
+
+		for (x = 0; x < width; x++, p++) {
+			uint32_t val = *p;
+
+			val = (val & 0xff00ff00) |
+			      (val & 0x000000ff) << 16 |
+			      (val & 0x00ff0000) >> 16;
+
+			writel_relaxed(val,
+				       base + LCD_SPU_SRAM_WRDAT);
+			writel_relaxed(addr | SRAM_WRITE,
+				       base + LCD_SPU_SRAM_CTRL);
+			addr += 1;
+			if ((addr & 0x00ff) == 0)
+				addr += 0xf00;
+			if ((addr & 0x30ff) == 0)
+				addr = SRAM_HWC32_RAM2;
+		}
+	}
+}
+
+static void armada_drm_crtc_cursor_tran(void __iomem *base)
+{
+	unsigned addr;
+
+	for (addr = 0; addr < 256; addr++) {
+		/* write the default value */
+		writel_relaxed(0x55555555, base + LCD_SPU_SRAM_WRDAT);
+		writel_relaxed(addr | SRAM_WRITE | SRAM_HWC32_TRAN,
+			       base + LCD_SPU_SRAM_CTRL);
+	}
+}
+
+static int armada_drm_crtc_cursor_update(struct armada_crtc *dcrtc, bool reload)
+{
+	uint32_t xoff, xscr, w = dcrtc->cursor_w, s;
+	uint32_t yoff, yscr, h = dcrtc->cursor_h;
+	uint32_t para1;
+
+	/*
+	 * Calculate the visible width and height of the cursor,
+	 * screen position, and the position in the cursor bitmap.
+	 */
+	if (dcrtc->cursor_x < 0) {
+		xoff = -dcrtc->cursor_x;
+		xscr = 0;
+		w -= min(xoff, w);
+	} else if (dcrtc->cursor_x + w > dcrtc->crtc.mode.hdisplay) {
+		xoff = 0;
+		xscr = dcrtc->cursor_x;
+		w = max_t(int, dcrtc->crtc.mode.hdisplay - dcrtc->cursor_x, 0);
+	} else {
+		xoff = 0;
+		xscr = dcrtc->cursor_x;
+	}
+
+	if (dcrtc->cursor_y < 0) {
+		yoff = -dcrtc->cursor_y;
+		yscr = 0;
+		h -= min(yoff, h);
+	} else if (dcrtc->cursor_y + h > dcrtc->crtc.mode.vdisplay) {
+		yoff = 0;
+		yscr = dcrtc->cursor_y;
+		h = max_t(int, dcrtc->crtc.mode.vdisplay - dcrtc->cursor_y, 0);
+	} else {
+		yoff = 0;
+		yscr = dcrtc->cursor_y;
+	}
+
+	/* On interlaced modes, the vertical cursor size must be halved */
+	s = dcrtc->cursor_w;
+	if (dcrtc->interlaced) {
+		s *= 2;
+		yscr /= 2;
+		h /= 2;
+	}
+
+	if (!dcrtc->cursor_obj || !h || !w) {
+		spin_lock_irq(&dcrtc->irq_lock);
+		armada_drm_crtc_disable_irq(dcrtc, DUMB_FRAMEDONE_ENA);
+		dcrtc->cursor_update = false;
+		armada_updatel(0, CFG_HWC_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0);
+		spin_unlock_irq(&dcrtc->irq_lock);
+		return 0;
+	}
+
+	para1 = readl_relaxed(dcrtc->base + LCD_SPU_SRAM_PARA1);
+	armada_updatel(CFG_CSB_256x32, CFG_CSB_256x32 | CFG_PDWN256x32,
+		       dcrtc->base + LCD_SPU_SRAM_PARA1);
+
+	/*
+	 * Initialize the transparency if the SRAM was powered down.
+	 * We must also reload the cursor data as well.
+	 */
+	if (!(para1 & CFG_CSB_256x32)) {
+		armada_drm_crtc_cursor_tran(dcrtc->base);
+		reload = true;
+	}
+
+	if (dcrtc->cursor_hw_sz != (h << 16 | w)) {
+		spin_lock_irq(&dcrtc->irq_lock);
+		armada_drm_crtc_disable_irq(dcrtc, DUMB_FRAMEDONE_ENA);
+		dcrtc->cursor_update = false;
+		armada_updatel(0, CFG_HWC_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0);
+		spin_unlock_irq(&dcrtc->irq_lock);
+		reload = true;
+	}
+	if (reload) {
+		struct armada_gem_object *obj = dcrtc->cursor_obj;
+		uint32_t *pix;
+		/* Set the top-left corner of the cursor image */
+		pix = obj->addr;
+		pix += yoff * s + xoff;
+		armada_load_cursor_argb(dcrtc->base, pix, s, w, h);
+	}
+
+	/* Reload the cursor position, size and enable in the IRQ handler */
+	spin_lock_irq(&dcrtc->irq_lock);
+	dcrtc->cursor_hw_pos = yscr << 16 | xscr;
+	dcrtc->cursor_hw_sz = h << 16 | w;
+	dcrtc->cursor_update = true;
+	armada_drm_crtc_enable_irq(dcrtc, DUMB_FRAMEDONE_ENA);
+	spin_unlock_irq(&dcrtc->irq_lock);
+
+	return 0;
+}
+
+static void cursor_update(void *data)
+{
+	armada_drm_crtc_cursor_update(data, true);
+}
+
+static int armada_drm_crtc_cursor_set(struct drm_crtc *crtc,
+	struct drm_file *file, uint32_t handle, uint32_t w, uint32_t h)
+{
+	struct drm_device *dev = crtc->dev;
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_private *priv = crtc->dev->dev_private;
+	struct armada_gem_object *obj = NULL;
+	int ret;
+
+	/* If no cursor support, replicate drm's return value */
+	if (!priv->variant->has_spu_adv_reg)
+		return -ENXIO;
+
+	if (handle && w > 0 && h > 0) {
+		/* maximum size is 64x32 or 32x64 */
+		if (w > 64 || h > 64 || (w > 32 && h > 32))
+			return -ENOMEM;
+
+		obj = armada_gem_object_lookup(dev, file, handle);
+		if (!obj)
+			return -ENOENT;
+
+		/* Must be a kernel-mapped object */
+		if (!obj->addr) {
+			drm_gem_object_unreference_unlocked(&obj->obj);
+			return -EINVAL;
+		}
+
+		if (obj->obj.size < w * h * 4) {
+			DRM_ERROR("buffer is too small\n");
+			drm_gem_object_unreference_unlocked(&obj->obj);
+			return -ENOMEM;
+		}
+	}
+
+	mutex_lock(&dev->struct_mutex);
+	if (dcrtc->cursor_obj) {
+		dcrtc->cursor_obj->update = NULL;
+		dcrtc->cursor_obj->update_data = NULL;
+		drm_gem_object_unreference(&dcrtc->cursor_obj->obj);
+	}
+	dcrtc->cursor_obj = obj;
+	dcrtc->cursor_w = w;
+	dcrtc->cursor_h = h;
+	ret = armada_drm_crtc_cursor_update(dcrtc, true);
+	if (obj) {
+		obj->update_data = dcrtc;
+		obj->update = cursor_update;
+	}
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+static int armada_drm_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct drm_device *dev = crtc->dev;
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_private *priv = crtc->dev->dev_private;
+	int ret;
+
+	/* If no cursor support, replicate drm's return value */
+	if (!priv->variant->has_spu_adv_reg)
+		return -EFAULT;
+
+	mutex_lock(&dev->struct_mutex);
+	dcrtc->cursor_x = x;
+	dcrtc->cursor_y = y;
+	ret = armada_drm_crtc_cursor_update(dcrtc, false);
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
 static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
 {
 	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
 	struct armada_private *priv = crtc->dev->dev_private;
 
+	if (dcrtc->cursor_obj)
+		drm_gem_object_unreference(&dcrtc->cursor_obj->obj);
+
 	priv->dcrtc[dcrtc->num] = NULL;
 	drm_crtc_cleanup(&dcrtc->crtc);
 
@@ -750,6 +985,8 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc,
 }
 
 static struct drm_crtc_funcs armada_crtc_funcs = {
+	.cursor_set	= armada_drm_crtc_cursor_set,
+	.cursor_move	= armada_drm_crtc_cursor_move,
 	.destroy	= armada_drm_crtc_destroy,
 	.set_config	= drm_crtc_helper_set_config,
 	.page_flip	= armada_drm_crtc_page_flip,
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
index 972da53..9c10a07 100644
--- a/drivers/gpu/drm/armada/armada_crtc.h
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -44,11 +44,20 @@ struct armada_crtc {
 		uint32_t	spu_adv_reg;
 	} v[2];
 	bool			interlaced;
+	bool			cursor_update;
 	uint8_t			csc_yuv_mode;
 	uint8_t			csc_rgb_mode;
 
 	struct drm_plane	*plane;
 
+	struct armada_gem_object	*cursor_obj;
+	int			cursor_x;
+	int			cursor_y;
+	uint32_t		cursor_hw_pos;
+	uint32_t		cursor_hw_sz;
+	uint32_t		cursor_w;
+	uint32_t		cursor_h;
+
 	int			dpms;
 	uint32_t		cfg_dumb_ctrl;
 	uint32_t		dumb_ctrl;
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index e8c4f80..eef09ec 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -60,6 +60,7 @@ struct armada_private;
 
 struct armada_variant {
 	bool	has_spu_adv_reg;
+	uint32_t spu_adv_reg;
 	int (*init)(struct armada_private *, struct device *);
 	int (*crtc_init)(struct armada_crtc *);
 	int (*crtc_compute_clock)(struct armada_crtc *,
diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
index 216a4b5..27319a8 100644
--- a/drivers/gpu/drm/armada/armada_hw.h
+++ b/drivers/gpu/drm/armada/armada_hw.h
@@ -168,8 +168,10 @@ enum {
 	SRAM_READ	= 0 << 14,
 	SRAM_WRITE	= 2 << 14,
 	SRAM_INIT	= 3 << 14,
-	SRAM_HWC32_RAMR	= 0xc << 8,
-	SRAM_HWC32_RAMG	= 0xd << 8,
+	SRAM_HWC32_RAM1	= 0xc << 8,
+	SRAM_HWC32_RAM2	= 0xd << 8,
+	SRAM_HWC32_RAMR	= SRAM_HWC32_RAM1,
+	SRAM_HWC32_RAMG	= SRAM_HWC32_RAM2,
 	SRAM_HWC32_RAMB	= 0xe << 8,
 	SRAM_HWC32_TRAN	= 0xf << 8,
 	SRAM_HWC	= 0xf << 8,
-- 
1.7.4.4

From mboxrd@z Thu Jan  1 00:00:00 1970
From: moinejf@free.fr (Jean-Francois Moine)
Date: Mon, 7 Oct 2013 10:59:44 +0200
Subject: [PATCH 1/5] drm/i2c: tda998x: set VIF for full range,
 underscanned display
In-Reply-To: <E1VSwUV-0000hl-Rw@rmk-PC.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwUV-0000hl-Rw@rmk-PC.arm.linux.org.uk>
Message-ID: <20131007105944.6746352b@armhf>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Sun, 06 Oct 2013 23:07:55 +0100
Russell King <rmk+kernel@arm.linux.org.uk> wrote:

> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  drivers/gpu/drm/i2c/tda998x_drv.c |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
> index 60e8404..704040b5 100644
> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
> @@ -549,6 +549,8 @@ tda998x_write_avi(struct drm_encoder *encoder, struct drm_display_mode *mode)
>  	buf[HB(0)] = 0x82;
>  	buf[HB(1)] = 0x02;
>  	buf[HB(2)] = 13;
> +	buf[PB(1)] = 2; /* underscanned display */
> +	buf[PB(3)] = 2 << 2; /* full range */
>  	buf[PB(4)] = drm_match_cea_mode(mode);
>  
>  	tda998x_write_if(encoder, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf,

You should use the 'hdmi.h' constants which are meaningful enough:

	buf[PB(1)] = HDMI_SCAN_MODE_UNDERSCAN;
	buf[PB(3)] = HDMI_QUANTIZATION_RANGE_FULL << 2;

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: moinejf@free.fr (Jean-Francois Moine)
Date: Mon, 7 Oct 2013 11:01:41 +0200
Subject: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
In-Reply-To: <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
Message-ID: <20131007110141.27f1ac25@armhf>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Sun, 06 Oct 2013 23:09:56 +0100
Russell King <rmk+kernel@arm.linux.org.uk> wrote:

> This patch adds ARGB hardware cursor support to the DRM driver for the
> Marvell Armada SoCs.  ARGB cursors are supported at either 32x64 or
> 64x32 resolutions.
	[snip]

I don't see the interest of such cursors. Actually, most often, the
cursors are 64x64 and 'A' is either 0 or 0xff. As the Armada 510
supports 64x64 cursors with transparency, it would be more useful to
implement these ones...

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: moinejf@free.fr (Jean-Francois Moine)
Date: Mon, 7 Oct 2013 11:18:07 +0200
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
Message-ID: <20131007111807.5e86ea6e@armhf>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Sun, 06 Oct 2013 23:11:56 +0100
Russell King <rmk+kernel@arm.linux.org.uk> wrote:

> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  drivers/gpu/drm/armada/Kconfig      |    9 +++++++
>  drivers/gpu/drm/armada/armada_drv.c |   42 +++++++++++++++++++++++++++++++++++
>  2 files changed, 51 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
> index c7a0a94..87e62dd 100644
> --- a/drivers/gpu/drm/armada/Kconfig
> +++ b/drivers/gpu/drm/armada/Kconfig
> @@ -13,3 +13,12 @@ config DRM_ARMADA
>  	  This driver provides no built-in acceleration; acceleration is
>  	  performed by other IP found on the SoC.  This driver provides
>  	  kernel mode setting and buffer management to userspace.
> +
> +config DRM_ARMADA_TDA1998X
> +	bool "Support TDA1998X HDMI output"
> +	depends on DRM_ARMADA != n
> +	depends on I2C && DRM_I2C_NXP_TDA998X = y
> +	default y
> +	help
> +	  Support the TDA1998x HDMI output device found on the Solid-Run
> +	  CuBox.

It seems we are going backwards: as the Armada based boards will soon
move to full DT (mvebu), you are making an exception for the Cubox, so
that there should be Cubox specific kernels. I don't like that...

> diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
> index db62f1b..69517cf 100644
> --- a/drivers/gpu/drm/armada/armada_drv.c
> +++ b/drivers/gpu/drm/armada/armada_drv.c
> @@ -16,6 +16,42 @@
>  #include <drm/armada_drm.h>
>  #include "armada_ioctlP.h"
>  
> +#ifdef CONFIG_DRM_ARMADA_TDA1998X
> +#include <drm/i2c/tda998x.h>
> +#include "armada_slave.h"
> +
> +static struct tda998x_encoder_params params = {
> +	/* With 0x24, there is no translation between vp_out and int_vp
> +	FB	LCD out	Pins	VIP	Int Vp
> +	R:23:16	R:7:0	VPC7:0	7:0	7:0[R]
> +	G:15:8	G:15:8	VPB7:0	23:16	23:16[G]
> +	B:7:0	B:23:16	VPA7:0	15:8	15:8[B]
> +	*/
> +	.swap_a = 2,
> +	.swap_b = 3,
> +	.swap_c = 4,
> +	.swap_d = 5,
> +	.swap_e = 0,
> +	.swap_f = 1,

I still don't agree. You don't need to invert R <-> B for the Cubox at
the tda998x level: this may be done setting as it should be the
CFG_GRA_SWAPRB flag of the lcd register LCD_SPU_DMA_CTRL0.

> +	.audio_cfg = BIT(2),
> +	.audio_frame[1] = 1,
> +	.audio_format = AFMT_SPDIF,
> +	.audio_sample_rate = 44100,

These values are rather mysterious!

Looking at the tda998x driver, I found that:
- audio_cfg can be 0x03 for i2s input and 0x04 for spdif input
- audio_frame[1] is the (channel count - 1)
- audio_format and audio_sample_rate are hardcoding the audio input to
  spdif and the sample rate to 44.1kHz

I don't think that these parameters are needed:

- the tda998x must be prepared to get either i2s or spdif as the audio
  input at any time. The choice of this input results from the audio
  subsystem constraints (codec) found at audio streaming start time.

- the channel count is always 2 for spdif. Do we need to accept four
  channels for i2s?

- audio on hdmi works fine for me at any input rate setting the tda998x
  sample rate to 96 kHz. Anyway, in the actual tda998x driver, this
  audio_sample_rate value is just used to set an approximate value of
  ACR. But this value is not used because an optimal value is computed
  by the hardware thanks to the flag AIP_CNTRL_0_ACR_MAN!

	[snip]

The remaining patch is Cubox specific.

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 7 Oct 2013 10:40:08 +0100
Subject: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
In-Reply-To: <20131007110141.27f1ac25@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk> <20131007110141.27f1ac25@armhf>
Message-ID: <20131007094008.GH12758@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, Oct 07, 2013 at 11:01:41AM +0200, Jean-Francois Moine wrote:
> On Sun, 06 Oct 2013 23:09:56 +0100
> Russell King <rmk+kernel@arm.linux.org.uk> wrote:
> 
> > This patch adds ARGB hardware cursor support to the DRM driver for the
> > Marvell Armada SoCs.  ARGB cursors are supported at either 32x64 or
> > 64x32 resolutions.
> 	[snip]
> 
> I don't see the interest of such cursors. Actually, most often, the
> cursors are 64x64 and 'A' is either 0 or 0xff. As the Armada 510
> supports 64x64 cursors with transparency, it would be more useful to
> implement these ones...

Sorry, you're completely wrong there.  Xorg uses an alphablended cursor.
This patch is a result of trialling each of the Armada's cursor options
and this is the only one which results in a reasonable looking cursor.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 7 Oct 2013 10:44:04 +0100
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131007111807.5e86ea6e@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk> <20131007111807.5e86ea6e@armhf>
Message-ID: <20131007094404.GI12758@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, Oct 07, 2013 at 11:18:07AM +0200, Jean-Francois Moine wrote:
> On Sun, 06 Oct 2013 23:11:56 +0100
> Russell King <rmk+kernel@arm.linux.org.uk> wrote:
> 
> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> > ---
> >  drivers/gpu/drm/armada/Kconfig      |    9 +++++++
> >  drivers/gpu/drm/armada/armada_drv.c |   42 +++++++++++++++++++++++++++++++++++
> >  2 files changed, 51 insertions(+), 0 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
> > index c7a0a94..87e62dd 100644
> > --- a/drivers/gpu/drm/armada/Kconfig
> > +++ b/drivers/gpu/drm/armada/Kconfig
> > @@ -13,3 +13,12 @@ config DRM_ARMADA
> >  	  This driver provides no built-in acceleration; acceleration is
> >  	  performed by other IP found on the SoC.  This driver provides
> >  	  kernel mode setting and buffer management to userspace.
> > +
> > +config DRM_ARMADA_TDA1998X
> > +	bool "Support TDA1998X HDMI output"
> > +	depends on DRM_ARMADA != n
> > +	depends on I2C && DRM_I2C_NXP_TDA998X = y
> > +	default y
> > +	help
> > +	  Support the TDA1998x HDMI output device found on the Solid-Run
> > +	  CuBox.
> 
> It seems we are going backwards: as the Armada based boards will soon
> move to full DT (mvebu), you are making an exception for the Cubox, so
> that there should be Cubox specific kernels. I don't like that...

*Ignored*.  You know why.

> > diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
> > index db62f1b..69517cf 100644
> > --- a/drivers/gpu/drm/armada/armada_drv.c
> > +++ b/drivers/gpu/drm/armada/armada_drv.c
> > @@ -16,6 +16,42 @@
> >  #include <drm/armada_drm.h>
> >  #include "armada_ioctlP.h"
> >  
> > +#ifdef CONFIG_DRM_ARMADA_TDA1998X
> > +#include <drm/i2c/tda998x.h>
> > +#include "armada_slave.h"
> > +
> > +static struct tda998x_encoder_params params = {
> > +	/* With 0x24, there is no translation between vp_out and int_vp
> > +	FB	LCD out	Pins	VIP	Int Vp
> > +	R:23:16	R:7:0	VPC7:0	7:0	7:0[R]
> > +	G:15:8	G:15:8	VPB7:0	23:16	23:16[G]
> > +	B:7:0	B:23:16	VPA7:0	15:8	15:8[B]
> > +	*/
> > +	.swap_a = 2,
> > +	.swap_b = 3,
> > +	.swap_c = 4,
> > +	.swap_d = 5,
> > +	.swap_e = 0,
> > +	.swap_f = 1,
> 
> I still don't agree. You don't need to invert R <-> B for the Cubox at
> the tda998x level: this may be done setting as it should be the
> CFG_GRA_SWAPRB flag of the lcd register LCD_SPU_DMA_CTRL0.

You are totally and utterly wrong there.  We need R and B presented on
their correct lanes to the TDA998x so that the Armadas YUV->RGB
conversion works.  Setting CFG_GRA_SWAPRB does not swap the YUV output
to match, neither does setting any of the other bits.

CFG_GRA_SWAPRB is all about the _graphics_ _framebuffer_ format, it's got
nothing to do at all with how the output is wired.

> > +	.audio_cfg = BIT(2),
> > +	.audio_frame[1] = 1,
> > +	.audio_format = AFMT_SPDIF,
> > +	.audio_sample_rate = 44100,
> 
> These values are rather mysterious!

Also I'm going to ignore this comment, because quite honestly, I think
this is worthless.  You haven't investigated how the TDA998x actually
gets setup by Rabeeh.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: moinejf@free.fr (Jean-Francois Moine)
Date: Mon, 7 Oct 2013 12:09:22 +0200
Subject: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
In-Reply-To: <20131007094008.GH12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
 <20131007110141.27f1ac25@armhf>
 <20131007094008.GH12758@n2100.arm.linux.org.uk>
Message-ID: <20131007120922.47df03b6@armhf>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, 7 Oct 2013 10:40:08 +0100
Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:

> > > This patch adds ARGB hardware cursor support to the DRM driver for the
> > > Marvell Armada SoCs.  ARGB cursors are supported at either 32x64 or
> > > 64x32 resolutions.  
> > 	[snip]
> > 
> > I don't see the interest of such cursors. Actually, most often, the
> > cursors are 64x64 and 'A' is either 0 or 0xff. As the Armada 510
> > supports 64x64 cursors with transparency, it would be more useful to
> > implement these ones...  
> 
> Sorry, you're completely wrong there.  Xorg uses an alphablended cursor.
> This patch is a result of trialling each of the Armada's cursor options
> and this is the only one which results in a reasonable looking cursor.

Strange. I am using the 64x64 cursor with transparency of the 510 for
many months and I never saw any problem.

If you absolutely want to have all transparency shades, you should
accept 64x64 cursors and test if they may be rendered as 64x32 or 32x64,
i.e. test that there is only pure transparency in the non-rendered
rectangles...

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 7 Oct 2013 11:32:50 +0100
Subject: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
In-Reply-To: <20131007120922.47df03b6@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk> <20131007110141.27f1ac25@armhf>
 <20131007094008.GH12758@n2100.arm.linux.org.uk>
 <20131007120922.47df03b6@armhf>
Message-ID: <20131007103250.GJ12758@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, Oct 07, 2013 at 12:09:22PM +0200, Jean-Francois Moine wrote:
> On Mon, 7 Oct 2013 10:40:08 +0100
> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
> 
> > > > This patch adds ARGB hardware cursor support to the DRM driver for the
> > > > Marvell Armada SoCs.  ARGB cursors are supported at either 32x64 or
> > > > 64x32 resolutions.  
> > > 	[snip]
> > > 
> > > I don't see the interest of such cursors. Actually, most often, the
> > > cursors are 64x64 and 'A' is either 0 or 0xff. As the Armada 510
> > > supports 64x64 cursors with transparency, it would be more useful to
> > > implement these ones...  
> > 
> > Sorry, you're completely wrong there.  Xorg uses an alphablended cursor.
> > This patch is a result of trialling each of the Armada's cursor options
> > and this is the only one which results in a reasonable looking cursor.
> 
> Strange. I am using the 64x64 cursor with transparency of the 510 for
> many months and I never saw any problem.

When I tried it, all cursors had variable alpha, and converting the
alpha to a single transparency bit made the cursor look rubbish against
certain backgrounds.

> If you absolutely want to have all transparency shades, you should
> accept 64x64 cursors and test if they may be rendered as 64x32 or
> 32x64, i.e. test that there is only pure transparency in the non-
> rendered rectangles...

That is policy, and that is something which can be done by the X server
rather than the kernel.  The kernel exposes the hardware capabilities,
which are to allow a 64x32 or a 32x64 cursor.  Userspace can make the
decision dynamically which it wishes to use.

However, what you're suggesting is dangerous.  What do you do when you're
presented with a cursor which is 64x64 ?  Do you:

(a) not display it
(b) crash the X server

There isn't a fallback to using software cursors available in the X server
because there's no error reporting for a failed hardware cursor update.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: moinejf@free.fr (Jean-Francois Moine)
Date: Mon, 7 Oct 2013 12:48:20 +0200
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131007094404.GI12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
Message-ID: <20131007124820.2189a4c3@armhf>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, 7 Oct 2013 10:44:04 +0100
Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:

> On Mon, Oct 07, 2013 at 11:18:07AM +0200, Jean-Francois Moine wrote:
	[snip]
> > It seems we are going backwards: as the Armada based boards will soon
> > move to full DT (mvebu), you are making an exception for the Cubox, so
> > that there should be Cubox specific kernels. I don't like that...
> 
> *Ignored*.  You know why.

Sorry. I don't see why. May you explain again?

> > > diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
	[snip]
> > > +static struct tda998x_encoder_params params = {
> > > +	/* With 0x24, there is no translation between vp_out and int_vp
> > > +	FB	LCD out	Pins	VIP	Int Vp
> > > +	R:23:16	R:7:0	VPC7:0	7:0	7:0[R]
> > > +	G:15:8	G:15:8	VPB7:0	23:16	23:16[G]
> > > +	B:7:0	B:23:16	VPA7:0	15:8	15:8[B]
> > > +	*/
> > > +	.swap_a = 2,
> > > +	.swap_b = 3,
> > > +	.swap_c = 4,
> > > +	.swap_d = 5,
> > > +	.swap_e = 0,
> > > +	.swap_f = 1,
> > 
> > I still don't agree. You don't need to invert R <-> B for the Cubox at
> > the tda998x level: this may be done setting as it should be the
> > CFG_GRA_SWAPRB flag of the lcd register LCD_SPU_DMA_CTRL0.
> 
> You are totally and utterly wrong there.  We need R and B presented on
> their correct lanes to the TDA998x so that the Armadas YUV->RGB
> conversion works.  Setting CFG_GRA_SWAPRB does not swap the YUV output
> to match, neither does setting any of the other bits.
> 
> CFG_GRA_SWAPRB is all about the _graphics_ _framebuffer_ format, it's got
> nothing to do at all with how the output is wired.

Then, may you explain why you must swap R/B on simple RGB output?

>>From your [PATCH 2/5] DRM: Armada: Add Armada DRM driver:

+	FMT(RGB888,	888PACK,	CFG_SWAPRB);
+	FMT(BGR888,	888PACK,	0);

+	FMT(YUYV,	422PACK,	CFG_YUV2RGB | CFG_SWAPYU | CFG_SWAPUV);

> > > +	.audio_cfg = BIT(2),
> > > +	.audio_frame[1] = 1,
> > > +	.audio_format = AFMT_SPDIF,
> > > +	.audio_sample_rate = 44100,
> > 
> > These values are rather mysterious!
> 
> Also I'm going to ignore this comment, because quite honestly, I think
> this is worthless.  You haven't investigated how the TDA998x actually
> gets setup by Rabeeh.

Rabeeh did the most he could to have a working Cubox. He used bad
written drivers and he had not the time to think about how the drivers
could be enhanced.

Here is a small story about i2s/spdif: once, I set the tda998x to use
the spdif input, and at this time, I was using the dummy codec.
This codec accepts the format 32_LE, as does the audio device, but the
output cannot go to spdif. Result: no hdmi sound.

Should we restrict the hdmi transmitter to spdif (thus 'no 32 bits
stream') or to i2s (thus 'no compressed stream') only, or accept both
i2s and spdif and allow a full range of supported audio streams?

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/
+

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 7 Oct 2013 12:09:02 +0100
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131007124820.2189a4c3@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk> <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
Message-ID: <20131007110902.GL12758@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, Oct 07, 2013 at 12:48:20PM +0200, Jean-Francois Moine wrote:
> On Mon, 7 Oct 2013 10:44:04 +0100
> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
> 
> > On Mon, Oct 07, 2013 at 11:18:07AM +0200, Jean-Francois Moine wrote:
> 	[snip]
> > > It seems we are going backwards: as the Armada based boards will soon
> > > move to full DT (mvebu), you are making an exception for the Cubox, so
> > > that there should be Cubox specific kernels. I don't like that...
> > 
> > *Ignored*.  You know why.
> 
> Sorry. I don't see why. May you explain again?

I don't run DT because DT lacks most of the features I require on the
cubox.  Therefore I can't develop for DT.  Simple.

> > > > diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
> 	[snip]
> > > > +static struct tda998x_encoder_params params = {
> > > > +	/* With 0x24, there is no translation between vp_out and int_vp
> > > > +	FB	LCD out	Pins	VIP	Int Vp
> > > > +	R:23:16	R:7:0	VPC7:0	7:0	7:0[R]
> > > > +	G:15:8	G:15:8	VPB7:0	23:16	23:16[G]
> > > > +	B:7:0	B:23:16	VPA7:0	15:8	15:8[B]
> > > > +	*/
> > > > +	.swap_a = 2,
> > > > +	.swap_b = 3,
> > > > +	.swap_c = 4,
> > > > +	.swap_d = 5,
> > > > +	.swap_e = 0,
> > > > +	.swap_f = 1,
> > > 
> > > I still don't agree. You don't need to invert R <-> B for the Cubox at
> > > the tda998x level: this may be done setting as it should be the
> > > CFG_GRA_SWAPRB flag of the lcd register LCD_SPU_DMA_CTRL0.
> > 
> > You are totally and utterly wrong there.  We need R and B presented on
> > their correct lanes to the TDA998x so that the Armadas YUV->RGB
> > conversion works.  Setting CFG_GRA_SWAPRB does not swap the YUV output
> > to match, neither does setting any of the other bits.
> > 
> > CFG_GRA_SWAPRB is all about the _graphics_ _framebuffer_ format, it's got
> > nothing to do at all with how the output is wired.
> 
> Then, may you explain why you must swap R/B on simple RGB output?
> 
> From your [PATCH 2/5] DRM: Armada: Add Armada DRM driver:
> 
> +	FMT(RGB888,	888PACK,	CFG_SWAPRB);
> +	FMT(BGR888,	888PACK,	0);

I think I explained above.  This is to do with the *graphics* *framebuffer*
*format* in *memory*.  This has nothing to do with how the hardware is
wired up.

With no swapping, the 888 format is defined by the documentation to be:

	[7:0] = red
	[15:8] = green
	[23:16] = blue

Now, if you look this up in the drm_fourcc.h header file, this corresponds
with this entry:

#define DRM_FORMAT_BGR888       fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */

Hence, this is the BGR888 format with no swapping.  Therefore, my second
line is correct.

With CFG_SWAPRB set, the format in hardware becomes:

	[7:0] = blue
	[15:8] = green
	[23:16] = red

Again, if you look this up in the drm_fourcc.h header, you get:

#define DRM_FORMAT_RGB888       fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */

So, the two entries you quote above are 100% correct.

> +	FMT(YUYV,	422PACK,	CFG_YUV2RGB | CFG_SWAPYU | CFG_SWAPUV);

Where is the RGB swap there?  Again, this is to do with swapping the
format to match the hardware.  Please read the documentation on the
framebuffer formats.

The native 422PACK format is:
	[7:0] = U
	[15:8] = Y0
	[23:16] = V
	[31:24] = Y1

and we need to set both CFG_SWAPYU and CFG_SWAPUV to get this to be:
	[7:0] = V
	[15:8] = Y1
	[23:16] = U
	[31:24] = Y0

which is what the YUYV format wants.

> Rabeeh did the most he could to have a working Cubox. He used bad
> written drivers and he had not the time to think about how the drivers
> could be enhanced.

What does I2S give us in terms of "enhancement" which SPDIF does not,
remembering that audio is transmitted over HDMI in a format which closely
resembles SPDIF (but with a 28-bit subframe size.)

> Here is a small story about i2s/spdif: once, I set the tda998x to use
> the spdif input, and at this time, I was using the dummy codec.
> This codec accepts the format 32_LE, as does the audio device, but the
> output cannot go to spdif. Result: no hdmi sound.

How ASoC works in this regard is that the capabilities are the _union_ of
the codec and the cpu DAIs.

The SPDIF transmitter codec supports 16, 20 and 24 bits per sample but not
32.  Quite simply, that's because the SPDIF format does not allow 32-bits
per sample.  Therefore, 32_LE is not available for use with audio output,
and userspace must convert down to something which the hardware does
support.

"Because I2S can support 32-bit audio" is a poor reason, because you can't
pass 32-bit audio via HDMI due to a subframe being limited to 28 bits - up
to 24 bits for the sample and 4 bits of control/status information.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: sebastian.hesselbarth@gmail.com (Sebastian Hesselbarth)
Date: Mon, 07 Oct 2013 13:29:30 +0200
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131007110902.GL12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk> <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
Message-ID: <52529B1A.7060306@gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On 10/07/2013 01:09 PM, Russell King - ARM Linux wrote:
> On Mon, Oct 07, 2013 at 12:48:20PM +0200, Jean-Francois Moine wrote:
>> On Mon, 7 Oct 2013 10:44:04 +0100
>> Rabeeh did the most he could to have a working Cubox. He used bad
>> written drivers and he had not the time to think about how the drivers
>> could be enhanced.
>
> What does I2S give us in terms of "enhancement" which SPDIF does not,
> remembering that audio is transmitted over HDMI in a format which closely
> resembles SPDIF (but with a 28-bit subframe size.)

With respect to what _most_ users want, we should use SPDIF and ignore
I2S. Consumer audio fits well into SPDIF and we get pass-through, which
we loose on I2S.

I2S _can_ support more than two channels, but only if you wire up more
DATA lines. Those are not available on Dove, so its I2S is limited to
two channel audio.

The CuBox is simply not designed for HBR or multi-channel PCM, it is a
_consumer_ settop box replacement.

Sebastian

From mboxrd@z Thu Jan  1 00:00:00 1970
From: moinejf@free.fr (Jean-Francois Moine)
Date: Mon, 7 Oct 2013 14:03:27 +0200
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131007110902.GL12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
Message-ID: <20131007140327.5bb4863b@armhf>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, 7 Oct 2013 12:09:02 +0100
Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:

> > Here is a small story about i2s/spdif: once, I set the tda998x to use
> > the spdif input, and at this time, I was using the dummy codec.
> > This codec accepts the format 32_LE, as does the audio device, but the
> > output cannot go to spdif. Result: no hdmi sound.  
> 
> How ASoC works in this regard is that the capabilities are the _union_ of
> the codec and the cpu DAIs.
> 
> The SPDIF transmitter codec supports 16, 20 and 24 bits per sample but not
> 32.  Quite simply, that's because the SPDIF format does not allow 32-bits
> per sample.  Therefore, 32_LE is not available for use with audio output,
> and userspace must convert down to something which the hardware does
> support.
> 
> "Because I2S can support 32-bit audio" is a poor reason, because you can't
> pass 32-bit audio via HDMI due to a subframe being limited to 28 bits - up
> to 24 bits for the sample and 4 bits of control/status information.

OK. So, to resume, if both i2s and spdif are furnished by the audio
subsystem, the tda998x must use spdif only (with the spdif codec).

Then, the declaration of the tda998x in the DT will include an
optional audio property, say 'audio-input' with the values "i2s" or
"spdif" which corresponds to your parameter 'audio_format'.

Also, from your video swap explanation, the DT will contain some video
property(ies) TBD.

The remaining question is: do we need more audio parameters?

- the audio_cfg value is defined by i2s/spdif (3 or 4)
- the audio_frame[1] value is always 1 (2 channels)
- audio_sample_rate is useless

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: siarhei.siamashka@gmail.com (Siarhei Siamashka)
Date: Mon, 7 Oct 2013 15:29:15 +0300
Subject: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
In-Reply-To: <20131007103250.GJ12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
 <20131007110141.27f1ac25@armhf>
 <20131007094008.GH12758@n2100.arm.linux.org.uk>
 <20131007120922.47df03b6@armhf>
 <20131007103250.GJ12758@n2100.arm.linux.org.uk>
Message-ID: <20131007152915.352cc4b2@i7>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, 7 Oct 2013 11:32:50 +0100
Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:

> On Mon, Oct 07, 2013 at 12:09:22PM +0200, Jean-Francois Moine wrote:
> > On Mon, 7 Oct 2013 10:40:08 +0100
> > Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
> > 
> > > > > This patch adds ARGB hardware cursor support to the DRM driver for the
> > > > > Marvell Armada SoCs.  ARGB cursors are supported at either 32x64 or
> > > > > 64x32 resolutions.  
> > > > 	[snip]
> > > > 
> > > > I don't see the interest of such cursors. Actually, most often, the
> > > > cursors are 64x64 and 'A' is either 0 or 0xff. As the Armada 510
> > > > supports 64x64 cursors with transparency, it would be more useful to
> > > > implement these ones...  
> > > 
> > > Sorry, you're completely wrong there.  Xorg uses an alphablended cursor.
> > > This patch is a result of trialling each of the Armada's cursor options
> > > and this is the only one which results in a reasonable looking cursor.
> > 
> > Strange. I am using the 64x64 cursor with transparency of the 510 for
> > many months and I never saw any problem.
> 
> When I tried it, all cursors had variable alpha, and converting the
> alpha to a single transparency bit made the cursor look rubbish against
> certain backgrounds.
> 
> > If you absolutely want to have all transparency shades, you should
> > accept 64x64 cursors and test if they may be rendered as 64x32 or
> > 32x64, i.e. test that there is only pure transparency in the non-
> > rendered rectangles...
> 
> That is policy, and that is something which can be done by the X server
> rather than the kernel.  The kernel exposes the hardware capabilities,
> which are to allow a 64x32 or a 32x64 cursor.  Userspace can make the
> decision dynamically which it wishes to use.
> 
> However, what you're suggesting is dangerous.  What do you do when you're
> presented with a cursor which is 64x64 ?  Do you:
> 
> (a) not display it
> (b) crash the X server
> 
> There isn't a fallback to using software cursors available in the X server
> because there's no error reporting for a failed hardware cursor update.

Hmm, maybe I'm missing something, but doesn't returning FALSE from
UseHWCursorARGB just make the X server fallback to using a software
cursor?

https://github.com/ssvb/xf86-video-fbturbo/blob/689c08256555/src/sunxi_disp_hwcursor.c#L72

I'm just doing this. And also have hooks to notify the DRI2 code about
the status of the cursor. In the case if the hardware cursor is not
enabled, hardware overlays can't be safely used with the software
cursor and we need to fallback to CPU/GPU copy instead of zero-copy
buffers swapping.

And I fully agree that it is the responsibility of the kernel to expose
as much of the hardware capabilities as possible (without compromising
reliability and/or security).

-- 
Best regards,
Siarhei Siamashka

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 7 Oct 2013 13:36:50 +0100
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131007140327.5bb4863b@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk> <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <20131007140327.5bb4863b@armhf>
Message-ID: <20131007123650.GN12758@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, Oct 07, 2013 at 02:03:27PM +0200, Jean-Francois Moine wrote:
> On Mon, 7 Oct 2013 12:09:02 +0100
> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
> 
> > > Here is a small story about i2s/spdif: once, I set the tda998x to use
> > > the spdif input, and at this time, I was using the dummy codec.
> > > This codec accepts the format 32_LE, as does the audio device, but the
> > > output cannot go to spdif. Result: no hdmi sound.  
> > 
> > How ASoC works in this regard is that the capabilities are the _union_ of
> > the codec and the cpu DAIs.
> > 
> > The SPDIF transmitter codec supports 16, 20 and 24 bits per sample but not
> > 32.  Quite simply, that's because the SPDIF format does not allow 32-bits
> > per sample.  Therefore, 32_LE is not available for use with audio output,
> > and userspace must convert down to something which the hardware does
> > support.
> > 
> > "Because I2S can support 32-bit audio" is a poor reason, because you can't
> > pass 32-bit audio via HDMI due to a subframe being limited to 28 bits - up
> > to 24 bits for the sample and 4 bits of control/status information.
> 
> OK. So, to resume, if both i2s and spdif are furnished by the audio
> subsystem, the tda998x must use spdif only (with the spdif codec).

This is going off-topic because the TDA998x bindings are a subject for
the TDA998x driver, not the Armada driver.  This data structure merely
exists to provide the required data for the TDA998x in absence of DT
information.

To do the job properly - which is what should be done _whenever_ DT
bindings are being considered - you have to look at the hardware with
an overview of its capabilities, never at the implementation.

So, the TDA998x family needs to be looked at in isolation, and its DT
bindings need to be considered on its own merit.

The TDA998x can accept a SPDIF signal on a single pin (on AP6), with or
without a clock (on AP5), or it can accept I2S: I2S clock in APCLK, I2S
word select on AP0, and up to four I2S streams on AP1..4 and auxillary
("internal test") data in AP7.  AP7 should therefore not be used.

The TDA19988 is slightly different, because it doesn't have soo many
AP pins.  Here, SPDIF can be supplied on either AP1 or AP2 with the
optional clock on AP3.  I2S is similar to the above but only AP1 and
AP2 accept streams.

I think the I2S is a special case - I'm not aware of anything which
outputs _four_ synchronised I2S data streams with a common word select.
Nevertheless, it's something that needs to be considered when creating
DT bindings.

So, we have some quite different capabilities depending on the device.
For I2S, we can get away with this:

	tda998x {
		compatible = "nxp,tda19988", "nxp,tda998x";
		i2s-source = <&i2s_source N>;
	};

where N is the number of coherent I2S streams supplied.  For the TDA998x,
N can be 1 to 4.  For TDA19988, N can be 1 or 2 but no more.

For SPDIF, the situation is more complex.  The TDA19988 could in theory
have two streams connected, and one of those streams can be selected.
So, maybe:

	tda998x {
		compatible = "nxp,tda998x";
		spdif-source = <&spdif_source>;
		spdif-has-mclk;
	};

and for the 19988:

	tda19988 {
		compatible = "nxp,tda19988";
		spdif0-source = <&spdif_source0>;
		spdif0-has-mclk;
		spdif1-source = <&spdif_source1>;
		spdif1-has-mclk;
	};

> Also, from your video swap explanation, the DT will contain some video
> property(ies) TBD.

The TDA998x needs some properties to define how it is connected to the
rest of the hardware - which pins are connected to what in terms of the
colour channel information.  As I hope I've made clear to you, this has
no bearing on the settings in the Dove for the SWAPRB bits.  This is
purely only to do with the TDA998x.

So, this also needs to be presented as properties for the TDA998x driver.

> The remaining question is: do we need more audio parameters?
> 
> - the audio_cfg value is defined by i2s/spdif (3 or 4)

This should be discovered from the DT binding information, because which
AP pins get used depends on the signals being supplied to it.

> - the audio_frame[1] value is always 1 (2 channels)
> - audio_sample_rate is useless

audio_sample_rate comes in if we wish to use a fixed sample rate and
have coherent video and audio clocks derived from a common source.  That
allows fixed CTS and N values to be used based on the audio sample rate
being supplied as the clocks have a fixed known relationship (and aren't
going to drift.)

However, you are right that this should not be specified in DT - it
should come from the audio subsystem.  However, that's something which
is a very very long way away from being possible (if ever) with Linux
since I don't see the DPCM issues ever getting resolved.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 7 Oct 2013 13:50:34 +0100
Subject: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
In-Reply-To: <20131007152915.352cc4b2@i7>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk> <20131007110141.27f1ac25@armhf>
 <20131007094008.GH12758@n2100.arm.linux.org.uk>
 <20131007120922.47df03b6@armhf>
 <20131007103250.GJ12758@n2100.arm.linux.org.uk> <20131007152915.352cc4b2@i7>
Message-ID: <20131007125034.GO12758@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, Oct 07, 2013 at 03:29:15PM +0300, Siarhei Siamashka wrote:
> On Mon, 7 Oct 2013 11:32:50 +0100
> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
> > However, what you're suggesting is dangerous.  What do you do when you're
> > presented with a cursor which is 64x64 ?  Do you:
> > 
> > (a) not display it
> > (b) crash the X server
> > 
> > There isn't a fallback to using software cursors available in the X server
> > because there's no error reporting for a failed hardware cursor update.
> 
> Hmm, maybe I'm missing something, but doesn't returning FALSE from
> UseHWCursorARGB just make the X server fallback to using a software
> cursor?
> 
> https://github.com/ssvb/xf86-video-fbturbo/blob/689c08256555/src/sunxi_disp_hwcursor.c#L72
> 
> I'm just doing this. And also have hooks to notify the DRI2 code about
> the status of the cursor. In the case if the hardware cursor is not
> enabled, hardware overlays can't be safely used with the software
> cursor and we need to fallback to CPU/GPU copy instead of zero-copy
> buffers swapping.
> 
> And I fully agree that it is the responsibility of the kernel to expose
> as much of the hardware capabilities as possible (without compromising
> reliability and/or security).

If you wish to go in below the level presented by
hw/xfree86/modes/xf86Cursors.c (as you are doing), then yes you can do
this, and it's something which maybe should be looked into.  You have a
good reason to do this (due to your hardware cursor being incompatible
with overlays).

We have no such restriction - the only issue here is the "odd" size of
cursors.  Practically, choosing one or other of 64x32 or 32x64 works
fine for the cases I've seen.  I haven't seen any cursors which are
64x64 yet.  I'm not saying they don't exist though!  I can imagine that
some accessibility options might want to display a large cursor.

Now, the way I handle this is that the kernel allows _either_ a
(1 to 32)x(1 to 64) or (1 to 64)x(1 to 32) cursor.  Both width and
height larger than 32 gets rejected with -EINVAL:

+               /* maximum size is 64x32 or 32x64 */
+               if (w > 64 || h > 64 || (w > 32 && h > 32))
+                       return -ENOMEM;

which is quite reasonable for this hardware.  However, there is no way
to export this from DRM - adding maximum cursor size properties wouldn't
really represent this.

The only question is whether DRM should export some capabilities to
indicate what's possible with the cursor, so that X knows about this
quirk of this hardware.  Overall, I suspect that it's just rare and
not worth the effort.  I think it's just easier to pick one of these
and stick with it, and if we happen to encounter a cursor larger than
our chosen dimentions, XFree86 will already automatically fall back
to s/w cursor.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: robdclark@gmail.com (Rob Clark)
Date: Mon, 7 Oct 2013 10:59:39 -0400
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131007110902.GL12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
Message-ID: <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, Oct 7, 2013 at 7:09 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Oct 07, 2013 at 12:48:20PM +0200, Jean-Francois Moine wrote:
>> On Mon, 7 Oct 2013 10:44:04 +0100
>> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
>>
>> > On Mon, Oct 07, 2013 at 11:18:07AM +0200, Jean-Francois Moine wrote:
>>       [snip]
>> > > It seems we are going backwards: as the Armada based boards will soon
>> > > move to full DT (mvebu), you are making an exception for the Cubox, so
>> > > that there should be Cubox specific kernels. I don't like that...
>> >
>> > *Ignored*.  You know why.
>>
>> Sorry. I don't see why. May you explain again?
>
> I don't run DT because DT lacks most of the features I require on the
> cubox.  Therefore I can't develop for DT.  Simple.

Jean-Fran?ois, just as an aside, I really don't think code that can be
shared, like tda998x, should encode a DT requirement.. there are
plenty of platforms that don't use DT (arm isn't everything, and last
I heard aarch64 was going to be ACPI).

Beyond that, it is a driver decision whether or not to support only-DT
or DT + other.. and as long as there is a common board which can use
the driver but which is not DT, there is probably a compelling reason
to still support the non-DT case.

BR,
-R

From mboxrd@z Thu Jan  1 00:00:00 1970
From: broonie@kernel.org (Mark Brown)
Date: Mon, 7 Oct 2013 16:53:26 +0100
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <52529B1A.7060306@gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <52529B1A.7060306@gmail.com>
Message-ID: <20131007155326.GP21581@sirena.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, Oct 07, 2013 at 01:29:30PM +0200, Sebastian Hesselbarth wrote:

> I2S _can_ support more than two channels, but only if you wire up more
> DATA lines. Those are not available on Dove, so its I2S is limited to
> two channel audio.

A lot of devices implement extra channels with TDM rather than with
extra wires - you get all the left channels and all the right channels
grouped together (like with DSP/PCM modes except the channels are
ordered differently).  I'm never sure that's actually useful, though,
since it's not something that just works with most hosts that don't
understand it in hardware and most of those can do DSP/PCM anyway.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131007/68e92cf3/attachment.sig>

From mboxrd@z Thu Jan  1 00:00:00 1970
From: sebastian.hesselbarth@gmail.com (Sebastian Hesselbarth)
Date: Mon, 07 Oct 2013 18:08:12 +0200
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131007155326.GP21581@sirena.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk> <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk> <52529B1A.7060306@gmail.com>
 <20131007155326.GP21581@sirena.org.uk>
Message-ID: <5252DC6C.9060503@gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On 10/07/2013 05:53 PM, Mark Brown wrote:
> On Mon, Oct 07, 2013 at 01:29:30PM +0200, Sebastian Hesselbarth wrote:
>
>> I2S _can_ support more than two channels, but only if you wire up more
>> DATA lines. Those are not available on Dove, so its I2S is limited to
>> two channel audio.
>
> A lot of devices implement extra channels with TDM rather than with
> extra wires - you get all the left channels and all the right channels
> grouped together (like with DSP/PCM modes except the channels are
> ordered differently).  I'm never sure that's actually useful, though,
> since it's not something that just works with most hosts that don't
> understand it in hardware and most of those can do DSP/PCM anyway.

True, I didn't mention TDM modes squeezing multiple channels into one
L/R frame. Neither Dove nor TDA998x support this, but thanks for the
clarification.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: broonie@kernel.org (Mark Brown)
Date: Mon, 7 Oct 2013 18:05:48 +0100
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <5252DC6C.9060503@gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <52529B1A.7060306@gmail.com> <20131007155326.GP21581@sirena.org.uk>
 <5252DC6C.9060503@gmail.com>
Message-ID: <20131007170548.GR21581@sirena.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, Oct 07, 2013 at 06:08:12PM +0200, Sebastian Hesselbarth wrote:

> True, I didn't mention TDM modes squeezing multiple channels into one
> L/R frame. Neither Dove nor TDA998x support this, but thanks for the
> clarification.

Depending on how the DMA and so on is done you can sometimes still do it
on the CPU side by lying to the CPU about the data format (eg, tell it
that two 16 bit samples are actually a 32 bit one) though it gets messy
for I2S since you need to be able to gather all the left samples and all
the right samples.  Though given that your CODEC doesn't support it it's
still all moot anyway as you say.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131007/bd99b77f/attachment.sig>

From mboxrd@z Thu Jan  1 00:00:00 1970
From: sebastian.hesselbarth@gmail.com (Sebastian Hesselbarth)
Date: Mon, 07 Oct 2013 23:47:55 +0200
Subject: [PATCH 0/5] Armada DRM stuff
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Message-ID: <52532C0B.3090503@gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On 10/07/2013 12:07 AM, Russell King - ARM Linux wrote:
> The Armada DRM drivers again, along with the TDA998x HDMI output support,
> and an illustration to show how to add Armada 610 support (and others.)
>
> Rob has looked at this a couple of times since its last posting, and
> has provided additional useful feedback which has been incorporated.
> I believe all the major issues have been addressed now.

Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>

on Marvell Armada 510, SolidRun CuBox with quick-hack DT support added.

Let's please get this driver mainlined and start working on proper DT
support for it. Thanks for driver and the patience to work out all
issues!

Sebastian

From mboxrd@z Thu Jan  1 00:00:00 1970
From: moinejf@free.fr (Jean-Francois Moine)
Date: Tue, 8 Oct 2013 11:19:13 +0200
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
Message-ID: <20131008111913.09bfe93e@armhf>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, 7 Oct 2013 10:59:39 -0400
Rob Clark <robdclark@gmail.com> wrote:

> Jean-Fran?ois, just as an aside, I really don't think code that can be
> shared, like tda998x, should encode a DT requirement.. there are
> plenty of platforms that don't use DT (arm isn't everything, and last
> I heard aarch64 was going to be ACPI).
> 
> Beyond that, it is a driver decision whether or not to support only-DT
> or DT + other.. and as long as there is a common board which can use
> the driver but which is not DT, there is probably a compelling reason
> to still support the non-DT case.

Rob,

The Cubox is an open platform, and I use it just like a desktop PC.
When its required drivers will be in the mainline, I will do the same
as I do with PCs: I will not recompile a specific kernel each time
there are kernel bugs or security issues. Instead, I will just upgrade
my system from my distributor (Debian), and, in the packages, there
will be a generic mvebu kernel as there is already one for Marvell
Armada 370/xp, Freescale iMX5x/iMX6 (linux-image-3.10-3-armmp).
But, for that, all the Cubox specific stuff must be described in a DT.

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Tue, 8 Oct 2013 10:49:39 +0100
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131008111913.09bfe93e@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk> <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
 <20131008111913.09bfe93e@armhf>
Message-ID: <20131008094939.GD25034@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Tue, Oct 08, 2013 at 11:19:13AM +0200, Jean-Francois Moine wrote:
> The Cubox is an open platform, and I use it just like a desktop PC.
> When its required drivers will be in the mainline, I will do the same
> as I do with PCs: I will not recompile a specific kernel each time
> there are kernel bugs or security issues. Instead, I will just upgrade
> my system from my distributor (Debian), and, in the packages, there
> will be a generic mvebu kernel as there is already one for Marvell
> Armada 370/xp, Freescale iMX5x/iMX6 (linux-image-3.10-3-armmp).
> But, for that, all the Cubox specific stuff must be described in a DT.

Which scenario is better:

1. To have something in mainline which is capable of driving the hardware,
   but may need some additional work to make it useful for DT based setups.

or

2. To have nothing.

Now, you may prefer to have nothing, but personally, I prefer there to be
forward progress.  Forward progress means getting some kind of DRM driver
into mainline.  Yes, it may not work with DT setups yet, but - as per
the discussions that have happened _endlessly_ on this topic, it's
something that can be resolved at a later date.

We _still_ haven't worked out how to properly deal with the TDA998x
driver (or indeed any DRM based outputs) in a DT based setup, and all
the time that problem exists, it won't be possible to write a proper
stable DT binding for this.

So please, get off your hobby horse about this and allow us to make some
modicum of progress.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: robdclark@gmail.com (Rob Clark)
Date: Tue, 8 Oct 2013 08:07:23 -0400
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131008111913.09bfe93e@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
 <20131008111913.09bfe93e@armhf>
Message-ID: <CAF6AEGtQLL_c3zLS+S83jm505O_fcCm2mKW+Kd-oWP8EgpwzSw@mail.gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Tue, Oct 8, 2013 at 5:19 AM, Jean-Francois Moine <moinejf@free.fr> wrote:
> On Mon, 7 Oct 2013 10:59:39 -0400
> Rob Clark <robdclark@gmail.com> wrote:
>
>> Jean-Fran?ois, just as an aside, I really don't think code that can be
>> shared, like tda998x, should encode a DT requirement.. there are
>> plenty of platforms that don't use DT (arm isn't everything, and last
>> I heard aarch64 was going to be ACPI).
>>
>> Beyond that, it is a driver decision whether or not to support only-DT
>> or DT + other.. and as long as there is a common board which can use
>> the driver but which is not DT, there is probably a compelling reason
>> to still support the non-DT case.
>
> Rob,
>
> The Cubox is an open platform, and I use it just like a desktop PC.
> When its required drivers will be in the mainline, I will do the same
> as I do with PCs: I will not recompile a specific kernel each time
> there are kernel bugs or security issues. Instead, I will just upgrade
> my system from my distributor (Debian), and, in the packages, there
> will be a generic mvebu kernel as there is already one for Marvell
> Armada 370/xp, Freescale iMX5x/iMX6 (linux-image-3.10-3-armmp).
> But, for that, all the Cubox specific stuff must be described in a DT.

sure, I'm not saying *not* to support DT (send patches if need be).
I'm just saying that it should be ok to also support non-DT case and
that shared components (like tda998x) should also still work in non-DT
case.

BR,
-R

> --
> Ken ar c'henta? |             ** Breizh ha Linux atav! **
> Jef             |               http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: moinejf@free.fr (Jean-Francois Moine)
Date: Tue, 8 Oct 2013 17:34:18 +0200
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131008094939.GD25034@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
 <20131008111913.09bfe93e@armhf>
 <20131008094939.GD25034@n2100.arm.linux.org.uk>
Message-ID: <20131008173418.0fc21d60@armhf>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Tue, 8 Oct 2013 10:49:39 +0100
Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:

> On Tue, Oct 08, 2013 at 11:19:13AM +0200, Jean-Francois Moine wrote:
> > The Cubox is an open platform, and I use it just like a desktop PC.
> > When its required drivers will be in the mainline, I will do the same
> > as I do with PCs: I will not recompile a specific kernel each time
> > there are kernel bugs or security issues. Instead, I will just upgrade
> > my system from my distributor (Debian), and, in the packages, there
> > will be a generic mvebu kernel as there is already one for Marvell
> > Armada 370/xp, Freescale iMX5x/iMX6 (linux-image-3.10-3-armmp).
> > But, for that, all the Cubox specific stuff must be described in a DT.
> 
> Which scenario is better:
> 
> 1. To have something in mainline which is capable of driving the hardware,
>    but may need some additional work to make it useful for DT based setups.
> 
> or
> 
> 2. To have nothing.
> 
> Now, you may prefer to have nothing, but personally, I prefer there to be
> forward progress.  Forward progress means getting some kind of DRM driver
> into mainline.  Yes, it may not work with DT setups yet, but - as per
> the discussions that have happened _endlessly_ on this topic, it's
> something that can be resolved at a later date.
> 
> We _still_ haven't worked out how to properly deal with the TDA998x
> driver (or indeed any DRM based outputs) in a DT based setup, and all
> the time that problem exists, it won't be possible to write a proper
> stable DT binding for this.
> 
> So please, get off your hobby horse about this and allow us to make some
> modicum of progress.

You forgot:

3. To have all patches ready for submission and have a working DT driven
   Cubox kernel.

I will submit a patch to add DT to the tda998x driver as soon as I have
checked the new audio properties we talked about yesterday.

Normally, this should have no impact on your Armada drm driver, and,
yes, I will add DT to your driver as soon as it will be accepted
(sorry to not ack it now: I had no time yet to have a look at it).

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Wed, 9 Oct 2013 15:31:20 +0100
Subject: [PATCH 0/5] Armada DRM stuff
In-Reply-To: <52532C0B.3090503@gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <52532C0B.3090503@gmail.com>
Message-ID: <20131009143120.GI25034@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, Oct 07, 2013 at 11:47:55PM +0200, Sebastian Hesselbarth wrote:
> On 10/07/2013 12:07 AM, Russell King - ARM Linux wrote:
>> The Armada DRM drivers again, along with the TDA998x HDMI output support,
>> and an illustration to show how to add Armada 610 support (and others.)
>>
>> Rob has looked at this a couple of times since its last posting, and
>> has provided additional useful feedback which has been incorporated.
>> I believe all the major issues have been addressed now.
>
> Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>
> on Marvell Armada 510, SolidRun CuBox with quick-hack DT support added.
>
> Let's please get this driver mainlined and start working on proper DT
> support for it. Thanks for driver and the patience to work out all
> issues!

Sebastian,

I've added your tested-by now, and also updated the TDA998x patch to use
the HDMI definitions that Jean-Francois pointed out (which is a really
small delta, so isn't worth resending the patch set just for that).
Thanks.

All the points brought up in previous reviews concerning the physical
address exposure, and the location of the DRM helpers have all been
addressed, so it is now ready to be merged into mainline.  So now the
question is how to proceed with it.

However, I see no response from any DRM developers, even though they are
around - they've been responding on a different thread about driver
model/sysfs abuse by DRM.

I'm going to pull it into my nightly build tree so it can have some
testing with non-dove builds, and if there's still no response from
DRM people next week, I'll put it in to linux-next via my tree so at
least it can get some exposure and integration validation there.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: robdclark@gmail.com (Rob Clark)
Date: Wed, 9 Oct 2013 10:48:34 -0400
Subject: [PATCH 0/5] Armada DRM stuff
In-Reply-To: <20131009143120.GI25034@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <52532C0B.3090503@gmail.com>
 <20131009143120.GI25034@n2100.arm.linux.org.uk>
Message-ID: <CAF6AEGtPtLHZiJbTFJ5BDpWzfD-o3cH=FHnQAg9TPs0p_ZKQEw@mail.gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Wed, Oct 9, 2013 at 10:31 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Oct 07, 2013 at 11:47:55PM +0200, Sebastian Hesselbarth wrote:
>> On 10/07/2013 12:07 AM, Russell King - ARM Linux wrote:
>>> The Armada DRM drivers again, along with the TDA998x HDMI output support,
>>> and an illustration to show how to add Armada 610 support (and others.)
>>>
>>> Rob has looked at this a couple of times since its last posting, and
>>> has provided additional useful feedback which has been incorporated.
>>> I believe all the major issues have been addressed now.
>>
>> Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>>
>> on Marvell Armada 510, SolidRun CuBox with quick-hack DT support added.
>>
>> Let's please get this driver mainlined and start working on proper DT
>> support for it. Thanks for driver and the patience to work out all
>> issues!
>
> Sebastian,
>
> I've added your tested-by now, and also updated the TDA998x patch to use
> the HDMI definitions that Jean-Francois pointed out (which is a really
> small delta, so isn't worth resending the patch set just for that).
> Thanks.
>
> All the points brought up in previous reviews concerning the physical
> address exposure, and the location of the DRM helpers have all been
> addressed, so it is now ready to be merged into mainline.  So now the
> question is how to proceed with it.
>
> However, I see no response from any DRM developers, even though they are
> around - they've been responding on a different thread about driver
> model/sysfs abuse by DRM.
>
> I'm going to pull it into my nightly build tree so it can have some
> testing with non-dove builds, and if there's still no response from
> DRM people next week, I'll put it in to linux-next via my tree so at
> least it can get some exposure and integration validation there.

fyi, I think this is in pretty good shape.. I've reviewed earlier
versions, and had an initial look at this version which addresses my
concerns, although I still intend to give a closer review of the final
version (still on my TODO list, but we have a bit of time before 3.13
merge window.. I should at least get to it by the weekend)

BR,
-R

From mboxrd@z Thu Jan  1 00:00:00 1970
From: robdclark@gmail.com (Rob Clark)
Date: Thu, 10 Oct 2013 17:25:15 -0400
Subject: [PATCH 2/5] DRM: Armada: Add Armada DRM driver
In-Reply-To: <E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
Message-ID: <CAF6AEGsvBaX5+c1P=ups+k=d1F3r+JphgYOt5wb7pEM3mihOQw@mail.gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Sun, Oct 6, 2013 at 6:08 PM, Russell King
<rmk+kernel@arm.linux.org.uk> wrote:
> This patch adds support for the pair of LCD controllers on the Marvell
> Armada 510 SoCs.  This driver supports:
> - multiple contiguous scanout buffers for video and graphics
> - shm backed cacheable buffer objects for X pixmaps for Vivante GPU
>   acceleration
> - dual lcd0 and lcd1 crt operation
> - video overlay on each LCD crt via DRM planes
> - page flipping of the main scanout buffers
> - DRM prime for buffer export/import
>
> This driver is trivial to extend to other Armada SoCs.
>
> Included in this commit is the core driver with no output support; output
> support is platform and encoder driver dependent.

w/ a couple minor comments below:

Reviewed-by: Rob Clark <robdclark@gmail.com>


> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  drivers/gpu/drm/Kconfig                 |    2 +
>  drivers/gpu/drm/Makefile                |    1 +
>  drivers/gpu/drm/armada/Kconfig          |   15 +
>  drivers/gpu/drm/armada/Makefile         |    7 +
>  drivers/gpu/drm/armada/armada_510.c     |   86 +++
>  drivers/gpu/drm/armada/armada_crtc.c    |  861 +++++++++++++++++++++++++++++++
>  drivers/gpu/drm/armada/armada_crtc.h    |   74 +++
>  drivers/gpu/drm/armada/armada_debugfs.c |  183 +++++++
>  drivers/gpu/drm/armada/armada_drm.h     |  112 ++++
>  drivers/gpu/drm/armada/armada_drv.c     |  380 ++++++++++++++
>  drivers/gpu/drm/armada/armada_fb.c      |  170 ++++++
>  drivers/gpu/drm/armada/armada_fb.h      |   24 +
>  drivers/gpu/drm/armada/armada_fbdev.c   |  202 ++++++++
>  drivers/gpu/drm/armada/armada_gem.c     |  616 ++++++++++++++++++++++
>  drivers/gpu/drm/armada/armada_gem.h     |   52 ++
>  drivers/gpu/drm/armada/armada_hw.h      |  316 +++++++++++
>  drivers/gpu/drm/armada/armada_ioctlP.h  |   18 +
>  drivers/gpu/drm/armada/armada_output.c  |  158 ++++++
>  drivers/gpu/drm/armada/armada_output.h  |   39 ++
>  drivers/gpu/drm/armada/armada_overlay.c |  477 +++++++++++++++++
>  drivers/gpu/drm/armada/armada_slave.c   |  139 +++++
>  drivers/gpu/drm/armada/armada_slave.h   |   26 +
>  include/drm/drm_crtc.h                  |   17 +
>  include/uapi/drm/armada_drm.h           |   45 ++
>  24 files changed, 4020 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/gpu/drm/armada/Kconfig
>  create mode 100644 drivers/gpu/drm/armada/Makefile
>  create mode 100644 drivers/gpu/drm/armada/armada_510.c
>  create mode 100644 drivers/gpu/drm/armada/armada_crtc.c
>  create mode 100644 drivers/gpu/drm/armada/armada_crtc.h
>  create mode 100644 drivers/gpu/drm/armada/armada_debugfs.c
>  create mode 100644 drivers/gpu/drm/armada/armada_drm.h
>  create mode 100644 drivers/gpu/drm/armada/armada_drv.c
>  create mode 100644 drivers/gpu/drm/armada/armada_fb.c
>  create mode 100644 drivers/gpu/drm/armada/armada_fb.h
>  create mode 100644 drivers/gpu/drm/armada/armada_fbdev.c
>  create mode 100644 drivers/gpu/drm/armada/armada_gem.c
>  create mode 100644 drivers/gpu/drm/armada/armada_gem.h
>  create mode 100644 drivers/gpu/drm/armada/armada_hw.h
>  create mode 100644 drivers/gpu/drm/armada/armada_ioctlP.h
>  create mode 100644 drivers/gpu/drm/armada/armada_output.c
>  create mode 100644 drivers/gpu/drm/armada/armada_output.h
>  create mode 100644 drivers/gpu/drm/armada/armada_overlay.c
>  create mode 100644 drivers/gpu/drm/armada/armada_slave.c
>  create mode 100644 drivers/gpu/drm/armada/armada_slave.h
>  create mode 100644 include/uapi/drm/armada_drm.h
>
[snip]
> +/*
> + * Prepare for a mode set.  Turn off overlay to ensure that we don't end
> + * up with the overlay size being bigger than the active screen size.
> + * We rely upon X refreshing this state after the mode set has completed.
> + *
> + * The mode_config.mutex will be held for this call
> + */
> +static void armada_drm_crtc_prepare(struct drm_crtc *crtc)
> +{
> +       struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
> +       struct drm_plane *plane;
> +
> +       /*
> +        * If we have an overlay plane associated with this CRTC, disable
> +        * it before the modeset to avoid its coordinates being outside
> +        * the new mode parameters.  DRM doesn't provide help with this.
> +        */

Getting a bit off topic, but yeah.. I'd be in favor of "clarifying"
things by having crtc helpers disable planes on setcrtc (rather than
only doing this on fbdev/lastclose restore).  I
don't know of any userspace that this would cause problems for.  But
not really sure if it would be considered an interface break or just
"fixing a bug".. since we have different behavior on different
drivers, I'd lean towards the latter.

> +       plane = dcrtc->plane;
> +       if (plane) {
> +               struct drm_framebuffer *fb = plane->fb;
> +
> +               plane->funcs->disable_plane(plane);
> +               plane->fb = NULL;
> +               plane->crtc = NULL;
> +               drm_framebuffer_unreference(fb);
> +       }
> +}


> diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
> new file mode 100644
> index 0000000..c865a9a
> --- /dev/null
> +++ b/drivers/gpu/drm/armada/armada_gem.c
> @@ -0,0 +1,616 @@
> +/*
> + * Copyright (C) 2012 Russell King
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#include <linux/dma-buf.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/shmem_fs.h>
> +#include <drm/drmP.h>
> +#include "armada_drm.h"
> +#include "armada_gem.h"
> +#include <drm/armada_drm.h>
> +#include "armada_ioctlP.h"
> +
> +static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
> +{
> +       struct armada_gem_object *obj = drm_to_armada_gem(vma->vm_private_data);
> +       unsigned long addr = (unsigned long)vmf->virtual_address;
> +       unsigned long pfn = obj->phys_addr >> PAGE_SHIFT;
> +       int ret;
> +
> +       pfn += (addr - vma->vm_start) >> PAGE_SHIFT;
> +       ret = vm_insert_pfn(vma, addr, pfn);
> +
> +       switch (ret) {
> +       case -EIO:
> +       case -EAGAIN:
> +               set_need_resched();

probably this thread is applicable here too?

https://lkml.org/lkml/2013/9/12/417

(although.. we have at least a few  slightly differet variants on the
same errno -> VM_FAULT_x switch in different drivers.. maybe we should
do something better)

> +       case 0:
> +       case -ERESTARTSYS:
> +       case -EINTR:
> +       case -EBUSY:
> +               return VM_FAULT_NOPAGE;
> +       case -ENOMEM:
> +               return VM_FAULT_OOM;
> +       default:
> +               return VM_FAULT_SIGBUS;
> +       }
> +}
> +

[snip]

> +/* Prime support */
> +struct sg_table *
> +armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
> +       enum dma_data_direction dir)
> +{
> +       struct drm_gem_object *obj = attach->dmabuf->priv;
> +       struct armada_gem_object *dobj = drm_to_armada_gem(obj);
> +       struct scatterlist *sg;
> +       struct sg_table *sgt;
> +       int i, num;
> +
> +       sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
> +       if (!sgt)
> +               return NULL;
> +
> +       if (dobj->obj.filp) {
> +               struct address_space *mapping;
> +               gfp_t gfp;
> +               int count;
> +
> +               count = dobj->obj.size / PAGE_SIZE;
> +               if (sg_alloc_table(sgt, count, GFP_KERNEL))
> +                       goto free_sgt;
> +
> +               mapping = file_inode(dobj->obj.filp)->i_mapping;
> +               gfp = mapping_gfp_mask(mapping);
> +
> +               for_each_sg(sgt->sgl, sg, count, i) {
> +                       struct page *page;
> +
> +                       page = shmem_read_mapping_page_gfp(mapping, i, gfp);

you could almost use drm_gem_get_pages().. although I guess you
otherwise have no need for the page[] array?

(the page array would be handy if you supported mmap on shmem backed
files.. which as long as they are cached should be the easy case)

> +                       if (IS_ERR(page)) {
> +                               num = i;
> +                               goto release;
> +                       }
> +
> +                       sg_set_page(sg, page, PAGE_SIZE, 0);
> +               }
> +
> +               if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0) {
> +                       num = sgt->nents;
> +                       goto release;
> +               }
> +       } else if (dobj->page) {
> +               /* Single contiguous page */
> +               if (sg_alloc_table(sgt, 1, GFP_KERNEL))
> +                       goto free_sgt;
> +
> +               sg_set_page(sgt->sgl, dobj->page, dobj->obj.size, 0);
> +
> +               if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0)
> +                       goto free_table;
> +       } else if (dobj->linear) {
> +               /* Single contiguous physical region - no struct page */
> +               if (sg_alloc_table(sgt, 1, GFP_KERNEL))
> +                       goto free_sgt;
> +               sg_dma_address(sgt->sgl) = dobj->dev_addr;
> +               sg_dma_len(sgt->sgl) = dobj->obj.size;
> +       } else {
> +               goto free_sgt;
> +       }
> +       return sgt;
> +
> + release:
> +       for_each_sg(sgt->sgl, sg, num, i)
> +               page_cache_release(sg_page(sg));
> + free_table:
> +       sg_free_table(sgt);
> + free_sgt:
> +       kfree(sgt);
> +       return NULL;
> +}
[snip]
> +> diff --git a/include/uapi/drm/armada_drm.h b/include/uapi/drm/armada_drm.h
> new file mode 100644
> index 0000000..8dec3fd
> --- /dev/null
> +++ b/include/uapi/drm/armada_drm.h
> @@ -0,0 +1,45 @@
> +/*
> + * Copyright (C) 2012 Russell King
> + *  With inspiration from the i915 driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#ifndef DRM_ARMADA_IOCTL_H
> +#define DRM_ARMADA_IOCTL_H
> +
> +#define DRM_ARMADA_GEM_CREATE          0x00
> +#define DRM_ARMADA_GEM_MMAP            0x02
> +#define DRM_ARMADA_GEM_PWRITE          0x03
> +
> +#define ARMADA_IOCTL(dir, name, str) \
> +       DRM_##dir(DRM_COMMAND_BASE + DRM_ARMADA_##name, struct drm_armada_##str)
> +
> +struct drm_armada_gem_create {

Any reason not to throw in a 'uint32_t flags' field?  At least then
you could indicate what sort of backing memory you want, and do things
like allocate linear scanout buffer w/ your gem_create rather than
having to use dumb_create.  Maybe not something you need now, but
seems like eventually you'll come up with some reason or another to
want to pass some flags into gem_create.

> +       uint32_t handle;
> +       uint32_t size;
> +};
> +#define DRM_IOCTL_ARMADA_GEM_CREATE \
> +       ARMADA_IOCTL(IOWR, GEM_CREATE, gem_create)
> +
> +struct drm_armada_gem_mmap {
> +       uint32_t handle;
> +       uint32_t pad;
> +       uint64_t offset;
> +       uint64_t size;
> +       uint64_t addr;
> +};
> +#define DRM_IOCTL_ARMADA_GEM_MMAP \
> +       ARMADA_IOCTL(IOWR, GEM_MMAP, gem_mmap)
> +
> +struct drm_armada_gem_pwrite {
> +       uint64_t ptr;
> +       uint32_t handle;
> +       uint32_t offset;
> +       uint32_t size;
> +};
> +#define DRM_IOCTL_ARMADA_GEM_PWRITE \
> +       ARMADA_IOCTL(IOW, GEM_PWRITE, gem_pwrite)
> +
> +#endif
> --
> 1.7.4.4
>

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Thu, 10 Oct 2013 22:59:51 +0100
Subject: [PATCH 2/5] DRM: Armada: Add Armada DRM driver
In-Reply-To: <CAF6AEGsvBaX5+c1P=ups+k=d1F3r+JphgYOt5wb7pEM3mihOQw@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
 <CAF6AEGsvBaX5+c1P=ups+k=d1F3r+JphgYOt5wb7pEM3mihOQw@mail.gmail.com>
Message-ID: <20131010215951.GS25034@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Thu, Oct 10, 2013 at 05:25:15PM -0400, Rob Clark wrote:
> On Sun, Oct 6, 2013 at 6:08 PM, Russell King
> <rmk+kernel@arm.linux.org.uk> wrote:
> > +       /*
> > +        * If we have an overlay plane associated with this CRTC, disable
> > +        * it before the modeset to avoid its coordinates being outside
> > +        * the new mode parameters.  DRM doesn't provide help with this.
> > +        */
> 
> Getting a bit off topic, but yeah.. I'd be in favor of "clarifying"
> things by having crtc helpers disable planes on setcrtc (rather than
> only doing this on fbdev/lastclose restore).  I
> don't know of any userspace that this would cause problems for.  But
> not really sure if it would be considered an interface break or just
> "fixing a bug".. since we have different behavior on different
> drivers, I'd lean towards the latter.

The reasoning here is if the overlay plane is larger than the mode being
set, we will end up having the hardware programmed in an inconsistent
state - the overlay plane position/width/height can be outside of the
active region, which is invalid for the hardware.  So, it's safer to
disable the plane and wait for the next plane to be sent and have that
validated against the new mode.

It's not like you would be able to see the plane immediately, because
most monitors blank while they retrain to the new mode settings.

> > +static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
> > +{
> > +       struct armada_gem_object *obj = drm_to_armada_gem(vma->vm_private_data);
> > +       unsigned long addr = (unsigned long)vmf->virtual_address;
> > +       unsigned long pfn = obj->phys_addr >> PAGE_SHIFT;
> > +       int ret;
> > +
> > +       pfn += (addr - vma->vm_start) >> PAGE_SHIFT;
> > +       ret = vm_insert_pfn(vma, addr, pfn);
> > +
> > +       switch (ret) {
> > +       case -EIO:
> > +       case -EAGAIN:
> > +               set_need_resched();
> 
> probably this thread is applicable here too?
> 
> https://lkml.org/lkml/2013/9/12/417
> 
> (although.. we have at least a few  slightly differet variants on the
> same errno -> VM_FAULT_x switch in different drivers.. maybe we should
> do something better)

Hmm.  It seems today's vm_insert_pfn() has the following error return
values:

-EFAULT - virtual address outside vma
-EINVAL - track_pfn_insert() failure
-ENOMEM - failed to get locked pte
-EBUSY - entry already exists in pte

So it seems my handling -EIO, -EAGAIN, -ERESTARTSYS and -EINTR are all
redundant and can be removed.  I'm not sure if it makes sense for this
to be generic - it looks like it's only Intel, gma500 and me who use
this, and Intel handles more error codes (due to it calling other
functions.)

I'll respin dropping those four unnecessary error codes, and post the
delta for this.

> > +/* Prime support */
> > +struct sg_table *
> > +armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
> > +       enum dma_data_direction dir)
> > +{
> > +       struct drm_gem_object *obj = attach->dmabuf->priv;
> > +       struct armada_gem_object *dobj = drm_to_armada_gem(obj);
> > +       struct scatterlist *sg;
> > +       struct sg_table *sgt;
> > +       int i, num;
> > +
> > +       sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
> > +       if (!sgt)
> > +               return NULL;
> > +
> > +       if (dobj->obj.filp) {
> > +               struct address_space *mapping;
> > +               gfp_t gfp;
> > +               int count;
> > +
> > +               count = dobj->obj.size / PAGE_SIZE;
> > +               if (sg_alloc_table(sgt, count, GFP_KERNEL))
> > +                       goto free_sgt;
> > +
> > +               mapping = file_inode(dobj->obj.filp)->i_mapping;
> > +               gfp = mapping_gfp_mask(mapping);
> > +
> > +               for_each_sg(sgt->sgl, sg, count, i) {
> > +                       struct page *page;
> > +
> > +                       page = shmem_read_mapping_page_gfp(mapping, i, gfp);
> 
> you could almost use drm_gem_get_pages().. although I guess you
> otherwise have no need for the page[] array?

Correct.  The page[] array would just be an additional unnecessary
allocation, and therefore would be an additional unnecessary point of
failure.

> > +#define DRM_ARMADA_GEM_CREATE          0x00
> > +#define DRM_ARMADA_GEM_MMAP            0x02
> > +#define DRM_ARMADA_GEM_PWRITE          0x03
> > +
> > +#define ARMADA_IOCTL(dir, name, str) \
> > +       DRM_##dir(DRM_COMMAND_BASE + DRM_ARMADA_##name, struct drm_armada_##str)
> > +
> > +struct drm_armada_gem_create {
> 
> Any reason not to throw in a 'uint32_t flags' field?  At least then
> you could indicate what sort of backing memory you want, and do things
> like allocate linear scanout buffer w/ your gem_create rather than
> having to use dumb_create.  Maybe not something you need now, but
> seems like eventually you'll come up with some reason or another to
> want to pass some flags into gem_create.

I thought one of the points of the dumb_create stuff was so that there
is a standard API for dumb scanout buffers across all DRM drivers.  It
has that advantage, and as I understand it, a generic KMS driver for X
is on the cards.

Thanks for the review.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: robdclark@gmail.com (Rob Clark)
Date: Thu, 10 Oct 2013 18:23:26 -0400
Subject: [PATCH 2/5] DRM: Armada: Add Armada DRM driver
In-Reply-To: <20131010215951.GS25034@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
 <CAF6AEGsvBaX5+c1P=ups+k=d1F3r+JphgYOt5wb7pEM3mihOQw@mail.gmail.com>
 <20131010215951.GS25034@n2100.arm.linux.org.uk>
Message-ID: <CAF6AEGvNyD8-_t2y69a5Gjey7Jg_LXVYNgpYW1rsFFyTkABg=Q@mail.gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Thu, Oct 10, 2013 at 5:59 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Oct 10, 2013 at 05:25:15PM -0400, Rob Clark wrote:
>> On Sun, Oct 6, 2013 at 6:08 PM, Russell King
>> <rmk+kernel@arm.linux.org.uk> wrote:
>> > +       /*
>> > +        * If we have an overlay plane associated with this CRTC, disable
>> > +        * it before the modeset to avoid its coordinates being outside
>> > +        * the new mode parameters.  DRM doesn't provide help with this.
>> > +        */
>>
>> Getting a bit off topic, but yeah.. I'd be in favor of "clarifying"
>> things by having crtc helpers disable planes on setcrtc (rather than
>> only doing this on fbdev/lastclose restore).  I
>> don't know of any userspace that this would cause problems for.  But
>> not really sure if it would be considered an interface break or just
>> "fixing a bug".. since we have different behavior on different
>> drivers, I'd lean towards the latter.
>
> The reasoning here is if the overlay plane is larger than the mode being
> set, we will end up having the hardware programmed in an inconsistent
> state - the overlay plane position/width/height can be outside of the
> active region, which is invalid for the hardware.  So, it's safer to
> disable the plane and wait for the next plane to be sent and have that
> validated against the new mode.

right.  I think disabling the planes is the correct behavior.  So
nothing to do here for armada.  I mostly just wanted to get some
opinions about making the crtc helpers do this automatically for us.

> It's not like you would be able to see the plane immediately, because
> most monitors blank while they retrain to the new mode settings.
>
>> > +static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
>> > +{
>> > +       struct armada_gem_object *obj = drm_to_armada_gem(vma->vm_private_data);
>> > +       unsigned long addr = (unsigned long)vmf->virtual_address;
>> > +       unsigned long pfn = obj->phys_addr >> PAGE_SHIFT;
>> > +       int ret;
>> > +
>> > +       pfn += (addr - vma->vm_start) >> PAGE_SHIFT;
>> > +       ret = vm_insert_pfn(vma, addr, pfn);
>> > +
>> > +       switch (ret) {
>> > +       case -EIO:
>> > +       case -EAGAIN:
>> > +               set_need_resched();
>>
>> probably this thread is applicable here too?
>>
>> https://lkml.org/lkml/2013/9/12/417
>>
>> (although.. we have at least a few  slightly differet variants on the
>> same errno -> VM_FAULT_x switch in different drivers.. maybe we should
>> do something better)
>
> Hmm.  It seems today's vm_insert_pfn() has the following error return
> values:
>
> -EFAULT - virtual address outside vma
> -EINVAL - track_pfn_insert() failure
> -ENOMEM - failed to get locked pte
> -EBUSY - entry already exists in pte
>
> So it seems my handling -EIO, -EAGAIN, -ERESTARTSYS and -EINTR are all
> redundant and can be removed.  I'm not sure if it makes sense for this
> to be generic - it looks like it's only Intel, gma500 and me who use
> this, and Intel handles more error codes (due to it calling other
> functions.)

I just noticed msm and omapdrm are missing the -EBUSY case (have some
patches I need to send), which was why I mentioned this.  They do have
other error cases from other fxns, so maybe something generic/common
doesn't make sense..  but I realized i915 fixed the same issue a while
back, so somewhere common has the advantage of somehow not forgetting
to fix other drivers ;-)

> I'll respin dropping those four unnecessary error codes, and post the
> delta for this.
>
>> > +/* Prime support */
>> > +struct sg_table *
>> > +armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
>> > +       enum dma_data_direction dir)
>> > +{
>> > +       struct drm_gem_object *obj = attach->dmabuf->priv;
>> > +       struct armada_gem_object *dobj = drm_to_armada_gem(obj);
>> > +       struct scatterlist *sg;
>> > +       struct sg_table *sgt;
>> > +       int i, num;
>> > +
>> > +       sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
>> > +       if (!sgt)
>> > +               return NULL;
>> > +
>> > +       if (dobj->obj.filp) {
>> > +               struct address_space *mapping;
>> > +               gfp_t gfp;
>> > +               int count;
>> > +
>> > +               count = dobj->obj.size / PAGE_SIZE;
>> > +               if (sg_alloc_table(sgt, count, GFP_KERNEL))
>> > +                       goto free_sgt;
>> > +
>> > +               mapping = file_inode(dobj->obj.filp)->i_mapping;
>> > +               gfp = mapping_gfp_mask(mapping);
>> > +
>> > +               for_each_sg(sgt->sgl, sg, count, i) {
>> > +                       struct page *page;
>> > +
>> > +                       page = shmem_read_mapping_page_gfp(mapping, i, gfp);
>>
>> you could almost use drm_gem_get_pages().. although I guess you
>> otherwise have no need for the page[] array?
>
> Correct.  The page[] array would just be an additional unnecessary
> allocation, and therefore would be an additional unnecessary point of
> failure.
>
>> > +#define DRM_ARMADA_GEM_CREATE          0x00
>> > +#define DRM_ARMADA_GEM_MMAP            0x02
>> > +#define DRM_ARMADA_GEM_PWRITE          0x03
>> > +
>> > +#define ARMADA_IOCTL(dir, name, str) \
>> > +       DRM_##dir(DRM_COMMAND_BASE + DRM_ARMADA_##name, struct drm_armada_##str)
>> > +
>> > +struct drm_armada_gem_create {
>>
>> Any reason not to throw in a 'uint32_t flags' field?  At least then
>> you could indicate what sort of backing memory you want, and do things
>> like allocate linear scanout buffer w/ your gem_create rather than
>> having to use dumb_create.  Maybe not something you need now, but
>> seems like eventually you'll come up with some reason or another to
>> want to pass some flags into gem_create.
>
> I thought one of the points of the dumb_create stuff was so that there
> is a standard API for dumb scanout buffers across all DRM drivers.  It
> has that advantage, and as I understand it, a generic KMS driver for X
> is on the cards.

Yeah, xf86-video-modesetting currently uses dumb allocation.  So you
definitely want to continue to support the dumb buffer path.

I can't really think of any immediate need for 'flags'..  but seems
like sooner or later someone will come up with some need for it, so it
seemed like a convenient placeholder to have.

Well, technically you can get away w/ adding new fields to the end of
the ioctl struct, and drm_ioctl() will take care of zero'ing that out
for you with an old userspace.  So I guess you could just rely on that
if you ever need to add 'flags' or some other fields.

> Thanks for the review.

no prob

BR,
-R

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Thu, 10 Oct 2013 23:53:31 +0100
Subject: [PATCH 2/5] DRM: Armada: Add Armada DRM driver
In-Reply-To: <CAF6AEGvNyD8-_t2y69a5Gjey7Jg_LXVYNgpYW1rsFFyTkABg=Q@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
 <CAF6AEGsvBaX5+c1P=ups+k=d1F3r+JphgYOt5wb7pEM3mihOQw@mail.gmail.com>
 <20131010215951.GS25034@n2100.arm.linux.org.uk>
 <CAF6AEGvNyD8-_t2y69a5Gjey7Jg_LXVYNgpYW1rsFFyTkABg=Q@mail.gmail.com>
Message-ID: <20131010225331.GT25034@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Thu, Oct 10, 2013 at 06:23:26PM -0400, Rob Clark wrote:
> On Thu, Oct 10, 2013 at 5:59 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Thu, Oct 10, 2013 at 05:25:15PM -0400, Rob Clark wrote:
> >> probably this thread is applicable here too?
> >>
> >> https://lkml.org/lkml/2013/9/12/417
> >>
> >> (although.. we have at least a few  slightly differet variants on the
> >> same errno -> VM_FAULT_x switch in different drivers.. maybe we should
> >> do something better)
> >
> > Hmm.  It seems today's vm_insert_pfn() has the following error return
> > values:
> >
> > -EFAULT - virtual address outside vma
> > -EINVAL - track_pfn_insert() failure
> > -ENOMEM - failed to get locked pte
> > -EBUSY - entry already exists in pte
> >
> > So it seems my handling -EIO, -EAGAIN, -ERESTARTSYS and -EINTR are all
> > redundant and can be removed.  I'm not sure if it makes sense for this
> > to be generic - it looks like it's only Intel, gma500 and me who use
> > this, and Intel handles more error codes (due to it calling other
> > functions.)
> 
> I just noticed msm and omapdrm are missing the -EBUSY case (have some
> patches I need to send), which was why I mentioned this.  They do have
> other error cases from other fxns, so maybe something generic/common
> doesn't make sense..  but I realized i915 fixed the same issue a while
> back, so somewhere common has the advantage of somehow not forgetting
> to fix other drivers ;-)

Here's the promised delta:

 drivers/gpu/drm/armada/armada_gem.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index 02de7a4..1e74f70 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -25,12 +25,7 @@ static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	ret = vm_insert_pfn(vma, addr, pfn);
 
 	switch (ret) {
-	case -EIO:
-	case -EAGAIN:
-		set_need_resched();
 	case 0:
-	case -ERESTARTSYS:
-	case -EINTR:
 	case -EBUSY:
 		return VM_FAULT_NOPAGE;
 	case -ENOMEM:

From mboxrd@z Thu Jan  1 00:00:00 1970
From: robdclark@gmail.com (Rob Clark)
Date: Thu, 10 Oct 2013 20:10:58 -0400
Subject: [PATCH 2/5] DRM: Armada: Add Armada DRM driver
In-Reply-To: <20131010225331.GT25034@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
 <CAF6AEGsvBaX5+c1P=ups+k=d1F3r+JphgYOt5wb7pEM3mihOQw@mail.gmail.com>
 <20131010215951.GS25034@n2100.arm.linux.org.uk>
 <CAF6AEGvNyD8-_t2y69a5Gjey7Jg_LXVYNgpYW1rsFFyTkABg=Q@mail.gmail.com>
 <20131010225331.GT25034@n2100.arm.linux.org.uk>
Message-ID: <CAF6AEGvb-oeQqYF-XyZ1PjCaqojJ=DurLVGkZxUFwC_WveoTwg@mail.gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Thu, Oct 10, 2013 at 6:53 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Oct 10, 2013 at 06:23:26PM -0400, Rob Clark wrote:
>> On Thu, Oct 10, 2013 at 5:59 PM, Russell King - ARM Linux
>> <linux@arm.linux.org.uk> wrote:
>> > On Thu, Oct 10, 2013 at 05:25:15PM -0400, Rob Clark wrote:
>> >> probably this thread is applicable here too?
>> >>
>> >> https://lkml.org/lkml/2013/9/12/417
>> >>
>> >> (although.. we have at least a few  slightly differet variants on the
>> >> same errno -> VM_FAULT_x switch in different drivers.. maybe we should
>> >> do something better)
>> >
>> > Hmm.  It seems today's vm_insert_pfn() has the following error return
>> > values:
>> >
>> > -EFAULT - virtual address outside vma
>> > -EINVAL - track_pfn_insert() failure
>> > -ENOMEM - failed to get locked pte
>> > -EBUSY - entry already exists in pte
>> >
>> > So it seems my handling -EIO, -EAGAIN, -ERESTARTSYS and -EINTR are all
>> > redundant and can be removed.  I'm not sure if it makes sense for this
>> > to be generic - it looks like it's only Intel, gma500 and me who use
>> > this, and Intel handles more error codes (due to it calling other
>> > functions.)
>>
>> I just noticed msm and omapdrm are missing the -EBUSY case (have some
>> patches I need to send), which was why I mentioned this.  They do have
>> other error cases from other fxns, so maybe something generic/common
>> doesn't make sense..  but I realized i915 fixed the same issue a while
>> back, so somewhere common has the advantage of somehow not forgetting
>> to fix other drivers ;-)
>
> Here's the promised delta:

looks good.. I'll try to get to reviewing the rest of the series
tomorrow, or at least before the end of the weekend

Reviewed-by: Rob Clark <robdclark@gmail.com>

BR,
-R

>  drivers/gpu/drm/armada/armada_gem.c |    5 -----
>  1 files changed, 0 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
> index 02de7a4..1e74f70 100644
> --- a/drivers/gpu/drm/armada/armada_gem.c
> +++ b/drivers/gpu/drm/armada/armada_gem.c
> @@ -25,12 +25,7 @@ static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
>         ret = vm_insert_pfn(vma, addr, pfn);
>
>         switch (ret) {
> -       case -EIO:
> -       case -EAGAIN:
> -               set_need_resched();
>         case 0:
> -       case -ERESTARTSYS:
> -       case -EINTR:
>         case -EBUSY:
>                 return VM_FAULT_NOPAGE;
>         case -ENOMEM:
>

From mboxrd@z Thu Jan  1 00:00:00 1970
From: rmk+kernel@arm.linux.org.uk (Russell King)
Date: Sun, 06 Oct 2013 23:08:56 +0100
Subject: [PATCH 2/5] DRM: Armada: Add Armada DRM driver
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Message-ID: <E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

This patch adds support for the pair of LCD controllers on the Marvell
Armada 510 SoCs.  This driver supports:
- multiple contiguous scanout buffers for video and graphics
- shm backed cacheable buffer objects for X pixmaps for Vivante GPU
  acceleration
- dual lcd0 and lcd1 crt operation
- video overlay on each LCD crt via DRM planes
- page flipping of the main scanout buffers
- DRM prime for buffer export/import

This driver is trivial to extend to other Armada SoCs.

Included in this commit is the core driver with no output support; output
support is platform and encoder driver dependent.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/Kconfig                 |    2 +
 drivers/gpu/drm/Makefile                |    1 +
 drivers/gpu/drm/armada/Kconfig          |   15 +
 drivers/gpu/drm/armada/Makefile         |    7 +
 drivers/gpu/drm/armada/armada_510.c     |   86 +++
 drivers/gpu/drm/armada/armada_crtc.c    |  861 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_crtc.h    |   74 +++
 drivers/gpu/drm/armada/armada_debugfs.c |  183 +++++++
 drivers/gpu/drm/armada/armada_drm.h     |  112 ++++
 drivers/gpu/drm/armada/armada_drv.c     |  380 ++++++++++++++
 drivers/gpu/drm/armada/armada_fb.c      |  170 ++++++
 drivers/gpu/drm/armada/armada_fb.h      |   24 +
 drivers/gpu/drm/armada/armada_fbdev.c   |  202 ++++++++
 drivers/gpu/drm/armada/armada_gem.c     |  616 ++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_gem.h     |   52 ++
 drivers/gpu/drm/armada/armada_hw.h      |  316 +++++++++++
 drivers/gpu/drm/armada/armada_ioctlP.h  |   18 +
 drivers/gpu/drm/armada/armada_output.c  |  158 ++++++
 drivers/gpu/drm/armada/armada_output.h  |   39 ++
 drivers/gpu/drm/armada/armada_overlay.c |  477 +++++++++++++++++
 drivers/gpu/drm/armada/armada_slave.c   |  139 +++++
 drivers/gpu/drm/armada/armada_slave.h   |   26 +
 include/drm/drm_crtc.h                  |   17 +
 include/uapi/drm/armada_drm.h           |   45 ++
 24 files changed, 4020 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/armada/Kconfig
 create mode 100644 drivers/gpu/drm/armada/Makefile
 create mode 100644 drivers/gpu/drm/armada/armada_510.c
 create mode 100644 drivers/gpu/drm/armada/armada_crtc.c
 create mode 100644 drivers/gpu/drm/armada/armada_crtc.h
 create mode 100644 drivers/gpu/drm/armada/armada_debugfs.c
 create mode 100644 drivers/gpu/drm/armada/armada_drm.h
 create mode 100644 drivers/gpu/drm/armada/armada_drv.c
 create mode 100644 drivers/gpu/drm/armada/armada_fb.c
 create mode 100644 drivers/gpu/drm/armada/armada_fb.h
 create mode 100644 drivers/gpu/drm/armada/armada_fbdev.c
 create mode 100644 drivers/gpu/drm/armada/armada_gem.c
 create mode 100644 drivers/gpu/drm/armada/armada_gem.h
 create mode 100644 drivers/gpu/drm/armada/armada_hw.h
 create mode 100644 drivers/gpu/drm/armada/armada_ioctlP.h
 create mode 100644 drivers/gpu/drm/armada/armada_output.c
 create mode 100644 drivers/gpu/drm/armada/armada_output.h
 create mode 100644 drivers/gpu/drm/armada/armada_overlay.c
 create mode 100644 drivers/gpu/drm/armada/armada_slave.c
 create mode 100644 drivers/gpu/drm/armada/armada_slave.h
 create mode 100644 include/uapi/drm/armada_drm.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 955555d..3b5176d 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -225,6 +225,8 @@ source "drivers/gpu/drm/mgag200/Kconfig"
 
 source "drivers/gpu/drm/cirrus/Kconfig"
 
+source "drivers/gpu/drm/armada/Kconfig"
+
 source "drivers/gpu/drm/rcar-du/Kconfig"
 
 source "drivers/gpu/drm/shmobile/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index f089adf..385f460 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_DRM_EXYNOS) +=exynos/
 obj-$(CONFIG_DRM_GMA500) += gma500/
 obj-$(CONFIG_DRM_UDL) += udl/
 obj-$(CONFIG_DRM_AST) += ast/
+obj-$(CONFIG_DRM_ARMADA) += armada/
 obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
 obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
 obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
new file mode 100644
index 0000000..c7a0a94
--- /dev/null
+++ b/drivers/gpu/drm/armada/Kconfig
@@ -0,0 +1,15 @@
+config DRM_ARMADA
+	tristate "DRM support for Marvell Armada SoCs"
+	depends on DRM && HAVE_CLK
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select DRM_KMS_HELPER
+	help
+	  Support the "LCD" controllers found on the Marvell Armada 510
+	  devices.  There are two controllers on the device, each controller
+	  supports graphics and video overlays.
+
+	  This driver provides no built-in acceleration; acceleration is
+	  performed by other IP found on the SoC.  This driver provides
+	  kernel mode setting and buffer management to userspace.
diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile
new file mode 100644
index 0000000..d6f43e0
--- /dev/null
+++ b/drivers/gpu/drm/armada/Makefile
@@ -0,0 +1,7 @@
+armada-y	:= armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
+		   armada_gem.o armada_output.o armada_overlay.o \
+		   armada_slave.o
+armada-y	+= armada_510.o
+armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
+
+obj-$(CONFIG_DRM_ARMADA) := armada.o
diff --git a/drivers/gpu/drm/armada/armada_510.c b/drivers/gpu/drm/armada/armada_510.c
new file mode 100644
index 0000000..a016888
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_510.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Armada 510 (aka Dove) variant support
+ */
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_hw.h"
+
+static int armada510_init(struct armada_private *priv, struct device *dev)
+{
+	priv->extclk[0] = devm_clk_get(dev, "ext_ref_clk_1");
+
+	if (IS_ERR(priv->extclk[0]) && PTR_ERR(priv->extclk[0]) == -ENOENT)
+		priv->extclk[0] = ERR_PTR(-EPROBE_DEFER);
+
+	return PTR_RET(priv->extclk[0]);
+}
+
+static int armada510_crtc_init(struct armada_crtc *dcrtc)
+{
+	/* Lower the watermark so to eliminate jitter at higher bandwidths */
+	armada_updatel(0x20, (1 << 11) | 0xff, dcrtc->base + LCD_CFG_RDREG4F);
+	return 0;
+}
+
+/*
+ * Armada510 specific SCLK register selection.
+ * This gets called with sclk = NULL to test whether the mode is
+ * supportable, and again with sclk != NULL to set the clocks up for
+ * that.  The former can return an error, but the latter is expected
+ * not to.
+ *
+ * We currently are pretty rudimentary here, always selecting
+ * EXT_REF_CLK_1 for LCD0 and erroring LCD1.  This needs improvement!
+ */
+static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
+	const struct drm_display_mode *mode, uint32_t *sclk)
+{
+	struct armada_private *priv = dcrtc->crtc.dev->dev_private;
+	struct clk *clk = priv->extclk[0];
+	int ret;
+
+	if (dcrtc->num == 1)
+		return -EINVAL;
+
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	if (dcrtc->clk != clk) {
+		ret = clk_prepare_enable(clk);
+		if (ret)
+			return ret;
+		dcrtc->clk = clk;
+	}
+
+	if (sclk) {
+		uint32_t rate, ref, div;
+
+		rate = mode->clock * 1000;
+		ref = clk_round_rate(clk, rate);
+		div = DIV_ROUND_UP(ref, rate);
+		if (div < 1)
+			div = 1;
+
+		clk_set_rate(clk, ref);
+		*sclk = div | SCLK_510_EXTCLK1;
+	}
+
+	return 0;
+}
+
+const struct armada_variant armada510_ops = {
+	.has_spu_adv_reg = true,
+	.init = armada510_init,
+	.crtc_init = armada510_crtc_init,
+	.crtc_compute_clock = armada510_crtc_compute_clock,
+};
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
new file mode 100644
index 0000000..7b379fd
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -0,0 +1,861 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Rewritten from the dovefb driver, and Armada510 manuals.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_fb.h"
+#include "armada_gem.h"
+#include "armada_hw.h"
+
+struct armada_frame_work {
+	struct drm_pending_vblank_event *event;
+	struct armada_regs regs[4];
+	struct drm_framebuffer *old_fb;
+};
+
+enum csc_mode {
+	CSC_AUTO = 0,
+	CSC_YUV_CCIR601 = 1,
+	CSC_YUV_CCIR709 = 2,
+	CSC_RGB_COMPUTER = 1,
+	CSC_RGB_STUDIO = 2,
+};
+
+/*
+ * A note about interlacing.  Let's consider HDMI 1920x1080i.
+ * The timing parameters we have from X are:
+ *  Hact HsyA HsyI Htot  Vact VsyA VsyI Vtot
+ *  1920 2448 2492 2640  1080 1084 1094 1125
+ * Which get translated to:
+ *  Hact HsyA HsyI Htot  Vact VsyA VsyI Vtot
+ *  1920 2448 2492 2640   540  542  547  562
+ *
+ * This is how it is defined by CEA-861-D - line and pixel numbers are
+ * referenced to the rising edge of VSYNC and HSYNC.  Total clocks per
+ * line: 2640.  The odd frame, the first active line is at line 21, and
+ * the even frame, the first active line is 584.
+ *
+ * LN:    560     561     562     563             567     568    569
+ * DE:    ~~~|____________________________//__________________________
+ * HSYNC: ____|~|_____|~|_____|~|_____|~|_//__|~|_____|~|_____|~|_____
+ * VSYNC: _________________________|~~~~~~//~~~~~~~~~~~~~~~|__________
+ *  22 blanking lines.  VSYNC at 1320 (referenced to the HSYNC rising edge).
+ *
+ * LN:    1123   1124    1125      1               5       6      7
+ * DE:    ~~~|____________________________//__________________________
+ * HSYNC: ____|~|_____|~|_____|~|_____|~|_//__|~|_____|~|_____|~|_____
+ * VSYNC: ____________________|~~~~~~~~~~~//~~~~~~~~~~|_______________
+ *  23 blanking lines
+ *
+ * The Armada LCD Controller line and pixel numbers are, like X timings,
+ * referenced to the top left of the active frame.
+ *
+ * So, translating these to our LCD controller:
+ *  Odd frame, 563 total lines, VSYNC at line 543-548, pixel 1128.
+ *  Even frame, 562 total lines, VSYNC at line 542-547, pixel 2448.
+ * Note: Vsync front porch remains constant!
+ *
+ * if (odd_frame) {
+ *   vtotal = mode->crtc_vtotal + 1;
+ *   vbackporch = mode->crtc_vsync_start - mode->crtc_vdisplay + 1;
+ *   vhorizpos = mode->crtc_hsync_start - mode->crtc_htotal / 2
+ * } else {
+ *   vtotal = mode->crtc_vtotal;
+ *   vbackporch = mode->crtc_vsync_start - mode->crtc_vdisplay;
+ *   vhorizpos = mode->crtc_hsync_start;
+ * }
+ * vfrontporch = mode->crtc_vtotal - mode->crtc_vsync_end;
+ *
+ * So, we need to reprogram these registers on each vsync event:
+ *  LCD_SPU_V_PORCH, LCD_SPU_ADV_REG, LCD_SPUT_V_H_TOTAL
+ *
+ * Note: we do not use the frame done interrupts because these appear
+ * to happen too early, and lead to jitter on the display (presumably
+ * they occur at the end of the last active line, before the vsync back
+ * porch, which we're reprogramming.)
+ */
+
+void
+armada_drm_crtc_update_regs(struct armada_crtc *dcrtc, struct armada_regs *regs)
+{
+	while (regs->offset != ~0) {
+		void __iomem *reg = dcrtc->base + regs->offset;
+		uint32_t val;
+
+		val = regs->mask;
+		if (val != 0)
+			val &= readl_relaxed(reg);
+		writel_relaxed(val | regs->val, reg);
+		++regs;
+	}
+}
+
+#define dpms_blanked(dpms)	((dpms) != DRM_MODE_DPMS_ON)
+
+static void armada_drm_crtc_update(struct armada_crtc *dcrtc)
+{
+	uint32_t dumb_ctrl;
+
+	dumb_ctrl = dcrtc->cfg_dumb_ctrl;
+
+	if (!dpms_blanked(dcrtc->dpms))
+		dumb_ctrl |= CFG_DUMB_ENA;
+
+	/*
+	 * When the dumb interface isn't in DUMB24_RGB888_0 mode, it might
+	 * be using SPI or GPIO.  If we set this to DUMB_BLANK, we will
+	 * force LCD_D[23:0] to output blank color, overriding the GPIO or
+	 * SPI usage.  So leave it as-is unless in DUMB24_RGB888_0 mode.
+	 */
+	if (dpms_blanked(dcrtc->dpms) &&
+	    (dumb_ctrl & DUMB_MASK) == DUMB24_RGB888_0) {
+		dumb_ctrl &= ~DUMB_MASK;
+		dumb_ctrl |= DUMB_BLANK;
+	}
+
+	/*
+	 * The documentation doesn't indicate what the normal state of
+	 * the sync signals are.  Sebastian Hesselbart kindly probed
+	 * these signals on his board to determine their state.
+	 *
+	 * The non-inverted state of the sync signals is active high.
+	 * Setting these bits makes the appropriate signal active low.
+	 */
+	if (dcrtc->crtc.mode.flags & DRM_MODE_FLAG_NCSYNC)
+		dumb_ctrl |= CFG_INV_CSYNC;
+	if (dcrtc->crtc.mode.flags & DRM_MODE_FLAG_NHSYNC)
+		dumb_ctrl |= CFG_INV_HSYNC;
+	if (dcrtc->crtc.mode.flags & DRM_MODE_FLAG_NVSYNC)
+		dumb_ctrl |= CFG_INV_VSYNC;
+
+	if (dcrtc->dumb_ctrl != dumb_ctrl) {
+		dcrtc->dumb_ctrl = dumb_ctrl;
+		writel_relaxed(dumb_ctrl, dcrtc->base + LCD_SPU_DUMB_CTRL);
+	}
+}
+
+static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb,
+	int x, int y, struct armada_regs *regs, bool interlaced)
+{
+	struct armada_gem_object *obj = drm_fb_obj(fb);
+	unsigned pitch = fb->pitches[0];
+	unsigned offset = y * pitch + x * fb->bits_per_pixel / 8;
+	uint32_t addr_odd, addr_even;
+	unsigned i = 0;
+
+	DRM_DEBUG_DRIVER("pitch %u x %d y %d bpp %d\n",
+		pitch, x, y, fb->bits_per_pixel);
+
+	addr_odd = addr_even = obj->dev_addr + offset;
+
+	if (interlaced) {
+		addr_even += pitch;
+		pitch *= 2;
+	}
+
+	/* write offset, base, and pitch */
+	armada_reg_queue_set(regs, i, addr_odd, LCD_CFG_GRA_START_ADDR0);
+	armada_reg_queue_set(regs, i, addr_even, LCD_CFG_GRA_START_ADDR1);
+	armada_reg_queue_mod(regs, i, pitch, 0xffff, LCD_CFG_GRA_PITCH);
+
+	return i;
+}
+
+static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc,
+	struct armada_frame_work *work)
+{
+	struct drm_device *dev = dcrtc->crtc.dev;
+	unsigned long flags;
+	int ret;
+
+	ret = drm_vblank_get(dev, dcrtc->num);
+	if (ret) {
+		DRM_ERROR("failed to acquire vblank counter\n");
+		return ret;
+	}
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	if (!dcrtc->frame_work)
+		dcrtc->frame_work = work;
+	else
+		ret = -EBUSY;
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	if (ret)
+		drm_vblank_put(dev, dcrtc->num);
+
+	return ret;
+}
+
+static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc)
+{
+	struct drm_device *dev = dcrtc->crtc.dev;
+	struct armada_frame_work *work = dcrtc->frame_work;
+
+	dcrtc->frame_work = NULL;
+
+	armada_drm_crtc_update_regs(dcrtc, work->regs);
+
+	if (work->event)
+		drm_send_vblank_event(dev, dcrtc->num, work->event);
+
+	drm_vblank_put(dev, dcrtc->num);
+
+	/* Finally, queue the process-half of the cleanup. */
+	__armada_drm_queue_unref_work(dcrtc->crtc.dev, work->old_fb);
+	kfree(work);
+}
+
+static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc,
+	struct drm_framebuffer *fb, bool force)
+{
+	struct armada_frame_work *work;
+
+	if (!fb)
+		return;
+
+	if (force) {
+		/* Display is disabled, so just drop the old fb */
+		drm_framebuffer_unreference(fb);
+		return;
+	}
+
+	work = kmalloc(sizeof(*work), GFP_KERNEL);
+	if (work) {
+		int i = 0;
+		work->event = NULL;
+		work->old_fb = fb;
+		armada_reg_queue_end(work->regs, i);
+
+		if (armada_drm_crtc_queue_frame_work(dcrtc, work) == 0)
+			return;
+
+		kfree(work);
+	}
+
+	/*
+	 * Oops - just drop the reference immediately and hope for
+	 * the best.  The worst that will happen is the buffer gets
+	 * reused before it has finished being displayed.
+	 */
+	drm_framebuffer_unreference(fb);
+}
+
+static void armada_drm_vblank_off(struct armada_crtc *dcrtc)
+{
+	struct drm_device *dev = dcrtc->crtc.dev;
+
+	/*
+	 * Tell the DRM core that vblank IRQs aren't going to happen for
+	 * a while.  This cleans up any pending vblank events for us.
+	 */
+	drm_vblank_off(dev, dcrtc->num);
+
+	/* Handle any pending flip event. */
+	spin_lock_irq(&dev->event_lock);
+	if (dcrtc->frame_work)
+		armada_drm_crtc_complete_frame_work(dcrtc);
+	spin_unlock_irq(&dev->event_lock);
+}
+
+void armada_drm_crtc_gamma_set(struct drm_crtc *crtc, u16 r, u16 g, u16 b,
+	int idx)
+{
+}
+
+void armada_drm_crtc_gamma_get(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
+	int idx)
+{
+}
+
+/* The mode_config.mutex will be held for this call */
+static void armada_drm_crtc_dpms(struct drm_crtc *crtc, int dpms)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+
+	if (dcrtc->dpms != dpms) {
+		dcrtc->dpms = dpms;
+		armada_drm_crtc_update(dcrtc);
+		if (dpms_blanked(dpms))
+			armada_drm_vblank_off(dcrtc);
+	}
+}
+
+/*
+ * Prepare for a mode set.  Turn off overlay to ensure that we don't end
+ * up with the overlay size being bigger than the active screen size.
+ * We rely upon X refreshing this state after the mode set has completed.
+ *
+ * The mode_config.mutex will be held for this call
+ */
+static void armada_drm_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct drm_plane *plane;
+
+	/*
+	 * If we have an overlay plane associated with this CRTC, disable
+	 * it before the modeset to avoid its coordinates being outside
+	 * the new mode parameters.  DRM doesn't provide help with this.
+	 */
+	plane = dcrtc->plane;
+	if (plane) {
+		struct drm_framebuffer *fb = plane->fb;
+
+		plane->funcs->disable_plane(plane);
+		plane->fb = NULL;
+		plane->crtc = NULL;
+		drm_framebuffer_unreference(fb);
+	}
+}
+
+/* The mode_config.mutex will be held for this call */
+static void armada_drm_crtc_commit(struct drm_crtc *crtc)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+
+	if (dcrtc->dpms != DRM_MODE_DPMS_ON) {
+		dcrtc->dpms = DRM_MODE_DPMS_ON;
+		armada_drm_crtc_update(dcrtc);
+	}
+}
+
+/* The mode_config.mutex will be held for this call */
+static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+	const struct drm_display_mode *mode, struct drm_display_mode *adj)
+{
+	struct armada_private *priv = crtc->dev->dev_private;
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	int ret;
+
+	/* We can't do interlaced modes if we don't have the SPU_ADV_REG */
+	if (!priv->variant->has_spu_adv_reg &&
+	    adj->flags & DRM_MODE_FLAG_INTERLACE)
+		return false;
+
+	/* Check whether the display mode is possible */
+	ret = priv->variant->crtc_compute_clock(dcrtc, adj, NULL);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
+{
+	struct armada_vbl_event *e, *n;
+	void __iomem *base = dcrtc->base;
+
+	if (stat & DMA_FF_UNDERFLOW)
+		DRM_ERROR("video underflow on crtc %u\n", dcrtc->num);
+	if (stat & GRA_FF_UNDERFLOW)
+		DRM_ERROR("graphics underflow on crtc %u\n", dcrtc->num);
+
+	if (stat & VSYNC_IRQ)
+		drm_handle_vblank(dcrtc->crtc.dev, dcrtc->num);
+
+	spin_lock(&dcrtc->irq_lock);
+
+	list_for_each_entry_safe(e, n, &dcrtc->vbl_list, node) {
+		list_del_init(&e->node);
+		drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
+		e->fn(dcrtc, e->data);
+	}
+
+	if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) {
+		int i = stat & GRA_FRAME_IRQ0 ? 0 : 1;
+		uint32_t val;
+
+		writel_relaxed(dcrtc->v[i].spu_v_porch, base + LCD_SPU_V_PORCH);
+		writel_relaxed(dcrtc->v[i].spu_v_h_total,
+			       base + LCD_SPUT_V_H_TOTAL);
+
+		val = readl_relaxed(base + LCD_SPU_ADV_REG);
+		val &= ~(ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF | ADV_VSYNCOFFEN);
+		val |= dcrtc->v[i].spu_adv_reg;
+		writel_relaxed(val, dcrtc->base + LCD_SPU_ADV_REG);
+	}
+	spin_unlock(&dcrtc->irq_lock);
+
+	if (stat & GRA_FRAME_IRQ) {
+		struct drm_device *dev = dcrtc->crtc.dev;
+
+		spin_lock(&dev->event_lock);
+		if (dcrtc->frame_work)
+			armada_drm_crtc_complete_frame_work(dcrtc);
+		spin_unlock(&dev->event_lock);
+
+		wake_up(&dcrtc->frame_wait);
+	}
+}
+
+/* These are locked by dev->vbl_lock */
+void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask)
+{
+	if (dcrtc->irq_ena & mask) {
+		dcrtc->irq_ena &= ~mask;
+		writel(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
+	}
+}
+
+void armada_drm_crtc_enable_irq(struct armada_crtc *dcrtc, u32 mask)
+{
+	if ((dcrtc->irq_ena & mask) != mask) {
+		dcrtc->irq_ena |= mask;
+		writel(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
+		if (readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR) & mask)
+			writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
+	}
+}
+
+static uint32_t armada_drm_crtc_calculate_csc(struct armada_crtc *dcrtc)
+{
+	struct drm_display_mode *adj = &dcrtc->crtc.mode;
+	uint32_t val = 0;
+
+	if (dcrtc->csc_yuv_mode == CSC_YUV_CCIR709)
+		val |= CFG_CSC_YUV_CCIR709;
+	if (dcrtc->csc_rgb_mode == CSC_RGB_STUDIO)
+		val |= CFG_CSC_RGB_STUDIO;
+
+	/*
+	 * In auto mode, set the colorimetry, based upon the HDMI spec.
+	 * 1280x720p, 1920x1080p and 1920x1080i use ITU709, others use
+	 * ITU601.  It may be more appropriate to set this depending on
+	 * the source - but what if the graphic frame is YUV and the
+	 * video frame is RGB?
+	 */
+	if ((adj->hdisplay == 1280 && adj->vdisplay == 720 &&
+	     !(adj->flags & DRM_MODE_FLAG_INTERLACE)) ||
+	    (adj->hdisplay == 1920 && adj->vdisplay == 1080)) {
+		if (dcrtc->csc_yuv_mode == CSC_AUTO)
+			val |= CFG_CSC_YUV_CCIR709;
+	}
+
+	/*
+	 * We assume we're connected to a TV-like device, so the YUV->RGB
+	 * conversion should produce a limited range.  We should set this
+	 * depending on the connectors attached to this CRTC, and what
+	 * kind of device they report being connected.
+	 */
+	if (dcrtc->csc_rgb_mode == CSC_AUTO)
+		val |= CFG_CSC_RGB_STUDIO;
+
+	return val;
+}
+
+/* The mode_config.mutex will be held for this call */
+static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
+	struct drm_display_mode *mode, struct drm_display_mode *adj,
+	int x, int y, struct drm_framebuffer *old_fb)
+{
+	struct armada_private *priv = crtc->dev->dev_private;
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_regs regs[17];
+	uint32_t lm, rm, tm, bm, val, sclk;
+	unsigned long flags;
+	unsigned i;
+	bool interlaced;
+
+	drm_framebuffer_reference(crtc->fb);
+
+	interlaced = !!(adj->flags & DRM_MODE_FLAG_INTERLACE);
+
+	i = armada_drm_crtc_calc_fb(dcrtc->crtc.fb, x, y, regs, interlaced);
+
+	rm = adj->crtc_hsync_start - adj->crtc_hdisplay;
+	lm = adj->crtc_htotal - adj->crtc_hsync_end;
+	bm = adj->crtc_vsync_start - adj->crtc_vdisplay;
+	tm = adj->crtc_vtotal - adj->crtc_vsync_end;
+
+	DRM_DEBUG_DRIVER("H: %d %d %d %d lm %d rm %d\n",
+		adj->crtc_hdisplay,
+		adj->crtc_hsync_start,
+		adj->crtc_hsync_end,
+		adj->crtc_htotal, lm, rm);
+	DRM_DEBUG_DRIVER("V: %d %d %d %d tm %d bm %d\n",
+		adj->crtc_vdisplay,
+		adj->crtc_vsync_start,
+		adj->crtc_vsync_end,
+		adj->crtc_vtotal, tm, bm);
+
+	/* Wait for pending flips to complete */
+	wait_event(dcrtc->frame_wait, !dcrtc->frame_work);
+
+	drm_vblank_pre_modeset(crtc->dev, dcrtc->num);
+
+	crtc->mode = *adj;
+
+	val = dcrtc->dumb_ctrl & ~CFG_DUMB_ENA;
+	if (val != dcrtc->dumb_ctrl) {
+		dcrtc->dumb_ctrl = val;
+		writel_relaxed(val, dcrtc->base + LCD_SPU_DUMB_CTRL);
+	}
+
+	/* Now compute the divider for real */
+	priv->variant->crtc_compute_clock(dcrtc, adj, &sclk);
+
+	/* Ensure graphic fifo is enabled */
+	armada_reg_queue_mod(regs, i, 0, CFG_PDWN64x66, LCD_SPU_SRAM_PARA1);
+	armada_reg_queue_set(regs, i, sclk, LCD_CFG_SCLK_DIV);
+
+	if (interlaced ^ dcrtc->interlaced) {
+		if (adj->flags & DRM_MODE_FLAG_INTERLACE)
+			drm_vblank_get(dcrtc->crtc.dev, dcrtc->num);
+		else
+			drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
+		dcrtc->interlaced = interlaced;
+	}
+
+	spin_lock_irqsave(&dcrtc->irq_lock, flags);
+
+	/* Even interlaced/progressive frame */
+	dcrtc->v[1].spu_v_h_total = adj->crtc_vtotal << 16 |
+				    adj->crtc_htotal;
+	dcrtc->v[1].spu_v_porch = tm << 16 | bm;
+	val = adj->crtc_hsync_start;
+	dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN;
+
+	if (interlaced) {
+		/* Odd interlaced frame */
+		dcrtc->v[0].spu_v_h_total = dcrtc->v[1].spu_v_h_total +
+						(1 << 16);
+		dcrtc->v[0].spu_v_porch = dcrtc->v[1].spu_v_porch + 1;
+		val = adj->crtc_hsync_start - adj->crtc_htotal / 2;
+		dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN;
+	} else {
+		dcrtc->v[0] = dcrtc->v[1];
+	}
+
+	val = adj->crtc_vdisplay << 16 | adj->crtc_hdisplay;
+
+	armada_reg_queue_set(regs, i, val, LCD_SPU_V_H_ACTIVE);
+	armada_reg_queue_set(regs, i, val, LCD_SPU_GRA_HPXL_VLN);
+	armada_reg_queue_set(regs, i, val, LCD_SPU_GZM_HPXL_VLN);
+	armada_reg_queue_set(regs, i, (lm << 16) | rm, LCD_SPU_H_PORCH);
+	armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_porch, LCD_SPU_V_PORCH);
+	armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total,
+			   LCD_SPUT_V_H_TOTAL);
+
+	if (priv->variant->has_spu_adv_reg)
+		armada_reg_queue_mod(regs, i, dcrtc->v[0].spu_adv_reg,
+				     ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF |
+				     ADV_VSYNCOFFEN, LCD_SPU_ADV_REG);
+
+	val = CFG_GRA_ENA | CFG_GRA_HSMOOTH;
+	val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.fb)->fmt);
+	val |= CFG_GRA_MOD(drm_fb_to_armada_fb(dcrtc->crtc.fb)->mod);
+
+	if (drm_fb_to_armada_fb(dcrtc->crtc.fb)->fmt > CFG_420)
+		val |= CFG_PALETTE_ENA;
+
+	if (interlaced)
+		val |= CFG_GRA_FTOGGLE;
+
+	armada_reg_queue_mod(regs, i, val, CFG_GRAFORMAT |
+			     CFG_GRA_MOD(CFG_SWAPRB | CFG_SWAPUV |
+					 CFG_SWAPYU | CFG_YUV2RGB) |
+			     CFG_PALETTE_ENA | CFG_GRA_FTOGGLE,
+			     LCD_SPU_DMA_CTRL0);
+
+	val = adj->flags & DRM_MODE_FLAG_NVSYNC ? CFG_VSYNC_INV : 0;
+	armada_reg_queue_mod(regs, i, val, CFG_VSYNC_INV, LCD_SPU_DMA_CTRL1);
+
+	val = dcrtc->spu_iopad_ctrl | armada_drm_crtc_calculate_csc(dcrtc);
+	armada_reg_queue_set(regs, i, val, LCD_SPU_IOPAD_CONTROL);
+	armada_reg_queue_end(regs, i);
+
+	armada_drm_crtc_update_regs(dcrtc, regs);
+	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
+
+	armada_drm_crtc_update(dcrtc);
+
+	drm_vblank_post_modeset(crtc->dev, dcrtc->num);
+	armada_drm_crtc_finish_fb(dcrtc, old_fb, dpms_blanked(dcrtc->dpms));
+
+	return 0;
+}
+
+/* The mode_config.mutex will be held for this call */
+static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+	struct drm_framebuffer *old_fb)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_regs regs[4];
+	unsigned i;
+
+	i = armada_drm_crtc_calc_fb(crtc->fb, crtc->x, crtc->y, regs,
+				    dcrtc->interlaced);
+	armada_reg_queue_end(regs, i);
+
+	/* Wait for pending flips to complete */
+	wait_event(dcrtc->frame_wait, !dcrtc->frame_work);
+
+	/* Take a reference to the new fb as we're using it */
+	drm_framebuffer_reference(crtc->fb);
+
+	/* Update the base in the CRTC */
+	armada_drm_crtc_update_regs(dcrtc, regs);
+
+	/* Drop our previously held reference */
+	armada_drm_crtc_finish_fb(dcrtc, old_fb, dpms_blanked(dcrtc->dpms));
+
+	return 0;
+}
+
+static void armada_drm_crtc_load_lut(struct drm_crtc *crtc)
+{
+}
+
+/* The mode_config.mutex will be held for this call */
+static void armada_drm_crtc_disable(struct drm_crtc *crtc)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+
+	armada_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+	armada_drm_crtc_finish_fb(dcrtc, crtc->fb, true);
+
+	/* Power down most RAMs and FIFOs */
+	writel_relaxed(CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 |
+		       CFG_PDWN32x32 | CFG_PDWN16x66 | CFG_PDWN32x66 |
+		       CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
+}
+
+static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = {
+	.dpms		= armada_drm_crtc_dpms,
+	.prepare	= armada_drm_crtc_prepare,
+	.commit		= armada_drm_crtc_commit,
+	.mode_fixup	= armada_drm_crtc_mode_fixup,
+	.mode_set	= armada_drm_crtc_mode_set,
+	.mode_set_base	= armada_drm_crtc_mode_set_base,
+	.load_lut	= armada_drm_crtc_load_lut,
+	.disable	= armada_drm_crtc_disable,
+};
+
+static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_private *priv = crtc->dev->dev_private;
+
+	priv->dcrtc[dcrtc->num] = NULL;
+	drm_crtc_cleanup(&dcrtc->crtc);
+
+	if (!IS_ERR(dcrtc->clk))
+		clk_disable_unprepare(dcrtc->clk);
+
+	kfree(dcrtc);
+}
+
+/*
+ * The mode_config lock is held here, to prevent races between this
+ * and a mode_set.
+ */
+static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
+	struct drm_framebuffer *fb, struct drm_pending_vblank_event *event)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_frame_work *work;
+	struct drm_device *dev = crtc->dev;
+	unsigned long flags;
+	unsigned i;
+	int ret;
+
+	/* We don't support changing the pixel format */
+	if (fb->pixel_format != crtc->fb->pixel_format)
+		return -EINVAL;
+
+	work = kmalloc(sizeof(*work), GFP_KERNEL);
+	if (!work)
+		return -ENOMEM;
+
+	work->event = event;
+	work->old_fb = dcrtc->crtc.fb;
+
+	i = armada_drm_crtc_calc_fb(fb, crtc->x, crtc->y, work->regs,
+				    dcrtc->interlaced);
+	armada_reg_queue_end(work->regs, i);
+
+	/*
+	 * Hold the old framebuffer for the work - DRM appears to drop our
+	 * reference to the old framebuffer in drm_mode_page_flip_ioctl().
+	 */
+	drm_framebuffer_reference(work->old_fb);
+
+	ret = armada_drm_crtc_queue_frame_work(dcrtc, work);
+	if (ret) {
+		/*
+		 * Undo our reference above; DRM does not drop the reference
+		 * to this object on error, so that's okay.
+		 */
+		drm_framebuffer_unreference(work->old_fb);
+		kfree(work);
+		return ret;
+	}
+
+	/*
+	 * Don't take a reference on the new framebuffer;
+	 * drm_mode_page_flip_ioctl() has already grabbed a reference and
+	 * will _not_ drop that reference on successful return from this
+	 * function.  Simply mark this new framebuffer as the current one.
+	 */
+	dcrtc->crtc.fb = fb;
+
+	/*
+	 * Finally, if the display is blanked, we won't receive an
+	 * interrupt, so complete it now.
+	 */
+	if (dpms_blanked(dcrtc->dpms)) {
+		spin_lock_irqsave(&dev->event_lock, flags);
+		if (dcrtc->frame_work)
+			armada_drm_crtc_complete_frame_work(dcrtc);
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+	}
+
+	return 0;
+}
+
+static int
+armada_drm_crtc_set_property(struct drm_crtc *crtc,
+	struct drm_property *property, uint64_t val)
+{
+	struct armada_private *priv = crtc->dev->dev_private;
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	bool update_csc = false;
+
+	if (property == priv->csc_yuv_prop) {
+		dcrtc->csc_yuv_mode = val;
+		update_csc = true;
+	} else if (property == priv->csc_rgb_prop) {
+		dcrtc->csc_rgb_mode = val;
+		update_csc = true;
+	}
+
+	if (update_csc) {
+		uint32_t val;
+
+		val = dcrtc->spu_iopad_ctrl |
+		      armada_drm_crtc_calculate_csc(dcrtc);
+		writel_relaxed(val, dcrtc->base + LCD_SPU_IOPAD_CONTROL);
+	}
+
+	return 0;
+}
+
+static struct drm_crtc_funcs armada_crtc_funcs = {
+	.destroy	= armada_drm_crtc_destroy,
+	.set_config	= drm_crtc_helper_set_config,
+	.page_flip	= armada_drm_crtc_page_flip,
+	.set_property	= armada_drm_crtc_set_property,
+};
+
+static struct drm_prop_enum_list armada_drm_csc_yuv_enum_list[] = {
+	{ CSC_AUTO,        "Auto" },
+	{ CSC_YUV_CCIR601, "CCIR601" },
+	{ CSC_YUV_CCIR709, "CCIR709" },
+};
+
+static struct drm_prop_enum_list armada_drm_csc_rgb_enum_list[] = {
+	{ CSC_AUTO,         "Auto" },
+	{ CSC_RGB_COMPUTER, "Computer system" },
+	{ CSC_RGB_STUDIO,   "Studio" },
+};
+
+static int armada_drm_crtc_create_properties(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+
+	if (priv->csc_yuv_prop)
+		return 0;
+
+	priv->csc_yuv_prop = drm_property_create_enum(dev, 0,
+				"CSC_YUV", armada_drm_csc_yuv_enum_list,
+				ARRAY_SIZE(armada_drm_csc_yuv_enum_list));
+	priv->csc_rgb_prop = drm_property_create_enum(dev, 0,
+				"CSC_RGB", armada_drm_csc_rgb_enum_list,
+				ARRAY_SIZE(armada_drm_csc_rgb_enum_list));
+
+	if (!priv->csc_yuv_prop || !priv->csc_rgb_prop)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
+	struct resource *res)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct armada_crtc *dcrtc;
+	void __iomem *base;
+	int ret;
+
+	ret = armada_drm_crtc_create_properties(dev);
+	if (ret)
+		return ret;
+
+	base = devm_request_and_ioremap(dev->dev, res);
+	if (!base) {
+		DRM_ERROR("failed to ioremap register\n");
+		return -ENOMEM;
+	}
+
+	dcrtc = kzalloc(sizeof(*dcrtc), GFP_KERNEL);
+	if (!dcrtc) {
+		DRM_ERROR("failed to allocate Armada crtc\n");
+		return -ENOMEM;
+	}
+
+	dcrtc->base = base;
+	dcrtc->num = num;
+	dcrtc->clk = ERR_PTR(-EINVAL);
+	dcrtc->csc_yuv_mode = CSC_AUTO;
+	dcrtc->csc_rgb_mode = CSC_AUTO;
+	dcrtc->cfg_dumb_ctrl = DUMB24_RGB888_0;
+	dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
+	spin_lock_init(&dcrtc->irq_lock);
+	dcrtc->irq_ena = CLEAN_SPU_IRQ_ISR;
+	INIT_LIST_HEAD(&dcrtc->vbl_list);
+	init_waitqueue_head(&dcrtc->frame_wait);
+
+	/* Initialize some registers which we don't otherwise set */
+	writel_relaxed(0x00000001, dcrtc->base + LCD_CFG_SCLK_DIV);
+	writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_BLANKCOLOR);
+	writel_relaxed(dcrtc->spu_iopad_ctrl,
+		       dcrtc->base + LCD_SPU_IOPAD_CONTROL);
+	writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_SRAM_PARA0);
+	writel_relaxed(CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 |
+		       CFG_PDWN32x32 | CFG_PDWN16x66 | CFG_PDWN32x66 |
+		       CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
+	writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1);
+	writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN);
+
+	if (priv->variant->crtc_init) {
+		ret = priv->variant->crtc_init(dcrtc);
+		if (ret) {
+			kfree(dcrtc);
+			return ret;
+		}
+	}
+
+	/* Ensure AXI pipeline is enabled */
+	armada_updatel(CFG_ARBFAST_ENA, 0, dcrtc->base + LCD_SPU_DMA_CTRL0);
+
+	priv->dcrtc[dcrtc->num] = dcrtc;
+
+	drm_crtc_init(dev, &dcrtc->crtc, &armada_crtc_funcs);
+	drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);
+
+	drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop,
+				   dcrtc->csc_yuv_mode);
+	drm_object_attach_property(&dcrtc->crtc.base, priv->csc_rgb_prop,
+				   dcrtc->csc_rgb_mode);
+
+	return armada_overlay_plane_create(dev, 1 << dcrtc->num);
+}
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
new file mode 100644
index 0000000..972da53
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_CRTC_H
+#define ARMADA_CRTC_H
+
+struct armada_gem_object;
+
+struct armada_regs {
+	uint32_t offset;
+	uint32_t mask;
+	uint32_t val;
+};
+
+#define armada_reg_queue_mod(_r, _i, _v, _m, _o)	\
+	do {					\
+		struct armada_regs *__reg = _r;	\
+		__reg[_i].offset = _o;		\
+		__reg[_i].mask = ~(_m);		\
+		__reg[_i].val = _v;		\
+		_i++;				\
+	} while (0)
+
+#define armada_reg_queue_set(_r, _i, _v, _o)	\
+	armada_reg_queue_mod(_r, _i, _v, ~0, _o)
+
+#define armada_reg_queue_end(_r, _i)		\
+	armada_reg_queue_mod(_r, _i, 0, 0, ~0)
+
+struct armada_frame_work;
+
+struct armada_crtc {
+	struct drm_crtc		crtc;
+	unsigned		num;
+	void __iomem		*base;
+	struct clk		*clk;
+	struct {
+		uint32_t	spu_v_h_total;
+		uint32_t	spu_v_porch;
+		uint32_t	spu_adv_reg;
+	} v[2];
+	bool			interlaced;
+	uint8_t			csc_yuv_mode;
+	uint8_t			csc_rgb_mode;
+
+	struct drm_plane	*plane;
+
+	int			dpms;
+	uint32_t		cfg_dumb_ctrl;
+	uint32_t		dumb_ctrl;
+	uint32_t		spu_iopad_ctrl;
+
+	wait_queue_head_t	frame_wait;
+	struct armada_frame_work *frame_work;
+
+	spinlock_t		irq_lock;
+	uint32_t		irq_ena;
+	struct list_head	vbl_list;
+};
+#define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)
+
+int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *);
+void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
+void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
+void armada_drm_crtc_irq(struct armada_crtc *, u32);
+void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
+void armada_drm_crtc_enable_irq(struct armada_crtc *, u32);
+void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
+
+#endif
diff --git a/drivers/gpu/drm/armada/armada_debugfs.c b/drivers/gpu/drm/armada/armada_debugfs.c
new file mode 100644
index 0000000..612f375
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_debugfs.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Rewritten from the dovefb driver, and Armada510 manuals.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <drm/drmP.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+
+static int armada_debugfs_gem_linear_show(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct armada_private *priv = dev->dev_private;
+	int ret;
+
+	mutex_lock(&dev->struct_mutex);
+	ret = drm_mm_dump_table(m, &priv->linear);
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+static int armada_debugfs_reg_show(struct seq_file *m, void *data)
+{
+	struct drm_device *dev = m->private;
+	struct armada_private *priv = dev->dev_private;
+	int n, i;
+
+	if (priv) {
+		for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
+			struct armada_crtc *dcrtc = priv->dcrtc[n];
+			if (!dcrtc)
+				continue;
+
+			for (i = 0x84; i <= 0x1c4; i += 4) {
+				uint32_t v = readl_relaxed(dcrtc->base + i);
+				seq_printf(m, "%u: 0x%04x: 0x%08x\n", n, i, v);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int armada_debugfs_reg_r_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, armada_debugfs_reg_show, inode->i_private);
+}
+
+static const struct file_operations fops_reg_r = {
+	.owner = THIS_MODULE,
+	.open = armada_debugfs_reg_r_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int armada_debugfs_write(struct file *file, const char __user *ptr,
+	size_t len, loff_t *off)
+{
+	struct drm_device *dev = file->private_data;
+	struct armada_private *priv = dev->dev_private;
+	struct armada_crtc *dcrtc = priv->dcrtc[0];
+	char buf[32], *p;
+	uint32_t reg, val;
+	int ret;
+
+	if (*off != 0)
+		return 0;
+
+	if (len > sizeof(buf) - 1)
+		len = sizeof(buf) - 1;
+
+	ret = strncpy_from_user(buf, ptr, len);
+	if (ret < 0)
+		return ret;
+	buf[len] = '\0';
+
+	reg = simple_strtoul(buf, &p, 16);
+	if (!isspace(*p))
+		return -EINVAL;
+	val = simple_strtoul(p + 1, NULL, 16);
+
+	if (reg >= 0x84 && reg <= 0x1c4)
+		writel(val, dcrtc->base + reg);
+
+	return len;
+}
+
+static int armada_debugfs_reg_w_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static const struct file_operations fops_reg_w = {
+	.owner = THIS_MODULE,
+	.open = armada_debugfs_reg_w_open,
+	.write = armada_debugfs_write,
+	.llseek = noop_llseek,
+};
+
+static struct drm_info_list armada_debugfs_list[] = {
+	{ "gem_linear", armada_debugfs_gem_linear_show, 0 },
+};
+#define ARMADA_DEBUGFS_ENTRIES ARRAY_SIZE(armada_debugfs_list)
+
+static int drm_add_fake_info_node(struct drm_minor *minor, struct dentry *ent,
+	const void *key)
+{
+	struct drm_info_node *node;
+
+	node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
+	if (node == NULL) {
+		debugfs_remove(ent);
+		return -ENOMEM;
+	}
+
+	node->minor = minor;
+	node->dent = ent;
+	node->info_ent = (void *) key;
+
+	mutex_lock(&minor->debugfs_lock);
+	list_add(&node->list, &minor->debugfs_list);
+	mutex_unlock(&minor->debugfs_lock);
+
+	return 0;
+}
+
+static int armada_debugfs_create(struct dentry *root, struct drm_minor *minor,
+	const char *name, umode_t mode, const struct file_operations *fops)
+{
+	struct dentry *de;
+
+	de = debugfs_create_file(name, mode, root, minor->dev, fops);
+
+	return drm_add_fake_info_node(minor, de, fops);
+}
+
+int armada_drm_debugfs_init(struct drm_minor *minor)
+{
+	int ret;
+
+	ret = drm_debugfs_create_files(armada_debugfs_list,
+				       ARMADA_DEBUGFS_ENTRIES,
+				       minor->debugfs_root, minor);
+	if (ret)
+		return ret;
+
+	ret = armada_debugfs_create(minor->debugfs_root, minor,
+				   "reg", S_IFREG | S_IRUSR, &fops_reg_r);
+	if (ret)
+		goto err_1;
+
+	ret = armada_debugfs_create(minor->debugfs_root, minor,
+				"reg_wr", S_IFREG | S_IWUSR, &fops_reg_w);
+	if (ret)
+		goto err_2;
+	return ret;
+
+ err_2:
+	drm_debugfs_remove_files((struct drm_info_list *)&fops_reg_r, 1, minor);
+ err_1:
+	drm_debugfs_remove_files(armada_debugfs_list, ARMADA_DEBUGFS_ENTRIES,
+				 minor);
+	return ret;
+}
+
+void armada_drm_debugfs_cleanup(struct drm_minor *minor)
+{
+	drm_debugfs_remove_files((struct drm_info_list *)&fops_reg_w, 1, minor);
+	drm_debugfs_remove_files((struct drm_info_list *)&fops_reg_r, 1, minor);
+	drm_debugfs_remove_files(armada_debugfs_list, ARMADA_DEBUGFS_ENTRIES,
+				 minor);
+}
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
new file mode 100644
index 0000000..e8c4f80
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_DRM_H
+#define ARMADA_DRM_H
+
+#include <linux/kfifo.h>
+#include <linux/io.h>
+#include <linux/workqueue.h>
+#include <drm/drmP.h>
+
+struct armada_crtc;
+struct armada_gem_object;
+struct clk;
+struct drm_fb_helper;
+
+static inline void
+armada_updatel(uint32_t val, uint32_t mask, void __iomem *ptr)
+{
+	uint32_t ov, v;
+
+	ov = v = readl_relaxed(ptr);
+	v = (v & ~mask) | val;
+	if (ov != v)
+		writel_relaxed(v, ptr);
+}
+
+static inline uint32_t armada_pitch(uint32_t width, uint32_t bpp)
+{
+	uint32_t pitch = bpp != 4 ? width * ((bpp + 7) / 8) : width / 2;
+
+	/* 88AP510 spec recommends pitch be a multiple of 128 */
+	return ALIGN(pitch, 128);
+}
+
+struct armada_vbl_event {
+	struct list_head	node;
+	void			*data;
+	void			(*fn)(struct armada_crtc *, void *);
+};
+void armada_drm_vbl_event_add(struct armada_crtc *,
+	struct armada_vbl_event *);
+void armada_drm_vbl_event_remove(struct armada_crtc *,
+	struct armada_vbl_event *);
+void armada_drm_vbl_event_remove_unlocked(struct armada_crtc *,
+	struct armada_vbl_event *);
+#define armada_drm_vbl_event_init(_e, _f, _d) do {	\
+	struct armada_vbl_event *__e = _e;		\
+	INIT_LIST_HEAD(&__e->node);			\
+	__e->data = _d;					\
+	__e->fn = _f;					\
+} while (0)
+
+
+struct armada_private;
+
+struct armada_variant {
+	bool	has_spu_adv_reg;
+	int (*init)(struct armada_private *, struct device *);
+	int (*crtc_init)(struct armada_crtc *);
+	int (*crtc_compute_clock)(struct armada_crtc *,
+				  const struct drm_display_mode *,
+				  uint32_t *);
+};
+
+/* Variant ops */
+extern const struct armada_variant armada510_ops;
+
+struct armada_private {
+	const struct armada_variant *variant;
+	struct work_struct	fb_unref_work;
+	DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8);
+	struct drm_fb_helper	*fbdev;
+	struct armada_crtc	*dcrtc[2];
+	struct drm_mm		linear;
+	struct clk		*extclk[2];
+	struct drm_property	*csc_yuv_prop;
+	struct drm_property	*csc_rgb_prop;
+	struct drm_property	*colorkey_prop;
+	struct drm_property	*colorkey_min_prop;
+	struct drm_property	*colorkey_max_prop;
+	struct drm_property	*colorkey_val_prop;
+	struct drm_property	*colorkey_alpha_prop;
+	struct drm_property	*colorkey_mode_prop;
+	struct drm_property	*brightness_prop;
+	struct drm_property	*contrast_prop;
+	struct drm_property	*saturation_prop;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry		*de;
+#endif
+};
+
+void __armada_drm_queue_unref_work(struct drm_device *,
+	struct drm_framebuffer *);
+void armada_drm_queue_unref_work(struct drm_device *,
+	struct drm_framebuffer *);
+
+extern const struct drm_mode_config_funcs armada_drm_mode_config_funcs;
+
+int armada_fbdev_init(struct drm_device *);
+void armada_fbdev_fini(struct drm_device *);
+
+int armada_overlay_plane_create(struct drm_device *, unsigned long);
+
+int armada_drm_debugfs_init(struct drm_minor *);
+void armada_drm_debugfs_cleanup(struct drm_minor *);
+
+#endif
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
new file mode 100644
index 0000000..7bfab9a
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_gem.h"
+#include "armada_hw.h"
+#include <drm/armada_drm.h>
+#include "armada_ioctlP.h"
+
+static void armada_drm_unref_work(struct work_struct *work)
+{
+	struct armada_private *priv =
+		container_of(work, struct armada_private, fb_unref_work);
+	struct drm_framebuffer *fb;
+
+	while (kfifo_get(&priv->fb_unref, &fb))
+		drm_framebuffer_unreference(fb);
+}
+
+/* Must be called with dev->event_lock held */
+void __armada_drm_queue_unref_work(struct drm_device *dev,
+	struct drm_framebuffer *fb)
+{
+	struct armada_private *priv = dev->dev_private;
+
+	/*
+	 * Yes, we really must jump through these hoops just to store a
+	 * _pointer_ to something into the kfifo.  This is utterly insane
+	 * and idiotic, because it kfifo requires the _data_ pointed to by
+	 * the pointer const, not the pointer itself.  Not only that, but
+	 * you have to pass a pointer _to_ the pointer you want stored.
+	 */
+	const struct drm_framebuffer *silly_api_alert = fb;
+	WARN_ON(!kfifo_put(&priv->fb_unref, &silly_api_alert));
+	schedule_work(&priv->fb_unref_work);
+}
+
+void armada_drm_queue_unref_work(struct drm_device *dev,
+	struct drm_framebuffer *fb)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	__armada_drm_queue_unref_work(dev, fb);
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static int armada_drm_load(struct drm_device *dev, unsigned long flags)
+{
+	const struct platform_device_id *id;
+	struct armada_private *priv;
+	struct resource *res[ARRAY_SIZE(priv->dcrtc)];
+	struct resource *mem = NULL;
+	int ret, n, i;
+
+	memset(res, 0, sizeof(res));
+
+	for (n = i = 0; ; n++) {
+		struct resource *r = platform_get_resource(dev->platformdev,
+							   IORESOURCE_MEM, n);
+		if (!r)
+			break;
+
+		/* Resources above 64K are graphics memory */
+		if (resource_size(r) > SZ_64K)
+			mem = r;
+		else if (i < ARRAY_SIZE(priv->dcrtc))
+			res[i++] = r;
+		else
+			return -EINVAL;
+	}
+
+	if (!res[0] || !mem)
+		return -ENXIO;
+
+	if (!devm_request_mem_region(dev->dev, mem->start,
+			resource_size(mem), "armada-drm"))
+		return -EBUSY;
+
+	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		DRM_ERROR("failed to allocate private\n");
+		return -ENOMEM;
+	}
+
+	dev->dev_private = priv;
+
+	/* Get the implementation specific driver data. */
+	id = platform_get_device_id(dev->platformdev);
+	if (!id)
+		return -ENXIO;
+
+	priv->variant = (struct armada_variant *)id->driver_data;
+
+	ret = priv->variant->init(priv, dev->dev);
+	if (ret)
+		return ret;
+
+	INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
+	INIT_KFIFO(priv->fb_unref);
+
+	/* Mode setting support */
+	drm_mode_config_init(dev);
+	dev->mode_config.min_width = 320;
+	dev->mode_config.min_height = 200;
+
+	/*
+	 * With vscale enabled, the maximum width is 1920 due to the
+	 * 1920 by 3 lines RAM
+	 */
+	dev->mode_config.max_width = 1920;
+	dev->mode_config.max_height = 2048;
+
+	dev->mode_config.preferred_depth = 24;
+	dev->mode_config.funcs = &armada_drm_mode_config_funcs;
+	drm_mm_init(&priv->linear, mem->start, resource_size(mem));
+
+	/* Create all LCD controllers */
+	for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
+		if (!res[n])
+			break;
+
+		ret = armada_drm_crtc_create(dev, n, res[n]);
+		if (ret)
+			goto err_kms;
+	}
+
+	ret = drm_vblank_init(dev, n);
+	if (ret)
+		goto err_kms;
+
+	ret = drm_irq_install(dev);
+	if (ret)
+		goto err_kms;
+
+	dev->vblank_disable_allowed = 1;
+
+	ret = armada_fbdev_init(dev);
+	if (ret)
+		goto err_irq;
+
+	drm_kms_helper_poll_init(dev);
+
+	return 0;
+
+ err_irq:
+	drm_irq_uninstall(dev);
+ err_kms:
+	drm_mode_config_cleanup(dev);
+	drm_mm_takedown(&priv->linear);
+	flush_work(&priv->fb_unref_work);
+
+	return ret;
+}
+
+static int armada_drm_unload(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+
+	drm_kms_helper_poll_fini(dev);
+	armada_fbdev_fini(dev);
+	drm_irq_uninstall(dev);
+	drm_mode_config_cleanup(dev);
+	drm_mm_takedown(&priv->linear);
+	flush_work(&priv->fb_unref_work);
+	dev->dev_private = NULL;
+
+	return 0;
+}
+
+void armada_drm_vbl_event_add(struct armada_crtc *dcrtc,
+	struct armada_vbl_event *evt)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dcrtc->irq_lock, flags);
+	if (list_empty(&evt->node)) {
+		list_add_tail(&evt->node, &dcrtc->vbl_list);
+
+		drm_vblank_get(dcrtc->crtc.dev, dcrtc->num);
+	}
+	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
+}
+
+void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc,
+	struct armada_vbl_event *evt)
+{
+	if (!list_empty(&evt->node)) {
+		list_del_init(&evt->node);
+		drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
+	}
+}
+
+void armada_drm_vbl_event_remove_unlocked(struct armada_crtc *dcrtc,
+	struct armada_vbl_event *evt)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dcrtc->irq_lock, flags);
+	armada_drm_vbl_event_remove(dcrtc, evt);
+	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
+}
+
+/* These are called under the vbl_lock. */
+static int armada_drm_enable_vblank(struct drm_device *dev, int crtc)
+{
+	struct armada_private *priv = dev->dev_private;
+	armada_drm_crtc_enable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
+	return 0;
+}
+
+static void armada_drm_disable_vblank(struct drm_device *dev, int crtc)
+{
+	struct armada_private *priv = dev->dev_private;
+	armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
+}
+
+static irqreturn_t armada_drm_irq_handler(int irq, void *arg)
+{
+	struct drm_device *dev = arg;
+	struct armada_private *priv = dev->dev_private;
+	struct armada_crtc *dcrtc = priv->dcrtc[0];
+	uint32_t v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
+	irqreturn_t handled = IRQ_NONE;
+
+	/*
+	 * This is rediculous - rather than writing bits to clear, we
+	 * have to set the actual status register value.  This is racy.
+	 */
+	writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
+
+	/* Mask out those interrupts we haven't enabled */
+	v = stat & dcrtc->irq_ena;
+
+	if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
+		armada_drm_crtc_irq(dcrtc, stat);
+		handled = IRQ_HANDLED;
+	}
+
+	return handled;
+}
+
+static int armada_drm_irq_postinstall(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct armada_crtc *dcrtc = priv->dcrtc[0];
+
+	spin_lock_irq(&dev->vbl_lock);
+	writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
+	writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
+	spin_unlock_irq(&dev->vbl_lock);
+
+	return 0;
+}
+
+static void armada_drm_irq_uninstall(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct armada_crtc *dcrtc = priv->dcrtc[0];
+
+	writel(0, dcrtc->base + LCD_SPU_IRQ_ENA);
+}
+
+static struct drm_ioctl_desc armada_ioctls[] = {
+	DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,
+		DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(ARMADA_GEM_MMAP, armada_gem_mmap_ioctl,
+		DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(ARMADA_GEM_PWRITE, armada_gem_pwrite_ioctl,
+		DRM_UNLOCKED),
+};
+
+static const struct file_operations armada_drm_fops = {
+	.owner			= THIS_MODULE,
+	.llseek			= no_llseek,
+	.read			= drm_read,
+	.poll			= drm_poll,
+	.unlocked_ioctl		= drm_ioctl,
+	.mmap			= drm_gem_mmap,
+	.open			= drm_open,
+	.release		= drm_release,
+};
+
+static struct drm_driver armada_drm_driver = {
+	.load			= armada_drm_load,
+	.open			= NULL,
+	.preclose		= NULL,
+	.postclose		= NULL,
+	.lastclose		= NULL,
+	.unload			= armada_drm_unload,
+	.get_vblank_counter	= drm_vblank_count,
+	.enable_vblank		= armada_drm_enable_vblank,
+	.disable_vblank		= armada_drm_disable_vblank,
+	.irq_handler		= armada_drm_irq_handler,
+	.irq_postinstall	= armada_drm_irq_postinstall,
+	.irq_uninstall		= armada_drm_irq_uninstall,
+#ifdef CONFIG_DEBUG_FS
+	.debugfs_init		= armada_drm_debugfs_init,
+	.debugfs_cleanup	= armada_drm_debugfs_cleanup,
+#endif
+	.gem_init_object	= NULL,
+	.gem_free_object	= armada_gem_free_object,
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_export	= armada_gem_prime_export,
+	.gem_prime_import	= armada_gem_prime_import,
+	.dumb_create		= armada_gem_dumb_create,
+	.dumb_map_offset	= armada_gem_dumb_map_offset,
+	.dumb_destroy		= armada_gem_dumb_destroy,
+	.gem_vm_ops		= &armada_gem_vm_ops,
+	.major			= 1,
+	.minor			= 0,
+	.name			= "armada-drm",
+	.desc			= "Armada SoC DRM",
+	.date			= "20120730",
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET |
+				  DRIVER_HAVE_IRQ | DRIVER_PRIME,
+	.ioctls			= armada_ioctls,
+	.fops			= &armada_drm_fops,
+};
+
+static int armada_drm_probe(struct platform_device *pdev)
+{
+	return drm_platform_init(&armada_drm_driver, pdev);
+}
+
+static int armada_drm_remove(struct platform_device *pdev)
+{
+	drm_platform_exit(&armada_drm_driver, pdev);
+	return 0;
+}
+
+static const struct platform_device_id armada_drm_platform_ids[] = {
+	{
+		.name		= "armada-drm",
+		.driver_data	= (unsigned long)&armada510_ops,
+	}, {
+		.name		= "armada-510-drm",
+		.driver_data	= (unsigned long)&armada510_ops,
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, armada_drm_platform_ids);
+
+static struct platform_driver armada_drm_platform_driver = {
+	.probe	= armada_drm_probe,
+	.remove	= armada_drm_remove,
+	.driver	= {
+		.name	= "armada-drm",
+		.owner	= THIS_MODULE,
+	},
+	.id_table = armada_drm_platform_ids,
+};
+
+static int __init armada_drm_init(void)
+{
+	armada_drm_driver.num_ioctls = DRM_ARRAY_SIZE(armada_ioctls);
+	return platform_driver_register(&armada_drm_platform_driver);
+}
+module_init(armada_drm_init);
+
+static void __exit armada_drm_exit(void)
+{
+	platform_driver_unregister(&armada_drm_platform_driver);
+}
+module_exit(armada_drm_exit);
+
+MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
+MODULE_DESCRIPTION("Armada DRM Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:armada-drm");
diff --git a/drivers/gpu/drm/armada/armada_fb.c b/drivers/gpu/drm/armada/armada_fb.c
new file mode 100644
index 0000000..1c90969
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_fb.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include "armada_drm.h"
+#include "armada_fb.h"
+#include "armada_gem.h"
+#include "armada_hw.h"
+
+static void armada_fb_destroy(struct drm_framebuffer *fb)
+{
+	struct armada_framebuffer *dfb = drm_fb_to_armada_fb(fb);
+
+	drm_framebuffer_cleanup(&dfb->fb);
+	drm_gem_object_unreference_unlocked(&dfb->obj->obj);
+	kfree(dfb);
+}
+
+static int armada_fb_create_handle(struct drm_framebuffer *fb,
+	struct drm_file *dfile, unsigned int *handle)
+{
+	struct armada_framebuffer *dfb = drm_fb_to_armada_fb(fb);
+	return drm_gem_handle_create(dfile, &dfb->obj->obj, handle);
+}
+
+static const struct drm_framebuffer_funcs armada_fb_funcs = {
+	.destroy	= armada_fb_destroy,
+	.create_handle	= armada_fb_create_handle,
+};
+
+struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev,
+	struct drm_mode_fb_cmd2 *mode, struct armada_gem_object *obj)
+{
+	struct armada_framebuffer *dfb;
+	uint8_t format, config;
+	int ret;
+
+	switch (mode->pixel_format) {
+#define FMT(drm, fmt, mod)		\
+	case DRM_FORMAT_##drm:		\
+		format = CFG_##fmt;	\
+		config = mod;		\
+		break
+	FMT(RGB565,	565,		CFG_SWAPRB);
+	FMT(BGR565,	565,		0);
+	FMT(ARGB1555,	1555,		CFG_SWAPRB);
+	FMT(ABGR1555,	1555,		0);
+	FMT(RGB888,	888PACK,	CFG_SWAPRB);
+	FMT(BGR888,	888PACK,	0);
+	FMT(XRGB8888,	X888,		CFG_SWAPRB);
+	FMT(XBGR8888,	X888,		0);
+	FMT(ARGB8888,	8888,		CFG_SWAPRB);
+	FMT(ABGR8888,	8888,		0);
+	FMT(YUYV,	422PACK,	CFG_YUV2RGB | CFG_SWAPYU | CFG_SWAPUV);
+	FMT(UYVY,	422PACK,	CFG_YUV2RGB);
+	FMT(VYUY,	422PACK,	CFG_YUV2RGB | CFG_SWAPUV);
+	FMT(YVYU,	422PACK,	CFG_YUV2RGB | CFG_SWAPYU);
+	FMT(YUV422,	422,		CFG_YUV2RGB);
+	FMT(YVU422,	422,		CFG_YUV2RGB | CFG_SWAPUV);
+	FMT(YUV420,	420,		CFG_YUV2RGB);
+	FMT(YVU420,	420,		CFG_YUV2RGB | CFG_SWAPUV);
+	FMT(C8,		PSEUDO8,	0);
+#undef FMT
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	dfb = kzalloc(sizeof(*dfb), GFP_KERNEL);
+	if (!dfb) {
+		DRM_ERROR("failed to allocate Armada fb object\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dfb->fmt = format;
+	dfb->mod = config;
+	dfb->obj = obj;
+
+	drm_helper_mode_fill_fb_struct(&dfb->fb, mode);
+
+	ret = drm_framebuffer_init(dev, &dfb->fb, &armada_fb_funcs);
+	if (ret) {
+		kfree(dfb);
+		return ERR_PTR(ret);
+	}
+
+	/*
+	 * Take a reference on our object as we're successful - the
+	 * caller already holds a reference, which keeps us safe for
+	 * the above call, but the caller will drop their reference
+	 * to it.  Hence we need to take our own reference.
+	 */
+	drm_gem_object_reference(&obj->obj);
+
+	return dfb;
+}
+
+static struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
+	struct drm_file *dfile, struct drm_mode_fb_cmd2 *mode)
+{
+	struct armada_gem_object *obj;
+	struct armada_framebuffer *dfb;
+	int ret;
+
+	DRM_DEBUG_DRIVER("w%u h%u pf%08x f%u p%u,%u,%u\n",
+		mode->width, mode->height, mode->pixel_format,
+		mode->flags, mode->pitches[0], mode->pitches[1],
+		mode->pitches[2]);
+
+	/* We can only handle a single plane at the moment */
+	if (drm_format_num_planes(mode->pixel_format) > 1 &&
+	    (mode->handles[0] != mode->handles[1] ||
+	     mode->handles[0] != mode->handles[2])) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	obj = armada_gem_object_lookup(dev, dfile, mode->handles[0]);
+	if (!obj) {
+		ret = -ENOENT;
+		goto err;
+	}
+
+	if (obj->obj.import_attach && !obj->sgt) {
+		ret = armada_gem_map_import(obj);
+		if (ret)
+			goto err_unref;
+	}
+
+	/* Framebuffer objects must have a valid device address for scanout */
+	if (obj->dev_addr == DMA_ERROR_CODE) {
+		ret = -EINVAL;
+		goto err_unref;
+	}
+
+	dfb = armada_framebuffer_create(dev, mode, obj);
+	if (IS_ERR(dfb)) {
+		ret = PTR_ERR(dfb);
+		goto err;
+	}
+
+	drm_gem_object_unreference_unlocked(&obj->obj);
+
+	return &dfb->fb;
+
+ err_unref:
+	drm_gem_object_unreference_unlocked(&obj->obj);
+ err:
+	DRM_ERROR("failed to initialize framebuffer: %d\n", ret);
+	return ERR_PTR(ret);
+}
+
+static void armada_output_poll_changed(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct drm_fb_helper *fbh = priv->fbdev;
+
+	if (fbh)
+		drm_fb_helper_hotplug_event(fbh);
+}
+
+const struct drm_mode_config_funcs armada_drm_mode_config_funcs = {
+	.fb_create		= armada_fb_create,
+	.output_poll_changed	= armada_output_poll_changed,
+};
diff --git a/drivers/gpu/drm/armada/armada_fb.h b/drivers/gpu/drm/armada/armada_fb.h
new file mode 100644
index 0000000..ce3f12e
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_fb.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_FB_H
+#define ARMADA_FB_H
+
+struct armada_framebuffer {
+	struct drm_framebuffer	fb;
+	struct armada_gem_object *obj;
+	uint8_t			fmt;
+	uint8_t			mod;
+};
+#define drm_fb_to_armada_fb(dfb) \
+	container_of(dfb, struct armada_framebuffer, fb)
+#define drm_fb_obj(fb) drm_fb_to_armada_fb(fb)->obj
+
+struct armada_framebuffer *armada_framebuffer_create(struct drm_device *,
+	struct drm_mode_fb_cmd2 *, struct armada_gem_object *);
+
+#endif
diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
new file mode 100644
index 0000000..dd5ea77
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_fbdev.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Written from the i915 driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_fb.h"
+#include "armada_gem.h"
+
+static /*const*/ struct fb_ops armada_fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= drm_fb_helper_check_var,
+	.fb_set_par	= drm_fb_helper_set_par,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_pan_display	= drm_fb_helper_pan_display,
+	.fb_blank	= drm_fb_helper_blank,
+	.fb_setcmap	= drm_fb_helper_setcmap,
+	.fb_debug_enter	= drm_fb_helper_debug_enter,
+	.fb_debug_leave	= drm_fb_helper_debug_leave,
+};
+
+static int armada_fb_create(struct drm_fb_helper *fbh,
+	struct drm_fb_helper_surface_size *sizes)
+{
+	struct drm_device *dev = fbh->dev;
+	struct drm_mode_fb_cmd2 mode;
+	struct armada_framebuffer *dfb;
+	struct armada_gem_object *obj;
+	struct fb_info *info;
+	int size, ret;
+	void *ptr;
+
+	memset(&mode, 0, sizeof(mode));
+	mode.width = sizes->surface_width;
+	mode.height = sizes->surface_height;
+	mode.pitches[0] = armada_pitch(mode.width, sizes->surface_bpp);
+	mode.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+					sizes->surface_depth);
+
+	size = mode.pitches[0] * mode.height;
+	obj = armada_gem_alloc_private_object(dev, size);
+	if (!obj) {
+		DRM_ERROR("failed to allocate fb memory\n");
+		return -ENOMEM;
+	}
+
+	ret = armada_gem_linear_back(dev, obj);
+	if (ret) {
+		drm_gem_object_unreference_unlocked(&obj->obj);
+		return ret;
+	}
+
+	ptr = armada_gem_map_object(dev, obj);
+	if (!ptr) {
+		drm_gem_object_unreference_unlocked(&obj->obj);
+		return -ENOMEM;
+	}
+
+	dfb = armada_framebuffer_create(dev, &mode, obj);
+
+	/*
+	 * A reference is now held by the framebuffer object if
+	 * successful, otherwise this drops the ref for the error path.
+	 */
+	drm_gem_object_unreference_unlocked(&obj->obj);
+
+	if (IS_ERR(dfb))
+		return PTR_ERR(dfb);
+
+	info = framebuffer_alloc(0, dev->dev);
+	if (!info) {
+		ret = -ENOMEM;
+		goto err_fballoc;
+	}
+
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret) {
+		ret = -ENOMEM;
+		goto err_fbcmap;
+	}
+
+	strlcpy(info->fix.id, "armada-drmfb", sizeof(info->fix.id));
+	info->par = fbh;
+	info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
+	info->fbops = &armada_fb_ops;
+	info->fix.smem_start = obj->phys_addr;
+	info->fix.smem_len = obj->obj.size;
+	info->screen_size = obj->obj.size;
+	info->screen_base = ptr;
+	fbh->fb = &dfb->fb;
+	fbh->fbdev = info;
+	drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth);
+	drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height);
+
+	DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08x\n",
+		dfb->fb.width, dfb->fb.height,
+		dfb->fb.bits_per_pixel, obj->phys_addr);
+
+	return 0;
+
+ err_fbcmap:
+	framebuffer_release(info);
+ err_fballoc:
+	dfb->fb.funcs->destroy(&dfb->fb);
+	return ret;
+}
+
+static int armada_fb_probe(struct drm_fb_helper *fbh,
+	struct drm_fb_helper_surface_size *sizes)
+{
+	int ret = 0;
+
+	if (!fbh->fb) {
+		ret = armada_fb_create(fbh, sizes);
+		if (ret == 0)
+			ret = 1;
+	}
+	return ret;
+}
+
+static struct drm_fb_helper_funcs armada_fb_helper_funcs = {
+	.gamma_set	= armada_drm_crtc_gamma_set,
+	.gamma_get	= armada_drm_crtc_gamma_get,
+	.fb_probe	= armada_fb_probe,
+};
+
+int armada_fbdev_init(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct drm_fb_helper *fbh;
+	int ret;
+
+	fbh = devm_kzalloc(dev->dev, sizeof(*fbh), GFP_KERNEL);
+	if (!fbh)
+		return -ENOMEM;
+
+	priv->fbdev = fbh;
+
+	fbh->funcs = &armada_fb_helper_funcs;
+
+	ret = drm_fb_helper_init(dev, fbh, 1, 1);
+	if (ret) {
+		DRM_ERROR("failed to initialize drm fb helper\n");
+		goto err_fb_helper;
+	}
+
+	ret = drm_fb_helper_single_add_all_connectors(fbh);
+	if (ret) {
+		DRM_ERROR("failed to add fb connectors\n");
+		goto err_fb_setup;
+	}
+
+	ret = drm_fb_helper_initial_config(fbh, 32);
+	if (ret) {
+		DRM_ERROR("failed to set initial config\n");
+		goto err_fb_setup;
+	}
+
+	return 0;
+ err_fb_setup:
+	drm_fb_helper_fini(fbh);
+ err_fb_helper:
+	priv->fbdev = NULL;
+	return ret;
+}
+
+void armada_fbdev_fini(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct drm_fb_helper *fbh = priv->fbdev;
+
+	if (fbh) {
+		struct fb_info *info = fbh->fbdev;
+
+		if (info) {
+			unregister_framebuffer(info);
+			if (info->cmap.len)
+				fb_dealloc_cmap(&info->cmap);
+			framebuffer_release(info);
+		}
+
+		if (fbh->fb)
+			fbh->fb->funcs->destroy(fbh->fb);
+
+		drm_fb_helper_fini(fbh);
+
+		priv->fbdev = NULL;
+	}
+}
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
new file mode 100644
index 0000000..c865a9a
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -0,0 +1,616 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/dma-buf.h>
+#include <linux/dma-mapping.h>
+#include <linux/shmem_fs.h>
+#include <drm/drmP.h>
+#include "armada_drm.h"
+#include "armada_gem.h"
+#include <drm/armada_drm.h>
+#include "armada_ioctlP.h"
+
+static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct armada_gem_object *obj = drm_to_armada_gem(vma->vm_private_data);
+	unsigned long addr = (unsigned long)vmf->virtual_address;
+	unsigned long pfn = obj->phys_addr >> PAGE_SHIFT;
+	int ret;
+
+	pfn += (addr - vma->vm_start) >> PAGE_SHIFT;
+	ret = vm_insert_pfn(vma, addr, pfn);
+
+	switch (ret) {
+	case -EIO:
+	case -EAGAIN:
+		set_need_resched();
+	case 0:
+	case -ERESTARTSYS:
+	case -EINTR:
+	case -EBUSY:
+		return VM_FAULT_NOPAGE;
+	case -ENOMEM:
+		return VM_FAULT_OOM;
+	default:
+		return VM_FAULT_SIGBUS;
+	}
+}
+
+const struct vm_operations_struct armada_gem_vm_ops = {
+	.fault	= armada_gem_vm_fault,
+	.open	= drm_gem_vm_open,
+	.close	= drm_gem_vm_close,
+};
+
+static size_t roundup_gem_size(size_t size)
+{
+	return roundup(size, PAGE_SIZE);
+}
+
+/* dev->struct_mutex is held here */
+void armada_gem_free_object(struct drm_gem_object *obj)
+{
+	struct armada_gem_object *dobj = drm_to_armada_gem(obj);
+
+	DRM_DEBUG_DRIVER("release obj %p\n", dobj);
+
+	drm_gem_free_mmap_offset(&dobj->obj);
+
+	if (dobj->page) {
+		/* page backed memory */
+		unsigned int order = get_order(dobj->obj.size);
+		__free_pages(dobj->page, order);
+	} else if (dobj->linear) {
+		/* linear backed memory */
+		drm_mm_remove_node(dobj->linear);
+		kfree(dobj->linear);
+		if (dobj->addr)
+			iounmap(dobj->addr);
+	}
+
+	if (dobj->obj.import_attach) {
+		/* We only ever display imported data */
+		dma_buf_unmap_attachment(dobj->obj.import_attach, dobj->sgt,
+					 DMA_TO_DEVICE);
+		drm_prime_gem_destroy(&dobj->obj, NULL);
+	}
+
+	drm_gem_object_release(&dobj->obj);
+
+	kfree(dobj);
+}
+
+int
+armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj)
+{
+	struct armada_private *priv = dev->dev_private;
+	size_t size = obj->obj.size;
+
+	if (obj->page || obj->linear)
+		return 0;
+
+	/*
+	 * If it is a small allocation (typically cursor, which will
+	 * be 32x64 or 64x32 ARGB pixels) try to get it from the system.
+	 * Framebuffers will never be this small (our minimum size for
+	 * framebuffers is larger than this anyway.)  Such objects are
+	 * only accessed by the CPU so we don't need any special handing
+	 * here.
+	 */
+	if (size <= 8192) {
+		unsigned int order = get_order(size);
+		struct page *p = alloc_pages(GFP_KERNEL, order);
+
+		if (p) {
+			obj->addr = page_address(p);
+			obj->phys_addr = page_to_phys(p);
+			obj->page = p;
+
+			memset(obj->addr, 0, PAGE_ALIGN(size));
+		}
+	}
+
+	/*
+	 * We could grab something from CMA if it's enabled, but that
+	 * involves building in a problem:
+	 *
+	 * CMA's interface uses dma_alloc_coherent(), which provides us
+	 * with an CPU virtual address and a device address.
+	 *
+	 * The CPU virtual address may be either an address in the kernel
+	 * direct mapped region (for example, as it would be on x86) or
+	 * it may be remapped into another part of kernel memory space
+	 * (eg, as it would be on ARM.)  This means virt_to_phys() on the
+	 * returned virtual address is invalid depending on the architecture
+	 * implementation.
+	 *
+	 * The device address may also not be a physical address; it may
+	 * be that there is some kind of remapping between the device and
+	 * system RAM, which makes the use of the device address also
+	 * unsafe to re-use as a physical address.
+	 *
+	 * This makes DRM usage of dma_alloc_coherent() in a generic way
+	 * at best very questionable and unsafe.
+	 */
+
+	/* Otherwise, grab it from our linear allocation */
+	if (!obj->page) {
+		struct drm_mm_node *node;
+		unsigned align = min_t(unsigned, size, SZ_2M);
+		void __iomem *ptr;
+		int ret;
+
+		node = kzalloc(sizeof(*node), GFP_KERNEL);
+		if (!node)
+			return -ENOSPC;
+
+		mutex_lock(&dev->struct_mutex);
+		ret = drm_mm_insert_node(&priv->linear, node, size, align,
+					 DRM_MM_SEARCH_DEFAULT);
+		mutex_unlock(&dev->struct_mutex);
+		if (ret) {
+			kfree(node);
+			return ret;
+		}
+
+		obj->linear = node;
+
+		/* Ensure that the memory we're returning is cleared. */
+		ptr = ioremap_wc(obj->linear->start, size);
+		if (!ptr) {
+			mutex_lock(&dev->struct_mutex);
+			drm_mm_remove_node(obj->linear);
+			mutex_unlock(&dev->struct_mutex);
+			kfree(obj->linear);
+			obj->linear = NULL;
+			return -ENOMEM;
+		}
+
+		memset_io(ptr, 0, size);
+		iounmap(ptr);
+
+		obj->phys_addr = obj->linear->start;
+		obj->dev_addr = obj->linear->start;
+	}
+
+	DRM_DEBUG_DRIVER("obj %p phys %#x dev %#x\n",
+			 obj, obj->phys_addr, obj->dev_addr);
+
+	return 0;
+}
+
+void *
+armada_gem_map_object(struct drm_device *dev, struct armada_gem_object *dobj)
+{
+	/* only linear objects need to be ioremap'd */
+	if (!dobj->addr && dobj->linear)
+		dobj->addr = ioremap_wc(dobj->phys_addr, dobj->obj.size);
+	return dobj->addr;
+}
+
+struct armada_gem_object *
+armada_gem_alloc_private_object(struct drm_device *dev, size_t size)
+{
+	struct armada_gem_object *obj;
+
+	size = roundup_gem_size(size);
+
+	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+	if (!obj)
+		return NULL;
+
+	drm_gem_private_object_init(dev, &obj->obj, size);
+	obj->dev_addr = DMA_ERROR_CODE;
+
+	DRM_DEBUG_DRIVER("alloc private obj %p size %zu\n", obj, size);
+
+	return obj;
+}
+
+struct armada_gem_object *armada_gem_alloc_object(struct drm_device *dev,
+	size_t size)
+{
+	struct armada_gem_object *obj;
+	struct address_space *mapping;
+
+	size = roundup_gem_size(size);
+
+	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+	if (!obj)
+		return NULL;
+
+	if (drm_gem_object_init(dev, &obj->obj, size)) {
+		kfree(obj);
+		return NULL;
+	}
+
+	obj->dev_addr = DMA_ERROR_CODE;
+
+	mapping = obj->obj.filp->f_path.dentry->d_inode->i_mapping;
+	mapping_set_gfp_mask(mapping, GFP_HIGHUSER | __GFP_RECLAIMABLE);
+
+	DRM_DEBUG_DRIVER("alloc obj %p size %zu\n", obj, size);
+
+	return obj;
+}
+
+/* Dumb alloc support */
+int armada_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
+	struct drm_mode_create_dumb *args)
+{
+	struct armada_gem_object *dobj;
+	u32 handle;
+	size_t size;
+	int ret;
+
+	args->pitch = armada_pitch(args->width, args->bpp);
+	args->size = size = args->pitch * args->height;
+
+	dobj = armada_gem_alloc_private_object(dev, size);
+	if (dobj == NULL)
+		return -ENOMEM;
+
+	ret = armada_gem_linear_back(dev, dobj);
+	if (ret)
+		goto err;
+
+	ret = drm_gem_handle_create(file, &dobj->obj, &handle);
+	if (ret)
+		goto err;
+
+	args->handle = handle;
+
+	/* drop reference from allocate - handle holds it now */
+	DRM_DEBUG_DRIVER("obj %p size %zu handle %#x\n", dobj, size, handle);
+ err:
+	drm_gem_object_unreference_unlocked(&dobj->obj);
+	return ret;
+}
+
+int armada_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
+	uint32_t handle, uint64_t *offset)
+{
+	struct armada_gem_object *obj;
+	int ret = 0;
+
+	mutex_lock(&dev->struct_mutex);
+	obj = armada_gem_object_lookup(dev, file, handle);
+	if (!obj) {
+		DRM_ERROR("failed to lookup gem object\n");
+		ret = -EINVAL;
+		goto err_unlock;
+	}
+
+	/* Don't allow imported objects to be mapped */
+	if (obj->obj.import_attach) {
+		ret = -EINVAL;
+		goto err_unlock;
+	}
+
+	ret = drm_gem_create_mmap_offset(&obj->obj);
+	if (ret == 0) {
+		*offset = drm_vma_node_offset_addr(&obj->obj.vma_node);
+		DRM_DEBUG_DRIVER("handle %#x offset %llx\n", handle, *offset);
+	}
+
+	drm_gem_object_unreference(&obj->obj);
+ err_unlock:
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+int armada_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
+	uint32_t handle)
+{
+	return drm_gem_handle_delete(file, handle);
+}
+
+/* Private driver gem ioctls */
+int armada_gem_create_ioctl(struct drm_device *dev, void *data,
+	struct drm_file *file)
+{
+	struct drm_armada_gem_create *args = data;
+	struct armada_gem_object *dobj;
+	size_t size;
+	u32 handle;
+	int ret;
+
+	if (args->size == 0)
+		return -ENOMEM;
+
+	size = args->size;
+
+	dobj = armada_gem_alloc_object(dev, size);
+	if (dobj == NULL)
+		return -ENOMEM;
+
+	ret = drm_gem_handle_create(file, &dobj->obj, &handle);
+	if (ret)
+		goto err;
+
+	args->handle = handle;
+
+	/* drop reference from allocate - handle holds it now */
+	DRM_DEBUG_DRIVER("obj %p size %zu handle %#x\n", dobj, size, handle);
+ err:
+	drm_gem_object_unreference_unlocked(&dobj->obj);
+	return ret;
+}
+
+/* Map a shmem-backed object into process memory space */
+int armada_gem_mmap_ioctl(struct drm_device *dev, void *data,
+	struct drm_file *file)
+{
+	struct drm_armada_gem_mmap *args = data;
+	struct armada_gem_object *dobj;
+	unsigned long addr;
+
+	dobj = armada_gem_object_lookup(dev, file, args->handle);
+	if (dobj == NULL)
+		return -ENOENT;
+
+	if (!dobj->obj.filp) {
+		drm_gem_object_unreference(&dobj->obj);
+		return -EINVAL;
+	}
+
+	addr = vm_mmap(dobj->obj.filp, 0, args->size, PROT_READ | PROT_WRITE,
+		       MAP_SHARED, args->offset);
+	drm_gem_object_unreference(&dobj->obj);
+	if (IS_ERR_VALUE(addr))
+		return addr;
+
+	args->addr = addr;
+
+	return 0;
+}
+
+int armada_gem_pwrite_ioctl(struct drm_device *dev, void *data,
+	struct drm_file *file)
+{
+	struct drm_armada_gem_pwrite *args = data;
+	struct armada_gem_object *dobj;
+	char __user *ptr;
+	int ret;
+
+	DRM_DEBUG_DRIVER("handle %u off %u size %u ptr 0x%llx\n",
+		args->handle, args->offset, args->size, args->ptr);
+
+	if (args->size == 0)
+		return 0;
+
+	ptr = (char __user *)(uintptr_t)args->ptr;
+
+	if (!access_ok(VERIFY_READ, ptr, args->size))
+		return -EFAULT;
+
+	ret = fault_in_multipages_readable(ptr, args->size);
+	if (ret)
+		return ret;
+
+	dobj = armada_gem_object_lookup(dev, file, args->handle);
+	if (dobj == NULL)
+		return -ENOENT;
+
+	/* Must be a kernel-mapped object */
+	if (!dobj->addr)
+		return -EINVAL;
+
+	if (args->offset > dobj->obj.size ||
+	    args->size > dobj->obj.size - args->offset) {
+		DRM_ERROR("invalid size: object size %u\n", dobj->obj.size);
+		ret = -EINVAL;
+		goto unref;
+	}
+
+	if (copy_from_user(dobj->addr + args->offset, ptr, args->size)) {
+		ret = -EFAULT;
+	} else if (dobj->update) {
+		dobj->update(dobj->update_data);
+		ret = 0;
+	}
+
+ unref:
+	drm_gem_object_unreference_unlocked(&dobj->obj);
+	return ret;
+}
+
+/* Prime support */
+struct sg_table *
+armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
+	enum dma_data_direction dir)
+{
+	struct drm_gem_object *obj = attach->dmabuf->priv;
+	struct armada_gem_object *dobj = drm_to_armada_gem(obj);
+	struct scatterlist *sg;
+	struct sg_table *sgt;
+	int i, num;
+
+	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt)
+		return NULL;
+
+	if (dobj->obj.filp) {
+		struct address_space *mapping;
+		gfp_t gfp;
+		int count;
+
+		count = dobj->obj.size / PAGE_SIZE;
+		if (sg_alloc_table(sgt, count, GFP_KERNEL))
+			goto free_sgt;
+
+		mapping = file_inode(dobj->obj.filp)->i_mapping;
+		gfp = mapping_gfp_mask(mapping);
+
+		for_each_sg(sgt->sgl, sg, count, i) {
+			struct page *page;
+
+			page = shmem_read_mapping_page_gfp(mapping, i, gfp);
+			if (IS_ERR(page)) {
+				num = i;
+				goto release;
+			}
+
+			sg_set_page(sg, page, PAGE_SIZE, 0);
+		}
+
+		if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0) {
+			num = sgt->nents;
+			goto release;
+		}
+	} else if (dobj->page) {
+		/* Single contiguous page */
+		if (sg_alloc_table(sgt, 1, GFP_KERNEL))
+			goto free_sgt;
+
+		sg_set_page(sgt->sgl, dobj->page, dobj->obj.size, 0);
+
+		if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0)
+			goto free_table;
+	} else if (dobj->linear) {
+		/* Single contiguous physical region - no struct page */
+		if (sg_alloc_table(sgt, 1, GFP_KERNEL))
+			goto free_sgt;
+		sg_dma_address(sgt->sgl) = dobj->dev_addr;
+		sg_dma_len(sgt->sgl) = dobj->obj.size;
+	} else {
+		goto free_sgt;
+	}
+	return sgt;
+
+ release:
+	for_each_sg(sgt->sgl, sg, num, i)
+		page_cache_release(sg_page(sg));
+ free_table:
+	sg_free_table(sgt);
+ free_sgt:
+	kfree(sgt);
+	return NULL;
+}
+
+static void armada_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
+	struct sg_table *sgt, enum dma_data_direction dir)
+{
+	struct drm_gem_object *obj = attach->dmabuf->priv;
+	struct armada_gem_object *dobj = drm_to_armada_gem(obj);
+	int i;
+
+	if (!dobj->linear)
+		dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
+
+	if (dobj->obj.filp) {
+		struct scatterlist *sg;
+		for_each_sg(sgt->sgl, sg, sgt->nents, i)
+			page_cache_release(sg_page(sg));
+	}
+
+	sg_free_table(sgt);
+	kfree(sgt);
+}
+
+static void *armada_gem_dmabuf_no_kmap(struct dma_buf *buf, unsigned long n)
+{
+	return NULL;
+}
+
+static void
+armada_gem_dmabuf_no_kunmap(struct dma_buf *buf, unsigned long n, void *addr)
+{
+}
+
+static int
+armada_gem_dmabuf_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
+{
+	return -EINVAL;
+}
+
+static const struct dma_buf_ops armada_gem_prime_dmabuf_ops = {
+	.map_dma_buf	= armada_gem_prime_map_dma_buf,
+	.unmap_dma_buf	= armada_gem_prime_unmap_dma_buf,
+	.release	= drm_gem_dmabuf_release,
+	.kmap_atomic	= armada_gem_dmabuf_no_kmap,
+	.kunmap_atomic	= armada_gem_dmabuf_no_kunmap,
+	.kmap		= armada_gem_dmabuf_no_kmap,
+	.kunmap		= armada_gem_dmabuf_no_kunmap,
+	.mmap		= armada_gem_dmabuf_mmap,
+};
+
+struct dma_buf *
+armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj,
+	int flags)
+{
+	return dma_buf_export(obj, &armada_gem_prime_dmabuf_ops, obj->size,
+			      O_RDWR);
+}
+
+struct drm_gem_object *
+armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
+{
+	struct dma_buf_attachment *attach;
+	struct armada_gem_object *dobj;
+
+	if (buf->ops == &armada_gem_prime_dmabuf_ops) {
+		struct drm_gem_object *obj = buf->priv;
+		if (obj->dev == dev) {
+			/*
+			 * Importing our own dmabuf(s) increases the
+			 * refcount on the gem object itself.
+			 */
+			drm_gem_object_reference(obj);
+			dma_buf_put(buf);
+			return obj;
+		}
+	}
+
+	attach = dma_buf_attach(buf, dev->dev);
+	if (IS_ERR(attach))
+		return ERR_CAST(attach);
+
+	dobj = armada_gem_alloc_private_object(dev, buf->size);
+	if (!dobj) {
+		dma_buf_detach(buf, attach);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dobj->obj.import_attach = attach;
+
+	/*
+	 * Don't call dma_buf_map_attachment() here - it maps the
+	 * scatterlist immediately for DMA, and this is not always
+	 * an appropriate thing to do.
+	 */
+	return &dobj->obj;
+}
+
+int armada_gem_map_import(struct armada_gem_object *dobj)
+{
+	int ret;
+
+	dobj->sgt = dma_buf_map_attachment(dobj->obj.import_attach,
+					  DMA_TO_DEVICE);
+	if (!dobj->sgt) {
+		DRM_ERROR("dma_buf_map_attachment() returned NULL\n");
+		return -EINVAL;
+	}
+	if (IS_ERR(dobj->sgt)) {
+		ret = PTR_ERR(dobj->sgt);
+		dobj->sgt = NULL;
+		DRM_ERROR("dma_buf_map_attachment() error: %d\n", ret);
+		return ret;
+	}
+	if (dobj->sgt->nents > 1) {
+		DRM_ERROR("dma_buf_map_attachment() returned an (unsupported) scattered list\n");
+		return -EINVAL;
+	}
+	if (sg_dma_len(dobj->sgt->sgl) < dobj->obj.size) {
+		DRM_ERROR("dma_buf_map_attachment() returned a small buffer\n");
+		return -EINVAL;
+	}
+	dobj->dev_addr = sg_dma_address(dobj->sgt->sgl);
+	return 0;
+}
diff --git a/drivers/gpu/drm/armada/armada_gem.h b/drivers/gpu/drm/armada/armada_gem.h
new file mode 100644
index 0000000..00b6cd4
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_gem.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_GEM_H
+#define ARMADA_GEM_H
+
+/* GEM */
+struct armada_gem_object {
+	struct drm_gem_object	obj;
+	void			*addr;
+	phys_addr_t		phys_addr;
+	resource_size_t		dev_addr;
+	struct drm_mm_node	*linear;	/* for linear backed */
+	struct page		*page;		/* for page backed */
+	struct sg_table		*sgt;		/* for imported */
+	void			(*update)(void *);
+	void			*update_data;
+};
+
+extern const struct vm_operations_struct armada_gem_vm_ops;
+
+#define drm_to_armada_gem(o) container_of(o, struct armada_gem_object, obj)
+
+void armada_gem_free_object(struct drm_gem_object *);
+int armada_gem_linear_back(struct drm_device *, struct armada_gem_object *);
+void *armada_gem_map_object(struct drm_device *, struct armada_gem_object *);
+struct armada_gem_object *armada_gem_alloc_private_object(struct drm_device *,
+	size_t);
+int armada_gem_dumb_create(struct drm_file *, struct drm_device *,
+	struct drm_mode_create_dumb *);
+int armada_gem_dumb_map_offset(struct drm_file *, struct drm_device *,
+	uint32_t, uint64_t *);
+int armada_gem_dumb_destroy(struct drm_file *, struct drm_device *,
+	uint32_t);
+struct dma_buf *armada_gem_prime_export(struct drm_device *dev,
+	struct drm_gem_object *obj, int flags);
+struct drm_gem_object *armada_gem_prime_import(struct drm_device *,
+	struct dma_buf *);
+int armada_gem_map_import(struct armada_gem_object *);
+
+static inline struct armada_gem_object *armada_gem_object_lookup(
+	struct drm_device *dev, struct drm_file *dfile, unsigned handle)
+{
+	struct drm_gem_object *obj = drm_gem_object_lookup(dev, dfile, handle);
+
+	return obj ? drm_to_armada_gem(obj) : NULL;
+}
+#endif
diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
new file mode 100644
index 0000000..216a4b5
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_hw.h
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Rewritten from the dovefb driver, and Armada510 manuals.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_HW_H
+#define ARMADA_HW_H
+
+/*
+ * Note: the following registers are written from IRQ context:
+ *  LCD_SPU_V_PORCH, LCD_SPU_ADV_REG, LCD_SPUT_V_H_TOTAL
+ *  LCD_SPU_DMA_START_ADDR_[YUV][01], LCD_SPU_DMA_PITCH_YC,
+ *  LCD_SPU_DMA_PITCH_UV, LCD_SPU_DMA_OVSA_HPXL_VLN,
+ *  LCD_SPU_DMA_HPXL_VLN, LCD_SPU_DZM_HPXL_VLN, LCD_SPU_DMA_CTRL0
+ */
+enum {
+	LCD_SPU_ADV_REG			= 0x0084,	/* Armada 510 */
+	LCD_SPU_DMA_START_ADDR_Y0	= 0x00c0,
+	LCD_SPU_DMA_START_ADDR_U0	= 0x00c4,
+	LCD_SPU_DMA_START_ADDR_V0	= 0x00c8,
+	LCD_CFG_DMA_START_ADDR_0	= 0x00cc,
+	LCD_SPU_DMA_START_ADDR_Y1	= 0x00d0,
+	LCD_SPU_DMA_START_ADDR_U1	= 0x00d4,
+	LCD_SPU_DMA_START_ADDR_V1	= 0x00d8,
+	LCD_CFG_DMA_START_ADDR_1	= 0x00dc,
+	LCD_SPU_DMA_PITCH_YC		= 0x00e0,
+	LCD_SPU_DMA_PITCH_UV		= 0x00e4,
+	LCD_SPU_DMA_OVSA_HPXL_VLN	= 0x00e8,
+	LCD_SPU_DMA_HPXL_VLN		= 0x00ec,
+	LCD_SPU_DZM_HPXL_VLN		= 0x00f0,
+	LCD_CFG_GRA_START_ADDR0		= 0x00f4,
+	LCD_CFG_GRA_START_ADDR1		= 0x00f8,
+	LCD_CFG_GRA_PITCH		= 0x00fc,
+	LCD_SPU_GRA_OVSA_HPXL_VLN	= 0x0100,
+	LCD_SPU_GRA_HPXL_VLN		= 0x0104,
+	LCD_SPU_GZM_HPXL_VLN		= 0x0108,
+	LCD_SPU_HWC_OVSA_HPXL_VLN	= 0x010c,
+	LCD_SPU_HWC_HPXL_VLN		= 0x0110,
+	LCD_SPUT_V_H_TOTAL		= 0x0114,
+	LCD_SPU_V_H_ACTIVE		= 0x0118,
+	LCD_SPU_H_PORCH			= 0x011c,
+	LCD_SPU_V_PORCH			= 0x0120,
+	LCD_SPU_BLANKCOLOR		= 0x0124,
+	LCD_SPU_ALPHA_COLOR1		= 0x0128,
+	LCD_SPU_ALPHA_COLOR2		= 0x012c,
+	LCD_SPU_COLORKEY_Y		= 0x0130,
+	LCD_SPU_COLORKEY_U		= 0x0134,
+	LCD_SPU_COLORKEY_V		= 0x0138,
+	LCD_CFG_RDREG4F			= 0x013c,	/* Armada 510 */
+	LCD_SPU_SPI_RXDATA		= 0x0140,
+	LCD_SPU_ISA_RXDATA		= 0x0144,
+	LCD_SPU_HWC_RDDAT		= 0x0158,
+	LCD_SPU_GAMMA_RDDAT		= 0x015c,
+	LCD_SPU_PALETTE_RDDAT		= 0x0160,
+	LCD_SPU_IOPAD_IN		= 0x0178,
+	LCD_CFG_RDREG5F			= 0x017c,
+	LCD_SPU_SPI_CTRL		= 0x0180,
+	LCD_SPU_SPI_TXDATA		= 0x0184,
+	LCD_SPU_SMPN_CTRL		= 0x0188,
+	LCD_SPU_DMA_CTRL0		= 0x0190,
+	LCD_SPU_DMA_CTRL1		= 0x0194,
+	LCD_SPU_SRAM_CTRL		= 0x0198,
+	LCD_SPU_SRAM_WRDAT		= 0x019c,
+	LCD_SPU_SRAM_PARA0		= 0x01a0,	/* Armada 510 */
+	LCD_SPU_SRAM_PARA1		= 0x01a4,
+	LCD_CFG_SCLK_DIV		= 0x01a8,
+	LCD_SPU_CONTRAST		= 0x01ac,
+	LCD_SPU_SATURATION		= 0x01b0,
+	LCD_SPU_CBSH_HUE		= 0x01b4,
+	LCD_SPU_DUMB_CTRL		= 0x01b8,
+	LCD_SPU_IOPAD_CONTROL		= 0x01bc,
+	LCD_SPU_IRQ_ENA			= 0x01c0,
+	LCD_SPU_IRQ_ISR			= 0x01c4,
+};
+
+/* For LCD_SPU_ADV_REG */
+enum {
+	ADV_VSYNC_L_OFF	= 0xfff << 20,
+	ADV_GRACOLORKEY	= 1 << 19,
+	ADV_VIDCOLORKEY	= 1 << 18,
+	ADV_HWC32BLEND	= 1 << 15,
+	ADV_HWC32ARGB	= 1 << 14,
+	ADV_HWC32ENABLE	= 1 << 13,
+	ADV_VSYNCOFFEN	= 1 << 12,
+	ADV_VSYNC_H_OFF	= 0xfff << 0,
+};
+
+enum {
+	CFG_565		= 0,
+	CFG_1555	= 1,
+	CFG_888PACK	= 2,
+	CFG_X888	= 3,
+	CFG_8888	= 4,
+	CFG_422PACK	= 5,
+	CFG_422		= 6,
+	CFG_420		= 7,
+	CFG_PSEUDO4	= 9,
+	CFG_PSEUDO8	= 10,
+	CFG_SWAPRB	= 1 << 4,
+	CFG_SWAPUV	= 1 << 3,
+	CFG_SWAPYU	= 1 << 2,
+	CFG_YUV2RGB	= 1 << 1,
+};
+
+/* For LCD_SPU_DMA_CTRL0 */
+enum {
+	CFG_NOBLENDING	= 1 << 31,
+	CFG_GAMMA_ENA	= 1 << 30,
+	CFG_CBSH_ENA	= 1 << 29,
+	CFG_PALETTE_ENA	= 1 << 28,
+	CFG_ARBFAST_ENA	= 1 << 27,
+	CFG_HWC_1BITMOD	= 1 << 26,
+	CFG_HWC_1BITENA	= 1 << 25,
+	CFG_HWC_ENA	= 1 << 24,
+	CFG_DMAFORMAT	= 0xf << 20,
+#define	CFG_DMA_FMT(x)	((x) << 20)
+	CFG_GRAFORMAT	= 0xf << 16,
+#define	CFG_GRA_FMT(x)	((x) << 16)
+#define CFG_GRA_MOD(x)	((x) << 8)
+	CFG_GRA_FTOGGLE	= 1 << 15,
+	CFG_GRA_HSMOOTH	= 1 << 14,
+	CFG_GRA_TSTMODE	= 1 << 13,
+	CFG_GRA_ENA	= 1 << 8,
+#define CFG_DMA_MOD(x)	((x) << 0)
+	CFG_DMA_FTOGGLE	= 1 << 7,
+	CFG_DMA_HSMOOTH	= 1 << 6,
+	CFG_DMA_TSTMODE	= 1 << 5,
+	CFG_DMA_ENA	= 1 << 0,
+};
+
+enum {
+	CKMODE_DISABLE	= 0,
+	CKMODE_Y	= 1,
+	CKMODE_U	= 2,
+	CKMODE_RGB	= 3,
+	CKMODE_V	= 4,
+	CKMODE_R	= 5,
+	CKMODE_G	= 6,
+	CKMODE_B	= 7,
+};
+
+/* For LCD_SPU_DMA_CTRL1 */
+enum {
+	CFG_FRAME_TRIG		= 1 << 31,
+	CFG_VSYNC_INV		= 1 << 27,
+	CFG_CKMODE_MASK		= 0x7 << 24,
+#define CFG_CKMODE(x)		((x) << 24)
+	CFG_CARRY		= 1 << 23,
+	CFG_GATED_CLK		= 1 << 21,
+	CFG_PWRDN_ENA		= 1 << 20,
+	CFG_DSCALE_MASK		= 0x3 << 18,
+	CFG_DSCALE_NONE		= 0x0 << 18,
+	CFG_DSCALE_HALF		= 0x1 << 18,
+	CFG_DSCALE_QUAR		= 0x2 << 18,
+	CFG_ALPHAM_MASK		= 0x3 << 16,
+	CFG_ALPHAM_VIDEO	= 0x0 << 16,
+	CFG_ALPHAM_GRA		= 0x1 << 16,
+	CFG_ALPHAM_CFG		= 0x2 << 16,
+	CFG_ALPHA_MASK		= 0xff << 8,
+	CFG_PIXCMD_MASK		= 0xff,
+};
+
+/* For LCD_SPU_SRAM_CTRL */
+enum {
+	SRAM_READ	= 0 << 14,
+	SRAM_WRITE	= 2 << 14,
+	SRAM_INIT	= 3 << 14,
+	SRAM_HWC32_RAMR	= 0xc << 8,
+	SRAM_HWC32_RAMG	= 0xd << 8,
+	SRAM_HWC32_RAMB	= 0xe << 8,
+	SRAM_HWC32_TRAN	= 0xf << 8,
+	SRAM_HWC	= 0xf << 8,
+};
+
+/* For LCD_SPU_SRAM_PARA1 */
+enum {
+	CFG_CSB_256x32	= 1 << 15,	/* cursor */
+	CFG_CSB_256x24	= 1 << 14,	/* palette */
+	CFG_CSB_256x8	= 1 << 13,	/* gamma */
+	CFG_PDWN1920x32	= 1 << 8,	/* Armada 510: power down vscale ram */
+	CFG_PDWN256x32	= 1 << 7,	/* power down cursor */
+	CFG_PDWN256x24	= 1 << 6,	/* power down palette */
+	CFG_PDWN256x8	= 1 << 5,	/* power down gamma */
+	CFG_PDWNHWC	= 1 << 4,	/* Armada 510: power down all hwc ram */
+	CFG_PDWN32x32	= 1 << 3,	/* power down slave->smart ram */
+	CFG_PDWN16x66	= 1 << 2,	/* power down UV fifo */
+	CFG_PDWN32x66	= 1 << 1,	/* power down Y fifo */
+	CFG_PDWN64x66	= 1 << 0,	/* power down graphic fifo */
+};
+
+/* For LCD_CFG_SCLK_DIV */
+enum {
+	/* Armada 510 */
+	SCLK_510_AXI		= 0x0 << 30,
+	SCLK_510_EXTCLK0	= 0x1 << 30,
+	SCLK_510_PLL		= 0x2 << 30,
+	SCLK_510_EXTCLK1	= 0x3 << 30,
+	SCLK_510_DIV_CHANGE	= 1 << 29,
+	SCLK_510_FRAC_DIV_MASK	= 0xfff << 16,
+	SCLK_510_INT_DIV_MASK	= 0xffff << 0,
+
+	/* Armada 16x */
+	SCLK_16X_AHB		= 0x0 << 28,
+	SCLK_16X_PCLK		= 0x1 << 28,
+	SCLK_16X_AXI		= 0x4 << 28,
+	SCLK_16X_PLL		= 0x8 << 28,
+	SCLK_16X_FRAC_DIV_MASK	= 0xfff << 16,
+	SCLK_16X_INT_DIV_MASK	= 0xffff << 0,
+};
+
+/* For LCD_SPU_DUMB_CTRL */
+enum {
+	DUMB16_RGB565_0	= 0x0 << 28,
+	DUMB16_RGB565_1	= 0x1 << 28,
+	DUMB18_RGB666_0	= 0x2 << 28,
+	DUMB18_RGB666_1	= 0x3 << 28,
+	DUMB12_RGB444_0	= 0x4 << 28,
+	DUMB12_RGB444_1	= 0x5 << 28,
+	DUMB24_RGB888_0	= 0x6 << 28,
+	DUMB_BLANK	= 0x7 << 28,
+	DUMB_MASK	= 0xf << 28,
+	CFG_BIAS_OUT	= 1 << 8,
+	CFG_REV_RGB	= 1 << 7,
+	CFG_INV_CBLANK	= 1 << 6,
+	CFG_INV_CSYNC	= 1 << 5,	/* Normally active high */
+	CFG_INV_HENA	= 1 << 4,
+	CFG_INV_VSYNC	= 1 << 3,	/* Normally active high */
+	CFG_INV_HSYNC	= 1 << 2,	/* Normally active high */
+	CFG_INV_PCLK	= 1 << 1,
+	CFG_DUMB_ENA	= 1 << 0,
+};
+
+/* For LCD_SPU_IOPAD_CONTROL */
+enum {
+	CFG_VSCALE_LN_EN	= 3 << 18,
+	CFG_GRA_VM_ENA		= 1 << 15,
+	CFG_DMA_VM_ENA		= 1 << 13,
+	CFG_CMD_VM_ENA		= 1 << 11,
+	CFG_CSC_MASK		= 3 << 8,
+	CFG_CSC_YUV_CCIR709	= 1 << 9,
+	CFG_CSC_YUV_CCIR601	= 0 << 9,
+	CFG_CSC_RGB_STUDIO	= 1 << 8,
+	CFG_CSC_RGB_COMPUTER	= 0 << 8,
+	CFG_IOPAD_MASK		= 0xf << 0,
+	CFG_IOPAD_DUMB24	= 0x0 << 0,
+	CFG_IOPAD_DUMB18SPI	= 0x1 << 0,
+	CFG_IOPAD_DUMB18GPIO	= 0x2 << 0,
+	CFG_IOPAD_DUMB16SPI	= 0x3 << 0,
+	CFG_IOPAD_DUMB16GPIO	= 0x4 << 0,
+	CFG_IOPAD_DUMB12GPIO	= 0x5 << 0,
+	CFG_IOPAD_SMART18	= 0x6 << 0,
+	CFG_IOPAD_SMART16	= 0x7 << 0,
+	CFG_IOPAD_SMART8	= 0x8 << 0,
+};
+
+#define IOPAD_DUMB24                0x0
+
+/* For LCD_SPU_IRQ_ENA */
+enum {
+	DMA_FRAME_IRQ0_ENA	= 1 << 31,
+	DMA_FRAME_IRQ1_ENA	= 1 << 30,
+	DMA_FRAME_IRQ_ENA	= DMA_FRAME_IRQ0_ENA | DMA_FRAME_IRQ1_ENA,
+	DMA_FF_UNDERFLOW_ENA	= 1 << 29,
+	GRA_FRAME_IRQ0_ENA	= 1 << 27,
+	GRA_FRAME_IRQ1_ENA	= 1 << 26,
+	GRA_FRAME_IRQ_ENA	= GRA_FRAME_IRQ0_ENA | GRA_FRAME_IRQ1_ENA,
+	GRA_FF_UNDERFLOW_ENA	= 1 << 25,
+	VSYNC_IRQ_ENA		= 1 << 23,
+	DUMB_FRAMEDONE_ENA	= 1 << 22,
+	TWC_FRAMEDONE_ENA	= 1 << 21,
+	HWC_FRAMEDONE_ENA	= 1 << 20,
+	SLV_IRQ_ENA		= 1 << 19,
+	SPI_IRQ_ENA		= 1 << 18,
+	PWRDN_IRQ_ENA		= 1 << 17,
+	ERR_IRQ_ENA		= 1 << 16,
+	CLEAN_SPU_IRQ_ISR	= 0xffff,
+};
+
+/* For LCD_SPU_IRQ_ISR */
+enum {
+	DMA_FRAME_IRQ0		= 1 << 31,
+	DMA_FRAME_IRQ1		= 1 << 30,
+	DMA_FRAME_IRQ		= DMA_FRAME_IRQ0 | DMA_FRAME_IRQ1,
+	DMA_FF_UNDERFLOW	= 1 << 29,
+	GRA_FRAME_IRQ0		= 1 << 27,
+	GRA_FRAME_IRQ1		= 1 << 26,
+	GRA_FRAME_IRQ		= GRA_FRAME_IRQ0 | GRA_FRAME_IRQ1,
+	GRA_FF_UNDERFLOW	= 1 << 25,
+	VSYNC_IRQ		= 1 << 23,
+	DUMB_FRAMEDONE		= 1 << 22,
+	TWC_FRAMEDONE		= 1 << 21,
+	HWC_FRAMEDONE		= 1 << 20,
+	SLV_IRQ			= 1 << 19,
+	SPI_IRQ			= 1 << 18,
+	PWRDN_IRQ		= 1 << 17,
+	ERR_IRQ			= 1 << 16,
+	DMA_FRAME_IRQ0_LEVEL	= 1 << 15,
+	DMA_FRAME_IRQ1_LEVEL	= 1 << 14,
+	DMA_FRAME_CNT_ISR	= 3 << 12,
+	GRA_FRAME_IRQ0_LEVEL	= 1 << 11,
+	GRA_FRAME_IRQ1_LEVEL	= 1 << 10,
+	GRA_FRAME_CNT_ISR	= 3 << 8,
+	VSYNC_IRQ_LEVEL		= 1 << 7,
+	DUMB_FRAMEDONE_LEVEL	= 1 << 6,
+	TWC_FRAMEDONE_LEVEL	= 1 << 5,
+	HWC_FRAMEDONE_LEVEL	= 1 << 4,
+	SLV_FF_EMPTY		= 1 << 3,
+	DMA_FF_ALLEMPTY		= 1 << 2,
+	GRA_FF_ALLEMPTY		= 1 << 1,
+	PWRDN_IRQ_LEVEL		= 1 << 0,
+};
+
+#endif
diff --git a/drivers/gpu/drm/armada/armada_ioctlP.h b/drivers/gpu/drm/armada/armada_ioctlP.h
new file mode 100644
index 0000000..bd8c456
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_ioctlP.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_IOCTLP_H
+#define ARMADA_IOCTLP_H
+
+#define ARMADA_IOCTL_PROTO(name)\
+extern int armada_##name##_ioctl(struct drm_device *, void *, struct drm_file *)
+
+ARMADA_IOCTL_PROTO(gem_create);
+ARMADA_IOCTL_PROTO(gem_mmap);
+ARMADA_IOCTL_PROTO(gem_pwrite);
+
+#endif
diff --git a/drivers/gpu/drm/armada/armada_output.c b/drivers/gpu/drm/armada/armada_output.c
new file mode 100644
index 0000000..d685a54
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_output.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_encoder_slave.h>
+#include "armada_output.h"
+#include "armada_drm.h"
+
+struct armada_connector {
+	struct drm_connector conn;
+	const struct armada_output_type *type;
+};
+
+#define drm_to_armada_conn(c) container_of(c, struct armada_connector, conn)
+
+struct drm_encoder *armada_drm_connector_encoder(struct drm_connector *conn)
+{
+	struct drm_encoder *enc = conn->encoder;
+
+	return enc ? enc : drm_encoder_find(conn->dev, conn->encoder_ids[0]);
+}
+
+static enum drm_connector_status armada_drm_connector_detect(
+	struct drm_connector *conn, bool force)
+{
+	struct armada_connector *dconn = drm_to_armada_conn(conn);
+	enum drm_connector_status status = connector_status_disconnected;
+
+	if (dconn->type->detect) {
+		status = dconn->type->detect(conn, force);
+	} else {
+		struct drm_encoder *enc = armada_drm_connector_encoder(conn);
+
+		if (enc)
+			status = encoder_helper_funcs(enc)->detect(enc, conn);
+	}
+
+	return status;
+}
+
+static void armada_drm_connector_destroy(struct drm_connector *conn)
+{
+	struct armada_connector *dconn = drm_to_armada_conn(conn);
+
+	drm_sysfs_connector_remove(conn);
+	drm_connector_cleanup(conn);
+	kfree(dconn);
+}
+
+static int armada_drm_connector_set_property(struct drm_connector *conn,
+	struct drm_property *property, uint64_t value)
+{
+	struct armada_connector *dconn = drm_to_armada_conn(conn);
+
+	if (!dconn->type->set_property)
+		return -EINVAL;
+
+	return dconn->type->set_property(conn, property, value);
+}
+
+static const struct drm_connector_funcs armada_drm_conn_funcs = {
+	.dpms		= drm_helper_connector_dpms,
+	.fill_modes	= drm_helper_probe_single_connector_modes,
+	.detect		= armada_drm_connector_detect,
+	.destroy	= armada_drm_connector_destroy,
+	.set_property	= armada_drm_connector_set_property,
+};
+
+void armada_drm_encoder_prepare(struct drm_encoder *encoder)
+{
+	encoder_helper_funcs(encoder)->dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+void armada_drm_encoder_commit(struct drm_encoder *encoder)
+{
+	encoder_helper_funcs(encoder)->dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+bool armada_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+	const struct drm_display_mode *mode, struct drm_display_mode *adjusted)
+{
+	return true;
+}
+
+/* Shouldn't this be a generic helper function? */
+int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn,
+	struct drm_display_mode *mode)
+{
+	struct drm_encoder *encoder = armada_drm_connector_encoder(conn);
+	int valid = MODE_BAD;
+
+	if (encoder) {
+		struct drm_encoder_slave *slave = to_encoder_slave(encoder);
+
+		valid = slave->slave_funcs->mode_valid(encoder, mode);
+	}
+	return valid;
+}
+
+int armada_drm_slave_encoder_set_property(struct drm_connector *conn,
+	struct drm_property *property, uint64_t value)
+{
+	struct drm_encoder *encoder = armada_drm_connector_encoder(conn);
+	int rc = -EINVAL;
+
+	if (encoder) {
+		struct drm_encoder_slave *slave = to_encoder_slave(encoder);
+
+		rc = slave->slave_funcs->set_property(encoder, conn, property,
+						      value);
+	}
+	return rc;
+}
+
+int armada_output_create(struct drm_device *dev,
+	const struct armada_output_type *type, const void *data)
+{
+	struct armada_connector *dconn;
+	int ret;
+
+	dconn = kzalloc(sizeof(*dconn), GFP_KERNEL);
+	if (!dconn)
+		return -ENOMEM;
+
+	dconn->type = type;
+
+	ret = drm_connector_init(dev, &dconn->conn, &armada_drm_conn_funcs,
+				 type->connector_type);
+	if (ret) {
+		DRM_ERROR("unable to init connector\n");
+		goto err_destroy_dconn;
+	}
+
+	ret = type->create(&dconn->conn, data);
+	if (ret)
+		goto err_conn;
+
+	ret = drm_sysfs_connector_add(&dconn->conn);
+	if (ret)
+		goto err_sysfs;
+
+	return 0;
+
+ err_sysfs:
+	if (dconn->conn.encoder)
+		dconn->conn.encoder->funcs->destroy(dconn->conn.encoder);
+ err_conn:
+	drm_connector_cleanup(&dconn->conn);
+ err_destroy_dconn:
+	kfree(dconn);
+	return ret;
+}
diff --git a/drivers/gpu/drm/armada/armada_output.h b/drivers/gpu/drm/armada/armada_output.h
new file mode 100644
index 0000000..4126d43
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_output.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_CONNETOR_H
+#define ARMADA_CONNETOR_H
+
+#define encoder_helper_funcs(encoder) \
+	((struct drm_encoder_helper_funcs *)encoder->helper_private)
+
+struct armada_output_type {
+	int connector_type;
+	enum drm_connector_status (*detect)(struct drm_connector *, bool);
+	int (*create)(struct drm_connector *, const void *);
+	int (*set_property)(struct drm_connector *, struct drm_property *,
+			    uint64_t);
+};
+
+struct drm_encoder *armada_drm_connector_encoder(struct drm_connector *conn);
+
+void armada_drm_encoder_prepare(struct drm_encoder *encoder);
+void armada_drm_encoder_commit(struct drm_encoder *encoder);
+
+bool armada_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+	const struct drm_display_mode *mode, struct drm_display_mode *adj);
+
+int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn,
+	struct drm_display_mode *mode);
+
+int armada_drm_slave_encoder_set_property(struct drm_connector *conn,
+	struct drm_property *property, uint64_t value);
+
+int armada_output_create(struct drm_device *dev,
+	const struct armada_output_type *type, const void *data);
+
+#endif
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
new file mode 100644
index 0000000..c5b06fd
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Rewritten from the dovefb driver, and Armada510 manuals.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <drm/drmP.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_fb.h"
+#include "armada_gem.h"
+#include "armada_hw.h"
+#include <drm/armada_drm.h>
+#include "armada_ioctlP.h"
+
+struct armada_plane_properties {
+	uint32_t colorkey_yr;
+	uint32_t colorkey_ug;
+	uint32_t colorkey_vb;
+#define K2R(val) (((val) >> 0) & 0xff)
+#define K2G(val) (((val) >> 8) & 0xff)
+#define K2B(val) (((val) >> 16) & 0xff)
+	int16_t  brightness;
+	uint16_t contrast;
+	uint16_t saturation;
+	uint32_t colorkey_mode;
+};
+
+struct armada_plane {
+	struct drm_plane base;
+	spinlock_t lock;
+	struct drm_framebuffer *old_fb;
+	uint32_t src_hw;
+	uint32_t dst_hw;
+	uint32_t dst_yx;
+	uint32_t ctrl0;
+	struct {
+		struct armada_vbl_event update;
+		struct armada_regs regs[13];
+		wait_queue_head_t wait;
+	} vbl;
+	struct armada_plane_properties prop;
+};
+#define drm_to_armada_plane(p) container_of(p, struct armada_plane, base)
+
+
+static void
+armada_ovl_update_attr(struct armada_plane_properties *prop,
+	struct armada_crtc *dcrtc)
+{
+	writel_relaxed(prop->colorkey_yr, dcrtc->base + LCD_SPU_COLORKEY_Y);
+	writel_relaxed(prop->colorkey_ug, dcrtc->base + LCD_SPU_COLORKEY_U);
+	writel_relaxed(prop->colorkey_vb, dcrtc->base + LCD_SPU_COLORKEY_V);
+
+	writel_relaxed(prop->brightness << 16 | prop->contrast,
+		       dcrtc->base + LCD_SPU_CONTRAST);
+	/* Docs say 15:0, but it seems to actually be 31:16 on Armada 510 */
+	writel_relaxed(prop->saturation << 16,
+		       dcrtc->base + LCD_SPU_SATURATION);
+	writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE);
+
+	spin_lock_irq(&dcrtc->irq_lock);
+	armada_updatel(prop->colorkey_mode | CFG_ALPHAM_GRA,
+		     CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK,
+		     dcrtc->base + LCD_SPU_DMA_CTRL1);
+
+	armada_updatel(ADV_GRACOLORKEY, 0, dcrtc->base + LCD_SPU_ADV_REG);
+	spin_unlock_irq(&dcrtc->irq_lock);
+}
+
+/* === Plane support === */
+static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data)
+{
+	struct armada_plane *dplane = data;
+	struct drm_framebuffer *fb;
+
+	armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs);
+
+	spin_lock(&dplane->lock);
+	fb = dplane->old_fb;
+	dplane->old_fb = NULL;
+	spin_unlock(&dplane->lock);
+
+	if (fb)
+		armada_drm_queue_unref_work(dcrtc->crtc.dev, fb);
+}
+
+static unsigned armada_limit(int start, unsigned size, unsigned max)
+{
+	int end = start + size;
+	if (end < 0)
+		return 0;
+	if (start < 0)
+		start = 0;
+	return (unsigned)end > max ? max - start : end - start;
+}
+
+static int
+armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
+	struct drm_framebuffer *fb,
+	int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
+	uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h)
+{
+	struct armada_plane *dplane = drm_to_armada_plane(plane);
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	uint32_t val, ctrl0;
+	unsigned idx = 0;
+	int ret;
+
+	crtc_w = armada_limit(crtc_x, crtc_w, dcrtc->crtc.mode.hdisplay);
+	crtc_h = armada_limit(crtc_y, crtc_h, dcrtc->crtc.mode.vdisplay);
+	ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) |
+		CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) |
+		CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA;
+
+	/* Does the position/size result in nothing to display? */
+	if (crtc_w == 0 || crtc_h == 0) {
+		ctrl0 &= ~CFG_DMA_ENA;
+	}
+
+	/*
+	 * FIXME: if the starting point is off screen, we need to
+	 * adjust src_x, src_y, src_w, src_h appropriately, and
+	 * according to the scale.
+	 */
+
+	if (!dcrtc->plane) {
+		dcrtc->plane = plane;
+		armada_ovl_update_attr(&dplane->prop, dcrtc);
+	}
+
+	/* FIXME: overlay on an interlaced display */
+	/* Just updating the position/size? */
+	if (plane->fb == fb && dplane->ctrl0 == ctrl0) {
+		val = (src_h & 0xffff0000) | src_w >> 16;
+		dplane->src_hw = val;
+		writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN);
+		val = crtc_h << 16 | crtc_w;
+		dplane->dst_hw = val;
+		writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN);
+		val = crtc_y << 16 | crtc_x;
+		dplane->dst_yx = val;
+		writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN);
+		return 0;
+	} else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) {
+		/* Power up the Y/U/V FIFOs on ENA 0->1 transitions */
+		armada_updatel(0, CFG_PDWN16x66 | CFG_PDWN32x66,
+			       dcrtc->base + LCD_SPU_SRAM_PARA1);
+	}
+
+	ret = wait_event_timeout(dplane->vbl.wait,
+				 list_empty(&dplane->vbl.update.node),
+				 HZ/25);
+	if (ret < 0)
+		return ret;
+
+	if (plane->fb != fb) {
+		struct armada_gem_object *obj = drm_fb_obj(fb);
+		uint32_t sy, su, sv;
+
+		/*
+		 * Take a reference on the new framebuffer - we want to
+		 * hold on to it while the hardware is displaying it.
+		 */
+		drm_framebuffer_reference(fb);
+
+		if (plane->fb) {
+			struct drm_framebuffer *older_fb;
+
+			spin_lock_irq(&dplane->lock);
+			older_fb = dplane->old_fb;
+			dplane->old_fb = plane->fb;
+			spin_unlock_irq(&dplane->lock);
+			if (older_fb)
+				armada_drm_queue_unref_work(dcrtc->crtc.dev,
+							    older_fb);
+		}
+
+		src_y >>= 16;
+		src_x >>= 16;
+		sy = obj->dev_addr + fb->offsets[0] + src_y * fb->pitches[0] +
+			src_x * fb->bits_per_pixel / 8;
+		su = obj->dev_addr + fb->offsets[1] + src_y * fb->pitches[1] +
+			src_x;
+		sv = obj->dev_addr + fb->offsets[2] + src_y * fb->pitches[2] +
+			src_x;
+
+		armada_reg_queue_set(dplane->vbl.regs, idx, sy,
+				     LCD_SPU_DMA_START_ADDR_Y0);
+		armada_reg_queue_set(dplane->vbl.regs, idx, su,
+				     LCD_SPU_DMA_START_ADDR_U0);
+		armada_reg_queue_set(dplane->vbl.regs, idx, sv,
+				     LCD_SPU_DMA_START_ADDR_V0);
+		armada_reg_queue_set(dplane->vbl.regs, idx, sy,
+				     LCD_SPU_DMA_START_ADDR_Y1);
+		armada_reg_queue_set(dplane->vbl.regs, idx, su,
+				     LCD_SPU_DMA_START_ADDR_U1);
+		armada_reg_queue_set(dplane->vbl.regs, idx, sv,
+				     LCD_SPU_DMA_START_ADDR_V1);
+
+		val = fb->pitches[0] << 16 | fb->pitches[0];
+		armada_reg_queue_set(dplane->vbl.regs, idx, val,
+				     LCD_SPU_DMA_PITCH_YC);
+		val = fb->pitches[1] << 16 | fb->pitches[2];
+		armada_reg_queue_set(dplane->vbl.regs, idx, val,
+				     LCD_SPU_DMA_PITCH_UV);
+	}
+
+	val = (src_h & 0xffff0000) | src_w >> 16;
+	if (dplane->src_hw != val) {
+		dplane->src_hw = val;
+		armada_reg_queue_set(dplane->vbl.regs, idx, val,
+				     LCD_SPU_DMA_HPXL_VLN);
+	}
+	val = crtc_h << 16 | crtc_w;
+	if (dplane->dst_hw != val) {
+		dplane->dst_hw = val;
+		armada_reg_queue_set(dplane->vbl.regs, idx, val,
+				     LCD_SPU_DZM_HPXL_VLN);
+	}
+	val = crtc_y << 16 | crtc_x;
+	if (dplane->dst_yx != val) {
+		dplane->dst_yx = val;
+		armada_reg_queue_set(dplane->vbl.regs, idx, val,
+				     LCD_SPU_DMA_OVSA_HPXL_VLN);
+	}
+	if (dplane->ctrl0 != ctrl0) {
+		dplane->ctrl0 = ctrl0;
+		armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0,
+			CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE |
+			CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE |
+			CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV | CFG_SWAPYU |
+			CFG_YUV2RGB) | CFG_DMA_ENA,
+			LCD_SPU_DMA_CTRL0);
+	}
+	if (idx) {
+		armada_reg_queue_end(dplane->vbl.regs, idx);
+		armada_drm_vbl_event_add(dcrtc, &dplane->vbl.update);
+	}
+	return 0;
+}
+
+static int armada_plane_disable(struct drm_plane *plane)
+{
+	struct armada_plane *dplane = drm_to_armada_plane(plane);
+	struct drm_framebuffer *fb;
+	struct armada_crtc *dcrtc;
+
+	if (!dplane->base.crtc)
+		return 0;
+
+	dcrtc = drm_to_armada_crtc(dplane->base.crtc);
+	dcrtc->plane = NULL;
+
+	spin_lock_irq(&dcrtc->irq_lock);
+	armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update);
+	armada_updatel(0, CFG_DMA_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0);
+	dplane->ctrl0 = 0;
+	spin_unlock_irq(&dcrtc->irq_lock);
+
+	/* Power down the Y/U/V FIFOs */
+	armada_updatel(CFG_PDWN16x66 | CFG_PDWN32x66, 0,
+		       dcrtc->base + LCD_SPU_SRAM_PARA1);
+
+	if (plane->fb)
+		drm_framebuffer_unreference(plane->fb);
+
+	spin_lock_irq(&dplane->lock);
+	fb = dplane->old_fb;
+	dplane->old_fb = NULL;
+	spin_unlock_irq(&dplane->lock);
+	if (fb)
+		drm_framebuffer_unreference(fb);
+
+	return 0;
+}
+
+static void armada_plane_destroy(struct drm_plane *plane)
+{
+	kfree(plane);
+}
+
+static int armada_plane_set_property(struct drm_plane *plane,
+	struct drm_property *property, uint64_t val)
+{
+	struct armada_private *priv = plane->dev->dev_private;
+	struct armada_plane *dplane = drm_to_armada_plane(plane);
+	bool update_attr = false;
+
+	if (property == priv->colorkey_prop) {
+#define CCC(v) ((v) << 24 | (v) << 16 | (v) << 8)
+		dplane->prop.colorkey_yr = CCC(K2R(val));
+		dplane->prop.colorkey_ug = CCC(K2G(val));
+		dplane->prop.colorkey_vb = CCC(K2B(val));
+#undef CCC
+		update_attr = true;
+	} else if (property == priv->colorkey_min_prop) {
+		dplane->prop.colorkey_yr &= ~0x00ff0000;
+		dplane->prop.colorkey_yr |= K2R(val) << 16;
+		dplane->prop.colorkey_ug &= ~0x00ff0000;
+		dplane->prop.colorkey_ug |= K2G(val) << 16;
+		dplane->prop.colorkey_vb &= ~0x00ff0000;
+		dplane->prop.colorkey_vb |= K2B(val) << 16;
+		update_attr = true;
+	} else if (property == priv->colorkey_max_prop) {
+		dplane->prop.colorkey_yr &= ~0xff000000;
+		dplane->prop.colorkey_yr |= K2R(val) << 24;
+		dplane->prop.colorkey_ug &= ~0xff000000;
+		dplane->prop.colorkey_ug |= K2G(val) << 24;
+		dplane->prop.colorkey_vb &= ~0xff000000;
+		dplane->prop.colorkey_vb |= K2B(val) << 24;
+		update_attr = true;
+	} else if (property == priv->colorkey_val_prop) {
+		dplane->prop.colorkey_yr &= ~0x0000ff00;
+		dplane->prop.colorkey_yr |= K2R(val) << 8;
+		dplane->prop.colorkey_ug &= ~0x0000ff00;
+		dplane->prop.colorkey_ug |= K2G(val) << 8;
+		dplane->prop.colorkey_vb &= ~0x0000ff00;
+		dplane->prop.colorkey_vb |= K2B(val) << 8;
+		update_attr = true;
+	} else if (property == priv->colorkey_alpha_prop) {
+		dplane->prop.colorkey_yr &= ~0x000000ff;
+		dplane->prop.colorkey_yr |= K2R(val);
+		dplane->prop.colorkey_ug &= ~0x000000ff;
+		dplane->prop.colorkey_ug |= K2G(val);
+		dplane->prop.colorkey_vb &= ~0x000000ff;
+		dplane->prop.colorkey_vb |= K2B(val);
+		update_attr = true;
+	} else if (property == priv->colorkey_mode_prop) {
+		dplane->prop.colorkey_mode &= ~CFG_CKMODE_MASK;
+		dplane->prop.colorkey_mode |= CFG_CKMODE(val);
+		update_attr = true;
+	} else if (property == priv->brightness_prop) {
+		dplane->prop.brightness = val - 256;
+		update_attr = true;
+	} else if (property == priv->contrast_prop) {
+		dplane->prop.contrast = val;
+		update_attr = true;
+	} else if (property == priv->saturation_prop) {
+		dplane->prop.saturation = val;
+		update_attr = true;
+	}
+
+	if (update_attr && dplane->base.crtc)
+		armada_ovl_update_attr(&dplane->prop,
+				       drm_to_armada_crtc(dplane->base.crtc));
+
+	return 0;
+}
+
+static const struct drm_plane_funcs armada_plane_funcs = {
+	.update_plane	= armada_plane_update,
+	.disable_plane	= armada_plane_disable,
+	.destroy	= armada_plane_destroy,
+	.set_property	= armada_plane_set_property,
+};
+
+static const uint32_t armada_formats[] = {
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YUV420,
+	DRM_FORMAT_YVU420,
+	DRM_FORMAT_YUV422,
+	DRM_FORMAT_YVU422,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_ABGR1555,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+};
+
+static struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = {
+	{ CKMODE_DISABLE, "disabled" },
+	{ CKMODE_Y,       "Y component" },
+	{ CKMODE_U,       "U component" },
+	{ CKMODE_V,       "V component" },
+	{ CKMODE_RGB,     "RGB" },
+	{ CKMODE_R,       "R component" },
+	{ CKMODE_G,       "G component" },
+	{ CKMODE_B,       "B component" },
+};
+
+static int armada_overlay_create_properties(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+
+	if (priv->colorkey_prop)
+		return 0;
+
+	priv->colorkey_prop = drm_property_create_range(dev, 0,
+				"colorkey", 0, 0xffffff);
+	priv->colorkey_min_prop = drm_property_create_range(dev, 0,
+				"colorkey_min", 0, 0xffffff);
+	priv->colorkey_max_prop = drm_property_create_range(dev, 0,
+				"colorkey_max", 0, 0xffffff);
+	priv->colorkey_val_prop = drm_property_create_range(dev, 0,
+				"colorkey_val", 0, 0xffffff);
+	priv->colorkey_alpha_prop = drm_property_create_range(dev, 0,
+				"colorkey_alpha", 0, 0xffffff);
+	priv->colorkey_mode_prop = drm_property_create_enum(dev, 0,
+				"colorkey_mode",
+				armada_drm_colorkey_enum_list,
+				ARRAY_SIZE(armada_drm_colorkey_enum_list));
+	priv->brightness_prop = drm_property_create_range(dev, 0,
+				"brightness", 0, 256 + 255);
+	priv->contrast_prop = drm_property_create_range(dev, 0,
+				"contrast", 0, 0x7fff);
+	priv->saturation_prop = drm_property_create_range(dev, 0,
+				"saturation", 0, 0x7fff);
+
+	if (!priv->colorkey_prop)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct drm_mode_object *mobj;
+	struct armada_plane *dplane;
+	int ret;
+
+	ret = armada_overlay_create_properties(dev);
+	if (ret)
+		return ret;
+
+	dplane = kzalloc(sizeof(*dplane), GFP_KERNEL);
+	if (!dplane)
+		return -ENOMEM;
+
+	spin_lock_init(&dplane->lock);
+	init_waitqueue_head(&dplane->vbl.wait);
+	armada_drm_vbl_event_init(&dplane->vbl.update, armada_plane_vbl,
+				  dplane);
+
+	drm_plane_init(dev, &dplane->base, crtcs, &armada_plane_funcs,
+		       armada_formats, ARRAY_SIZE(armada_formats), false);
+
+	dplane->prop.colorkey_yr = 0xfefefe00;
+	dplane->prop.colorkey_ug = 0x01010100;
+	dplane->prop.colorkey_vb = 0x01010100;
+	dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB);
+	dplane->prop.brightness = 0;
+	dplane->prop.contrast = 0x4000;
+	dplane->prop.saturation = 0x4000;
+
+	mobj = &dplane->base.base;
+	drm_object_attach_property(mobj, priv->colorkey_prop,
+				   0x0101fe);
+	drm_object_attach_property(mobj, priv->colorkey_min_prop,
+				   0x0101fe);
+	drm_object_attach_property(mobj, priv->colorkey_max_prop,
+				   0x0101fe);
+	drm_object_attach_property(mobj, priv->colorkey_val_prop,
+				   0x0101fe);
+	drm_object_attach_property(mobj, priv->colorkey_alpha_prop,
+				   0x000000);
+	drm_object_attach_property(mobj, priv->colorkey_mode_prop,
+				   CKMODE_RGB);
+	drm_object_attach_property(mobj, priv->brightness_prop, 256);
+	drm_object_attach_property(mobj, priv->contrast_prop,
+				   dplane->prop.contrast);
+	drm_object_attach_property(mobj, priv->saturation_prop,
+				   dplane->prop.saturation);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/armada/armada_slave.c b/drivers/gpu/drm/armada/armada_slave.c
new file mode 100644
index 0000000..00d0fac
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_slave.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Rewritten from the dovefb driver, and Armada510 manuals.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_encoder_slave.h>
+#include "armada_drm.h"
+#include "armada_output.h"
+#include "armada_slave.h"
+
+static int armada_drm_slave_get_modes(struct drm_connector *conn)
+{
+	struct drm_encoder *enc = armada_drm_connector_encoder(conn);
+	int count = 0;
+
+	if (enc) {
+		struct drm_encoder_slave *slave = to_encoder_slave(enc);
+
+		count = slave->slave_funcs->get_modes(enc, conn);
+	}
+
+	return count;
+}
+
+static void armada_drm_slave_destroy(struct drm_encoder *enc)
+{
+	struct drm_encoder_slave *slave = to_encoder_slave(enc);
+	struct i2c_client *client = drm_i2c_encoder_get_client(enc);
+
+	if (slave->slave_funcs)
+		slave->slave_funcs->destroy(enc);
+	if (client)
+		i2c_put_adapter(client->adapter);
+
+	drm_encoder_cleanup(&slave->base);
+	kfree(slave);
+}
+
+static const struct drm_encoder_funcs armada_drm_slave_encoder_funcs = {
+	.destroy	= armada_drm_slave_destroy,
+};
+
+static const struct drm_connector_helper_funcs armada_drm_slave_helper_funcs = {
+	.get_modes	= armada_drm_slave_get_modes,
+	.mode_valid	= armada_drm_slave_encoder_mode_valid,
+	.best_encoder	= armada_drm_connector_encoder,
+};
+
+static const struct drm_encoder_helper_funcs drm_slave_encoder_helpers = {
+	.dpms = drm_i2c_encoder_dpms,
+	.save = drm_i2c_encoder_save,
+	.restore = drm_i2c_encoder_restore,
+	.mode_fixup = drm_i2c_encoder_mode_fixup,
+	.prepare = drm_i2c_encoder_prepare,
+	.commit = drm_i2c_encoder_commit,
+	.mode_set = drm_i2c_encoder_mode_set,
+	.detect = drm_i2c_encoder_detect,
+};
+
+static int
+armada_drm_conn_slave_create(struct drm_connector *conn, const void *data)
+{
+	const struct armada_drm_slave_config *config = data;
+	struct drm_encoder_slave *slave;
+	struct i2c_adapter *adap;
+	int ret;
+
+	conn->interlace_allowed = config->interlace_allowed;
+	conn->doublescan_allowed = config->doublescan_allowed;
+	conn->polled = config->polled;
+
+	drm_connector_helper_add(conn, &armada_drm_slave_helper_funcs);
+
+	slave = kzalloc(sizeof(*slave), GFP_KERNEL);
+	if (!slave)
+		return -ENOMEM;
+
+	slave->base.possible_crtcs = config->crtcs;
+
+	adap = i2c_get_adapter(config->i2c_adapter_id);
+	if (!adap) {
+		kfree(slave);
+		return -EPROBE_DEFER;
+	}
+
+	ret = drm_encoder_init(conn->dev, &slave->base,
+			       &armada_drm_slave_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS);
+	if (ret) {
+		DRM_ERROR("unable to init encoder\n");
+		i2c_put_adapter(adap);
+		kfree(slave);
+		return ret;
+	}
+
+	ret = drm_i2c_encoder_init(conn->dev, slave, adap, &config->info);
+	i2c_put_adapter(adap);
+	if (ret) {
+		DRM_ERROR("unable to init encoder slave\n");
+		armada_drm_slave_destroy(&slave->base);
+		return ret;
+	}
+
+	drm_encoder_helper_add(&slave->base, &drm_slave_encoder_helpers);
+
+	ret = slave->slave_funcs->create_resources(&slave->base, conn);
+	if (ret) {
+		armada_drm_slave_destroy(&slave->base);
+		return ret;
+	}
+
+	ret = drm_mode_connector_attach_encoder(conn, &slave->base);
+	if (ret) {
+		armada_drm_slave_destroy(&slave->base);
+		return ret;
+	}
+
+	conn->encoder = &slave->base;
+
+	return ret;
+}
+
+static const struct armada_output_type armada_drm_conn_slave = {
+	.connector_type	= DRM_MODE_CONNECTOR_HDMIA,
+	.create		= armada_drm_conn_slave_create,
+	.set_property	= armada_drm_slave_encoder_set_property,
+};
+
+int armada_drm_connector_slave_create(struct drm_device *dev,
+	const struct armada_drm_slave_config *config)
+{
+	return armada_output_create(dev, &armada_drm_conn_slave, config);
+}
diff --git a/drivers/gpu/drm/armada/armada_slave.h b/drivers/gpu/drm/armada/armada_slave.h
new file mode 100644
index 0000000..bf2374c
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_slave.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_SLAVE_H
+#define ARMADA_SLAVE_H
+
+#include <linux/i2c.h>
+#include <drm/drmP.h>
+
+struct armada_drm_slave_config {
+	int i2c_adapter_id;
+	uint32_t crtcs;
+	uint8_t polled;
+	bool interlace_allowed;
+	bool doublescan_allowed;
+	struct i2c_board_info info;
+};
+
+int armada_drm_connector_slave_create(struct drm_device *dev,
+	const struct armada_drm_slave_config *);
+
+#endif
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 24f4995..e5e6e91 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1135,4 +1135,21 @@ extern int drm_format_horz_chroma_subsampling(uint32_t format);
 extern int drm_format_vert_chroma_subsampling(uint32_t format);
 extern const char *drm_get_format_name(uint32_t format);
 
+/* Helpers */
+static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
+	uint32_t id)
+{
+	struct drm_mode_object *mo;
+	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CRTC);
+	return mo ? obj_to_crtc(mo) : NULL;
+}
+
+static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
+	uint32_t id)
+{
+	struct drm_mode_object *mo;
+	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
+	return mo ? obj_to_encoder(mo) : NULL;
+}
+
 #endif /* __DRM_CRTC_H__ */
diff --git a/include/uapi/drm/armada_drm.h b/include/uapi/drm/armada_drm.h
new file mode 100644
index 0000000..8dec3fd
--- /dev/null
+++ b/include/uapi/drm/armada_drm.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  With inspiration from the i915 driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef DRM_ARMADA_IOCTL_H
+#define DRM_ARMADA_IOCTL_H
+
+#define DRM_ARMADA_GEM_CREATE		0x00
+#define DRM_ARMADA_GEM_MMAP		0x02
+#define DRM_ARMADA_GEM_PWRITE		0x03
+
+#define ARMADA_IOCTL(dir, name, str) \
+	DRM_##dir(DRM_COMMAND_BASE + DRM_ARMADA_##name, struct drm_armada_##str)
+
+struct drm_armada_gem_create {
+	uint32_t handle;
+	uint32_t size;
+};
+#define DRM_IOCTL_ARMADA_GEM_CREATE \
+	ARMADA_IOCTL(IOWR, GEM_CREATE, gem_create)
+
+struct drm_armada_gem_mmap {
+	uint32_t handle;
+	uint32_t pad;
+	uint64_t offset;
+	uint64_t size;
+	uint64_t addr;
+};
+#define DRM_IOCTL_ARMADA_GEM_MMAP \
+	ARMADA_IOCTL(IOWR, GEM_MMAP, gem_mmap)
+
+struct drm_armada_gem_pwrite {
+	uint64_t ptr;
+	uint32_t handle;
+	uint32_t offset;
+	uint32_t size;
+};
+#define DRM_IOCTL_ARMADA_GEM_PWRITE \
+	ARMADA_IOCTL(IOW, GEM_PWRITE, gem_pwrite)
+
+#endif
-- 
1.7.4.4

From mboxrd@z Thu Jan  1 00:00:00 1970
From: robdclark@gmail.com (Rob Clark)
Date: Thu, 17 Oct 2013 19:58:32 -0400
Subject: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
In-Reply-To: <20131007125034.GO12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
 <20131007110141.27f1ac25@armhf>
 <20131007094008.GH12758@n2100.arm.linux.org.uk>
 <20131007120922.47df03b6@armhf>
 <20131007103250.GJ12758@n2100.arm.linux.org.uk>
 <20131007152915.352cc4b2@i7>
 <20131007125034.GO12758@n2100.arm.linux.org.uk>
Message-ID: <CAF6AEGt1uOsE5V6rAtxpLNNaYkaKiw9G8CNdt31JZVdS6TX-hA@mail.gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, Oct 7, 2013 at 8:50 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Oct 07, 2013 at 03:29:15PM +0300, Siarhei Siamashka wrote:
>> On Mon, 7 Oct 2013 11:32:50 +0100
>> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
>> > However, what you're suggesting is dangerous.  What do you do when you're
>> > presented with a cursor which is 64x64 ?  Do you:
>> >
>> > (a) not display it
>> > (b) crash the X server
>> >
>> > There isn't a fallback to using software cursors available in the X server
>> > because there's no error reporting for a failed hardware cursor update.
>>
>> Hmm, maybe I'm missing something, but doesn't returning FALSE from
>> UseHWCursorARGB just make the X server fallback to using a software
>> cursor?
>>
>> https://github.com/ssvb/xf86-video-fbturbo/blob/689c08256555/src/sunxi_disp_hwcursor.c#L72
>>
>> I'm just doing this. And also have hooks to notify the DRI2 code about
>> the status of the cursor. In the case if the hardware cursor is not
>> enabled, hardware overlays can't be safely used with the software
>> cursor and we need to fallback to CPU/GPU copy instead of zero-copy
>> buffers swapping.
>>
>> And I fully agree that it is the responsibility of the kernel to expose
>> as much of the hardware capabilities as possible (without compromising
>> reliability and/or security).
>
> If you wish to go in below the level presented by
> hw/xfree86/modes/xf86Cursors.c (as you are doing), then yes you can do
> this, and it's something which maybe should be looked into.  You have a
> good reason to do this (due to your hardware cursor being incompatible
> with overlays).
>
> We have no such restriction - the only issue here is the "odd" size of
> cursors.  Practically, choosing one or other of 64x32 or 32x64 works
> fine for the cases I've seen.  I haven't seen any cursors which are
> 64x64 yet.  I'm not saying they don't exist though!  I can imagine that
> some accessibility options might want to display a large cursor.
>
> Now, the way I handle this is that the kernel allows _either_ a
> (1 to 32)x(1 to 64) or (1 to 64)x(1 to 32) cursor.  Both width and
> height larger than 32 gets rejected with -EINVAL:
>
> +               /* maximum size is 64x32 or 32x64 */
> +               if (w > 64 || h > 64 || (w > 32 && h > 32))
> +                       return -ENOMEM;
>
> which is quite reasonable for this hardware.  However, there is no way
> to export this from DRM - adding maximum cursor size properties wouldn't
> really represent this.

Until relatively recently, it had always been a device specific ddx
which would somehow know what w/h values to pass to
xf86_cursors_init().  I think for xf86-video-modesetting and wayland
compositors, we probably need to come up with something better.
Although off the top of my head I can't think of a good way to express
64x32 or 32x64.. that is a weird restriction.

Anyways, right now I don't think there is anything different that I'd
do in the kernel part.  I *suppose* you could try and figure out that
all the alpha values are either 0x00 or 0xff and support 64x64 in that
special case.  I'm not sure that is actually better.. it at least
makes the failure vs success cases more confusing.  And unless you are
rockin' the twm+xterm+xcalc setup, I doubt you will see many cursors
with only 0x00 or 0xff alpha.

So,

Signed-off-by: Rob Clark <robdclark@gmail.com>


> The only question is whether DRM should export some capabilities to
> indicate what's possible with the cursor, so that X knows about this
> quirk of this hardware.  Overall, I suspect that it's just rare and
> not worth the effort.  I think it's just easier to pick one of these
> and stick with it, and if we happen to encounter a cursor larger than
> our chosen dimentions, XFree86 will already automatically fall back
> to s/w cursor.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: robdclark@gmail.com (Rob Clark)
Date: Thu, 17 Oct 2013 20:11:35 -0400
Subject: [PATCH 4/5] DRM: Armada: start of MMP2/MMP3 support
In-Reply-To: <E1VSwXQ-0000iL-8N@rmk-PC.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwXQ-0000iL-8N@rmk-PC.arm.linux.org.uk>
Message-ID: <CAF6AEGtTdmdTE_qeojTkPY8WYv86TRuzX-ms3Nb3UQHfvoWRwg@mail.gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Sun, Oct 6, 2013 at 6:10 PM, Russell King
<rmk+kernel@arm.linux.org.uk> wrote:
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  drivers/gpu/drm/armada/Makefile      |    1 +
>  drivers/gpu/drm/armada/armada_610.c  |   49 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/armada/armada_crtc.c |    1 +
>  drivers/gpu/drm/armada/armada_drm.h  |    1 +
>  drivers/gpu/drm/armada/armada_drv.c  |    6 ++++
>  drivers/gpu/drm/armada/armada_hw.h   |    8 +++++
>  6 files changed, 66 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/gpu/drm/armada/armada_610.c
>
> diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile
> index d6f43e0..088db4a 100644
> --- a/drivers/gpu/drm/armada/Makefile
> +++ b/drivers/gpu/drm/armada/Makefile
> @@ -2,6 +2,7 @@ armada-y        := armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
>                    armada_gem.o armada_output.o armada_overlay.o \
>                    armada_slave.o
>  armada-y       += armada_510.o
> +armada-y       += armada_610.o
>  armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
>
>  obj-$(CONFIG_DRM_ARMADA) := armada.o
> diff --git a/drivers/gpu/drm/armada/armada_610.c b/drivers/gpu/drm/armada/armada_610.c
> new file mode 100644
> index 0000000..36a10e3
> --- /dev/null
> +++ b/drivers/gpu/drm/armada/armada_610.c
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright (C) 2012 Russell King
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Armada 610/MMP2/MMP3 variant support
> + */
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc_helper.h>
> +#include "armada_crtc.h"
> +#include "armada_drm.h"
> +#include "armada_hw.h"
> +
> +static int mmp23_init(struct armada_private *priv, struct device *dev)
> +{
> +       priv->extclk[0] = devm_clk_get(dev, NULL);
> +
> +       if (IS_ERR(priv->extclk[0]) && PTR_ERR(priv->extclk[0]) == -ENOENT)
> +               priv->extclk[0] = ERR_PTR(-EPROBE_DEFER);
> +
> +       return PTR_RET(priv->extclk[0]);
> +}
> +
> +/*
> + * This gets called with sclk = NULL to test whether the mode is
> + * supportable, and again with sclk != NULL to set the clocks up for
> + * that.  The former can return an error, but the latter is expected
> + * not to.
> + */
> +static int mmp23_crtc_compute_clock(struct armada_crtc *dcrtc,
> +       const struct drm_display_mode *mode, uint32_t *sclk)
> +{
> +       /*
> +        * on MMP3 bits 31:29 select the clock, OLPC wants 0x1 here, LCD clock 1
> +        * on MMP2 bits 31:30 select the clock, OLPC wants 0x1 here, LCD clock 1
> +        */
> +       *sclk = 0x20001100; // FIXME hardcoded mmp3 value
> +

maybe fix this?  Or comment out for now mmp2 below in armada_drm_platform_ids?

BR,
-R

> +       return 0;
> +}
> +
> +const struct armada_variant mmp23_ops = {
> +       .init = mmp23_init,
> +       .crtc_compute_clock = mmp23_crtc_compute_clock,
> +};
> diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
> index e8605bf..b5877ee 100644
> --- a/drivers/gpu/drm/armada/armada_crtc.c
> +++ b/drivers/gpu/drm/armada/armada_crtc.c
> @@ -1054,6 +1054,7 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
>         dcrtc->clk = ERR_PTR(-EINVAL);
>         dcrtc->csc_yuv_mode = CSC_AUTO;
>         dcrtc->csc_rgb_mode = CSC_AUTO;
> +       /* FIXME: MMP2/MMP3: OLPC panel is RGB666 */
>         dcrtc->cfg_dumb_ctrl = DUMB24_RGB888_0;
>         dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
>         spin_lock_init(&dcrtc->irq_lock);
> diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
> index eef09ec..f52fccb 100644
> --- a/drivers/gpu/drm/armada/armada_drm.h
> +++ b/drivers/gpu/drm/armada/armada_drm.h
> @@ -70,6 +70,7 @@ struct armada_variant {
>
>  /* Variant ops */
>  extern const struct armada_variant armada510_ops;
> +extern const struct armada_variant mmp23_ops;
>
>  struct armada_private {
>         const struct armada_variant *variant;
> diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
> index 7bfab9a..db62f1b 100644
> --- a/drivers/gpu/drm/armada/armada_drv.c
> +++ b/drivers/gpu/drm/armada/armada_drv.c
> @@ -344,6 +344,12 @@ static const struct platform_device_id armada_drm_platform_ids[] = {
>                 .name           = "armada-drm",
>                 .driver_data    = (unsigned long)&armada510_ops,
>         }, {
> +               .name           = "armada-610-drm", /* aka MMP2 */
> +               .driver_data    = (unsigned long)&mmp23_ops,
> +       }, {
> +               .name           = "mmp3-drm",
> +               .driver_data    = (unsigned long)&mmp23_ops,
> +       }, {
>                 .name           = "armada-510-drm",
>                 .driver_data    = (unsigned long)&armada510_ops,
>         },
> diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
> index 27319a8..1688716 100644
> --- a/drivers/gpu/drm/armada/armada_hw.h
> +++ b/drivers/gpu/drm/armada/armada_hw.h
> @@ -74,6 +74,7 @@ enum {
>         LCD_SPU_IOPAD_CONTROL           = 0x01bc,
>         LCD_SPU_IRQ_ENA                 = 0x01c0,
>         LCD_SPU_IRQ_ISR                 = 0x01c4,
> +       LCD_MISC_CNTL                   = 0x01c8,       /* Armada 168 */
>  };
>
>  /* For LCD_SPU_ADV_REG */
> @@ -211,6 +212,13 @@ enum {
>         SCLK_16X_PLL            = 0x8 << 28,
>         SCLK_16X_FRAC_DIV_MASK  = 0xfff << 16,
>         SCLK_16X_INT_DIV_MASK   = 0xffff << 0,
> +
> +       /* PXA910 / MMP2 (Armada 610) / MMP3 / PXA988 */
> +       SCLK_MMP_SRC_SEL        = 1 << 31,
> +       SCLK_MMP_DISABLE        = 1 << 28,
> +       SCLK_MMP_FRAC_DIV_MASK  = 0xfff << 16,
> +       SCLK_MMP_DSI_DIV_MASK   = 0xf << 8,
> +       SCLK_MMP_INT_DIV_MASK   = 0xff << 0,
>  };
>
>  /* For LCD_SPU_DUMB_CTRL */
> --
> 1.7.4.4
>

From mboxrd@z Thu Jan  1 00:00:00 1970
From: robdclark@gmail.com (Rob Clark)
Date: Thu, 17 Oct 2013 20:20:45 -0400
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
In-Reply-To: <20131008173418.0fc21d60@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
 <20131008111913.09bfe93e@armhf>
 <20131008094939.GD25034@n2100.arm.linux.org.uk>
 <20131008173418.0fc21d60@armhf>
Message-ID: <CAF6AEGsGMzc8iUZMFqsWdhbS_fSwg38eLfaOG515WNxXg029FA@mail.gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Tue, Oct 8, 2013 at 11:34 AM, Jean-Francois Moine <moinejf@free.fr> wrote:
> On Tue, 8 Oct 2013 10:49:39 +0100
> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
>
>> On Tue, Oct 08, 2013 at 11:19:13AM +0200, Jean-Francois Moine wrote:
>> > The Cubox is an open platform, and I use it just like a desktop PC.
>> > When its required drivers will be in the mainline, I will do the same
>> > as I do with PCs: I will not recompile a specific kernel each time
>> > there are kernel bugs or security issues. Instead, I will just upgrade
>> > my system from my distributor (Debian), and, in the packages, there
>> > will be a generic mvebu kernel as there is already one for Marvell
>> > Armada 370/xp, Freescale iMX5x/iMX6 (linux-image-3.10-3-armmp).
>> > But, for that, all the Cubox specific stuff must be described in a DT.
>>
>> Which scenario is better:
>>
>> 1. To have something in mainline which is capable of driving the hardware,
>>    but may need some additional work to make it useful for DT based setups.
>>
>> or
>>
>> 2. To have nothing.
>>
>> Now, you may prefer to have nothing, but personally, I prefer there to be
>> forward progress.  Forward progress means getting some kind of DRM driver
>> into mainline.  Yes, it may not work with DT setups yet, but - as per
>> the discussions that have happened _endlessly_ on this topic, it's
>> something that can be resolved at a later date.
>>
>> We _still_ haven't worked out how to properly deal with the TDA998x
>> driver (or indeed any DRM based outputs) in a DT based setup, and all
>> the time that problem exists, it won't be possible to write a proper
>> stable DT binding for this.
>>
>> So please, get off your hobby horse about this and allow us to make some
>> modicum of progress.
>
> You forgot:
>
> 3. To have all patches ready for submission and have a working DT driven
>    Cubox kernel.

No need to block this patch on DT support for all platforms that can
use this driver.  I don't see an issue with removing non-DT support
later if it is no longer needed, or adding DT support in a future
patch for platforms which can use it.  So this patch looks fine to me.

Signed-off-by: Rob Clark <robdclark@gmail.com


> I will submit a patch to add DT to the tda998x driver as soon as I have
> checked the new audio properties we talked about yesterday.
>
> Normally, this should have no impact on your Armada drm driver, and,
> yes, I will add DT to your driver as soon as it will be accepted
> (sorry to not ack it now: I had no time yet to have a look at it).
>
> --
> Ken ar c'henta? |             ** Breizh ha Linux atav! **
> Jef             |               http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: alexdeucher@gmail.com (Alex Deucher)
Date: Fri, 18 Oct 2013 10:31:57 -0400
Subject: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
In-Reply-To: <CAF6AEGt1uOsE5V6rAtxpLNNaYkaKiw9G8CNdt31JZVdS6TX-hA@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
 <20131007110141.27f1ac25@armhf>
 <20131007094008.GH12758@n2100.arm.linux.org.uk>
 <20131007120922.47df03b6@armhf>
 <20131007103250.GJ12758@n2100.arm.linux.org.uk>
 <20131007152915.352cc4b2@i7>
 <20131007125034.GO12758@n2100.arm.linux.org.uk>
 <CAF6AEGt1uOsE5V6rAtxpLNNaYkaKiw9G8CNdt31JZVdS6TX-hA@mail.gmail.com>
Message-ID: <CADnq5_Nc9ZK94BO=S7wK=nVoKVUFkJowxo2MvBNMSj+6-cPHUw@mail.gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Thu, Oct 17, 2013 at 7:58 PM, Rob Clark <robdclark@gmail.com> wrote:
> On Mon, Oct 7, 2013 at 8:50 AM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
>> On Mon, Oct 07, 2013 at 03:29:15PM +0300, Siarhei Siamashka wrote:
>>> On Mon, 7 Oct 2013 11:32:50 +0100
>>> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
>>> > However, what you're suggesting is dangerous.  What do you do when you're
>>> > presented with a cursor which is 64x64 ?  Do you:
>>> >
>>> > (a) not display it
>>> > (b) crash the X server
>>> >
>>> > There isn't a fallback to using software cursors available in the X server
>>> > because there's no error reporting for a failed hardware cursor update.
>>>
>>> Hmm, maybe I'm missing something, but doesn't returning FALSE from
>>> UseHWCursorARGB just make the X server fallback to using a software
>>> cursor?
>>>
>>> https://github.com/ssvb/xf86-video-fbturbo/blob/689c08256555/src/sunxi_disp_hwcursor.c#L72
>>>
>>> I'm just doing this. And also have hooks to notify the DRI2 code about
>>> the status of the cursor. In the case if the hardware cursor is not
>>> enabled, hardware overlays can't be safely used with the software
>>> cursor and we need to fallback to CPU/GPU copy instead of zero-copy
>>> buffers swapping.
>>>
>>> And I fully agree that it is the responsibility of the kernel to expose
>>> as much of the hardware capabilities as possible (without compromising
>>> reliability and/or security).
>>
>> If you wish to go in below the level presented by
>> hw/xfree86/modes/xf86Cursors.c (as you are doing), then yes you can do
>> this, and it's something which maybe should be looked into.  You have a
>> good reason to do this (due to your hardware cursor being incompatible
>> with overlays).
>>
>> We have no such restriction - the only issue here is the "odd" size of
>> cursors.  Practically, choosing one or other of 64x32 or 32x64 works
>> fine for the cases I've seen.  I haven't seen any cursors which are
>> 64x64 yet.  I'm not saying they don't exist though!  I can imagine that
>> some accessibility options might want to display a large cursor.
>>
>> Now, the way I handle this is that the kernel allows _either_ a
>> (1 to 32)x(1 to 64) or (1 to 64)x(1 to 32) cursor.  Both width and
>> height larger than 32 gets rejected with -EINVAL:
>>
>> +               /* maximum size is 64x32 or 32x64 */
>> +               if (w > 64 || h > 64 || (w > 32 && h > 32))
>> +                       return -ENOMEM;
>>
>> which is quite reasonable for this hardware.  However, there is no way
>> to export this from DRM - adding maximum cursor size properties wouldn't
>> really represent this.
>
> Until relatively recently, it had always been a device specific ddx
> which would somehow know what w/h values to pass to
> xf86_cursors_init().  I think for xf86-video-modesetting and wayland
> compositors, we probably need to come up with something better.
> Although off the top of my head I can't think of a good way to express
> 64x32 or 32x64.. that is a weird restriction.
>

We have a similar problem on our newer asics.  They require a 128x128
cursors so when you use xf86-video-modesetting, you end up with messed
up cursors because it assumes 64x64.  We could add cursor size to drm
caps.

Alex

> Anyways, right now I don't think there is anything different that I'd
> do in the kernel part.  I *suppose* you could try and figure out that
> all the alpha values are either 0x00 or 0xff and support 64x64 in that
> special case.  I'm not sure that is actually better.. it at least
> makes the failure vs success cases more confusing.  And unless you are
> rockin' the twm+xterm+xcalc setup, I doubt you will see many cursors
> with only 0x00 or 0xff alpha.
>
> So,
>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
>
>
>> The only question is whether DRM should export some capabilities to
>> indicate what's possible with the cursor, so that X knows about this
>> quirk of this hardware.  Overall, I suspect that it's just rare and
>> not worth the effort.  I think it's just easier to pick one of these
>> and stick with it, and if we happen to encounter a cursor larger than
>> our chosen dimentions, XFree86 will already automatically fall back
>> to s/w cursor.
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

From mboxrd@z Thu Jan  1 00:00:00 1970
From: robdclark@gmail.com (Rob Clark)
Date: Fri, 18 Oct 2013 11:00:34 -0400
Subject: [PATCH 1/5] drm/i2c: tda998x: set VIF for full range,
 underscanned display
In-Reply-To: <20131007105944.6746352b@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwUV-0000hl-Rw@rmk-PC.arm.linux.org.uk>
 <20131007105944.6746352b@armhf>
Message-ID: <CAF6AEGt_gn2EYhMq5xA4RFbFmmFuYr5_yTXeK-9MkmRpJS85-w@mail.gmail.com>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Mon, Oct 7, 2013 at 4:59 AM, Jean-Francois Moine <moinejf@free.fr> wrote:
> On Sun, 06 Oct 2013 23:07:55 +0100
> Russell King <rmk+kernel@arm.linux.org.uk> wrote:
>
>> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
>> ---
>>  drivers/gpu/drm/i2c/tda998x_drv.c |    2 ++
>>  1 files changed, 2 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
>> index 60e8404..704040b5 100644
>> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
>> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
>> @@ -549,6 +549,8 @@ tda998x_write_avi(struct drm_encoder *encoder, struct drm_display_mode *mode)
>>       buf[HB(0)] = 0x82;
>>       buf[HB(1)] = 0x02;
>>       buf[HB(2)] = 13;
>> +     buf[PB(1)] = 2; /* underscanned display */
>> +     buf[PB(3)] = 2 << 2; /* full range */
>>       buf[PB(4)] = drm_match_cea_mode(mode);
>>
>>       tda998x_write_if(encoder, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf,
>
> You should use the 'hdmi.h' constants which are meaningful enough:
>
>         buf[PB(1)] = HDMI_SCAN_MODE_UNDERSCAN;
>         buf[PB(3)] = HDMI_QUANTIZATION_RANGE_FULL << 2;
>

with the update to use hdmi.h const, this has my

Reviewed-by: Rob Clark <robdclark@gmail.com>

(and other ones I replied last night, s/s-o-b/r-b/)

> --
> Ken ar c'henta? |             ** Breizh ha Linux atav! **
> Jef             |               http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Fri, 18 Oct 2013 16:15:57 +0100
Subject: [GIT PULL] Armada DRM support
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Message-ID: <20131018151557.GA25034@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

David,

Rob Clark has now reviewed this and has given his blessing for it to be
pulled for the coming merge window.

This adds support for the Armada 510 display subsystem found on the
Marvell Dove devices.  This IP is re-used across several different Marvell
SoCs with various tweaks, and this driver has been structured to allow
the other IPs to re-use the bulk of this code; further work in this area
is expected from interested parties.

This has been extensively tested on the SolidRun Cubox platform and
appears to work well there.

Please pull this driver for the next merge window.  Thanks.

The following changes since commit 15c03dd4859ab16f9212238f29dd315654aa94f6:

  Linux 3.12-rc3 (2013-09-29 15:02:38 -0700)

are available in the git repository at:

  git://ftp.arm.linux.org.uk/~rmk/linux-cubox.git drm-tda998x-3.12

which is commit: 585b691e2180e1501637050290292f77f5c30c7b

Russell King (5):
      DRM: Armada: Add Armada DRM driver
      DRM: Armada: Add support for ARGB 32x64 or 64x32 hardware cursors
      drm/i2c: tda998x: set VIF for full range, underscanned display
      Merge branches 'drm-3.12' and 'tda998x-3.12' into drm-tda998x-3.12
      DRM: Armada: add support for drm tda19988 driver

 drivers/gpu/drm/Kconfig                 |    2 +
 drivers/gpu/drm/Makefile                |    1 +
 drivers/gpu/drm/armada/Kconfig          |   24 +
 drivers/gpu/drm/armada/Makefile         |    7 +
 drivers/gpu/drm/armada/armada_510.c     |   87 +++
 drivers/gpu/drm/armada/armada_crtc.c    | 1098 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_crtc.h    |   83 +++
 drivers/gpu/drm/armada/armada_debugfs.c |  183 +++++
 drivers/gpu/drm/armada/armada_drm.h     |  113 ++++
 drivers/gpu/drm/armada/armada_drv.c     |  422 ++++++++++++
 drivers/gpu/drm/armada/armada_fb.c      |  170 +++++
 drivers/gpu/drm/armada/armada_fb.h      |   24 +
 drivers/gpu/drm/armada/armada_fbdev.c   |  202 ++++++
 drivers/gpu/drm/armada/armada_gem.c     |  611 +++++++++++++++++
 drivers/gpu/drm/armada/armada_gem.h     |   52 ++
 drivers/gpu/drm/armada/armada_hw.h      |  318 +++++++++
 drivers/gpu/drm/armada/armada_ioctlP.h  |   18 +
 drivers/gpu/drm/armada/armada_output.c  |  158 +++++
 drivers/gpu/drm/armada/armada_output.h  |   39 ++
 drivers/gpu/drm/armada/armada_overlay.c |  477 ++++++++++++++
 drivers/gpu/drm/armada/armada_slave.c   |  139 ++++
 drivers/gpu/drm/armada/armada_slave.h   |   26 +
 drivers/gpu/drm/i2c/tda998x_drv.c       |    3 +
 include/drm/drm_crtc.h                  |   17 +
 include/uapi/drm/armada_drm.h           |   45 ++
 25 files changed, 4319 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/armada/Kconfig
 create mode 100644 drivers/gpu/drm/armada/Makefile
 create mode 100644 drivers/gpu/drm/armada/armada_510.c
 create mode 100644 drivers/gpu/drm/armada/armada_crtc.c
 create mode 100644 drivers/gpu/drm/armada/armada_crtc.h
 create mode 100644 drivers/gpu/drm/armada/armada_debugfs.c
 create mode 100644 drivers/gpu/drm/armada/armada_drm.h
 create mode 100644 drivers/gpu/drm/armada/armada_drv.c
 create mode 100644 drivers/gpu/drm/armada/armada_fb.c
 create mode 100644 drivers/gpu/drm/armada/armada_fb.h
 create mode 100644 drivers/gpu/drm/armada/armada_fbdev.c
 create mode 100644 drivers/gpu/drm/armada/armada_gem.c
 create mode 100644 drivers/gpu/drm/armada/armada_gem.h
 create mode 100644 drivers/gpu/drm/armada/armada_hw.h
 create mode 100644 drivers/gpu/drm/armada/armada_ioctlP.h
 create mode 100644 drivers/gpu/drm/armada/armada_output.c
 create mode 100644 drivers/gpu/drm/armada/armada_output.h
 create mode 100644 drivers/gpu/drm/armada/armada_overlay.c
 create mode 100644 drivers/gpu/drm/armada/armada_slave.c
 create mode 100644 drivers/gpu/drm/armada/armada_slave.h
 create mode 100644 include/uapi/drm/armada_drm.h

From mboxrd@z Thu Jan  1 00:00:00 1970
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
Date: Tue, 22 Oct 2013 14:36:52 +0100
Subject: [GIT PULL] Armada DRM support
In-Reply-To: <20131018151557.GA25034@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <20131018151557.GA25034@n2100.arm.linux.org.uk>
Message-ID: <20131022133652.GC25034@n2100.arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
List-Id: linux-arm-kernel.lists.infradead.org

On Fri, Oct 18, 2013 at 04:15:57PM +0100, Russell King - ARM Linux wrote:
> David,
> 
> Rob Clark has now reviewed this and has given his blessing for it to be
> pulled for the coming merge window.
> 
> This adds support for the Armada 510 display subsystem found on the
> Marvell Dove devices.  This IP is re-used across several different Marvell
> SoCs with various tweaks, and this driver has been structured to allow
> the other IPs to re-use the bulk of this code; further work in this area
> is expected from interested parties.
> 
> This has been extensively tested on the SolidRun Cubox platform and
> appears to work well there.

David,

The zero day tester found a problem with this building on some non-ARM.
Please add this fix to it, which Rob Clark has acked.  It's a small patch
to add a dependency on ARM.

Thanks.

The following changes since commit 585b691e2180e1501637050290292f77f5c30c7b:

  DRM: Armada: add support for drm tda19988 driver (2013-10-18 16:00:33 +0100)

are available in the git repository at:
  git://ftp.arm.linux.org.uk/~rmk/linux-cubox.git drm-tda998x-3.12-fixes

Russell King (1):
      DRM: Armada: depend on ARM

 drivers/gpu/drm/armada/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King <rmk+kernel@arm.linux.org.uk>
Subject: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Sun, 06 Oct 2013 23:11:56 +0100
Message-ID: <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org
Cc: David Airlie <airlied@linux.ie>, Rob Clark <robdclark@gmail.com>, Jason Cooper <jason@lakedaemon.net>, Daniel Vetter <daniel@ffwll.ch>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/armada/Kconfig      |    9 +++++++
 drivers/gpu/drm/armada/armada_drv.c |   42 +++++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
index c7a0a94..87e62dd 100644
--- a/drivers/gpu/drm/armada/Kconfig
+++ b/drivers/gpu/drm/armada/Kconfig
@@ -13,3 +13,12 @@ config DRM_ARMADA
 	  This driver provides no built-in acceleration; acceleration is
 	  performed by other IP found on the SoC.  This driver provides
 	  kernel mode setting and buffer management to userspace.
+
+config DRM_ARMADA_TDA1998X
+	bool "Support TDA1998X HDMI output"
+	depends on DRM_ARMADA != n
+	depends on I2C && DRM_I2C_NXP_TDA998X = y
+	default y
+	help
+	  Support the TDA1998x HDMI output device found on the Solid-Run
+	  CuBox.
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index db62f1b..69517cf 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -16,6 +16,42 @@
 #include <drm/armada_drm.h>
 #include "armada_ioctlP.h"
 
+#ifdef CONFIG_DRM_ARMADA_TDA1998X
+#include <drm/i2c/tda998x.h>
+#include "armada_slave.h"
+
+static struct tda998x_encoder_params params = {
+	/* With 0x24, there is no translation between vp_out and int_vp
+	FB	LCD out	Pins	VIP	Int Vp
+	R:23:16	R:7:0	VPC7:0	7:0	7:0[R]
+	G:15:8	G:15:8	VPB7:0	23:16	23:16[G]
+	B:7:0	B:23:16	VPA7:0	15:8	15:8[B]
+	*/
+	.swap_a = 2,
+	.swap_b = 3,
+	.swap_c = 4,
+	.swap_d = 5,
+	.swap_e = 0,
+	.swap_f = 1,
+	.audio_cfg = BIT(2),
+	.audio_frame[1] = 1,
+	.audio_format = AFMT_SPDIF,
+	.audio_sample_rate = 44100,
+};
+
+static const struct armada_drm_slave_config tda19988_config = {
+	.i2c_adapter_id = 0,
+	.crtcs = 1 << 0, /* Only LCD0 at the moment */
+	.polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT,
+	.interlace_allowed = true,
+	.info = {
+		.type = "tda998x",
+		.addr = 0x70,
+		.platform_data = &params,
+	},
+};
+#endif
+
 static void armada_drm_unref_work(struct work_struct *work)
 {
 	struct armada_private *priv =
@@ -134,6 +170,12 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
 			goto err_kms;
 	}
 
+#ifdef CONFIG_DRM_ARMADA_TDA1998X
+	ret = armada_drm_connector_slave_create(dev, &tda19988_config);
+	if (ret)
+		goto err_kms;
+#endif
+
 	ret = drm_vblank_init(dev, n);
 	if (ret)
 		goto err_kms;
-- 
1.7.4.4

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: [PATCH 0/5] Armada DRM stuff
Date: Sun, 6 Oct 2013 23:07:29 +0100
Message-ID: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org
Cc: David Airlie <airlied@linux.ie>, Rob Clark <robdclark@gmail.com>, Jason Cooper <jason@lakedaemon.net>, Daniel Vetter <daniel@ffwll.ch>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

The Armada DRM drivers again, along with the TDA998x HDMI output support,
and an illustration to show how to add Armada 610 support (and others.)

Rob has looked at this a couple of times since its last posting, and
has provided additional useful feedback which has been incorporated.
I believe all the major issues have been addressed now.

 drivers/gpu/drm/Kconfig                 |    2 +
 drivers/gpu/drm/Makefile                |    1 +
 drivers/gpu/drm/armada/Kconfig          |   24 +
 drivers/gpu/drm/armada/Makefile         |    8 +
 drivers/gpu/drm/armada/armada_510.c     |   87 +++
 drivers/gpu/drm/armada/armada_610.c     |   49 ++
 drivers/gpu/drm/armada/armada_crtc.c    | 1099 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_crtc.h    |   83 +++
 drivers/gpu/drm/armada/armada_debugfs.c |  183 +++++
 drivers/gpu/drm/armada/armada_drm.h     |  114 ++++
 drivers/gpu/drm/armada/armada_drv.c     |  428 ++++++++++++
 drivers/gpu/drm/armada/armada_fb.c      |  170 +++++
 drivers/gpu/drm/armada/armada_fb.h      |   24 +
 drivers/gpu/drm/armada/armada_fbdev.c   |  202 ++++++
 drivers/gpu/drm/armada/armada_gem.c     |  616 +++++++++++++++++
 drivers/gpu/drm/armada/armada_gem.h     |   52 ++
 drivers/gpu/drm/armada/armada_hw.h      |  326 +++++++++
 drivers/gpu/drm/armada/armada_ioctlP.h  |   18 +
 drivers/gpu/drm/armada/armada_output.c  |  158 +++++
 drivers/gpu/drm/armada/armada_output.h  |   39 ++
 drivers/gpu/drm/armada/armada_overlay.c |  477 ++++++++++++++
 drivers/gpu/drm/armada/armada_slave.c   |  139 ++++
 drivers/gpu/drm/armada/armada_slave.h   |   26 +
 drivers/gpu/drm/i2c/tda998x_drv.c       |    2 +
 include/drm/drm_crtc.h                  |   17 +
 include/uapi/drm/armada_drm.h           |   45 ++
 26 files changed, 4389 insertions(+), 0 deletions(-)

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King <rmk+kernel@arm.linux.org.uk>
Subject: [PATCH 1/5] drm/i2c: tda998x: set VIF for full range, underscanned
 display
Date: Sun, 06 Oct 2013 23:07:55 +0100
Message-ID: <E1VSwUV-0000hl-Rw@rmk-PC.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org
Cc: David Airlie <airlied@linux.ie>, Rob Clark <robdclark@gmail.com>, Jason Cooper <jason@lakedaemon.net>, Daniel Vetter <daniel@ffwll.ch>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/i2c/tda998x_drv.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 60e8404..704040b5 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -549,6 +549,8 @@ tda998x_write_avi(struct drm_encoder *encoder, struct drm_display_mode *mode)
 	buf[HB(0)] = 0x82;
 	buf[HB(1)] = 0x02;
 	buf[HB(2)] = 13;
+	buf[PB(1)] = 2; /* underscanned display */
+	buf[PB(3)] = 2 << 2; /* full range */
 	buf[PB(4)] = drm_match_cea_mode(mode);
 
 	tda998x_write_if(encoder, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf,
-- 
1.7.4.4

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King <rmk+kernel@arm.linux.org.uk>
Subject: [PATCH 4/5] DRM: Armada: start of MMP2/MMP3 support
Date: Sun, 06 Oct 2013 23:10:56 +0100
Message-ID: <E1VSwXQ-0000iL-8N@rmk-PC.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org
Cc: David Airlie <airlied@linux.ie>, Rob Clark <robdclark@gmail.com>, Jason Cooper <jason@lakedaemon.net>, Daniel Vetter <daniel@ffwll.ch>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/armada/Makefile      |    1 +
 drivers/gpu/drm/armada/armada_610.c  |   49 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_crtc.c |    1 +
 drivers/gpu/drm/armada/armada_drm.h  |    1 +
 drivers/gpu/drm/armada/armada_drv.c  |    6 ++++
 drivers/gpu/drm/armada/armada_hw.h   |    8 +++++
 6 files changed, 66 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/armada/armada_610.c

diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile
index d6f43e0..088db4a 100644
--- a/drivers/gpu/drm/armada/Makefile
+++ b/drivers/gpu/drm/armada/Makefile
@@ -2,6 +2,7 @@ armada-y	:= armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
 		   armada_gem.o armada_output.o armada_overlay.o \
 		   armada_slave.o
 armada-y	+= armada_510.o
+armada-y	+= armada_610.o
 armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
 
 obj-$(CONFIG_DRM_ARMADA) := armada.o
diff --git a/drivers/gpu/drm/armada/armada_610.c b/drivers/gpu/drm/armada/armada_610.c
new file mode 100644
index 0000000..36a10e3
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_610.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Armada 610/MMP2/MMP3 variant support
+ */
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_hw.h"
+
+static int mmp23_init(struct armada_private *priv, struct device *dev)
+{
+	priv->extclk[0] = devm_clk_get(dev, NULL);
+
+	if (IS_ERR(priv->extclk[0]) && PTR_ERR(priv->extclk[0]) == -ENOENT)
+		priv->extclk[0] = ERR_PTR(-EPROBE_DEFER);
+
+	return PTR_RET(priv->extclk[0]);
+}
+
+/*
+ * This gets called with sclk = NULL to test whether the mode is
+ * supportable, and again with sclk != NULL to set the clocks up for
+ * that.  The former can return an error, but the latter is expected
+ * not to.
+ */
+static int mmp23_crtc_compute_clock(struct armada_crtc *dcrtc,
+	const struct drm_display_mode *mode, uint32_t *sclk)
+{
+	/*
+	 * on MMP3 bits 31:29 select the clock, OLPC wants 0x1 here, LCD clock 1
+	 * on MMP2 bits 31:30 select the clock, OLPC wants 0x1 here, LCD clock 1
+	 */
+	*sclk = 0x20001100; // FIXME hardcoded mmp3 value
+
+	return 0;
+}
+
+const struct armada_variant mmp23_ops = {
+	.init = mmp23_init,
+	.crtc_compute_clock = mmp23_crtc_compute_clock,
+};
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index e8605bf..b5877ee 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1054,6 +1054,7 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
 	dcrtc->clk = ERR_PTR(-EINVAL);
 	dcrtc->csc_yuv_mode = CSC_AUTO;
 	dcrtc->csc_rgb_mode = CSC_AUTO;
+	/* FIXME: MMP2/MMP3: OLPC panel is RGB666 */
 	dcrtc->cfg_dumb_ctrl = DUMB24_RGB888_0;
 	dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
 	spin_lock_init(&dcrtc->irq_lock);
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index eef09ec..f52fccb 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -70,6 +70,7 @@ struct armada_variant {
 
 /* Variant ops */
 extern const struct armada_variant armada510_ops;
+extern const struct armada_variant mmp23_ops;
 
 struct armada_private {
 	const struct armada_variant *variant;
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 7bfab9a..db62f1b 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -344,6 +344,12 @@ static const struct platform_device_id armada_drm_platform_ids[] = {
 		.name		= "armada-drm",
 		.driver_data	= (unsigned long)&armada510_ops,
 	}, {
+		.name		= "armada-610-drm", /* aka MMP2 */
+		.driver_data	= (unsigned long)&mmp23_ops,
+	}, {
+		.name		= "mmp3-drm",
+		.driver_data	= (unsigned long)&mmp23_ops,
+	}, {
 		.name		= "armada-510-drm",
 		.driver_data	= (unsigned long)&armada510_ops,
 	},
diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
index 27319a8..1688716 100644
--- a/drivers/gpu/drm/armada/armada_hw.h
+++ b/drivers/gpu/drm/armada/armada_hw.h
@@ -74,6 +74,7 @@ enum {
 	LCD_SPU_IOPAD_CONTROL		= 0x01bc,
 	LCD_SPU_IRQ_ENA			= 0x01c0,
 	LCD_SPU_IRQ_ISR			= 0x01c4,
+	LCD_MISC_CNTL			= 0x01c8,	/* Armada 168 */
 };
 
 /* For LCD_SPU_ADV_REG */
@@ -211,6 +212,13 @@ enum {
 	SCLK_16X_PLL		= 0x8 << 28,
 	SCLK_16X_FRAC_DIV_MASK	= 0xfff << 16,
 	SCLK_16X_INT_DIV_MASK	= 0xffff << 0,
+
+	/* PXA910 / MMP2 (Armada 610) / MMP3 / PXA988 */
+	SCLK_MMP_SRC_SEL	= 1 << 31,
+	SCLK_MMP_DISABLE	= 1 << 28,
+	SCLK_MMP_FRAC_DIV_MASK	= 0xfff << 16,
+	SCLK_MMP_DSI_DIV_MASK	= 0xf << 8,
+	SCLK_MMP_INT_DIV_MASK	= 0xff << 0,
 };
 
 /* For LCD_SPU_DUMB_CTRL */
-- 
1.7.4.4

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King <rmk+kernel@arm.linux.org.uk>
Subject: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
Date: Sun, 06 Oct 2013 23:09:56 +0100
Message-ID: <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org
Cc: David Airlie <airlied@linux.ie>, Rob Clark <robdclark@gmail.com>, Jason Cooper <jason@lakedaemon.net>, Daniel Vetter <daniel@ffwll.ch>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

This patch adds ARGB hardware cursor support to the DRM driver for the
Marvell Armada SoCs.  ARGB cursors are supported at either 32x64 or
64x32 resolutions.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/armada/armada_510.c  |    1 +
 drivers/gpu/drm/armada/armada_crtc.c |  245 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/armada/armada_crtc.h |    9 ++
 drivers/gpu/drm/armada/armada_drm.h  |    1 +
 drivers/gpu/drm/armada/armada_hw.h   |    6 +-
 5 files changed, 256 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_510.c b/drivers/gpu/drm/armada/armada_510.c
index a016888..59948ef 100644
--- a/drivers/gpu/drm/armada/armada_510.c
+++ b/drivers/gpu/drm/armada/armada_510.c
@@ -80,6 +80,7 @@ static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
 
 const struct armada_variant armada510_ops = {
 	.has_spu_adv_reg = true,
+	.spu_adv_reg = ADV_HWC32ENABLE | ADV_HWC32ARGB | ADV_HWC32BLEND,
 	.init = armada510_init,
 	.crtc_init = armada510_crtc_init,
 	.crtc_compute_clock = armada510_crtc_compute_clock,
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 7b379fd..e8605bf 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -381,8 +381,21 @@ void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
 		val = readl_relaxed(base + LCD_SPU_ADV_REG);
 		val &= ~(ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF | ADV_VSYNCOFFEN);
 		val |= dcrtc->v[i].spu_adv_reg;
-		writel_relaxed(val, dcrtc->base + LCD_SPU_ADV_REG);
+		writel_relaxed(val, base + LCD_SPU_ADV_REG);
 	}
+
+	if (stat & DUMB_FRAMEDONE && dcrtc->cursor_update) {
+		writel_relaxed(dcrtc->cursor_hw_pos,
+			       base + LCD_SPU_HWC_OVSA_HPXL_VLN);
+		writel_relaxed(dcrtc->cursor_hw_sz,
+			       base + LCD_SPU_HWC_HPXL_VLN);
+		armada_updatel(CFG_HWC_ENA,
+			       CFG_HWC_ENA | CFG_HWC_1BITMOD | CFG_HWC_1BITENA,
+			       base + LCD_SPU_DMA_CTRL0);
+		dcrtc->cursor_update = false;
+		armada_drm_crtc_disable_irq(dcrtc, DUMB_FRAMEDONE_ENA);
+	}
+
 	spin_unlock(&dcrtc->irq_lock);
 
 	if (stat & GRA_FRAME_IRQ) {
@@ -522,7 +535,8 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
 				    adj->crtc_htotal;
 	dcrtc->v[1].spu_v_porch = tm << 16 | bm;
 	val = adj->crtc_hsync_start;
-	dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN;
+	dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
+		priv->variant->spu_adv_reg;
 
 	if (interlaced) {
 		/* Odd interlaced frame */
@@ -530,7 +544,8 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
 						(1 << 16);
 		dcrtc->v[0].spu_v_porch = dcrtc->v[1].spu_v_porch + 1;
 		val = adj->crtc_hsync_start - adj->crtc_htotal / 2;
-		dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN;
+		dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
+			priv->variant->spu_adv_reg;
 	} else {
 		dcrtc->v[0] = dcrtc->v[1];
 	}
@@ -545,10 +560,11 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
 	armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total,
 			   LCD_SPUT_V_H_TOTAL);
 
-	if (priv->variant->has_spu_adv_reg)
+	if (priv->variant->has_spu_adv_reg) {
 		armada_reg_queue_mod(regs, i, dcrtc->v[0].spu_adv_reg,
 				     ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF |
 				     ADV_VSYNCOFFEN, LCD_SPU_ADV_REG);
+	}
 
 	val = CFG_GRA_ENA | CFG_GRA_HSMOOTH;
 	val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.fb)->fmt);
@@ -640,11 +656,230 @@ static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = {
 	.disable	= armada_drm_crtc_disable,
 };
 
+static void armada_load_cursor_argb(void __iomem *base, uint32_t *pix,
+	unsigned stride, unsigned width, unsigned height)
+{
+	uint32_t addr;
+	unsigned y;
+
+	addr = SRAM_HWC32_RAM1;
+	for (y = 0; y < height; y++) {
+		uint32_t *p = &pix[y * stride];
+		unsigned x;
+
+		for (x = 0; x < width; x++, p++) {
+			uint32_t val = *p;
+
+			val = (val & 0xff00ff00) |
+			      (val & 0x000000ff) << 16 |
+			      (val & 0x00ff0000) >> 16;
+
+			writel_relaxed(val,
+				       base + LCD_SPU_SRAM_WRDAT);
+			writel_relaxed(addr | SRAM_WRITE,
+				       base + LCD_SPU_SRAM_CTRL);
+			addr += 1;
+			if ((addr & 0x00ff) == 0)
+				addr += 0xf00;
+			if ((addr & 0x30ff) == 0)
+				addr = SRAM_HWC32_RAM2;
+		}
+	}
+}
+
+static void armada_drm_crtc_cursor_tran(void __iomem *base)
+{
+	unsigned addr;
+
+	for (addr = 0; addr < 256; addr++) {
+		/* write the default value */
+		writel_relaxed(0x55555555, base + LCD_SPU_SRAM_WRDAT);
+		writel_relaxed(addr | SRAM_WRITE | SRAM_HWC32_TRAN,
+			       base + LCD_SPU_SRAM_CTRL);
+	}
+}
+
+static int armada_drm_crtc_cursor_update(struct armada_crtc *dcrtc, bool reload)
+{
+	uint32_t xoff, xscr, w = dcrtc->cursor_w, s;
+	uint32_t yoff, yscr, h = dcrtc->cursor_h;
+	uint32_t para1;
+
+	/*
+	 * Calculate the visible width and height of the cursor,
+	 * screen position, and the position in the cursor bitmap.
+	 */
+	if (dcrtc->cursor_x < 0) {
+		xoff = -dcrtc->cursor_x;
+		xscr = 0;
+		w -= min(xoff, w);
+	} else if (dcrtc->cursor_x + w > dcrtc->crtc.mode.hdisplay) {
+		xoff = 0;
+		xscr = dcrtc->cursor_x;
+		w = max_t(int, dcrtc->crtc.mode.hdisplay - dcrtc->cursor_x, 0);
+	} else {
+		xoff = 0;
+		xscr = dcrtc->cursor_x;
+	}
+
+	if (dcrtc->cursor_y < 0) {
+		yoff = -dcrtc->cursor_y;
+		yscr = 0;
+		h -= min(yoff, h);
+	} else if (dcrtc->cursor_y + h > dcrtc->crtc.mode.vdisplay) {
+		yoff = 0;
+		yscr = dcrtc->cursor_y;
+		h = max_t(int, dcrtc->crtc.mode.vdisplay - dcrtc->cursor_y, 0);
+	} else {
+		yoff = 0;
+		yscr = dcrtc->cursor_y;
+	}
+
+	/* On interlaced modes, the vertical cursor size must be halved */
+	s = dcrtc->cursor_w;
+	if (dcrtc->interlaced) {
+		s *= 2;
+		yscr /= 2;
+		h /= 2;
+	}
+
+	if (!dcrtc->cursor_obj || !h || !w) {
+		spin_lock_irq(&dcrtc->irq_lock);
+		armada_drm_crtc_disable_irq(dcrtc, DUMB_FRAMEDONE_ENA);
+		dcrtc->cursor_update = false;
+		armada_updatel(0, CFG_HWC_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0);
+		spin_unlock_irq(&dcrtc->irq_lock);
+		return 0;
+	}
+
+	para1 = readl_relaxed(dcrtc->base + LCD_SPU_SRAM_PARA1);
+	armada_updatel(CFG_CSB_256x32, CFG_CSB_256x32 | CFG_PDWN256x32,
+		       dcrtc->base + LCD_SPU_SRAM_PARA1);
+
+	/*
+	 * Initialize the transparency if the SRAM was powered down.
+	 * We must also reload the cursor data as well.
+	 */
+	if (!(para1 & CFG_CSB_256x32)) {
+		armada_drm_crtc_cursor_tran(dcrtc->base);
+		reload = true;
+	}
+
+	if (dcrtc->cursor_hw_sz != (h << 16 | w)) {
+		spin_lock_irq(&dcrtc->irq_lock);
+		armada_drm_crtc_disable_irq(dcrtc, DUMB_FRAMEDONE_ENA);
+		dcrtc->cursor_update = false;
+		armada_updatel(0, CFG_HWC_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0);
+		spin_unlock_irq(&dcrtc->irq_lock);
+		reload = true;
+	}
+	if (reload) {
+		struct armada_gem_object *obj = dcrtc->cursor_obj;
+		uint32_t *pix;
+		/* Set the top-left corner of the cursor image */
+		pix = obj->addr;
+		pix += yoff * s + xoff;
+		armada_load_cursor_argb(dcrtc->base, pix, s, w, h);
+	}
+
+	/* Reload the cursor position, size and enable in the IRQ handler */
+	spin_lock_irq(&dcrtc->irq_lock);
+	dcrtc->cursor_hw_pos = yscr << 16 | xscr;
+	dcrtc->cursor_hw_sz = h << 16 | w;
+	dcrtc->cursor_update = true;
+	armada_drm_crtc_enable_irq(dcrtc, DUMB_FRAMEDONE_ENA);
+	spin_unlock_irq(&dcrtc->irq_lock);
+
+	return 0;
+}
+
+static void cursor_update(void *data)
+{
+	armada_drm_crtc_cursor_update(data, true);
+}
+
+static int armada_drm_crtc_cursor_set(struct drm_crtc *crtc,
+	struct drm_file *file, uint32_t handle, uint32_t w, uint32_t h)
+{
+	struct drm_device *dev = crtc->dev;
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_private *priv = crtc->dev->dev_private;
+	struct armada_gem_object *obj = NULL;
+	int ret;
+
+	/* If no cursor support, replicate drm's return value */
+	if (!priv->variant->has_spu_adv_reg)
+		return -ENXIO;
+
+	if (handle && w > 0 && h > 0) {
+		/* maximum size is 64x32 or 32x64 */
+		if (w > 64 || h > 64 || (w > 32 && h > 32))
+			return -ENOMEM;
+
+		obj = armada_gem_object_lookup(dev, file, handle);
+		if (!obj)
+			return -ENOENT;
+
+		/* Must be a kernel-mapped object */
+		if (!obj->addr) {
+			drm_gem_object_unreference_unlocked(&obj->obj);
+			return -EINVAL;
+		}
+
+		if (obj->obj.size < w * h * 4) {
+			DRM_ERROR("buffer is too small\n");
+			drm_gem_object_unreference_unlocked(&obj->obj);
+			return -ENOMEM;
+		}
+	}
+
+	mutex_lock(&dev->struct_mutex);
+	if (dcrtc->cursor_obj) {
+		dcrtc->cursor_obj->update = NULL;
+		dcrtc->cursor_obj->update_data = NULL;
+		drm_gem_object_unreference(&dcrtc->cursor_obj->obj);
+	}
+	dcrtc->cursor_obj = obj;
+	dcrtc->cursor_w = w;
+	dcrtc->cursor_h = h;
+	ret = armada_drm_crtc_cursor_update(dcrtc, true);
+	if (obj) {
+		obj->update_data = dcrtc;
+		obj->update = cursor_update;
+	}
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+static int armada_drm_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct drm_device *dev = crtc->dev;
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_private *priv = crtc->dev->dev_private;
+	int ret;
+
+	/* If no cursor support, replicate drm's return value */
+	if (!priv->variant->has_spu_adv_reg)
+		return -EFAULT;
+
+	mutex_lock(&dev->struct_mutex);
+	dcrtc->cursor_x = x;
+	dcrtc->cursor_y = y;
+	ret = armada_drm_crtc_cursor_update(dcrtc, false);
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
 static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
 {
 	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
 	struct armada_private *priv = crtc->dev->dev_private;
 
+	if (dcrtc->cursor_obj)
+		drm_gem_object_unreference(&dcrtc->cursor_obj->obj);
+
 	priv->dcrtc[dcrtc->num] = NULL;
 	drm_crtc_cleanup(&dcrtc->crtc);
 
@@ -750,6 +985,8 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc,
 }
 
 static struct drm_crtc_funcs armada_crtc_funcs = {
+	.cursor_set	= armada_drm_crtc_cursor_set,
+	.cursor_move	= armada_drm_crtc_cursor_move,
 	.destroy	= armada_drm_crtc_destroy,
 	.set_config	= drm_crtc_helper_set_config,
 	.page_flip	= armada_drm_crtc_page_flip,
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
index 972da53..9c10a07 100644
--- a/drivers/gpu/drm/armada/armada_crtc.h
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -44,11 +44,20 @@ struct armada_crtc {
 		uint32_t	spu_adv_reg;
 	} v[2];
 	bool			interlaced;
+	bool			cursor_update;
 	uint8_t			csc_yuv_mode;
 	uint8_t			csc_rgb_mode;
 
 	struct drm_plane	*plane;
 
+	struct armada_gem_object	*cursor_obj;
+	int			cursor_x;
+	int			cursor_y;
+	uint32_t		cursor_hw_pos;
+	uint32_t		cursor_hw_sz;
+	uint32_t		cursor_w;
+	uint32_t		cursor_h;
+
 	int			dpms;
 	uint32_t		cfg_dumb_ctrl;
 	uint32_t		dumb_ctrl;
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index e8c4f80..eef09ec 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -60,6 +60,7 @@ struct armada_private;
 
 struct armada_variant {
 	bool	has_spu_adv_reg;
+	uint32_t spu_adv_reg;
 	int (*init)(struct armada_private *, struct device *);
 	int (*crtc_init)(struct armada_crtc *);
 	int (*crtc_compute_clock)(struct armada_crtc *,
diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
index 216a4b5..27319a8 100644
--- a/drivers/gpu/drm/armada/armada_hw.h
+++ b/drivers/gpu/drm/armada/armada_hw.h
@@ -168,8 +168,10 @@ enum {
 	SRAM_READ	= 0 << 14,
 	SRAM_WRITE	= 2 << 14,
 	SRAM_INIT	= 3 << 14,
-	SRAM_HWC32_RAMR	= 0xc << 8,
-	SRAM_HWC32_RAMG	= 0xd << 8,
+	SRAM_HWC32_RAM1	= 0xc << 8,
+	SRAM_HWC32_RAM2	= 0xd << 8,
+	SRAM_HWC32_RAMR	= SRAM_HWC32_RAM1,
+	SRAM_HWC32_RAMG	= SRAM_HWC32_RAM2,
 	SRAM_HWC32_RAMB	= 0xe << 8,
 	SRAM_HWC32_TRAN	= 0xf << 8,
 	SRAM_HWC	= 0xf << 8,
-- 
1.7.4.4

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King <rmk+kernel@arm.linux.org.uk>
Subject: [PATCH 2/5] DRM: Armada: Add Armada DRM driver
Date: Sun, 06 Oct 2013 23:08:56 +0100
Message-ID: <E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org>
Received: from caramon.arm.linux.org.uk (caramon.arm.linux.org.uk
	[78.32.30.218])
	by gabe.freedesktop.org (Postfix) with ESMTP id 5D505E6A4D
	for <dri-devel@lists.freedesktop.org>;
	Sun,  6 Oct 2013 15:09:02 -0700 (PDT)
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.freedesktop.org/mailman/options/dri-devel>,
	<mailto:dri-devel-request@lists.freedesktop.org?subject=unsubscribe>
List-Archive: <http://lists.freedesktop.org/archives/dri-devel>
List-Post: <mailto:dri-devel@lists.freedesktop.org>
List-Help: <mailto:dri-devel-request@lists.freedesktop.org?subject=help>
List-Subscribe: <http://lists.freedesktop.org/mailman/listinfo/dri-devel>,
	<mailto:dri-devel-request@lists.freedesktop.org?subject=subscribe>
Sender: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org
Errors-To: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org
To: dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org
Cc: Jason Cooper <jason@lakedaemon.net>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

This patch adds support for the pair of LCD controllers on the Marvell
Armada 510 SoCs.  This driver supports:
- multiple contiguous scanout buffers for video and graphics
- shm backed cacheable buffer objects for X pixmaps for Vivante GPU
  acceleration
- dual lcd0 and lcd1 crt operation
- video overlay on each LCD crt via DRM planes
- page flipping of the main scanout buffers
- DRM prime for buffer export/import

This driver is trivial to extend to other Armada SoCs.

Included in this commit is the core driver with no output support; output
support is platform and encoder driver dependent.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/Kconfig                 |    2 +
 drivers/gpu/drm/Makefile                |    1 +
 drivers/gpu/drm/armada/Kconfig          |   15 +
 drivers/gpu/drm/armada/Makefile         |    7 +
 drivers/gpu/drm/armada/armada_510.c     |   86 +++
 drivers/gpu/drm/armada/armada_crtc.c    |  861 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_crtc.h    |   74 +++
 drivers/gpu/drm/armada/armada_debugfs.c |  183 +++++++
 drivers/gpu/drm/armada/armada_drm.h     |  112 ++++
 drivers/gpu/drm/armada/armada_drv.c     |  380 ++++++++++++++
 drivers/gpu/drm/armada/armada_fb.c      |  170 ++++++
 drivers/gpu/drm/armada/armada_fb.h      |   24 +
 drivers/gpu/drm/armada/armada_fbdev.c   |  202 ++++++++
 drivers/gpu/drm/armada/armada_gem.c     |  616 ++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_gem.h     |   52 ++
 drivers/gpu/drm/armada/armada_hw.h      |  316 +++++++++++
 drivers/gpu/drm/armada/armada_ioctlP.h  |   18 +
 drivers/gpu/drm/armada/armada_output.c  |  158 ++++++
 drivers/gpu/drm/armada/armada_output.h  |   39 ++
 drivers/gpu/drm/armada/armada_overlay.c |  477 +++++++++++++++++
 drivers/gpu/drm/armada/armada_slave.c   |  139 +++++
 drivers/gpu/drm/armada/armada_slave.h   |   26 +
 include/drm/drm_crtc.h                  |   17 +
 include/uapi/drm/armada_drm.h           |   45 ++
 24 files changed, 4020 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/armada/Kconfig
 create mode 100644 drivers/gpu/drm/armada/Makefile
 create mode 100644 drivers/gpu/drm/armada/armada_510.c
 create mode 100644 drivers/gpu/drm/armada/armada_crtc.c
 create mode 100644 drivers/gpu/drm/armada/armada_crtc.h
 create mode 100644 drivers/gpu/drm/armada/armada_debugfs.c
 create mode 100644 drivers/gpu/drm/armada/armada_drm.h
 create mode 100644 drivers/gpu/drm/armada/armada_drv.c
 create mode 100644 drivers/gpu/drm/armada/armada_fb.c
 create mode 100644 drivers/gpu/drm/armada/armada_fb.h
 create mode 100644 drivers/gpu/drm/armada/armada_fbdev.c
 create mode 100644 drivers/gpu/drm/armada/armada_gem.c
 create mode 100644 drivers/gpu/drm/armada/armada_gem.h
 create mode 100644 drivers/gpu/drm/armada/armada_hw.h
 create mode 100644 drivers/gpu/drm/armada/armada_ioctlP.h
 create mode 100644 drivers/gpu/drm/armada/armada_output.c
 create mode 100644 drivers/gpu/drm/armada/armada_output.h
 create mode 100644 drivers/gpu/drm/armada/armada_overlay.c
 create mode 100644 drivers/gpu/drm/armada/armada_slave.c
 create mode 100644 drivers/gpu/drm/armada/armada_slave.h
 create mode 100644 include/uapi/drm/armada_drm.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 955555d..3b5176d 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -225,6 +225,8 @@ source "drivers/gpu/drm/mgag200/Kconfig"
 
 source "drivers/gpu/drm/cirrus/Kconfig"
 
+source "drivers/gpu/drm/armada/Kconfig"
+
 source "drivers/gpu/drm/rcar-du/Kconfig"
 
 source "drivers/gpu/drm/shmobile/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index f089adf..385f460 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_DRM_EXYNOS) +=exynos/
 obj-$(CONFIG_DRM_GMA500) += gma500/
 obj-$(CONFIG_DRM_UDL) += udl/
 obj-$(CONFIG_DRM_AST) += ast/
+obj-$(CONFIG_DRM_ARMADA) += armada/
 obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
 obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
 obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
new file mode 100644
index 0000000..c7a0a94
--- /dev/null
+++ b/drivers/gpu/drm/armada/Kconfig
@@ -0,0 +1,15 @@
+config DRM_ARMADA
+	tristate "DRM support for Marvell Armada SoCs"
+	depends on DRM && HAVE_CLK
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select DRM_KMS_HELPER
+	help
+	  Support the "LCD" controllers found on the Marvell Armada 510
+	  devices.  There are two controllers on the device, each controller
+	  supports graphics and video overlays.
+
+	  This driver provides no built-in acceleration; acceleration is
+	  performed by other IP found on the SoC.  This driver provides
+	  kernel mode setting and buffer management to userspace.
diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile
new file mode 100644
index 0000000..d6f43e0
--- /dev/null
+++ b/drivers/gpu/drm/armada/Makefile
@@ -0,0 +1,7 @@
+armada-y	:= armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
+		   armada_gem.o armada_output.o armada_overlay.o \
+		   armada_slave.o
+armada-y	+= armada_510.o
+armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
+
+obj-$(CONFIG_DRM_ARMADA) := armada.o
diff --git a/drivers/gpu/drm/armada/armada_510.c b/drivers/gpu/drm/armada/armada_510.c
new file mode 100644
index 0000000..a016888
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_510.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Armada 510 (aka Dove) variant support
+ */
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_hw.h"
+
+static int armada510_init(struct armada_private *priv, struct device *dev)
+{
+	priv->extclk[0] = devm_clk_get(dev, "ext_ref_clk_1");
+
+	if (IS_ERR(priv->extclk[0]) && PTR_ERR(priv->extclk[0]) == -ENOENT)
+		priv->extclk[0] = ERR_PTR(-EPROBE_DEFER);
+
+	return PTR_RET(priv->extclk[0]);
+}
+
+static int armada510_crtc_init(struct armada_crtc *dcrtc)
+{
+	/* Lower the watermark so to eliminate jitter at higher bandwidths */
+	armada_updatel(0x20, (1 << 11) | 0xff, dcrtc->base + LCD_CFG_RDREG4F);
+	return 0;
+}
+
+/*
+ * Armada510 specific SCLK register selection.
+ * This gets called with sclk = NULL to test whether the mode is
+ * supportable, and again with sclk != NULL to set the clocks up for
+ * that.  The former can return an error, but the latter is expected
+ * not to.
+ *
+ * We currently are pretty rudimentary here, always selecting
+ * EXT_REF_CLK_1 for LCD0 and erroring LCD1.  This needs improvement!
+ */
+static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
+	const struct drm_display_mode *mode, uint32_t *sclk)
+{
+	struct armada_private *priv = dcrtc->crtc.dev->dev_private;
+	struct clk *clk = priv->extclk[0];
+	int ret;
+
+	if (dcrtc->num == 1)
+		return -EINVAL;
+
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	if (dcrtc->clk != clk) {
+		ret = clk_prepare_enable(clk);
+		if (ret)
+			return ret;
+		dcrtc->clk = clk;
+	}
+
+	if (sclk) {
+		uint32_t rate, ref, div;
+
+		rate = mode->clock * 1000;
+		ref = clk_round_rate(clk, rate);
+		div = DIV_ROUND_UP(ref, rate);
+		if (div < 1)
+			div = 1;
+
+		clk_set_rate(clk, ref);
+		*sclk = div | SCLK_510_EXTCLK1;
+	}
+
+	return 0;
+}
+
+const struct armada_variant armada510_ops = {
+	.has_spu_adv_reg = true,
+	.init = armada510_init,
+	.crtc_init = armada510_crtc_init,
+	.crtc_compute_clock = armada510_crtc_compute_clock,
+};
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
new file mode 100644
index 0000000..7b379fd
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -0,0 +1,861 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Rewritten from the dovefb driver, and Armada510 manuals.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_fb.h"
+#include "armada_gem.h"
+#include "armada_hw.h"
+
+struct armada_frame_work {
+	struct drm_pending_vblank_event *event;
+	struct armada_regs regs[4];
+	struct drm_framebuffer *old_fb;
+};
+
+enum csc_mode {
+	CSC_AUTO = 0,
+	CSC_YUV_CCIR601 = 1,
+	CSC_YUV_CCIR709 = 2,
+	CSC_RGB_COMPUTER = 1,
+	CSC_RGB_STUDIO = 2,
+};
+
+/*
+ * A note about interlacing.  Let's consider HDMI 1920x1080i.
+ * The timing parameters we have from X are:
+ *  Hact HsyA HsyI Htot  Vact VsyA VsyI Vtot
+ *  1920 2448 2492 2640  1080 1084 1094 1125
+ * Which get translated to:
+ *  Hact HsyA HsyI Htot  Vact VsyA VsyI Vtot
+ *  1920 2448 2492 2640   540  542  547  562
+ *
+ * This is how it is defined by CEA-861-D - line and pixel numbers are
+ * referenced to the rising edge of VSYNC and HSYNC.  Total clocks per
+ * line: 2640.  The odd frame, the first active line is at line 21, and
+ * the even frame, the first active line is 584.
+ *
+ * LN:    560     561     562     563             567     568    569
+ * DE:    ~~~|____________________________//__________________________
+ * HSYNC: ____|~|_____|~|_____|~|_____|~|_//__|~|_____|~|_____|~|_____
+ * VSYNC: _________________________|~~~~~~//~~~~~~~~~~~~~~~|__________
+ *  22 blanking lines.  VSYNC at 1320 (referenced to the HSYNC rising edge).
+ *
+ * LN:    1123   1124    1125      1               5       6      7
+ * DE:    ~~~|____________________________//__________________________
+ * HSYNC: ____|~|_____|~|_____|~|_____|~|_//__|~|_____|~|_____|~|_____
+ * VSYNC: ____________________|~~~~~~~~~~~//~~~~~~~~~~|_______________
+ *  23 blanking lines
+ *
+ * The Armada LCD Controller line and pixel numbers are, like X timings,
+ * referenced to the top left of the active frame.
+ *
+ * So, translating these to our LCD controller:
+ *  Odd frame, 563 total lines, VSYNC at line 543-548, pixel 1128.
+ *  Even frame, 562 total lines, VSYNC at line 542-547, pixel 2448.
+ * Note: Vsync front porch remains constant!
+ *
+ * if (odd_frame) {
+ *   vtotal = mode->crtc_vtotal + 1;
+ *   vbackporch = mode->crtc_vsync_start - mode->crtc_vdisplay + 1;
+ *   vhorizpos = mode->crtc_hsync_start - mode->crtc_htotal / 2
+ * } else {
+ *   vtotal = mode->crtc_vtotal;
+ *   vbackporch = mode->crtc_vsync_start - mode->crtc_vdisplay;
+ *   vhorizpos = mode->crtc_hsync_start;
+ * }
+ * vfrontporch = mode->crtc_vtotal - mode->crtc_vsync_end;
+ *
+ * So, we need to reprogram these registers on each vsync event:
+ *  LCD_SPU_V_PORCH, LCD_SPU_ADV_REG, LCD_SPUT_V_H_TOTAL
+ *
+ * Note: we do not use the frame done interrupts because these appear
+ * to happen too early, and lead to jitter on the display (presumably
+ * they occur at the end of the last active line, before the vsync back
+ * porch, which we're reprogramming.)
+ */
+
+void
+armada_drm_crtc_update_regs(struct armada_crtc *dcrtc, struct armada_regs *regs)
+{
+	while (regs->offset != ~0) {
+		void __iomem *reg = dcrtc->base + regs->offset;
+		uint32_t val;
+
+		val = regs->mask;
+		if (val != 0)
+			val &= readl_relaxed(reg);
+		writel_relaxed(val | regs->val, reg);
+		++regs;
+	}
+}
+
+#define dpms_blanked(dpms)	((dpms) != DRM_MODE_DPMS_ON)
+
+static void armada_drm_crtc_update(struct armada_crtc *dcrtc)
+{
+	uint32_t dumb_ctrl;
+
+	dumb_ctrl = dcrtc->cfg_dumb_ctrl;
+
+	if (!dpms_blanked(dcrtc->dpms))
+		dumb_ctrl |= CFG_DUMB_ENA;
+
+	/*
+	 * When the dumb interface isn't in DUMB24_RGB888_0 mode, it might
+	 * be using SPI or GPIO.  If we set this to DUMB_BLANK, we will
+	 * force LCD_D[23:0] to output blank color, overriding the GPIO or
+	 * SPI usage.  So leave it as-is unless in DUMB24_RGB888_0 mode.
+	 */
+	if (dpms_blanked(dcrtc->dpms) &&
+	    (dumb_ctrl & DUMB_MASK) == DUMB24_RGB888_0) {
+		dumb_ctrl &= ~DUMB_MASK;
+		dumb_ctrl |= DUMB_BLANK;
+	}
+
+	/*
+	 * The documentation doesn't indicate what the normal state of
+	 * the sync signals are.  Sebastian Hesselbart kindly probed
+	 * these signals on his board to determine their state.
+	 *
+	 * The non-inverted state of the sync signals is active high.
+	 * Setting these bits makes the appropriate signal active low.
+	 */
+	if (dcrtc->crtc.mode.flags & DRM_MODE_FLAG_NCSYNC)
+		dumb_ctrl |= CFG_INV_CSYNC;
+	if (dcrtc->crtc.mode.flags & DRM_MODE_FLAG_NHSYNC)
+		dumb_ctrl |= CFG_INV_HSYNC;
+	if (dcrtc->crtc.mode.flags & DRM_MODE_FLAG_NVSYNC)
+		dumb_ctrl |= CFG_INV_VSYNC;
+
+	if (dcrtc->dumb_ctrl != dumb_ctrl) {
+		dcrtc->dumb_ctrl = dumb_ctrl;
+		writel_relaxed(dumb_ctrl, dcrtc->base + LCD_SPU_DUMB_CTRL);
+	}
+}
+
+static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb,
+	int x, int y, struct armada_regs *regs, bool interlaced)
+{
+	struct armada_gem_object *obj = drm_fb_obj(fb);
+	unsigned pitch = fb->pitches[0];
+	unsigned offset = y * pitch + x * fb->bits_per_pixel / 8;
+	uint32_t addr_odd, addr_even;
+	unsigned i = 0;
+
+	DRM_DEBUG_DRIVER("pitch %u x %d y %d bpp %d\n",
+		pitch, x, y, fb->bits_per_pixel);
+
+	addr_odd = addr_even = obj->dev_addr + offset;
+
+	if (interlaced) {
+		addr_even += pitch;
+		pitch *= 2;
+	}
+
+	/* write offset, base, and pitch */
+	armada_reg_queue_set(regs, i, addr_odd, LCD_CFG_GRA_START_ADDR0);
+	armada_reg_queue_set(regs, i, addr_even, LCD_CFG_GRA_START_ADDR1);
+	armada_reg_queue_mod(regs, i, pitch, 0xffff, LCD_CFG_GRA_PITCH);
+
+	return i;
+}
+
+static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc,
+	struct armada_frame_work *work)
+{
+	struct drm_device *dev = dcrtc->crtc.dev;
+	unsigned long flags;
+	int ret;
+
+	ret = drm_vblank_get(dev, dcrtc->num);
+	if (ret) {
+		DRM_ERROR("failed to acquire vblank counter\n");
+		return ret;
+	}
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	if (!dcrtc->frame_work)
+		dcrtc->frame_work = work;
+	else
+		ret = -EBUSY;
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	if (ret)
+		drm_vblank_put(dev, dcrtc->num);
+
+	return ret;
+}
+
+static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc)
+{
+	struct drm_device *dev = dcrtc->crtc.dev;
+	struct armada_frame_work *work = dcrtc->frame_work;
+
+	dcrtc->frame_work = NULL;
+
+	armada_drm_crtc_update_regs(dcrtc, work->regs);
+
+	if (work->event)
+		drm_send_vblank_event(dev, dcrtc->num, work->event);
+
+	drm_vblank_put(dev, dcrtc->num);
+
+	/* Finally, queue the process-half of the cleanup. */
+	__armada_drm_queue_unref_work(dcrtc->crtc.dev, work->old_fb);
+	kfree(work);
+}
+
+static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc,
+	struct drm_framebuffer *fb, bool force)
+{
+	struct armada_frame_work *work;
+
+	if (!fb)
+		return;
+
+	if (force) {
+		/* Display is disabled, so just drop the old fb */
+		drm_framebuffer_unreference(fb);
+		return;
+	}
+
+	work = kmalloc(sizeof(*work), GFP_KERNEL);
+	if (work) {
+		int i = 0;
+		work->event = NULL;
+		work->old_fb = fb;
+		armada_reg_queue_end(work->regs, i);
+
+		if (armada_drm_crtc_queue_frame_work(dcrtc, work) == 0)
+			return;
+
+		kfree(work);
+	}
+
+	/*
+	 * Oops - just drop the reference immediately and hope for
+	 * the best.  The worst that will happen is the buffer gets
+	 * reused before it has finished being displayed.
+	 */
+	drm_framebuffer_unreference(fb);
+}
+
+static void armada_drm_vblank_off(struct armada_crtc *dcrtc)
+{
+	struct drm_device *dev = dcrtc->crtc.dev;
+
+	/*
+	 * Tell the DRM core that vblank IRQs aren't going to happen for
+	 * a while.  This cleans up any pending vblank events for us.
+	 */
+	drm_vblank_off(dev, dcrtc->num);
+
+	/* Handle any pending flip event. */
+	spin_lock_irq(&dev->event_lock);
+	if (dcrtc->frame_work)
+		armada_drm_crtc_complete_frame_work(dcrtc);
+	spin_unlock_irq(&dev->event_lock);
+}
+
+void armada_drm_crtc_gamma_set(struct drm_crtc *crtc, u16 r, u16 g, u16 b,
+	int idx)
+{
+}
+
+void armada_drm_crtc_gamma_get(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
+	int idx)
+{
+}
+
+/* The mode_config.mutex will be held for this call */
+static void armada_drm_crtc_dpms(struct drm_crtc *crtc, int dpms)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+
+	if (dcrtc->dpms != dpms) {
+		dcrtc->dpms = dpms;
+		armada_drm_crtc_update(dcrtc);
+		if (dpms_blanked(dpms))
+			armada_drm_vblank_off(dcrtc);
+	}
+}
+
+/*
+ * Prepare for a mode set.  Turn off overlay to ensure that we don't end
+ * up with the overlay size being bigger than the active screen size.
+ * We rely upon X refreshing this state after the mode set has completed.
+ *
+ * The mode_config.mutex will be held for this call
+ */
+static void armada_drm_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct drm_plane *plane;
+
+	/*
+	 * If we have an overlay plane associated with this CRTC, disable
+	 * it before the modeset to avoid its coordinates being outside
+	 * the new mode parameters.  DRM doesn't provide help with this.
+	 */
+	plane = dcrtc->plane;
+	if (plane) {
+		struct drm_framebuffer *fb = plane->fb;
+
+		plane->funcs->disable_plane(plane);
+		plane->fb = NULL;
+		plane->crtc = NULL;
+		drm_framebuffer_unreference(fb);
+	}
+}
+
+/* The mode_config.mutex will be held for this call */
+static void armada_drm_crtc_commit(struct drm_crtc *crtc)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+
+	if (dcrtc->dpms != DRM_MODE_DPMS_ON) {
+		dcrtc->dpms = DRM_MODE_DPMS_ON;
+		armada_drm_crtc_update(dcrtc);
+	}
+}
+
+/* The mode_config.mutex will be held for this call */
+static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+	const struct drm_display_mode *mode, struct drm_display_mode *adj)
+{
+	struct armada_private *priv = crtc->dev->dev_private;
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	int ret;
+
+	/* We can't do interlaced modes if we don't have the SPU_ADV_REG */
+	if (!priv->variant->has_spu_adv_reg &&
+	    adj->flags & DRM_MODE_FLAG_INTERLACE)
+		return false;
+
+	/* Check whether the display mode is possible */
+	ret = priv->variant->crtc_compute_clock(dcrtc, adj, NULL);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
+{
+	struct armada_vbl_event *e, *n;
+	void __iomem *base = dcrtc->base;
+
+	if (stat & DMA_FF_UNDERFLOW)
+		DRM_ERROR("video underflow on crtc %u\n", dcrtc->num);
+	if (stat & GRA_FF_UNDERFLOW)
+		DRM_ERROR("graphics underflow on crtc %u\n", dcrtc->num);
+
+	if (stat & VSYNC_IRQ)
+		drm_handle_vblank(dcrtc->crtc.dev, dcrtc->num);
+
+	spin_lock(&dcrtc->irq_lock);
+
+	list_for_each_entry_safe(e, n, &dcrtc->vbl_list, node) {
+		list_del_init(&e->node);
+		drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
+		e->fn(dcrtc, e->data);
+	}
+
+	if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) {
+		int i = stat & GRA_FRAME_IRQ0 ? 0 : 1;
+		uint32_t val;
+
+		writel_relaxed(dcrtc->v[i].spu_v_porch, base + LCD_SPU_V_PORCH);
+		writel_relaxed(dcrtc->v[i].spu_v_h_total,
+			       base + LCD_SPUT_V_H_TOTAL);
+
+		val = readl_relaxed(base + LCD_SPU_ADV_REG);
+		val &= ~(ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF | ADV_VSYNCOFFEN);
+		val |= dcrtc->v[i].spu_adv_reg;
+		writel_relaxed(val, dcrtc->base + LCD_SPU_ADV_REG);
+	}
+	spin_unlock(&dcrtc->irq_lock);
+
+	if (stat & GRA_FRAME_IRQ) {
+		struct drm_device *dev = dcrtc->crtc.dev;
+
+		spin_lock(&dev->event_lock);
+		if (dcrtc->frame_work)
+			armada_drm_crtc_complete_frame_work(dcrtc);
+		spin_unlock(&dev->event_lock);
+
+		wake_up(&dcrtc->frame_wait);
+	}
+}
+
+/* These are locked by dev->vbl_lock */
+void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask)
+{
+	if (dcrtc->irq_ena & mask) {
+		dcrtc->irq_ena &= ~mask;
+		writel(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
+	}
+}
+
+void armada_drm_crtc_enable_irq(struct armada_crtc *dcrtc, u32 mask)
+{
+	if ((dcrtc->irq_ena & mask) != mask) {
+		dcrtc->irq_ena |= mask;
+		writel(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
+		if (readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR) & mask)
+			writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
+	}
+}
+
+static uint32_t armada_drm_crtc_calculate_csc(struct armada_crtc *dcrtc)
+{
+	struct drm_display_mode *adj = &dcrtc->crtc.mode;
+	uint32_t val = 0;
+
+	if (dcrtc->csc_yuv_mode == CSC_YUV_CCIR709)
+		val |= CFG_CSC_YUV_CCIR709;
+	if (dcrtc->csc_rgb_mode == CSC_RGB_STUDIO)
+		val |= CFG_CSC_RGB_STUDIO;
+
+	/*
+	 * In auto mode, set the colorimetry, based upon the HDMI spec.
+	 * 1280x720p, 1920x1080p and 1920x1080i use ITU709, others use
+	 * ITU601.  It may be more appropriate to set this depending on
+	 * the source - but what if the graphic frame is YUV and the
+	 * video frame is RGB?
+	 */
+	if ((adj->hdisplay == 1280 && adj->vdisplay == 720 &&
+	     !(adj->flags & DRM_MODE_FLAG_INTERLACE)) ||
+	    (adj->hdisplay == 1920 && adj->vdisplay == 1080)) {
+		if (dcrtc->csc_yuv_mode == CSC_AUTO)
+			val |= CFG_CSC_YUV_CCIR709;
+	}
+
+	/*
+	 * We assume we're connected to a TV-like device, so the YUV->RGB
+	 * conversion should produce a limited range.  We should set this
+	 * depending on the connectors attached to this CRTC, and what
+	 * kind of device they report being connected.
+	 */
+	if (dcrtc->csc_rgb_mode == CSC_AUTO)
+		val |= CFG_CSC_RGB_STUDIO;
+
+	return val;
+}
+
+/* The mode_config.mutex will be held for this call */
+static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
+	struct drm_display_mode *mode, struct drm_display_mode *adj,
+	int x, int y, struct drm_framebuffer *old_fb)
+{
+	struct armada_private *priv = crtc->dev->dev_private;
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_regs regs[17];
+	uint32_t lm, rm, tm, bm, val, sclk;
+	unsigned long flags;
+	unsigned i;
+	bool interlaced;
+
+	drm_framebuffer_reference(crtc->fb);
+
+	interlaced = !!(adj->flags & DRM_MODE_FLAG_INTERLACE);
+
+	i = armada_drm_crtc_calc_fb(dcrtc->crtc.fb, x, y, regs, interlaced);
+
+	rm = adj->crtc_hsync_start - adj->crtc_hdisplay;
+	lm = adj->crtc_htotal - adj->crtc_hsync_end;
+	bm = adj->crtc_vsync_start - adj->crtc_vdisplay;
+	tm = adj->crtc_vtotal - adj->crtc_vsync_end;
+
+	DRM_DEBUG_DRIVER("H: %d %d %d %d lm %d rm %d\n",
+		adj->crtc_hdisplay,
+		adj->crtc_hsync_start,
+		adj->crtc_hsync_end,
+		adj->crtc_htotal, lm, rm);
+	DRM_DEBUG_DRIVER("V: %d %d %d %d tm %d bm %d\n",
+		adj->crtc_vdisplay,
+		adj->crtc_vsync_start,
+		adj->crtc_vsync_end,
+		adj->crtc_vtotal, tm, bm);
+
+	/* Wait for pending flips to complete */
+	wait_event(dcrtc->frame_wait, !dcrtc->frame_work);
+
+	drm_vblank_pre_modeset(crtc->dev, dcrtc->num);
+
+	crtc->mode = *adj;
+
+	val = dcrtc->dumb_ctrl & ~CFG_DUMB_ENA;
+	if (val != dcrtc->dumb_ctrl) {
+		dcrtc->dumb_ctrl = val;
+		writel_relaxed(val, dcrtc->base + LCD_SPU_DUMB_CTRL);
+	}
+
+	/* Now compute the divider for real */
+	priv->variant->crtc_compute_clock(dcrtc, adj, &sclk);
+
+	/* Ensure graphic fifo is enabled */
+	armada_reg_queue_mod(regs, i, 0, CFG_PDWN64x66, LCD_SPU_SRAM_PARA1);
+	armada_reg_queue_set(regs, i, sclk, LCD_CFG_SCLK_DIV);
+
+	if (interlaced ^ dcrtc->interlaced) {
+		if (adj->flags & DRM_MODE_FLAG_INTERLACE)
+			drm_vblank_get(dcrtc->crtc.dev, dcrtc->num);
+		else
+			drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
+		dcrtc->interlaced = interlaced;
+	}
+
+	spin_lock_irqsave(&dcrtc->irq_lock, flags);
+
+	/* Even interlaced/progressive frame */
+	dcrtc->v[1].spu_v_h_total = adj->crtc_vtotal << 16 |
+				    adj->crtc_htotal;
+	dcrtc->v[1].spu_v_porch = tm << 16 | bm;
+	val = adj->crtc_hsync_start;
+	dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN;
+
+	if (interlaced) {
+		/* Odd interlaced frame */
+		dcrtc->v[0].spu_v_h_total = dcrtc->v[1].spu_v_h_total +
+						(1 << 16);
+		dcrtc->v[0].spu_v_porch = dcrtc->v[1].spu_v_porch + 1;
+		val = adj->crtc_hsync_start - adj->crtc_htotal / 2;
+		dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN;
+	} else {
+		dcrtc->v[0] = dcrtc->v[1];
+	}
+
+	val = adj->crtc_vdisplay << 16 | adj->crtc_hdisplay;
+
+	armada_reg_queue_set(regs, i, val, LCD_SPU_V_H_ACTIVE);
+	armada_reg_queue_set(regs, i, val, LCD_SPU_GRA_HPXL_VLN);
+	armada_reg_queue_set(regs, i, val, LCD_SPU_GZM_HPXL_VLN);
+	armada_reg_queue_set(regs, i, (lm << 16) | rm, LCD_SPU_H_PORCH);
+	armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_porch, LCD_SPU_V_PORCH);
+	armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total,
+			   LCD_SPUT_V_H_TOTAL);
+
+	if (priv->variant->has_spu_adv_reg)
+		armada_reg_queue_mod(regs, i, dcrtc->v[0].spu_adv_reg,
+				     ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF |
+				     ADV_VSYNCOFFEN, LCD_SPU_ADV_REG);
+
+	val = CFG_GRA_ENA | CFG_GRA_HSMOOTH;
+	val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.fb)->fmt);
+	val |= CFG_GRA_MOD(drm_fb_to_armada_fb(dcrtc->crtc.fb)->mod);
+
+	if (drm_fb_to_armada_fb(dcrtc->crtc.fb)->fmt > CFG_420)
+		val |= CFG_PALETTE_ENA;
+
+	if (interlaced)
+		val |= CFG_GRA_FTOGGLE;
+
+	armada_reg_queue_mod(regs, i, val, CFG_GRAFORMAT |
+			     CFG_GRA_MOD(CFG_SWAPRB | CFG_SWAPUV |
+					 CFG_SWAPYU | CFG_YUV2RGB) |
+			     CFG_PALETTE_ENA | CFG_GRA_FTOGGLE,
+			     LCD_SPU_DMA_CTRL0);
+
+	val = adj->flags & DRM_MODE_FLAG_NVSYNC ? CFG_VSYNC_INV : 0;
+	armada_reg_queue_mod(regs, i, val, CFG_VSYNC_INV, LCD_SPU_DMA_CTRL1);
+
+	val = dcrtc->spu_iopad_ctrl | armada_drm_crtc_calculate_csc(dcrtc);
+	armada_reg_queue_set(regs, i, val, LCD_SPU_IOPAD_CONTROL);
+	armada_reg_queue_end(regs, i);
+
+	armada_drm_crtc_update_regs(dcrtc, regs);
+	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
+
+	armada_drm_crtc_update(dcrtc);
+
+	drm_vblank_post_modeset(crtc->dev, dcrtc->num);
+	armada_drm_crtc_finish_fb(dcrtc, old_fb, dpms_blanked(dcrtc->dpms));
+
+	return 0;
+}
+
+/* The mode_config.mutex will be held for this call */
+static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+	struct drm_framebuffer *old_fb)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_regs regs[4];
+	unsigned i;
+
+	i = armada_drm_crtc_calc_fb(crtc->fb, crtc->x, crtc->y, regs,
+				    dcrtc->interlaced);
+	armada_reg_queue_end(regs, i);
+
+	/* Wait for pending flips to complete */
+	wait_event(dcrtc->frame_wait, !dcrtc->frame_work);
+
+	/* Take a reference to the new fb as we're using it */
+	drm_framebuffer_reference(crtc->fb);
+
+	/* Update the base in the CRTC */
+	armada_drm_crtc_update_regs(dcrtc, regs);
+
+	/* Drop our previously held reference */
+	armada_drm_crtc_finish_fb(dcrtc, old_fb, dpms_blanked(dcrtc->dpms));
+
+	return 0;
+}
+
+static void armada_drm_crtc_load_lut(struct drm_crtc *crtc)
+{
+}
+
+/* The mode_config.mutex will be held for this call */
+static void armada_drm_crtc_disable(struct drm_crtc *crtc)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+
+	armada_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+	armada_drm_crtc_finish_fb(dcrtc, crtc->fb, true);
+
+	/* Power down most RAMs and FIFOs */
+	writel_relaxed(CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 |
+		       CFG_PDWN32x32 | CFG_PDWN16x66 | CFG_PDWN32x66 |
+		       CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
+}
+
+static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = {
+	.dpms		= armada_drm_crtc_dpms,
+	.prepare	= armada_drm_crtc_prepare,
+	.commit		= armada_drm_crtc_commit,
+	.mode_fixup	= armada_drm_crtc_mode_fixup,
+	.mode_set	= armada_drm_crtc_mode_set,
+	.mode_set_base	= armada_drm_crtc_mode_set_base,
+	.load_lut	= armada_drm_crtc_load_lut,
+	.disable	= armada_drm_crtc_disable,
+};
+
+static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_private *priv = crtc->dev->dev_private;
+
+	priv->dcrtc[dcrtc->num] = NULL;
+	drm_crtc_cleanup(&dcrtc->crtc);
+
+	if (!IS_ERR(dcrtc->clk))
+		clk_disable_unprepare(dcrtc->clk);
+
+	kfree(dcrtc);
+}
+
+/*
+ * The mode_config lock is held here, to prevent races between this
+ * and a mode_set.
+ */
+static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
+	struct drm_framebuffer *fb, struct drm_pending_vblank_event *event)
+{
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_frame_work *work;
+	struct drm_device *dev = crtc->dev;
+	unsigned long flags;
+	unsigned i;
+	int ret;
+
+	/* We don't support changing the pixel format */
+	if (fb->pixel_format != crtc->fb->pixel_format)
+		return -EINVAL;
+
+	work = kmalloc(sizeof(*work), GFP_KERNEL);
+	if (!work)
+		return -ENOMEM;
+
+	work->event = event;
+	work->old_fb = dcrtc->crtc.fb;
+
+	i = armada_drm_crtc_calc_fb(fb, crtc->x, crtc->y, work->regs,
+				    dcrtc->interlaced);
+	armada_reg_queue_end(work->regs, i);
+
+	/*
+	 * Hold the old framebuffer for the work - DRM appears to drop our
+	 * reference to the old framebuffer in drm_mode_page_flip_ioctl().
+	 */
+	drm_framebuffer_reference(work->old_fb);
+
+	ret = armada_drm_crtc_queue_frame_work(dcrtc, work);
+	if (ret) {
+		/*
+		 * Undo our reference above; DRM does not drop the reference
+		 * to this object on error, so that's okay.
+		 */
+		drm_framebuffer_unreference(work->old_fb);
+		kfree(work);
+		return ret;
+	}
+
+	/*
+	 * Don't take a reference on the new framebuffer;
+	 * drm_mode_page_flip_ioctl() has already grabbed a reference and
+	 * will _not_ drop that reference on successful return from this
+	 * function.  Simply mark this new framebuffer as the current one.
+	 */
+	dcrtc->crtc.fb = fb;
+
+	/*
+	 * Finally, if the display is blanked, we won't receive an
+	 * interrupt, so complete it now.
+	 */
+	if (dpms_blanked(dcrtc->dpms)) {
+		spin_lock_irqsave(&dev->event_lock, flags);
+		if (dcrtc->frame_work)
+			armada_drm_crtc_complete_frame_work(dcrtc);
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+	}
+
+	return 0;
+}
+
+static int
+armada_drm_crtc_set_property(struct drm_crtc *crtc,
+	struct drm_property *property, uint64_t val)
+{
+	struct armada_private *priv = crtc->dev->dev_private;
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	bool update_csc = false;
+
+	if (property == priv->csc_yuv_prop) {
+		dcrtc->csc_yuv_mode = val;
+		update_csc = true;
+	} else if (property == priv->csc_rgb_prop) {
+		dcrtc->csc_rgb_mode = val;
+		update_csc = true;
+	}
+
+	if (update_csc) {
+		uint32_t val;
+
+		val = dcrtc->spu_iopad_ctrl |
+		      armada_drm_crtc_calculate_csc(dcrtc);
+		writel_relaxed(val, dcrtc->base + LCD_SPU_IOPAD_CONTROL);
+	}
+
+	return 0;
+}
+
+static struct drm_crtc_funcs armada_crtc_funcs = {
+	.destroy	= armada_drm_crtc_destroy,
+	.set_config	= drm_crtc_helper_set_config,
+	.page_flip	= armada_drm_crtc_page_flip,
+	.set_property	= armada_drm_crtc_set_property,
+};
+
+static struct drm_prop_enum_list armada_drm_csc_yuv_enum_list[] = {
+	{ CSC_AUTO,        "Auto" },
+	{ CSC_YUV_CCIR601, "CCIR601" },
+	{ CSC_YUV_CCIR709, "CCIR709" },
+};
+
+static struct drm_prop_enum_list armada_drm_csc_rgb_enum_list[] = {
+	{ CSC_AUTO,         "Auto" },
+	{ CSC_RGB_COMPUTER, "Computer system" },
+	{ CSC_RGB_STUDIO,   "Studio" },
+};
+
+static int armada_drm_crtc_create_properties(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+
+	if (priv->csc_yuv_prop)
+		return 0;
+
+	priv->csc_yuv_prop = drm_property_create_enum(dev, 0,
+				"CSC_YUV", armada_drm_csc_yuv_enum_list,
+				ARRAY_SIZE(armada_drm_csc_yuv_enum_list));
+	priv->csc_rgb_prop = drm_property_create_enum(dev, 0,
+				"CSC_RGB", armada_drm_csc_rgb_enum_list,
+				ARRAY_SIZE(armada_drm_csc_rgb_enum_list));
+
+	if (!priv->csc_yuv_prop || !priv->csc_rgb_prop)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
+	struct resource *res)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct armada_crtc *dcrtc;
+	void __iomem *base;
+	int ret;
+
+	ret = armada_drm_crtc_create_properties(dev);
+	if (ret)
+		return ret;
+
+	base = devm_request_and_ioremap(dev->dev, res);
+	if (!base) {
+		DRM_ERROR("failed to ioremap register\n");
+		return -ENOMEM;
+	}
+
+	dcrtc = kzalloc(sizeof(*dcrtc), GFP_KERNEL);
+	if (!dcrtc) {
+		DRM_ERROR("failed to allocate Armada crtc\n");
+		return -ENOMEM;
+	}
+
+	dcrtc->base = base;
+	dcrtc->num = num;
+	dcrtc->clk = ERR_PTR(-EINVAL);
+	dcrtc->csc_yuv_mode = CSC_AUTO;
+	dcrtc->csc_rgb_mode = CSC_AUTO;
+	dcrtc->cfg_dumb_ctrl = DUMB24_RGB888_0;
+	dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
+	spin_lock_init(&dcrtc->irq_lock);
+	dcrtc->irq_ena = CLEAN_SPU_IRQ_ISR;
+	INIT_LIST_HEAD(&dcrtc->vbl_list);
+	init_waitqueue_head(&dcrtc->frame_wait);
+
+	/* Initialize some registers which we don't otherwise set */
+	writel_relaxed(0x00000001, dcrtc->base + LCD_CFG_SCLK_DIV);
+	writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_BLANKCOLOR);
+	writel_relaxed(dcrtc->spu_iopad_ctrl,
+		       dcrtc->base + LCD_SPU_IOPAD_CONTROL);
+	writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_SRAM_PARA0);
+	writel_relaxed(CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 |
+		       CFG_PDWN32x32 | CFG_PDWN16x66 | CFG_PDWN32x66 |
+		       CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
+	writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1);
+	writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN);
+
+	if (priv->variant->crtc_init) {
+		ret = priv->variant->crtc_init(dcrtc);
+		if (ret) {
+			kfree(dcrtc);
+			return ret;
+		}
+	}
+
+	/* Ensure AXI pipeline is enabled */
+	armada_updatel(CFG_ARBFAST_ENA, 0, dcrtc->base + LCD_SPU_DMA_CTRL0);
+
+	priv->dcrtc[dcrtc->num] = dcrtc;
+
+	drm_crtc_init(dev, &dcrtc->crtc, &armada_crtc_funcs);
+	drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);
+
+	drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop,
+				   dcrtc->csc_yuv_mode);
+	drm_object_attach_property(&dcrtc->crtc.base, priv->csc_rgb_prop,
+				   dcrtc->csc_rgb_mode);
+
+	return armada_overlay_plane_create(dev, 1 << dcrtc->num);
+}
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
new file mode 100644
index 0000000..972da53
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_CRTC_H
+#define ARMADA_CRTC_H
+
+struct armada_gem_object;
+
+struct armada_regs {
+	uint32_t offset;
+	uint32_t mask;
+	uint32_t val;
+};
+
+#define armada_reg_queue_mod(_r, _i, _v, _m, _o)	\
+	do {					\
+		struct armada_regs *__reg = _r;	\
+		__reg[_i].offset = _o;		\
+		__reg[_i].mask = ~(_m);		\
+		__reg[_i].val = _v;		\
+		_i++;				\
+	} while (0)
+
+#define armada_reg_queue_set(_r, _i, _v, _o)	\
+	armada_reg_queue_mod(_r, _i, _v, ~0, _o)
+
+#define armada_reg_queue_end(_r, _i)		\
+	armada_reg_queue_mod(_r, _i, 0, 0, ~0)
+
+struct armada_frame_work;
+
+struct armada_crtc {
+	struct drm_crtc		crtc;
+	unsigned		num;
+	void __iomem		*base;
+	struct clk		*clk;
+	struct {
+		uint32_t	spu_v_h_total;
+		uint32_t	spu_v_porch;
+		uint32_t	spu_adv_reg;
+	} v[2];
+	bool			interlaced;
+	uint8_t			csc_yuv_mode;
+	uint8_t			csc_rgb_mode;
+
+	struct drm_plane	*plane;
+
+	int			dpms;
+	uint32_t		cfg_dumb_ctrl;
+	uint32_t		dumb_ctrl;
+	uint32_t		spu_iopad_ctrl;
+
+	wait_queue_head_t	frame_wait;
+	struct armada_frame_work *frame_work;
+
+	spinlock_t		irq_lock;
+	uint32_t		irq_ena;
+	struct list_head	vbl_list;
+};
+#define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)
+
+int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *);
+void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
+void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
+void armada_drm_crtc_irq(struct armada_crtc *, u32);
+void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
+void armada_drm_crtc_enable_irq(struct armada_crtc *, u32);
+void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
+
+#endif
diff --git a/drivers/gpu/drm/armada/armada_debugfs.c b/drivers/gpu/drm/armada/armada_debugfs.c
new file mode 100644
index 0000000..612f375
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_debugfs.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Rewritten from the dovefb driver, and Armada510 manuals.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <drm/drmP.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+
+static int armada_debugfs_gem_linear_show(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct armada_private *priv = dev->dev_private;
+	int ret;
+
+	mutex_lock(&dev->struct_mutex);
+	ret = drm_mm_dump_table(m, &priv->linear);
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+static int armada_debugfs_reg_show(struct seq_file *m, void *data)
+{
+	struct drm_device *dev = m->private;
+	struct armada_private *priv = dev->dev_private;
+	int n, i;
+
+	if (priv) {
+		for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
+			struct armada_crtc *dcrtc = priv->dcrtc[n];
+			if (!dcrtc)
+				continue;
+
+			for (i = 0x84; i <= 0x1c4; i += 4) {
+				uint32_t v = readl_relaxed(dcrtc->base + i);
+				seq_printf(m, "%u: 0x%04x: 0x%08x\n", n, i, v);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int armada_debugfs_reg_r_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, armada_debugfs_reg_show, inode->i_private);
+}
+
+static const struct file_operations fops_reg_r = {
+	.owner = THIS_MODULE,
+	.open = armada_debugfs_reg_r_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int armada_debugfs_write(struct file *file, const char __user *ptr,
+	size_t len, loff_t *off)
+{
+	struct drm_device *dev = file->private_data;
+	struct armada_private *priv = dev->dev_private;
+	struct armada_crtc *dcrtc = priv->dcrtc[0];
+	char buf[32], *p;
+	uint32_t reg, val;
+	int ret;
+
+	if (*off != 0)
+		return 0;
+
+	if (len > sizeof(buf) - 1)
+		len = sizeof(buf) - 1;
+
+	ret = strncpy_from_user(buf, ptr, len);
+	if (ret < 0)
+		return ret;
+	buf[len] = '\0';
+
+	reg = simple_strtoul(buf, &p, 16);
+	if (!isspace(*p))
+		return -EINVAL;
+	val = simple_strtoul(p + 1, NULL, 16);
+
+	if (reg >= 0x84 && reg <= 0x1c4)
+		writel(val, dcrtc->base + reg);
+
+	return len;
+}
+
+static int armada_debugfs_reg_w_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static const struct file_operations fops_reg_w = {
+	.owner = THIS_MODULE,
+	.open = armada_debugfs_reg_w_open,
+	.write = armada_debugfs_write,
+	.llseek = noop_llseek,
+};
+
+static struct drm_info_list armada_debugfs_list[] = {
+	{ "gem_linear", armada_debugfs_gem_linear_show, 0 },
+};
+#define ARMADA_DEBUGFS_ENTRIES ARRAY_SIZE(armada_debugfs_list)
+
+static int drm_add_fake_info_node(struct drm_minor *minor, struct dentry *ent,
+	const void *key)
+{
+	struct drm_info_node *node;
+
+	node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
+	if (node == NULL) {
+		debugfs_remove(ent);
+		return -ENOMEM;
+	}
+
+	node->minor = minor;
+	node->dent = ent;
+	node->info_ent = (void *) key;
+
+	mutex_lock(&minor->debugfs_lock);
+	list_add(&node->list, &minor->debugfs_list);
+	mutex_unlock(&minor->debugfs_lock);
+
+	return 0;
+}
+
+static int armada_debugfs_create(struct dentry *root, struct drm_minor *minor,
+	const char *name, umode_t mode, const struct file_operations *fops)
+{
+	struct dentry *de;
+
+	de = debugfs_create_file(name, mode, root, minor->dev, fops);
+
+	return drm_add_fake_info_node(minor, de, fops);
+}
+
+int armada_drm_debugfs_init(struct drm_minor *minor)
+{
+	int ret;
+
+	ret = drm_debugfs_create_files(armada_debugfs_list,
+				       ARMADA_DEBUGFS_ENTRIES,
+				       minor->debugfs_root, minor);
+	if (ret)
+		return ret;
+
+	ret = armada_debugfs_create(minor->debugfs_root, minor,
+				   "reg", S_IFREG | S_IRUSR, &fops_reg_r);
+	if (ret)
+		goto err_1;
+
+	ret = armada_debugfs_create(minor->debugfs_root, minor,
+				"reg_wr", S_IFREG | S_IWUSR, &fops_reg_w);
+	if (ret)
+		goto err_2;
+	return ret;
+
+ err_2:
+	drm_debugfs_remove_files((struct drm_info_list *)&fops_reg_r, 1, minor);
+ err_1:
+	drm_debugfs_remove_files(armada_debugfs_list, ARMADA_DEBUGFS_ENTRIES,
+				 minor);
+	return ret;
+}
+
+void armada_drm_debugfs_cleanup(struct drm_minor *minor)
+{
+	drm_debugfs_remove_files((struct drm_info_list *)&fops_reg_w, 1, minor);
+	drm_debugfs_remove_files((struct drm_info_list *)&fops_reg_r, 1, minor);
+	drm_debugfs_remove_files(armada_debugfs_list, ARMADA_DEBUGFS_ENTRIES,
+				 minor);
+}
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
new file mode 100644
index 0000000..e8c4f80
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_DRM_H
+#define ARMADA_DRM_H
+
+#include <linux/kfifo.h>
+#include <linux/io.h>
+#include <linux/workqueue.h>
+#include <drm/drmP.h>
+
+struct armada_crtc;
+struct armada_gem_object;
+struct clk;
+struct drm_fb_helper;
+
+static inline void
+armada_updatel(uint32_t val, uint32_t mask, void __iomem *ptr)
+{
+	uint32_t ov, v;
+
+	ov = v = readl_relaxed(ptr);
+	v = (v & ~mask) | val;
+	if (ov != v)
+		writel_relaxed(v, ptr);
+}
+
+static inline uint32_t armada_pitch(uint32_t width, uint32_t bpp)
+{
+	uint32_t pitch = bpp != 4 ? width * ((bpp + 7) / 8) : width / 2;
+
+	/* 88AP510 spec recommends pitch be a multiple of 128 */
+	return ALIGN(pitch, 128);
+}
+
+struct armada_vbl_event {
+	struct list_head	node;
+	void			*data;
+	void			(*fn)(struct armada_crtc *, void *);
+};
+void armada_drm_vbl_event_add(struct armada_crtc *,
+	struct armada_vbl_event *);
+void armada_drm_vbl_event_remove(struct armada_crtc *,
+	struct armada_vbl_event *);
+void armada_drm_vbl_event_remove_unlocked(struct armada_crtc *,
+	struct armada_vbl_event *);
+#define armada_drm_vbl_event_init(_e, _f, _d) do {	\
+	struct armada_vbl_event *__e = _e;		\
+	INIT_LIST_HEAD(&__e->node);			\
+	__e->data = _d;					\
+	__e->fn = _f;					\
+} while (0)
+
+
+struct armada_private;
+
+struct armada_variant {
+	bool	has_spu_adv_reg;
+	int (*init)(struct armada_private *, struct device *);
+	int (*crtc_init)(struct armada_crtc *);
+	int (*crtc_compute_clock)(struct armada_crtc *,
+				  const struct drm_display_mode *,
+				  uint32_t *);
+};
+
+/* Variant ops */
+extern const struct armada_variant armada510_ops;
+
+struct armada_private {
+	const struct armada_variant *variant;
+	struct work_struct	fb_unref_work;
+	DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8);
+	struct drm_fb_helper	*fbdev;
+	struct armada_crtc	*dcrtc[2];
+	struct drm_mm		linear;
+	struct clk		*extclk[2];
+	struct drm_property	*csc_yuv_prop;
+	struct drm_property	*csc_rgb_prop;
+	struct drm_property	*colorkey_prop;
+	struct drm_property	*colorkey_min_prop;
+	struct drm_property	*colorkey_max_prop;
+	struct drm_property	*colorkey_val_prop;
+	struct drm_property	*colorkey_alpha_prop;
+	struct drm_property	*colorkey_mode_prop;
+	struct drm_property	*brightness_prop;
+	struct drm_property	*contrast_prop;
+	struct drm_property	*saturation_prop;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry		*de;
+#endif
+};
+
+void __armada_drm_queue_unref_work(struct drm_device *,
+	struct drm_framebuffer *);
+void armada_drm_queue_unref_work(struct drm_device *,
+	struct drm_framebuffer *);
+
+extern const struct drm_mode_config_funcs armada_drm_mode_config_funcs;
+
+int armada_fbdev_init(struct drm_device *);
+void armada_fbdev_fini(struct drm_device *);
+
+int armada_overlay_plane_create(struct drm_device *, unsigned long);
+
+int armada_drm_debugfs_init(struct drm_minor *);
+void armada_drm_debugfs_cleanup(struct drm_minor *);
+
+#endif
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
new file mode 100644
index 0000000..7bfab9a
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_gem.h"
+#include "armada_hw.h"
+#include <drm/armada_drm.h>
+#include "armada_ioctlP.h"
+
+static void armada_drm_unref_work(struct work_struct *work)
+{
+	struct armada_private *priv =
+		container_of(work, struct armada_private, fb_unref_work);
+	struct drm_framebuffer *fb;
+
+	while (kfifo_get(&priv->fb_unref, &fb))
+		drm_framebuffer_unreference(fb);
+}
+
+/* Must be called with dev->event_lock held */
+void __armada_drm_queue_unref_work(struct drm_device *dev,
+	struct drm_framebuffer *fb)
+{
+	struct armada_private *priv = dev->dev_private;
+
+	/*
+	 * Yes, we really must jump through these hoops just to store a
+	 * _pointer_ to something into the kfifo.  This is utterly insane
+	 * and idiotic, because it kfifo requires the _data_ pointed to by
+	 * the pointer const, not the pointer itself.  Not only that, but
+	 * you have to pass a pointer _to_ the pointer you want stored.
+	 */
+	const struct drm_framebuffer *silly_api_alert = fb;
+	WARN_ON(!kfifo_put(&priv->fb_unref, &silly_api_alert));
+	schedule_work(&priv->fb_unref_work);
+}
+
+void armada_drm_queue_unref_work(struct drm_device *dev,
+	struct drm_framebuffer *fb)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	__armada_drm_queue_unref_work(dev, fb);
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static int armada_drm_load(struct drm_device *dev, unsigned long flags)
+{
+	const struct platform_device_id *id;
+	struct armada_private *priv;
+	struct resource *res[ARRAY_SIZE(priv->dcrtc)];
+	struct resource *mem = NULL;
+	int ret, n, i;
+
+	memset(res, 0, sizeof(res));
+
+	for (n = i = 0; ; n++) {
+		struct resource *r = platform_get_resource(dev->platformdev,
+							   IORESOURCE_MEM, n);
+		if (!r)
+			break;
+
+		/* Resources above 64K are graphics memory */
+		if (resource_size(r) > SZ_64K)
+			mem = r;
+		else if (i < ARRAY_SIZE(priv->dcrtc))
+			res[i++] = r;
+		else
+			return -EINVAL;
+	}
+
+	if (!res[0] || !mem)
+		return -ENXIO;
+
+	if (!devm_request_mem_region(dev->dev, mem->start,
+			resource_size(mem), "armada-drm"))
+		return -EBUSY;
+
+	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		DRM_ERROR("failed to allocate private\n");
+		return -ENOMEM;
+	}
+
+	dev->dev_private = priv;
+
+	/* Get the implementation specific driver data. */
+	id = platform_get_device_id(dev->platformdev);
+	if (!id)
+		return -ENXIO;
+
+	priv->variant = (struct armada_variant *)id->driver_data;
+
+	ret = priv->variant->init(priv, dev->dev);
+	if (ret)
+		return ret;
+
+	INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
+	INIT_KFIFO(priv->fb_unref);
+
+	/* Mode setting support */
+	drm_mode_config_init(dev);
+	dev->mode_config.min_width = 320;
+	dev->mode_config.min_height = 200;
+
+	/*
+	 * With vscale enabled, the maximum width is 1920 due to the
+	 * 1920 by 3 lines RAM
+	 */
+	dev->mode_config.max_width = 1920;
+	dev->mode_config.max_height = 2048;
+
+	dev->mode_config.preferred_depth = 24;
+	dev->mode_config.funcs = &armada_drm_mode_config_funcs;
+	drm_mm_init(&priv->linear, mem->start, resource_size(mem));
+
+	/* Create all LCD controllers */
+	for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
+		if (!res[n])
+			break;
+
+		ret = armada_drm_crtc_create(dev, n, res[n]);
+		if (ret)
+			goto err_kms;
+	}
+
+	ret = drm_vblank_init(dev, n);
+	if (ret)
+		goto err_kms;
+
+	ret = drm_irq_install(dev);
+	if (ret)
+		goto err_kms;
+
+	dev->vblank_disable_allowed = 1;
+
+	ret = armada_fbdev_init(dev);
+	if (ret)
+		goto err_irq;
+
+	drm_kms_helper_poll_init(dev);
+
+	return 0;
+
+ err_irq:
+	drm_irq_uninstall(dev);
+ err_kms:
+	drm_mode_config_cleanup(dev);
+	drm_mm_takedown(&priv->linear);
+	flush_work(&priv->fb_unref_work);
+
+	return ret;
+}
+
+static int armada_drm_unload(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+
+	drm_kms_helper_poll_fini(dev);
+	armada_fbdev_fini(dev);
+	drm_irq_uninstall(dev);
+	drm_mode_config_cleanup(dev);
+	drm_mm_takedown(&priv->linear);
+	flush_work(&priv->fb_unref_work);
+	dev->dev_private = NULL;
+
+	return 0;
+}
+
+void armada_drm_vbl_event_add(struct armada_crtc *dcrtc,
+	struct armada_vbl_event *evt)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dcrtc->irq_lock, flags);
+	if (list_empty(&evt->node)) {
+		list_add_tail(&evt->node, &dcrtc->vbl_list);
+
+		drm_vblank_get(dcrtc->crtc.dev, dcrtc->num);
+	}
+	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
+}
+
+void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc,
+	struct armada_vbl_event *evt)
+{
+	if (!list_empty(&evt->node)) {
+		list_del_init(&evt->node);
+		drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
+	}
+}
+
+void armada_drm_vbl_event_remove_unlocked(struct armada_crtc *dcrtc,
+	struct armada_vbl_event *evt)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dcrtc->irq_lock, flags);
+	armada_drm_vbl_event_remove(dcrtc, evt);
+	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
+}
+
+/* These are called under the vbl_lock. */
+static int armada_drm_enable_vblank(struct drm_device *dev, int crtc)
+{
+	struct armada_private *priv = dev->dev_private;
+	armada_drm_crtc_enable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
+	return 0;
+}
+
+static void armada_drm_disable_vblank(struct drm_device *dev, int crtc)
+{
+	struct armada_private *priv = dev->dev_private;
+	armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
+}
+
+static irqreturn_t armada_drm_irq_handler(int irq, void *arg)
+{
+	struct drm_device *dev = arg;
+	struct armada_private *priv = dev->dev_private;
+	struct armada_crtc *dcrtc = priv->dcrtc[0];
+	uint32_t v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
+	irqreturn_t handled = IRQ_NONE;
+
+	/*
+	 * This is rediculous - rather than writing bits to clear, we
+	 * have to set the actual status register value.  This is racy.
+	 */
+	writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
+
+	/* Mask out those interrupts we haven't enabled */
+	v = stat & dcrtc->irq_ena;
+
+	if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
+		armada_drm_crtc_irq(dcrtc, stat);
+		handled = IRQ_HANDLED;
+	}
+
+	return handled;
+}
+
+static int armada_drm_irq_postinstall(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct armada_crtc *dcrtc = priv->dcrtc[0];
+
+	spin_lock_irq(&dev->vbl_lock);
+	writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
+	writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
+	spin_unlock_irq(&dev->vbl_lock);
+
+	return 0;
+}
+
+static void armada_drm_irq_uninstall(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct armada_crtc *dcrtc = priv->dcrtc[0];
+
+	writel(0, dcrtc->base + LCD_SPU_IRQ_ENA);
+}
+
+static struct drm_ioctl_desc armada_ioctls[] = {
+	DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,
+		DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(ARMADA_GEM_MMAP, armada_gem_mmap_ioctl,
+		DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(ARMADA_GEM_PWRITE, armada_gem_pwrite_ioctl,
+		DRM_UNLOCKED),
+};
+
+static const struct file_operations armada_drm_fops = {
+	.owner			= THIS_MODULE,
+	.llseek			= no_llseek,
+	.read			= drm_read,
+	.poll			= drm_poll,
+	.unlocked_ioctl		= drm_ioctl,
+	.mmap			= drm_gem_mmap,
+	.open			= drm_open,
+	.release		= drm_release,
+};
+
+static struct drm_driver armada_drm_driver = {
+	.load			= armada_drm_load,
+	.open			= NULL,
+	.preclose		= NULL,
+	.postclose		= NULL,
+	.lastclose		= NULL,
+	.unload			= armada_drm_unload,
+	.get_vblank_counter	= drm_vblank_count,
+	.enable_vblank		= armada_drm_enable_vblank,
+	.disable_vblank		= armada_drm_disable_vblank,
+	.irq_handler		= armada_drm_irq_handler,
+	.irq_postinstall	= armada_drm_irq_postinstall,
+	.irq_uninstall		= armada_drm_irq_uninstall,
+#ifdef CONFIG_DEBUG_FS
+	.debugfs_init		= armada_drm_debugfs_init,
+	.debugfs_cleanup	= armada_drm_debugfs_cleanup,
+#endif
+	.gem_init_object	= NULL,
+	.gem_free_object	= armada_gem_free_object,
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_export	= armada_gem_prime_export,
+	.gem_prime_import	= armada_gem_prime_import,
+	.dumb_create		= armada_gem_dumb_create,
+	.dumb_map_offset	= armada_gem_dumb_map_offset,
+	.dumb_destroy		= armada_gem_dumb_destroy,
+	.gem_vm_ops		= &armada_gem_vm_ops,
+	.major			= 1,
+	.minor			= 0,
+	.name			= "armada-drm",
+	.desc			= "Armada SoC DRM",
+	.date			= "20120730",
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET |
+				  DRIVER_HAVE_IRQ | DRIVER_PRIME,
+	.ioctls			= armada_ioctls,
+	.fops			= &armada_drm_fops,
+};
+
+static int armada_drm_probe(struct platform_device *pdev)
+{
+	return drm_platform_init(&armada_drm_driver, pdev);
+}
+
+static int armada_drm_remove(struct platform_device *pdev)
+{
+	drm_platform_exit(&armada_drm_driver, pdev);
+	return 0;
+}
+
+static const struct platform_device_id armada_drm_platform_ids[] = {
+	{
+		.name		= "armada-drm",
+		.driver_data	= (unsigned long)&armada510_ops,
+	}, {
+		.name		= "armada-510-drm",
+		.driver_data	= (unsigned long)&armada510_ops,
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, armada_drm_platform_ids);
+
+static struct platform_driver armada_drm_platform_driver = {
+	.probe	= armada_drm_probe,
+	.remove	= armada_drm_remove,
+	.driver	= {
+		.name	= "armada-drm",
+		.owner	= THIS_MODULE,
+	},
+	.id_table = armada_drm_platform_ids,
+};
+
+static int __init armada_drm_init(void)
+{
+	armada_drm_driver.num_ioctls = DRM_ARRAY_SIZE(armada_ioctls);
+	return platform_driver_register(&armada_drm_platform_driver);
+}
+module_init(armada_drm_init);
+
+static void __exit armada_drm_exit(void)
+{
+	platform_driver_unregister(&armada_drm_platform_driver);
+}
+module_exit(armada_drm_exit);
+
+MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
+MODULE_DESCRIPTION("Armada DRM Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:armada-drm");
diff --git a/drivers/gpu/drm/armada/armada_fb.c b/drivers/gpu/drm/armada/armada_fb.c
new file mode 100644
index 0000000..1c90969
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_fb.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include "armada_drm.h"
+#include "armada_fb.h"
+#include "armada_gem.h"
+#include "armada_hw.h"
+
+static void armada_fb_destroy(struct drm_framebuffer *fb)
+{
+	struct armada_framebuffer *dfb = drm_fb_to_armada_fb(fb);
+
+	drm_framebuffer_cleanup(&dfb->fb);
+	drm_gem_object_unreference_unlocked(&dfb->obj->obj);
+	kfree(dfb);
+}
+
+static int armada_fb_create_handle(struct drm_framebuffer *fb,
+	struct drm_file *dfile, unsigned int *handle)
+{
+	struct armada_framebuffer *dfb = drm_fb_to_armada_fb(fb);
+	return drm_gem_handle_create(dfile, &dfb->obj->obj, handle);
+}
+
+static const struct drm_framebuffer_funcs armada_fb_funcs = {
+	.destroy	= armada_fb_destroy,
+	.create_handle	= armada_fb_create_handle,
+};
+
+struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev,
+	struct drm_mode_fb_cmd2 *mode, struct armada_gem_object *obj)
+{
+	struct armada_framebuffer *dfb;
+	uint8_t format, config;
+	int ret;
+
+	switch (mode->pixel_format) {
+#define FMT(drm, fmt, mod)		\
+	case DRM_FORMAT_##drm:		\
+		format = CFG_##fmt;	\
+		config = mod;		\
+		break
+	FMT(RGB565,	565,		CFG_SWAPRB);
+	FMT(BGR565,	565,		0);
+	FMT(ARGB1555,	1555,		CFG_SWAPRB);
+	FMT(ABGR1555,	1555,		0);
+	FMT(RGB888,	888PACK,	CFG_SWAPRB);
+	FMT(BGR888,	888PACK,	0);
+	FMT(XRGB8888,	X888,		CFG_SWAPRB);
+	FMT(XBGR8888,	X888,		0);
+	FMT(ARGB8888,	8888,		CFG_SWAPRB);
+	FMT(ABGR8888,	8888,		0);
+	FMT(YUYV,	422PACK,	CFG_YUV2RGB | CFG_SWAPYU | CFG_SWAPUV);
+	FMT(UYVY,	422PACK,	CFG_YUV2RGB);
+	FMT(VYUY,	422PACK,	CFG_YUV2RGB | CFG_SWAPUV);
+	FMT(YVYU,	422PACK,	CFG_YUV2RGB | CFG_SWAPYU);
+	FMT(YUV422,	422,		CFG_YUV2RGB);
+	FMT(YVU422,	422,		CFG_YUV2RGB | CFG_SWAPUV);
+	FMT(YUV420,	420,		CFG_YUV2RGB);
+	FMT(YVU420,	420,		CFG_YUV2RGB | CFG_SWAPUV);
+	FMT(C8,		PSEUDO8,	0);
+#undef FMT
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	dfb = kzalloc(sizeof(*dfb), GFP_KERNEL);
+	if (!dfb) {
+		DRM_ERROR("failed to allocate Armada fb object\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dfb->fmt = format;
+	dfb->mod = config;
+	dfb->obj = obj;
+
+	drm_helper_mode_fill_fb_struct(&dfb->fb, mode);
+
+	ret = drm_framebuffer_init(dev, &dfb->fb, &armada_fb_funcs);
+	if (ret) {
+		kfree(dfb);
+		return ERR_PTR(ret);
+	}
+
+	/*
+	 * Take a reference on our object as we're successful - the
+	 * caller already holds a reference, which keeps us safe for
+	 * the above call, but the caller will drop their reference
+	 * to it.  Hence we need to take our own reference.
+	 */
+	drm_gem_object_reference(&obj->obj);
+
+	return dfb;
+}
+
+static struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
+	struct drm_file *dfile, struct drm_mode_fb_cmd2 *mode)
+{
+	struct armada_gem_object *obj;
+	struct armada_framebuffer *dfb;
+	int ret;
+
+	DRM_DEBUG_DRIVER("w%u h%u pf%08x f%u p%u,%u,%u\n",
+		mode->width, mode->height, mode->pixel_format,
+		mode->flags, mode->pitches[0], mode->pitches[1],
+		mode->pitches[2]);
+
+	/* We can only handle a single plane at the moment */
+	if (drm_format_num_planes(mode->pixel_format) > 1 &&
+	    (mode->handles[0] != mode->handles[1] ||
+	     mode->handles[0] != mode->handles[2])) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	obj = armada_gem_object_lookup(dev, dfile, mode->handles[0]);
+	if (!obj) {
+		ret = -ENOENT;
+		goto err;
+	}
+
+	if (obj->obj.import_attach && !obj->sgt) {
+		ret = armada_gem_map_import(obj);
+		if (ret)
+			goto err_unref;
+	}
+
+	/* Framebuffer objects must have a valid device address for scanout */
+	if (obj->dev_addr == DMA_ERROR_CODE) {
+		ret = -EINVAL;
+		goto err_unref;
+	}
+
+	dfb = armada_framebuffer_create(dev, mode, obj);
+	if (IS_ERR(dfb)) {
+		ret = PTR_ERR(dfb);
+		goto err;
+	}
+
+	drm_gem_object_unreference_unlocked(&obj->obj);
+
+	return &dfb->fb;
+
+ err_unref:
+	drm_gem_object_unreference_unlocked(&obj->obj);
+ err:
+	DRM_ERROR("failed to initialize framebuffer: %d\n", ret);
+	return ERR_PTR(ret);
+}
+
+static void armada_output_poll_changed(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct drm_fb_helper *fbh = priv->fbdev;
+
+	if (fbh)
+		drm_fb_helper_hotplug_event(fbh);
+}
+
+const struct drm_mode_config_funcs armada_drm_mode_config_funcs = {
+	.fb_create		= armada_fb_create,
+	.output_poll_changed	= armada_output_poll_changed,
+};
diff --git a/drivers/gpu/drm/armada/armada_fb.h b/drivers/gpu/drm/armada/armada_fb.h
new file mode 100644
index 0000000..ce3f12e
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_fb.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_FB_H
+#define ARMADA_FB_H
+
+struct armada_framebuffer {
+	struct drm_framebuffer	fb;
+	struct armada_gem_object *obj;
+	uint8_t			fmt;
+	uint8_t			mod;
+};
+#define drm_fb_to_armada_fb(dfb) \
+	container_of(dfb, struct armada_framebuffer, fb)
+#define drm_fb_obj(fb) drm_fb_to_armada_fb(fb)->obj
+
+struct armada_framebuffer *armada_framebuffer_create(struct drm_device *,
+	struct drm_mode_fb_cmd2 *, struct armada_gem_object *);
+
+#endif
diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
new file mode 100644
index 0000000..dd5ea77
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_fbdev.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Written from the i915 driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_fb.h"
+#include "armada_gem.h"
+
+static /*const*/ struct fb_ops armada_fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= drm_fb_helper_check_var,
+	.fb_set_par	= drm_fb_helper_set_par,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_pan_display	= drm_fb_helper_pan_display,
+	.fb_blank	= drm_fb_helper_blank,
+	.fb_setcmap	= drm_fb_helper_setcmap,
+	.fb_debug_enter	= drm_fb_helper_debug_enter,
+	.fb_debug_leave	= drm_fb_helper_debug_leave,
+};
+
+static int armada_fb_create(struct drm_fb_helper *fbh,
+	struct drm_fb_helper_surface_size *sizes)
+{
+	struct drm_device *dev = fbh->dev;
+	struct drm_mode_fb_cmd2 mode;
+	struct armada_framebuffer *dfb;
+	struct armada_gem_object *obj;
+	struct fb_info *info;
+	int size, ret;
+	void *ptr;
+
+	memset(&mode, 0, sizeof(mode));
+	mode.width = sizes->surface_width;
+	mode.height = sizes->surface_height;
+	mode.pitches[0] = armada_pitch(mode.width, sizes->surface_bpp);
+	mode.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+					sizes->surface_depth);
+
+	size = mode.pitches[0] * mode.height;
+	obj = armada_gem_alloc_private_object(dev, size);
+	if (!obj) {
+		DRM_ERROR("failed to allocate fb memory\n");
+		return -ENOMEM;
+	}
+
+	ret = armada_gem_linear_back(dev, obj);
+	if (ret) {
+		drm_gem_object_unreference_unlocked(&obj->obj);
+		return ret;
+	}
+
+	ptr = armada_gem_map_object(dev, obj);
+	if (!ptr) {
+		drm_gem_object_unreference_unlocked(&obj->obj);
+		return -ENOMEM;
+	}
+
+	dfb = armada_framebuffer_create(dev, &mode, obj);
+
+	/*
+	 * A reference is now held by the framebuffer object if
+	 * successful, otherwise this drops the ref for the error path.
+	 */
+	drm_gem_object_unreference_unlocked(&obj->obj);
+
+	if (IS_ERR(dfb))
+		return PTR_ERR(dfb);
+
+	info = framebuffer_alloc(0, dev->dev);
+	if (!info) {
+		ret = -ENOMEM;
+		goto err_fballoc;
+	}
+
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret) {
+		ret = -ENOMEM;
+		goto err_fbcmap;
+	}
+
+	strlcpy(info->fix.id, "armada-drmfb", sizeof(info->fix.id));
+	info->par = fbh;
+	info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
+	info->fbops = &armada_fb_ops;
+	info->fix.smem_start = obj->phys_addr;
+	info->fix.smem_len = obj->obj.size;
+	info->screen_size = obj->obj.size;
+	info->screen_base = ptr;
+	fbh->fb = &dfb->fb;
+	fbh->fbdev = info;
+	drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth);
+	drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height);
+
+	DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08x\n",
+		dfb->fb.width, dfb->fb.height,
+		dfb->fb.bits_per_pixel, obj->phys_addr);
+
+	return 0;
+
+ err_fbcmap:
+	framebuffer_release(info);
+ err_fballoc:
+	dfb->fb.funcs->destroy(&dfb->fb);
+	return ret;
+}
+
+static int armada_fb_probe(struct drm_fb_helper *fbh,
+	struct drm_fb_helper_surface_size *sizes)
+{
+	int ret = 0;
+
+	if (!fbh->fb) {
+		ret = armada_fb_create(fbh, sizes);
+		if (ret == 0)
+			ret = 1;
+	}
+	return ret;
+}
+
+static struct drm_fb_helper_funcs armada_fb_helper_funcs = {
+	.gamma_set	= armada_drm_crtc_gamma_set,
+	.gamma_get	= armada_drm_crtc_gamma_get,
+	.fb_probe	= armada_fb_probe,
+};
+
+int armada_fbdev_init(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct drm_fb_helper *fbh;
+	int ret;
+
+	fbh = devm_kzalloc(dev->dev, sizeof(*fbh), GFP_KERNEL);
+	if (!fbh)
+		return -ENOMEM;
+
+	priv->fbdev = fbh;
+
+	fbh->funcs = &armada_fb_helper_funcs;
+
+	ret = drm_fb_helper_init(dev, fbh, 1, 1);
+	if (ret) {
+		DRM_ERROR("failed to initialize drm fb helper\n");
+		goto err_fb_helper;
+	}
+
+	ret = drm_fb_helper_single_add_all_connectors(fbh);
+	if (ret) {
+		DRM_ERROR("failed to add fb connectors\n");
+		goto err_fb_setup;
+	}
+
+	ret = drm_fb_helper_initial_config(fbh, 32);
+	if (ret) {
+		DRM_ERROR("failed to set initial config\n");
+		goto err_fb_setup;
+	}
+
+	return 0;
+ err_fb_setup:
+	drm_fb_helper_fini(fbh);
+ err_fb_helper:
+	priv->fbdev = NULL;
+	return ret;
+}
+
+void armada_fbdev_fini(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct drm_fb_helper *fbh = priv->fbdev;
+
+	if (fbh) {
+		struct fb_info *info = fbh->fbdev;
+
+		if (info) {
+			unregister_framebuffer(info);
+			if (info->cmap.len)
+				fb_dealloc_cmap(&info->cmap);
+			framebuffer_release(info);
+		}
+
+		if (fbh->fb)
+			fbh->fb->funcs->destroy(fbh->fb);
+
+		drm_fb_helper_fini(fbh);
+
+		priv->fbdev = NULL;
+	}
+}
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
new file mode 100644
index 0000000..c865a9a
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -0,0 +1,616 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/dma-buf.h>
+#include <linux/dma-mapping.h>
+#include <linux/shmem_fs.h>
+#include <drm/drmP.h>
+#include "armada_drm.h"
+#include "armada_gem.h"
+#include <drm/armada_drm.h>
+#include "armada_ioctlP.h"
+
+static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct armada_gem_object *obj = drm_to_armada_gem(vma->vm_private_data);
+	unsigned long addr = (unsigned long)vmf->virtual_address;
+	unsigned long pfn = obj->phys_addr >> PAGE_SHIFT;
+	int ret;
+
+	pfn += (addr - vma->vm_start) >> PAGE_SHIFT;
+	ret = vm_insert_pfn(vma, addr, pfn);
+
+	switch (ret) {
+	case -EIO:
+	case -EAGAIN:
+		set_need_resched();
+	case 0:
+	case -ERESTARTSYS:
+	case -EINTR:
+	case -EBUSY:
+		return VM_FAULT_NOPAGE;
+	case -ENOMEM:
+		return VM_FAULT_OOM;
+	default:
+		return VM_FAULT_SIGBUS;
+	}
+}
+
+const struct vm_operations_struct armada_gem_vm_ops = {
+	.fault	= armada_gem_vm_fault,
+	.open	= drm_gem_vm_open,
+	.close	= drm_gem_vm_close,
+};
+
+static size_t roundup_gem_size(size_t size)
+{
+	return roundup(size, PAGE_SIZE);
+}
+
+/* dev->struct_mutex is held here */
+void armada_gem_free_object(struct drm_gem_object *obj)
+{
+	struct armada_gem_object *dobj = drm_to_armada_gem(obj);
+
+	DRM_DEBUG_DRIVER("release obj %p\n", dobj);
+
+	drm_gem_free_mmap_offset(&dobj->obj);
+
+	if (dobj->page) {
+		/* page backed memory */
+		unsigned int order = get_order(dobj->obj.size);
+		__free_pages(dobj->page, order);
+	} else if (dobj->linear) {
+		/* linear backed memory */
+		drm_mm_remove_node(dobj->linear);
+		kfree(dobj->linear);
+		if (dobj->addr)
+			iounmap(dobj->addr);
+	}
+
+	if (dobj->obj.import_attach) {
+		/* We only ever display imported data */
+		dma_buf_unmap_attachment(dobj->obj.import_attach, dobj->sgt,
+					 DMA_TO_DEVICE);
+		drm_prime_gem_destroy(&dobj->obj, NULL);
+	}
+
+	drm_gem_object_release(&dobj->obj);
+
+	kfree(dobj);
+}
+
+int
+armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj)
+{
+	struct armada_private *priv = dev->dev_private;
+	size_t size = obj->obj.size;
+
+	if (obj->page || obj->linear)
+		return 0;
+
+	/*
+	 * If it is a small allocation (typically cursor, which will
+	 * be 32x64 or 64x32 ARGB pixels) try to get it from the system.
+	 * Framebuffers will never be this small (our minimum size for
+	 * framebuffers is larger than this anyway.)  Such objects are
+	 * only accessed by the CPU so we don't need any special handing
+	 * here.
+	 */
+	if (size <= 8192) {
+		unsigned int order = get_order(size);
+		struct page *p = alloc_pages(GFP_KERNEL, order);
+
+		if (p) {
+			obj->addr = page_address(p);
+			obj->phys_addr = page_to_phys(p);
+			obj->page = p;
+
+			memset(obj->addr, 0, PAGE_ALIGN(size));
+		}
+	}
+
+	/*
+	 * We could grab something from CMA if it's enabled, but that
+	 * involves building in a problem:
+	 *
+	 * CMA's interface uses dma_alloc_coherent(), which provides us
+	 * with an CPU virtual address and a device address.
+	 *
+	 * The CPU virtual address may be either an address in the kernel
+	 * direct mapped region (for example, as it would be on x86) or
+	 * it may be remapped into another part of kernel memory space
+	 * (eg, as it would be on ARM.)  This means virt_to_phys() on the
+	 * returned virtual address is invalid depending on the architecture
+	 * implementation.
+	 *
+	 * The device address may also not be a physical address; it may
+	 * be that there is some kind of remapping between the device and
+	 * system RAM, which makes the use of the device address also
+	 * unsafe to re-use as a physical address.
+	 *
+	 * This makes DRM usage of dma_alloc_coherent() in a generic way
+	 * at best very questionable and unsafe.
+	 */
+
+	/* Otherwise, grab it from our linear allocation */
+	if (!obj->page) {
+		struct drm_mm_node *node;
+		unsigned align = min_t(unsigned, size, SZ_2M);
+		void __iomem *ptr;
+		int ret;
+
+		node = kzalloc(sizeof(*node), GFP_KERNEL);
+		if (!node)
+			return -ENOSPC;
+
+		mutex_lock(&dev->struct_mutex);
+		ret = drm_mm_insert_node(&priv->linear, node, size, align,
+					 DRM_MM_SEARCH_DEFAULT);
+		mutex_unlock(&dev->struct_mutex);
+		if (ret) {
+			kfree(node);
+			return ret;
+		}
+
+		obj->linear = node;
+
+		/* Ensure that the memory we're returning is cleared. */
+		ptr = ioremap_wc(obj->linear->start, size);
+		if (!ptr) {
+			mutex_lock(&dev->struct_mutex);
+			drm_mm_remove_node(obj->linear);
+			mutex_unlock(&dev->struct_mutex);
+			kfree(obj->linear);
+			obj->linear = NULL;
+			return -ENOMEM;
+		}
+
+		memset_io(ptr, 0, size);
+		iounmap(ptr);
+
+		obj->phys_addr = obj->linear->start;
+		obj->dev_addr = obj->linear->start;
+	}
+
+	DRM_DEBUG_DRIVER("obj %p phys %#x dev %#x\n",
+			 obj, obj->phys_addr, obj->dev_addr);
+
+	return 0;
+}
+
+void *
+armada_gem_map_object(struct drm_device *dev, struct armada_gem_object *dobj)
+{
+	/* only linear objects need to be ioremap'd */
+	if (!dobj->addr && dobj->linear)
+		dobj->addr = ioremap_wc(dobj->phys_addr, dobj->obj.size);
+	return dobj->addr;
+}
+
+struct armada_gem_object *
+armada_gem_alloc_private_object(struct drm_device *dev, size_t size)
+{
+	struct armada_gem_object *obj;
+
+	size = roundup_gem_size(size);
+
+	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+	if (!obj)
+		return NULL;
+
+	drm_gem_private_object_init(dev, &obj->obj, size);
+	obj->dev_addr = DMA_ERROR_CODE;
+
+	DRM_DEBUG_DRIVER("alloc private obj %p size %zu\n", obj, size);
+
+	return obj;
+}
+
+struct armada_gem_object *armada_gem_alloc_object(struct drm_device *dev,
+	size_t size)
+{
+	struct armada_gem_object *obj;
+	struct address_space *mapping;
+
+	size = roundup_gem_size(size);
+
+	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+	if (!obj)
+		return NULL;
+
+	if (drm_gem_object_init(dev, &obj->obj, size)) {
+		kfree(obj);
+		return NULL;
+	}
+
+	obj->dev_addr = DMA_ERROR_CODE;
+
+	mapping = obj->obj.filp->f_path.dentry->d_inode->i_mapping;
+	mapping_set_gfp_mask(mapping, GFP_HIGHUSER | __GFP_RECLAIMABLE);
+
+	DRM_DEBUG_DRIVER("alloc obj %p size %zu\n", obj, size);
+
+	return obj;
+}
+
+/* Dumb alloc support */
+int armada_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
+	struct drm_mode_create_dumb *args)
+{
+	struct armada_gem_object *dobj;
+	u32 handle;
+	size_t size;
+	int ret;
+
+	args->pitch = armada_pitch(args->width, args->bpp);
+	args->size = size = args->pitch * args->height;
+
+	dobj = armada_gem_alloc_private_object(dev, size);
+	if (dobj == NULL)
+		return -ENOMEM;
+
+	ret = armada_gem_linear_back(dev, dobj);
+	if (ret)
+		goto err;
+
+	ret = drm_gem_handle_create(file, &dobj->obj, &handle);
+	if (ret)
+		goto err;
+
+	args->handle = handle;
+
+	/* drop reference from allocate - handle holds it now */
+	DRM_DEBUG_DRIVER("obj %p size %zu handle %#x\n", dobj, size, handle);
+ err:
+	drm_gem_object_unreference_unlocked(&dobj->obj);
+	return ret;
+}
+
+int armada_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
+	uint32_t handle, uint64_t *offset)
+{
+	struct armada_gem_object *obj;
+	int ret = 0;
+
+	mutex_lock(&dev->struct_mutex);
+	obj = armada_gem_object_lookup(dev, file, handle);
+	if (!obj) {
+		DRM_ERROR("failed to lookup gem object\n");
+		ret = -EINVAL;
+		goto err_unlock;
+	}
+
+	/* Don't allow imported objects to be mapped */
+	if (obj->obj.import_attach) {
+		ret = -EINVAL;
+		goto err_unlock;
+	}
+
+	ret = drm_gem_create_mmap_offset(&obj->obj);
+	if (ret == 0) {
+		*offset = drm_vma_node_offset_addr(&obj->obj.vma_node);
+		DRM_DEBUG_DRIVER("handle %#x offset %llx\n", handle, *offset);
+	}
+
+	drm_gem_object_unreference(&obj->obj);
+ err_unlock:
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+int armada_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
+	uint32_t handle)
+{
+	return drm_gem_handle_delete(file, handle);
+}
+
+/* Private driver gem ioctls */
+int armada_gem_create_ioctl(struct drm_device *dev, void *data,
+	struct drm_file *file)
+{
+	struct drm_armada_gem_create *args = data;
+	struct armada_gem_object *dobj;
+	size_t size;
+	u32 handle;
+	int ret;
+
+	if (args->size == 0)
+		return -ENOMEM;
+
+	size = args->size;
+
+	dobj = armada_gem_alloc_object(dev, size);
+	if (dobj == NULL)
+		return -ENOMEM;
+
+	ret = drm_gem_handle_create(file, &dobj->obj, &handle);
+	if (ret)
+		goto err;
+
+	args->handle = handle;
+
+	/* drop reference from allocate - handle holds it now */
+	DRM_DEBUG_DRIVER("obj %p size %zu handle %#x\n", dobj, size, handle);
+ err:
+	drm_gem_object_unreference_unlocked(&dobj->obj);
+	return ret;
+}
+
+/* Map a shmem-backed object into process memory space */
+int armada_gem_mmap_ioctl(struct drm_device *dev, void *data,
+	struct drm_file *file)
+{
+	struct drm_armada_gem_mmap *args = data;
+	struct armada_gem_object *dobj;
+	unsigned long addr;
+
+	dobj = armada_gem_object_lookup(dev, file, args->handle);
+	if (dobj == NULL)
+		return -ENOENT;
+
+	if (!dobj->obj.filp) {
+		drm_gem_object_unreference(&dobj->obj);
+		return -EINVAL;
+	}
+
+	addr = vm_mmap(dobj->obj.filp, 0, args->size, PROT_READ | PROT_WRITE,
+		       MAP_SHARED, args->offset);
+	drm_gem_object_unreference(&dobj->obj);
+	if (IS_ERR_VALUE(addr))
+		return addr;
+
+	args->addr = addr;
+
+	return 0;
+}
+
+int armada_gem_pwrite_ioctl(struct drm_device *dev, void *data,
+	struct drm_file *file)
+{
+	struct drm_armada_gem_pwrite *args = data;
+	struct armada_gem_object *dobj;
+	char __user *ptr;
+	int ret;
+
+	DRM_DEBUG_DRIVER("handle %u off %u size %u ptr 0x%llx\n",
+		args->handle, args->offset, args->size, args->ptr);
+
+	if (args->size == 0)
+		return 0;
+
+	ptr = (char __user *)(uintptr_t)args->ptr;
+
+	if (!access_ok(VERIFY_READ, ptr, args->size))
+		return -EFAULT;
+
+	ret = fault_in_multipages_readable(ptr, args->size);
+	if (ret)
+		return ret;
+
+	dobj = armada_gem_object_lookup(dev, file, args->handle);
+	if (dobj == NULL)
+		return -ENOENT;
+
+	/* Must be a kernel-mapped object */
+	if (!dobj->addr)
+		return -EINVAL;
+
+	if (args->offset > dobj->obj.size ||
+	    args->size > dobj->obj.size - args->offset) {
+		DRM_ERROR("invalid size: object size %u\n", dobj->obj.size);
+		ret = -EINVAL;
+		goto unref;
+	}
+
+	if (copy_from_user(dobj->addr + args->offset, ptr, args->size)) {
+		ret = -EFAULT;
+	} else if (dobj->update) {
+		dobj->update(dobj->update_data);
+		ret = 0;
+	}
+
+ unref:
+	drm_gem_object_unreference_unlocked(&dobj->obj);
+	return ret;
+}
+
+/* Prime support */
+struct sg_table *
+armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
+	enum dma_data_direction dir)
+{
+	struct drm_gem_object *obj = attach->dmabuf->priv;
+	struct armada_gem_object *dobj = drm_to_armada_gem(obj);
+	struct scatterlist *sg;
+	struct sg_table *sgt;
+	int i, num;
+
+	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt)
+		return NULL;
+
+	if (dobj->obj.filp) {
+		struct address_space *mapping;
+		gfp_t gfp;
+		int count;
+
+		count = dobj->obj.size / PAGE_SIZE;
+		if (sg_alloc_table(sgt, count, GFP_KERNEL))
+			goto free_sgt;
+
+		mapping = file_inode(dobj->obj.filp)->i_mapping;
+		gfp = mapping_gfp_mask(mapping);
+
+		for_each_sg(sgt->sgl, sg, count, i) {
+			struct page *page;
+
+			page = shmem_read_mapping_page_gfp(mapping, i, gfp);
+			if (IS_ERR(page)) {
+				num = i;
+				goto release;
+			}
+
+			sg_set_page(sg, page, PAGE_SIZE, 0);
+		}
+
+		if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0) {
+			num = sgt->nents;
+			goto release;
+		}
+	} else if (dobj->page) {
+		/* Single contiguous page */
+		if (sg_alloc_table(sgt, 1, GFP_KERNEL))
+			goto free_sgt;
+
+		sg_set_page(sgt->sgl, dobj->page, dobj->obj.size, 0);
+
+		if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0)
+			goto free_table;
+	} else if (dobj->linear) {
+		/* Single contiguous physical region - no struct page */
+		if (sg_alloc_table(sgt, 1, GFP_KERNEL))
+			goto free_sgt;
+		sg_dma_address(sgt->sgl) = dobj->dev_addr;
+		sg_dma_len(sgt->sgl) = dobj->obj.size;
+	} else {
+		goto free_sgt;
+	}
+	return sgt;
+
+ release:
+	for_each_sg(sgt->sgl, sg, num, i)
+		page_cache_release(sg_page(sg));
+ free_table:
+	sg_free_table(sgt);
+ free_sgt:
+	kfree(sgt);
+	return NULL;
+}
+
+static void armada_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
+	struct sg_table *sgt, enum dma_data_direction dir)
+{
+	struct drm_gem_object *obj = attach->dmabuf->priv;
+	struct armada_gem_object *dobj = drm_to_armada_gem(obj);
+	int i;
+
+	if (!dobj->linear)
+		dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
+
+	if (dobj->obj.filp) {
+		struct scatterlist *sg;
+		for_each_sg(sgt->sgl, sg, sgt->nents, i)
+			page_cache_release(sg_page(sg));
+	}
+
+	sg_free_table(sgt);
+	kfree(sgt);
+}
+
+static void *armada_gem_dmabuf_no_kmap(struct dma_buf *buf, unsigned long n)
+{
+	return NULL;
+}
+
+static void
+armada_gem_dmabuf_no_kunmap(struct dma_buf *buf, unsigned long n, void *addr)
+{
+}
+
+static int
+armada_gem_dmabuf_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
+{
+	return -EINVAL;
+}
+
+static const struct dma_buf_ops armada_gem_prime_dmabuf_ops = {
+	.map_dma_buf	= armada_gem_prime_map_dma_buf,
+	.unmap_dma_buf	= armada_gem_prime_unmap_dma_buf,
+	.release	= drm_gem_dmabuf_release,
+	.kmap_atomic	= armada_gem_dmabuf_no_kmap,
+	.kunmap_atomic	= armada_gem_dmabuf_no_kunmap,
+	.kmap		= armada_gem_dmabuf_no_kmap,
+	.kunmap		= armada_gem_dmabuf_no_kunmap,
+	.mmap		= armada_gem_dmabuf_mmap,
+};
+
+struct dma_buf *
+armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj,
+	int flags)
+{
+	return dma_buf_export(obj, &armada_gem_prime_dmabuf_ops, obj->size,
+			      O_RDWR);
+}
+
+struct drm_gem_object *
+armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
+{
+	struct dma_buf_attachment *attach;
+	struct armada_gem_object *dobj;
+
+	if (buf->ops == &armada_gem_prime_dmabuf_ops) {
+		struct drm_gem_object *obj = buf->priv;
+		if (obj->dev == dev) {
+			/*
+			 * Importing our own dmabuf(s) increases the
+			 * refcount on the gem object itself.
+			 */
+			drm_gem_object_reference(obj);
+			dma_buf_put(buf);
+			return obj;
+		}
+	}
+
+	attach = dma_buf_attach(buf, dev->dev);
+	if (IS_ERR(attach))
+		return ERR_CAST(attach);
+
+	dobj = armada_gem_alloc_private_object(dev, buf->size);
+	if (!dobj) {
+		dma_buf_detach(buf, attach);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dobj->obj.import_attach = attach;
+
+	/*
+	 * Don't call dma_buf_map_attachment() here - it maps the
+	 * scatterlist immediately for DMA, and this is not always
+	 * an appropriate thing to do.
+	 */
+	return &dobj->obj;
+}
+
+int armada_gem_map_import(struct armada_gem_object *dobj)
+{
+	int ret;
+
+	dobj->sgt = dma_buf_map_attachment(dobj->obj.import_attach,
+					  DMA_TO_DEVICE);
+	if (!dobj->sgt) {
+		DRM_ERROR("dma_buf_map_attachment() returned NULL\n");
+		return -EINVAL;
+	}
+	if (IS_ERR(dobj->sgt)) {
+		ret = PTR_ERR(dobj->sgt);
+		dobj->sgt = NULL;
+		DRM_ERROR("dma_buf_map_attachment() error: %d\n", ret);
+		return ret;
+	}
+	if (dobj->sgt->nents > 1) {
+		DRM_ERROR("dma_buf_map_attachment() returned an (unsupported) scattered list\n");
+		return -EINVAL;
+	}
+	if (sg_dma_len(dobj->sgt->sgl) < dobj->obj.size) {
+		DRM_ERROR("dma_buf_map_attachment() returned a small buffer\n");
+		return -EINVAL;
+	}
+	dobj->dev_addr = sg_dma_address(dobj->sgt->sgl);
+	return 0;
+}
diff --git a/drivers/gpu/drm/armada/armada_gem.h b/drivers/gpu/drm/armada/armada_gem.h
new file mode 100644
index 0000000..00b6cd4
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_gem.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_GEM_H
+#define ARMADA_GEM_H
+
+/* GEM */
+struct armada_gem_object {
+	struct drm_gem_object	obj;
+	void			*addr;
+	phys_addr_t		phys_addr;
+	resource_size_t		dev_addr;
+	struct drm_mm_node	*linear;	/* for linear backed */
+	struct page		*page;		/* for page backed */
+	struct sg_table		*sgt;		/* for imported */
+	void			(*update)(void *);
+	void			*update_data;
+};
+
+extern const struct vm_operations_struct armada_gem_vm_ops;
+
+#define drm_to_armada_gem(o) container_of(o, struct armada_gem_object, obj)
+
+void armada_gem_free_object(struct drm_gem_object *);
+int armada_gem_linear_back(struct drm_device *, struct armada_gem_object *);
+void *armada_gem_map_object(struct drm_device *, struct armada_gem_object *);
+struct armada_gem_object *armada_gem_alloc_private_object(struct drm_device *,
+	size_t);
+int armada_gem_dumb_create(struct drm_file *, struct drm_device *,
+	struct drm_mode_create_dumb *);
+int armada_gem_dumb_map_offset(struct drm_file *, struct drm_device *,
+	uint32_t, uint64_t *);
+int armada_gem_dumb_destroy(struct drm_file *, struct drm_device *,
+	uint32_t);
+struct dma_buf *armada_gem_prime_export(struct drm_device *dev,
+	struct drm_gem_object *obj, int flags);
+struct drm_gem_object *armada_gem_prime_import(struct drm_device *,
+	struct dma_buf *);
+int armada_gem_map_import(struct armada_gem_object *);
+
+static inline struct armada_gem_object *armada_gem_object_lookup(
+	struct drm_device *dev, struct drm_file *dfile, unsigned handle)
+{
+	struct drm_gem_object *obj = drm_gem_object_lookup(dev, dfile, handle);
+
+	return obj ? drm_to_armada_gem(obj) : NULL;
+}
+#endif
diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
new file mode 100644
index 0000000..216a4b5
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_hw.h
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Rewritten from the dovefb driver, and Armada510 manuals.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_HW_H
+#define ARMADA_HW_H
+
+/*
+ * Note: the following registers are written from IRQ context:
+ *  LCD_SPU_V_PORCH, LCD_SPU_ADV_REG, LCD_SPUT_V_H_TOTAL
+ *  LCD_SPU_DMA_START_ADDR_[YUV][01], LCD_SPU_DMA_PITCH_YC,
+ *  LCD_SPU_DMA_PITCH_UV, LCD_SPU_DMA_OVSA_HPXL_VLN,
+ *  LCD_SPU_DMA_HPXL_VLN, LCD_SPU_DZM_HPXL_VLN, LCD_SPU_DMA_CTRL0
+ */
+enum {
+	LCD_SPU_ADV_REG			= 0x0084,	/* Armada 510 */
+	LCD_SPU_DMA_START_ADDR_Y0	= 0x00c0,
+	LCD_SPU_DMA_START_ADDR_U0	= 0x00c4,
+	LCD_SPU_DMA_START_ADDR_V0	= 0x00c8,
+	LCD_CFG_DMA_START_ADDR_0	= 0x00cc,
+	LCD_SPU_DMA_START_ADDR_Y1	= 0x00d0,
+	LCD_SPU_DMA_START_ADDR_U1	= 0x00d4,
+	LCD_SPU_DMA_START_ADDR_V1	= 0x00d8,
+	LCD_CFG_DMA_START_ADDR_1	= 0x00dc,
+	LCD_SPU_DMA_PITCH_YC		= 0x00e0,
+	LCD_SPU_DMA_PITCH_UV		= 0x00e4,
+	LCD_SPU_DMA_OVSA_HPXL_VLN	= 0x00e8,
+	LCD_SPU_DMA_HPXL_VLN		= 0x00ec,
+	LCD_SPU_DZM_HPXL_VLN		= 0x00f0,
+	LCD_CFG_GRA_START_ADDR0		= 0x00f4,
+	LCD_CFG_GRA_START_ADDR1		= 0x00f8,
+	LCD_CFG_GRA_PITCH		= 0x00fc,
+	LCD_SPU_GRA_OVSA_HPXL_VLN	= 0x0100,
+	LCD_SPU_GRA_HPXL_VLN		= 0x0104,
+	LCD_SPU_GZM_HPXL_VLN		= 0x0108,
+	LCD_SPU_HWC_OVSA_HPXL_VLN	= 0x010c,
+	LCD_SPU_HWC_HPXL_VLN		= 0x0110,
+	LCD_SPUT_V_H_TOTAL		= 0x0114,
+	LCD_SPU_V_H_ACTIVE		= 0x0118,
+	LCD_SPU_H_PORCH			= 0x011c,
+	LCD_SPU_V_PORCH			= 0x0120,
+	LCD_SPU_BLANKCOLOR		= 0x0124,
+	LCD_SPU_ALPHA_COLOR1		= 0x0128,
+	LCD_SPU_ALPHA_COLOR2		= 0x012c,
+	LCD_SPU_COLORKEY_Y		= 0x0130,
+	LCD_SPU_COLORKEY_U		= 0x0134,
+	LCD_SPU_COLORKEY_V		= 0x0138,
+	LCD_CFG_RDREG4F			= 0x013c,	/* Armada 510 */
+	LCD_SPU_SPI_RXDATA		= 0x0140,
+	LCD_SPU_ISA_RXDATA		= 0x0144,
+	LCD_SPU_HWC_RDDAT		= 0x0158,
+	LCD_SPU_GAMMA_RDDAT		= 0x015c,
+	LCD_SPU_PALETTE_RDDAT		= 0x0160,
+	LCD_SPU_IOPAD_IN		= 0x0178,
+	LCD_CFG_RDREG5F			= 0x017c,
+	LCD_SPU_SPI_CTRL		= 0x0180,
+	LCD_SPU_SPI_TXDATA		= 0x0184,
+	LCD_SPU_SMPN_CTRL		= 0x0188,
+	LCD_SPU_DMA_CTRL0		= 0x0190,
+	LCD_SPU_DMA_CTRL1		= 0x0194,
+	LCD_SPU_SRAM_CTRL		= 0x0198,
+	LCD_SPU_SRAM_WRDAT		= 0x019c,
+	LCD_SPU_SRAM_PARA0		= 0x01a0,	/* Armada 510 */
+	LCD_SPU_SRAM_PARA1		= 0x01a4,
+	LCD_CFG_SCLK_DIV		= 0x01a8,
+	LCD_SPU_CONTRAST		= 0x01ac,
+	LCD_SPU_SATURATION		= 0x01b0,
+	LCD_SPU_CBSH_HUE		= 0x01b4,
+	LCD_SPU_DUMB_CTRL		= 0x01b8,
+	LCD_SPU_IOPAD_CONTROL		= 0x01bc,
+	LCD_SPU_IRQ_ENA			= 0x01c0,
+	LCD_SPU_IRQ_ISR			= 0x01c4,
+};
+
+/* For LCD_SPU_ADV_REG */
+enum {
+	ADV_VSYNC_L_OFF	= 0xfff << 20,
+	ADV_GRACOLORKEY	= 1 << 19,
+	ADV_VIDCOLORKEY	= 1 << 18,
+	ADV_HWC32BLEND	= 1 << 15,
+	ADV_HWC32ARGB	= 1 << 14,
+	ADV_HWC32ENABLE	= 1 << 13,
+	ADV_VSYNCOFFEN	= 1 << 12,
+	ADV_VSYNC_H_OFF	= 0xfff << 0,
+};
+
+enum {
+	CFG_565		= 0,
+	CFG_1555	= 1,
+	CFG_888PACK	= 2,
+	CFG_X888	= 3,
+	CFG_8888	= 4,
+	CFG_422PACK	= 5,
+	CFG_422		= 6,
+	CFG_420		= 7,
+	CFG_PSEUDO4	= 9,
+	CFG_PSEUDO8	= 10,
+	CFG_SWAPRB	= 1 << 4,
+	CFG_SWAPUV	= 1 << 3,
+	CFG_SWAPYU	= 1 << 2,
+	CFG_YUV2RGB	= 1 << 1,
+};
+
+/* For LCD_SPU_DMA_CTRL0 */
+enum {
+	CFG_NOBLENDING	= 1 << 31,
+	CFG_GAMMA_ENA	= 1 << 30,
+	CFG_CBSH_ENA	= 1 << 29,
+	CFG_PALETTE_ENA	= 1 << 28,
+	CFG_ARBFAST_ENA	= 1 << 27,
+	CFG_HWC_1BITMOD	= 1 << 26,
+	CFG_HWC_1BITENA	= 1 << 25,
+	CFG_HWC_ENA	= 1 << 24,
+	CFG_DMAFORMAT	= 0xf << 20,
+#define	CFG_DMA_FMT(x)	((x) << 20)
+	CFG_GRAFORMAT	= 0xf << 16,
+#define	CFG_GRA_FMT(x)	((x) << 16)
+#define CFG_GRA_MOD(x)	((x) << 8)
+	CFG_GRA_FTOGGLE	= 1 << 15,
+	CFG_GRA_HSMOOTH	= 1 << 14,
+	CFG_GRA_TSTMODE	= 1 << 13,
+	CFG_GRA_ENA	= 1 << 8,
+#define CFG_DMA_MOD(x)	((x) << 0)
+	CFG_DMA_FTOGGLE	= 1 << 7,
+	CFG_DMA_HSMOOTH	= 1 << 6,
+	CFG_DMA_TSTMODE	= 1 << 5,
+	CFG_DMA_ENA	= 1 << 0,
+};
+
+enum {
+	CKMODE_DISABLE	= 0,
+	CKMODE_Y	= 1,
+	CKMODE_U	= 2,
+	CKMODE_RGB	= 3,
+	CKMODE_V	= 4,
+	CKMODE_R	= 5,
+	CKMODE_G	= 6,
+	CKMODE_B	= 7,
+};
+
+/* For LCD_SPU_DMA_CTRL1 */
+enum {
+	CFG_FRAME_TRIG		= 1 << 31,
+	CFG_VSYNC_INV		= 1 << 27,
+	CFG_CKMODE_MASK		= 0x7 << 24,
+#define CFG_CKMODE(x)		((x) << 24)
+	CFG_CARRY		= 1 << 23,
+	CFG_GATED_CLK		= 1 << 21,
+	CFG_PWRDN_ENA		= 1 << 20,
+	CFG_DSCALE_MASK		= 0x3 << 18,
+	CFG_DSCALE_NONE		= 0x0 << 18,
+	CFG_DSCALE_HALF		= 0x1 << 18,
+	CFG_DSCALE_QUAR		= 0x2 << 18,
+	CFG_ALPHAM_MASK		= 0x3 << 16,
+	CFG_ALPHAM_VIDEO	= 0x0 << 16,
+	CFG_ALPHAM_GRA		= 0x1 << 16,
+	CFG_ALPHAM_CFG		= 0x2 << 16,
+	CFG_ALPHA_MASK		= 0xff << 8,
+	CFG_PIXCMD_MASK		= 0xff,
+};
+
+/* For LCD_SPU_SRAM_CTRL */
+enum {
+	SRAM_READ	= 0 << 14,
+	SRAM_WRITE	= 2 << 14,
+	SRAM_INIT	= 3 << 14,
+	SRAM_HWC32_RAMR	= 0xc << 8,
+	SRAM_HWC32_RAMG	= 0xd << 8,
+	SRAM_HWC32_RAMB	= 0xe << 8,
+	SRAM_HWC32_TRAN	= 0xf << 8,
+	SRAM_HWC	= 0xf << 8,
+};
+
+/* For LCD_SPU_SRAM_PARA1 */
+enum {
+	CFG_CSB_256x32	= 1 << 15,	/* cursor */
+	CFG_CSB_256x24	= 1 << 14,	/* palette */
+	CFG_CSB_256x8	= 1 << 13,	/* gamma */
+	CFG_PDWN1920x32	= 1 << 8,	/* Armada 510: power down vscale ram */
+	CFG_PDWN256x32	= 1 << 7,	/* power down cursor */
+	CFG_PDWN256x24	= 1 << 6,	/* power down palette */
+	CFG_PDWN256x8	= 1 << 5,	/* power down gamma */
+	CFG_PDWNHWC	= 1 << 4,	/* Armada 510: power down all hwc ram */
+	CFG_PDWN32x32	= 1 << 3,	/* power down slave->smart ram */
+	CFG_PDWN16x66	= 1 << 2,	/* power down UV fifo */
+	CFG_PDWN32x66	= 1 << 1,	/* power down Y fifo */
+	CFG_PDWN64x66	= 1 << 0,	/* power down graphic fifo */
+};
+
+/* For LCD_CFG_SCLK_DIV */
+enum {
+	/* Armada 510 */
+	SCLK_510_AXI		= 0x0 << 30,
+	SCLK_510_EXTCLK0	= 0x1 << 30,
+	SCLK_510_PLL		= 0x2 << 30,
+	SCLK_510_EXTCLK1	= 0x3 << 30,
+	SCLK_510_DIV_CHANGE	= 1 << 29,
+	SCLK_510_FRAC_DIV_MASK	= 0xfff << 16,
+	SCLK_510_INT_DIV_MASK	= 0xffff << 0,
+
+	/* Armada 16x */
+	SCLK_16X_AHB		= 0x0 << 28,
+	SCLK_16X_PCLK		= 0x1 << 28,
+	SCLK_16X_AXI		= 0x4 << 28,
+	SCLK_16X_PLL		= 0x8 << 28,
+	SCLK_16X_FRAC_DIV_MASK	= 0xfff << 16,
+	SCLK_16X_INT_DIV_MASK	= 0xffff << 0,
+};
+
+/* For LCD_SPU_DUMB_CTRL */
+enum {
+	DUMB16_RGB565_0	= 0x0 << 28,
+	DUMB16_RGB565_1	= 0x1 << 28,
+	DUMB18_RGB666_0	= 0x2 << 28,
+	DUMB18_RGB666_1	= 0x3 << 28,
+	DUMB12_RGB444_0	= 0x4 << 28,
+	DUMB12_RGB444_1	= 0x5 << 28,
+	DUMB24_RGB888_0	= 0x6 << 28,
+	DUMB_BLANK	= 0x7 << 28,
+	DUMB_MASK	= 0xf << 28,
+	CFG_BIAS_OUT	= 1 << 8,
+	CFG_REV_RGB	= 1 << 7,
+	CFG_INV_CBLANK	= 1 << 6,
+	CFG_INV_CSYNC	= 1 << 5,	/* Normally active high */
+	CFG_INV_HENA	= 1 << 4,
+	CFG_INV_VSYNC	= 1 << 3,	/* Normally active high */
+	CFG_INV_HSYNC	= 1 << 2,	/* Normally active high */
+	CFG_INV_PCLK	= 1 << 1,
+	CFG_DUMB_ENA	= 1 << 0,
+};
+
+/* For LCD_SPU_IOPAD_CONTROL */
+enum {
+	CFG_VSCALE_LN_EN	= 3 << 18,
+	CFG_GRA_VM_ENA		= 1 << 15,
+	CFG_DMA_VM_ENA		= 1 << 13,
+	CFG_CMD_VM_ENA		= 1 << 11,
+	CFG_CSC_MASK		= 3 << 8,
+	CFG_CSC_YUV_CCIR709	= 1 << 9,
+	CFG_CSC_YUV_CCIR601	= 0 << 9,
+	CFG_CSC_RGB_STUDIO	= 1 << 8,
+	CFG_CSC_RGB_COMPUTER	= 0 << 8,
+	CFG_IOPAD_MASK		= 0xf << 0,
+	CFG_IOPAD_DUMB24	= 0x0 << 0,
+	CFG_IOPAD_DUMB18SPI	= 0x1 << 0,
+	CFG_IOPAD_DUMB18GPIO	= 0x2 << 0,
+	CFG_IOPAD_DUMB16SPI	= 0x3 << 0,
+	CFG_IOPAD_DUMB16GPIO	= 0x4 << 0,
+	CFG_IOPAD_DUMB12GPIO	= 0x5 << 0,
+	CFG_IOPAD_SMART18	= 0x6 << 0,
+	CFG_IOPAD_SMART16	= 0x7 << 0,
+	CFG_IOPAD_SMART8	= 0x8 << 0,
+};
+
+#define IOPAD_DUMB24                0x0
+
+/* For LCD_SPU_IRQ_ENA */
+enum {
+	DMA_FRAME_IRQ0_ENA	= 1 << 31,
+	DMA_FRAME_IRQ1_ENA	= 1 << 30,
+	DMA_FRAME_IRQ_ENA	= DMA_FRAME_IRQ0_ENA | DMA_FRAME_IRQ1_ENA,
+	DMA_FF_UNDERFLOW_ENA	= 1 << 29,
+	GRA_FRAME_IRQ0_ENA	= 1 << 27,
+	GRA_FRAME_IRQ1_ENA	= 1 << 26,
+	GRA_FRAME_IRQ_ENA	= GRA_FRAME_IRQ0_ENA | GRA_FRAME_IRQ1_ENA,
+	GRA_FF_UNDERFLOW_ENA	= 1 << 25,
+	VSYNC_IRQ_ENA		= 1 << 23,
+	DUMB_FRAMEDONE_ENA	= 1 << 22,
+	TWC_FRAMEDONE_ENA	= 1 << 21,
+	HWC_FRAMEDONE_ENA	= 1 << 20,
+	SLV_IRQ_ENA		= 1 << 19,
+	SPI_IRQ_ENA		= 1 << 18,
+	PWRDN_IRQ_ENA		= 1 << 17,
+	ERR_IRQ_ENA		= 1 << 16,
+	CLEAN_SPU_IRQ_ISR	= 0xffff,
+};
+
+/* For LCD_SPU_IRQ_ISR */
+enum {
+	DMA_FRAME_IRQ0		= 1 << 31,
+	DMA_FRAME_IRQ1		= 1 << 30,
+	DMA_FRAME_IRQ		= DMA_FRAME_IRQ0 | DMA_FRAME_IRQ1,
+	DMA_FF_UNDERFLOW	= 1 << 29,
+	GRA_FRAME_IRQ0		= 1 << 27,
+	GRA_FRAME_IRQ1		= 1 << 26,
+	GRA_FRAME_IRQ		= GRA_FRAME_IRQ0 | GRA_FRAME_IRQ1,
+	GRA_FF_UNDERFLOW	= 1 << 25,
+	VSYNC_IRQ		= 1 << 23,
+	DUMB_FRAMEDONE		= 1 << 22,
+	TWC_FRAMEDONE		= 1 << 21,
+	HWC_FRAMEDONE		= 1 << 20,
+	SLV_IRQ			= 1 << 19,
+	SPI_IRQ			= 1 << 18,
+	PWRDN_IRQ		= 1 << 17,
+	ERR_IRQ			= 1 << 16,
+	DMA_FRAME_IRQ0_LEVEL	= 1 << 15,
+	DMA_FRAME_IRQ1_LEVEL	= 1 << 14,
+	DMA_FRAME_CNT_ISR	= 3 << 12,
+	GRA_FRAME_IRQ0_LEVEL	= 1 << 11,
+	GRA_FRAME_IRQ1_LEVEL	= 1 << 10,
+	GRA_FRAME_CNT_ISR	= 3 << 8,
+	VSYNC_IRQ_LEVEL		= 1 << 7,
+	DUMB_FRAMEDONE_LEVEL	= 1 << 6,
+	TWC_FRAMEDONE_LEVEL	= 1 << 5,
+	HWC_FRAMEDONE_LEVEL	= 1 << 4,
+	SLV_FF_EMPTY		= 1 << 3,
+	DMA_FF_ALLEMPTY		= 1 << 2,
+	GRA_FF_ALLEMPTY		= 1 << 1,
+	PWRDN_IRQ_LEVEL		= 1 << 0,
+};
+
+#endif
diff --git a/drivers/gpu/drm/armada/armada_ioctlP.h b/drivers/gpu/drm/armada/armada_ioctlP.h
new file mode 100644
index 0000000..bd8c456
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_ioctlP.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_IOCTLP_H
+#define ARMADA_IOCTLP_H
+
+#define ARMADA_IOCTL_PROTO(name)\
+extern int armada_##name##_ioctl(struct drm_device *, void *, struct drm_file *)
+
+ARMADA_IOCTL_PROTO(gem_create);
+ARMADA_IOCTL_PROTO(gem_mmap);
+ARMADA_IOCTL_PROTO(gem_pwrite);
+
+#endif
diff --git a/drivers/gpu/drm/armada/armada_output.c b/drivers/gpu/drm/armada/armada_output.c
new file mode 100644
index 0000000..d685a54
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_output.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_encoder_slave.h>
+#include "armada_output.h"
+#include "armada_drm.h"
+
+struct armada_connector {
+	struct drm_connector conn;
+	const struct armada_output_type *type;
+};
+
+#define drm_to_armada_conn(c) container_of(c, struct armada_connector, conn)
+
+struct drm_encoder *armada_drm_connector_encoder(struct drm_connector *conn)
+{
+	struct drm_encoder *enc = conn->encoder;
+
+	return enc ? enc : drm_encoder_find(conn->dev, conn->encoder_ids[0]);
+}
+
+static enum drm_connector_status armada_drm_connector_detect(
+	struct drm_connector *conn, bool force)
+{
+	struct armada_connector *dconn = drm_to_armada_conn(conn);
+	enum drm_connector_status status = connector_status_disconnected;
+
+	if (dconn->type->detect) {
+		status = dconn->type->detect(conn, force);
+	} else {
+		struct drm_encoder *enc = armada_drm_connector_encoder(conn);
+
+		if (enc)
+			status = encoder_helper_funcs(enc)->detect(enc, conn);
+	}
+
+	return status;
+}
+
+static void armada_drm_connector_destroy(struct drm_connector *conn)
+{
+	struct armada_connector *dconn = drm_to_armada_conn(conn);
+
+	drm_sysfs_connector_remove(conn);
+	drm_connector_cleanup(conn);
+	kfree(dconn);
+}
+
+static int armada_drm_connector_set_property(struct drm_connector *conn,
+	struct drm_property *property, uint64_t value)
+{
+	struct armada_connector *dconn = drm_to_armada_conn(conn);
+
+	if (!dconn->type->set_property)
+		return -EINVAL;
+
+	return dconn->type->set_property(conn, property, value);
+}
+
+static const struct drm_connector_funcs armada_drm_conn_funcs = {
+	.dpms		= drm_helper_connector_dpms,
+	.fill_modes	= drm_helper_probe_single_connector_modes,
+	.detect		= armada_drm_connector_detect,
+	.destroy	= armada_drm_connector_destroy,
+	.set_property	= armada_drm_connector_set_property,
+};
+
+void armada_drm_encoder_prepare(struct drm_encoder *encoder)
+{
+	encoder_helper_funcs(encoder)->dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+void armada_drm_encoder_commit(struct drm_encoder *encoder)
+{
+	encoder_helper_funcs(encoder)->dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+bool armada_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+	const struct drm_display_mode *mode, struct drm_display_mode *adjusted)
+{
+	return true;
+}
+
+/* Shouldn't this be a generic helper function? */
+int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn,
+	struct drm_display_mode *mode)
+{
+	struct drm_encoder *encoder = armada_drm_connector_encoder(conn);
+	int valid = MODE_BAD;
+
+	if (encoder) {
+		struct drm_encoder_slave *slave = to_encoder_slave(encoder);
+
+		valid = slave->slave_funcs->mode_valid(encoder, mode);
+	}
+	return valid;
+}
+
+int armada_drm_slave_encoder_set_property(struct drm_connector *conn,
+	struct drm_property *property, uint64_t value)
+{
+	struct drm_encoder *encoder = armada_drm_connector_encoder(conn);
+	int rc = -EINVAL;
+
+	if (encoder) {
+		struct drm_encoder_slave *slave = to_encoder_slave(encoder);
+
+		rc = slave->slave_funcs->set_property(encoder, conn, property,
+						      value);
+	}
+	return rc;
+}
+
+int armada_output_create(struct drm_device *dev,
+	const struct armada_output_type *type, const void *data)
+{
+	struct armada_connector *dconn;
+	int ret;
+
+	dconn = kzalloc(sizeof(*dconn), GFP_KERNEL);
+	if (!dconn)
+		return -ENOMEM;
+
+	dconn->type = type;
+
+	ret = drm_connector_init(dev, &dconn->conn, &armada_drm_conn_funcs,
+				 type->connector_type);
+	if (ret) {
+		DRM_ERROR("unable to init connector\n");
+		goto err_destroy_dconn;
+	}
+
+	ret = type->create(&dconn->conn, data);
+	if (ret)
+		goto err_conn;
+
+	ret = drm_sysfs_connector_add(&dconn->conn);
+	if (ret)
+		goto err_sysfs;
+
+	return 0;
+
+ err_sysfs:
+	if (dconn->conn.encoder)
+		dconn->conn.encoder->funcs->destroy(dconn->conn.encoder);
+ err_conn:
+	drm_connector_cleanup(&dconn->conn);
+ err_destroy_dconn:
+	kfree(dconn);
+	return ret;
+}
diff --git a/drivers/gpu/drm/armada/armada_output.h b/drivers/gpu/drm/armada/armada_output.h
new file mode 100644
index 0000000..4126d43
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_output.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_CONNETOR_H
+#define ARMADA_CONNETOR_H
+
+#define encoder_helper_funcs(encoder) \
+	((struct drm_encoder_helper_funcs *)encoder->helper_private)
+
+struct armada_output_type {
+	int connector_type;
+	enum drm_connector_status (*detect)(struct drm_connector *, bool);
+	int (*create)(struct drm_connector *, const void *);
+	int (*set_property)(struct drm_connector *, struct drm_property *,
+			    uint64_t);
+};
+
+struct drm_encoder *armada_drm_connector_encoder(struct drm_connector *conn);
+
+void armada_drm_encoder_prepare(struct drm_encoder *encoder);
+void armada_drm_encoder_commit(struct drm_encoder *encoder);
+
+bool armada_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+	const struct drm_display_mode *mode, struct drm_display_mode *adj);
+
+int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn,
+	struct drm_display_mode *mode);
+
+int armada_drm_slave_encoder_set_property(struct drm_connector *conn,
+	struct drm_property *property, uint64_t value);
+
+int armada_output_create(struct drm_device *dev,
+	const struct armada_output_type *type, const void *data);
+
+#endif
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
new file mode 100644
index 0000000..c5b06fd
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Rewritten from the dovefb driver, and Armada510 manuals.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <drm/drmP.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_fb.h"
+#include "armada_gem.h"
+#include "armada_hw.h"
+#include <drm/armada_drm.h>
+#include "armada_ioctlP.h"
+
+struct armada_plane_properties {
+	uint32_t colorkey_yr;
+	uint32_t colorkey_ug;
+	uint32_t colorkey_vb;
+#define K2R(val) (((val) >> 0) & 0xff)
+#define K2G(val) (((val) >> 8) & 0xff)
+#define K2B(val) (((val) >> 16) & 0xff)
+	int16_t  brightness;
+	uint16_t contrast;
+	uint16_t saturation;
+	uint32_t colorkey_mode;
+};
+
+struct armada_plane {
+	struct drm_plane base;
+	spinlock_t lock;
+	struct drm_framebuffer *old_fb;
+	uint32_t src_hw;
+	uint32_t dst_hw;
+	uint32_t dst_yx;
+	uint32_t ctrl0;
+	struct {
+		struct armada_vbl_event update;
+		struct armada_regs regs[13];
+		wait_queue_head_t wait;
+	} vbl;
+	struct armada_plane_properties prop;
+};
+#define drm_to_armada_plane(p) container_of(p, struct armada_plane, base)
+
+
+static void
+armada_ovl_update_attr(struct armada_plane_properties *prop,
+	struct armada_crtc *dcrtc)
+{
+	writel_relaxed(prop->colorkey_yr, dcrtc->base + LCD_SPU_COLORKEY_Y);
+	writel_relaxed(prop->colorkey_ug, dcrtc->base + LCD_SPU_COLORKEY_U);
+	writel_relaxed(prop->colorkey_vb, dcrtc->base + LCD_SPU_COLORKEY_V);
+
+	writel_relaxed(prop->brightness << 16 | prop->contrast,
+		       dcrtc->base + LCD_SPU_CONTRAST);
+	/* Docs say 15:0, but it seems to actually be 31:16 on Armada 510 */
+	writel_relaxed(prop->saturation << 16,
+		       dcrtc->base + LCD_SPU_SATURATION);
+	writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE);
+
+	spin_lock_irq(&dcrtc->irq_lock);
+	armada_updatel(prop->colorkey_mode | CFG_ALPHAM_GRA,
+		     CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK,
+		     dcrtc->base + LCD_SPU_DMA_CTRL1);
+
+	armada_updatel(ADV_GRACOLORKEY, 0, dcrtc->base + LCD_SPU_ADV_REG);
+	spin_unlock_irq(&dcrtc->irq_lock);
+}
+
+/* === Plane support === */
+static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data)
+{
+	struct armada_plane *dplane = data;
+	struct drm_framebuffer *fb;
+
+	armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs);
+
+	spin_lock(&dplane->lock);
+	fb = dplane->old_fb;
+	dplane->old_fb = NULL;
+	spin_unlock(&dplane->lock);
+
+	if (fb)
+		armada_drm_queue_unref_work(dcrtc->crtc.dev, fb);
+}
+
+static unsigned armada_limit(int start, unsigned size, unsigned max)
+{
+	int end = start + size;
+	if (end < 0)
+		return 0;
+	if (start < 0)
+		start = 0;
+	return (unsigned)end > max ? max - start : end - start;
+}
+
+static int
+armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
+	struct drm_framebuffer *fb,
+	int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
+	uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h)
+{
+	struct armada_plane *dplane = drm_to_armada_plane(plane);
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	uint32_t val, ctrl0;
+	unsigned idx = 0;
+	int ret;
+
+	crtc_w = armada_limit(crtc_x, crtc_w, dcrtc->crtc.mode.hdisplay);
+	crtc_h = armada_limit(crtc_y, crtc_h, dcrtc->crtc.mode.vdisplay);
+	ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) |
+		CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) |
+		CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA;
+
+	/* Does the position/size result in nothing to display? */
+	if (crtc_w == 0 || crtc_h == 0) {
+		ctrl0 &= ~CFG_DMA_ENA;
+	}
+
+	/*
+	 * FIXME: if the starting point is off screen, we need to
+	 * adjust src_x, src_y, src_w, src_h appropriately, and
+	 * according to the scale.
+	 */
+
+	if (!dcrtc->plane) {
+		dcrtc->plane = plane;
+		armada_ovl_update_attr(&dplane->prop, dcrtc);
+	}
+
+	/* FIXME: overlay on an interlaced display */
+	/* Just updating the position/size? */
+	if (plane->fb == fb && dplane->ctrl0 == ctrl0) {
+		val = (src_h & 0xffff0000) | src_w >> 16;
+		dplane->src_hw = val;
+		writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN);
+		val = crtc_h << 16 | crtc_w;
+		dplane->dst_hw = val;
+		writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN);
+		val = crtc_y << 16 | crtc_x;
+		dplane->dst_yx = val;
+		writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN);
+		return 0;
+	} else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) {
+		/* Power up the Y/U/V FIFOs on ENA 0->1 transitions */
+		armada_updatel(0, CFG_PDWN16x66 | CFG_PDWN32x66,
+			       dcrtc->base + LCD_SPU_SRAM_PARA1);
+	}
+
+	ret = wait_event_timeout(dplane->vbl.wait,
+				 list_empty(&dplane->vbl.update.node),
+				 HZ/25);
+	if (ret < 0)
+		return ret;
+
+	if (plane->fb != fb) {
+		struct armada_gem_object *obj = drm_fb_obj(fb);
+		uint32_t sy, su, sv;
+
+		/*
+		 * Take a reference on the new framebuffer - we want to
+		 * hold on to it while the hardware is displaying it.
+		 */
+		drm_framebuffer_reference(fb);
+
+		if (plane->fb) {
+			struct drm_framebuffer *older_fb;
+
+			spin_lock_irq(&dplane->lock);
+			older_fb = dplane->old_fb;
+			dplane->old_fb = plane->fb;
+			spin_unlock_irq(&dplane->lock);
+			if (older_fb)
+				armada_drm_queue_unref_work(dcrtc->crtc.dev,
+							    older_fb);
+		}
+
+		src_y >>= 16;
+		src_x >>= 16;
+		sy = obj->dev_addr + fb->offsets[0] + src_y * fb->pitches[0] +
+			src_x * fb->bits_per_pixel / 8;
+		su = obj->dev_addr + fb->offsets[1] + src_y * fb->pitches[1] +
+			src_x;
+		sv = obj->dev_addr + fb->offsets[2] + src_y * fb->pitches[2] +
+			src_x;
+
+		armada_reg_queue_set(dplane->vbl.regs, idx, sy,
+				     LCD_SPU_DMA_START_ADDR_Y0);
+		armada_reg_queue_set(dplane->vbl.regs, idx, su,
+				     LCD_SPU_DMA_START_ADDR_U0);
+		armada_reg_queue_set(dplane->vbl.regs, idx, sv,
+				     LCD_SPU_DMA_START_ADDR_V0);
+		armada_reg_queue_set(dplane->vbl.regs, idx, sy,
+				     LCD_SPU_DMA_START_ADDR_Y1);
+		armada_reg_queue_set(dplane->vbl.regs, idx, su,
+				     LCD_SPU_DMA_START_ADDR_U1);
+		armada_reg_queue_set(dplane->vbl.regs, idx, sv,
+				     LCD_SPU_DMA_START_ADDR_V1);
+
+		val = fb->pitches[0] << 16 | fb->pitches[0];
+		armada_reg_queue_set(dplane->vbl.regs, idx, val,
+				     LCD_SPU_DMA_PITCH_YC);
+		val = fb->pitches[1] << 16 | fb->pitches[2];
+		armada_reg_queue_set(dplane->vbl.regs, idx, val,
+				     LCD_SPU_DMA_PITCH_UV);
+	}
+
+	val = (src_h & 0xffff0000) | src_w >> 16;
+	if (dplane->src_hw != val) {
+		dplane->src_hw = val;
+		armada_reg_queue_set(dplane->vbl.regs, idx, val,
+				     LCD_SPU_DMA_HPXL_VLN);
+	}
+	val = crtc_h << 16 | crtc_w;
+	if (dplane->dst_hw != val) {
+		dplane->dst_hw = val;
+		armada_reg_queue_set(dplane->vbl.regs, idx, val,
+				     LCD_SPU_DZM_HPXL_VLN);
+	}
+	val = crtc_y << 16 | crtc_x;
+	if (dplane->dst_yx != val) {
+		dplane->dst_yx = val;
+		armada_reg_queue_set(dplane->vbl.regs, idx, val,
+				     LCD_SPU_DMA_OVSA_HPXL_VLN);
+	}
+	if (dplane->ctrl0 != ctrl0) {
+		dplane->ctrl0 = ctrl0;
+		armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0,
+			CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE |
+			CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE |
+			CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV | CFG_SWAPYU |
+			CFG_YUV2RGB) | CFG_DMA_ENA,
+			LCD_SPU_DMA_CTRL0);
+	}
+	if (idx) {
+		armada_reg_queue_end(dplane->vbl.regs, idx);
+		armada_drm_vbl_event_add(dcrtc, &dplane->vbl.update);
+	}
+	return 0;
+}
+
+static int armada_plane_disable(struct drm_plane *plane)
+{
+	struct armada_plane *dplane = drm_to_armada_plane(plane);
+	struct drm_framebuffer *fb;
+	struct armada_crtc *dcrtc;
+
+	if (!dplane->base.crtc)
+		return 0;
+
+	dcrtc = drm_to_armada_crtc(dplane->base.crtc);
+	dcrtc->plane = NULL;
+
+	spin_lock_irq(&dcrtc->irq_lock);
+	armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update);
+	armada_updatel(0, CFG_DMA_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0);
+	dplane->ctrl0 = 0;
+	spin_unlock_irq(&dcrtc->irq_lock);
+
+	/* Power down the Y/U/V FIFOs */
+	armada_updatel(CFG_PDWN16x66 | CFG_PDWN32x66, 0,
+		       dcrtc->base + LCD_SPU_SRAM_PARA1);
+
+	if (plane->fb)
+		drm_framebuffer_unreference(plane->fb);
+
+	spin_lock_irq(&dplane->lock);
+	fb = dplane->old_fb;
+	dplane->old_fb = NULL;
+	spin_unlock_irq(&dplane->lock);
+	if (fb)
+		drm_framebuffer_unreference(fb);
+
+	return 0;
+}
+
+static void armada_plane_destroy(struct drm_plane *plane)
+{
+	kfree(plane);
+}
+
+static int armada_plane_set_property(struct drm_plane *plane,
+	struct drm_property *property, uint64_t val)
+{
+	struct armada_private *priv = plane->dev->dev_private;
+	struct armada_plane *dplane = drm_to_armada_plane(plane);
+	bool update_attr = false;
+
+	if (property == priv->colorkey_prop) {
+#define CCC(v) ((v) << 24 | (v) << 16 | (v) << 8)
+		dplane->prop.colorkey_yr = CCC(K2R(val));
+		dplane->prop.colorkey_ug = CCC(K2G(val));
+		dplane->prop.colorkey_vb = CCC(K2B(val));
+#undef CCC
+		update_attr = true;
+	} else if (property == priv->colorkey_min_prop) {
+		dplane->prop.colorkey_yr &= ~0x00ff0000;
+		dplane->prop.colorkey_yr |= K2R(val) << 16;
+		dplane->prop.colorkey_ug &= ~0x00ff0000;
+		dplane->prop.colorkey_ug |= K2G(val) << 16;
+		dplane->prop.colorkey_vb &= ~0x00ff0000;
+		dplane->prop.colorkey_vb |= K2B(val) << 16;
+		update_attr = true;
+	} else if (property == priv->colorkey_max_prop) {
+		dplane->prop.colorkey_yr &= ~0xff000000;
+		dplane->prop.colorkey_yr |= K2R(val) << 24;
+		dplane->prop.colorkey_ug &= ~0xff000000;
+		dplane->prop.colorkey_ug |= K2G(val) << 24;
+		dplane->prop.colorkey_vb &= ~0xff000000;
+		dplane->prop.colorkey_vb |= K2B(val) << 24;
+		update_attr = true;
+	} else if (property == priv->colorkey_val_prop) {
+		dplane->prop.colorkey_yr &= ~0x0000ff00;
+		dplane->prop.colorkey_yr |= K2R(val) << 8;
+		dplane->prop.colorkey_ug &= ~0x0000ff00;
+		dplane->prop.colorkey_ug |= K2G(val) << 8;
+		dplane->prop.colorkey_vb &= ~0x0000ff00;
+		dplane->prop.colorkey_vb |= K2B(val) << 8;
+		update_attr = true;
+	} else if (property == priv->colorkey_alpha_prop) {
+		dplane->prop.colorkey_yr &= ~0x000000ff;
+		dplane->prop.colorkey_yr |= K2R(val);
+		dplane->prop.colorkey_ug &= ~0x000000ff;
+		dplane->prop.colorkey_ug |= K2G(val);
+		dplane->prop.colorkey_vb &= ~0x000000ff;
+		dplane->prop.colorkey_vb |= K2B(val);
+		update_attr = true;
+	} else if (property == priv->colorkey_mode_prop) {
+		dplane->prop.colorkey_mode &= ~CFG_CKMODE_MASK;
+		dplane->prop.colorkey_mode |= CFG_CKMODE(val);
+		update_attr = true;
+	} else if (property == priv->brightness_prop) {
+		dplane->prop.brightness = val - 256;
+		update_attr = true;
+	} else if (property == priv->contrast_prop) {
+		dplane->prop.contrast = val;
+		update_attr = true;
+	} else if (property == priv->saturation_prop) {
+		dplane->prop.saturation = val;
+		update_attr = true;
+	}
+
+	if (update_attr && dplane->base.crtc)
+		armada_ovl_update_attr(&dplane->prop,
+				       drm_to_armada_crtc(dplane->base.crtc));
+
+	return 0;
+}
+
+static const struct drm_plane_funcs armada_plane_funcs = {
+	.update_plane	= armada_plane_update,
+	.disable_plane	= armada_plane_disable,
+	.destroy	= armada_plane_destroy,
+	.set_property	= armada_plane_set_property,
+};
+
+static const uint32_t armada_formats[] = {
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YUV420,
+	DRM_FORMAT_YVU420,
+	DRM_FORMAT_YUV422,
+	DRM_FORMAT_YVU422,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_ABGR1555,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+};
+
+static struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = {
+	{ CKMODE_DISABLE, "disabled" },
+	{ CKMODE_Y,       "Y component" },
+	{ CKMODE_U,       "U component" },
+	{ CKMODE_V,       "V component" },
+	{ CKMODE_RGB,     "RGB" },
+	{ CKMODE_R,       "R component" },
+	{ CKMODE_G,       "G component" },
+	{ CKMODE_B,       "B component" },
+};
+
+static int armada_overlay_create_properties(struct drm_device *dev)
+{
+	struct armada_private *priv = dev->dev_private;
+
+	if (priv->colorkey_prop)
+		return 0;
+
+	priv->colorkey_prop = drm_property_create_range(dev, 0,
+				"colorkey", 0, 0xffffff);
+	priv->colorkey_min_prop = drm_property_create_range(dev, 0,
+				"colorkey_min", 0, 0xffffff);
+	priv->colorkey_max_prop = drm_property_create_range(dev, 0,
+				"colorkey_max", 0, 0xffffff);
+	priv->colorkey_val_prop = drm_property_create_range(dev, 0,
+				"colorkey_val", 0, 0xffffff);
+	priv->colorkey_alpha_prop = drm_property_create_range(dev, 0,
+				"colorkey_alpha", 0, 0xffffff);
+	priv->colorkey_mode_prop = drm_property_create_enum(dev, 0,
+				"colorkey_mode",
+				armada_drm_colorkey_enum_list,
+				ARRAY_SIZE(armada_drm_colorkey_enum_list));
+	priv->brightness_prop = drm_property_create_range(dev, 0,
+				"brightness", 0, 256 + 255);
+	priv->contrast_prop = drm_property_create_range(dev, 0,
+				"contrast", 0, 0x7fff);
+	priv->saturation_prop = drm_property_create_range(dev, 0,
+				"saturation", 0, 0x7fff);
+
+	if (!priv->colorkey_prop)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
+{
+	struct armada_private *priv = dev->dev_private;
+	struct drm_mode_object *mobj;
+	struct armada_plane *dplane;
+	int ret;
+
+	ret = armada_overlay_create_properties(dev);
+	if (ret)
+		return ret;
+
+	dplane = kzalloc(sizeof(*dplane), GFP_KERNEL);
+	if (!dplane)
+		return -ENOMEM;
+
+	spin_lock_init(&dplane->lock);
+	init_waitqueue_head(&dplane->vbl.wait);
+	armada_drm_vbl_event_init(&dplane->vbl.update, armada_plane_vbl,
+				  dplane);
+
+	drm_plane_init(dev, &dplane->base, crtcs, &armada_plane_funcs,
+		       armada_formats, ARRAY_SIZE(armada_formats), false);
+
+	dplane->prop.colorkey_yr = 0xfefefe00;
+	dplane->prop.colorkey_ug = 0x01010100;
+	dplane->prop.colorkey_vb = 0x01010100;
+	dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB);
+	dplane->prop.brightness = 0;
+	dplane->prop.contrast = 0x4000;
+	dplane->prop.saturation = 0x4000;
+
+	mobj = &dplane->base.base;
+	drm_object_attach_property(mobj, priv->colorkey_prop,
+				   0x0101fe);
+	drm_object_attach_property(mobj, priv->colorkey_min_prop,
+				   0x0101fe);
+	drm_object_attach_property(mobj, priv->colorkey_max_prop,
+				   0x0101fe);
+	drm_object_attach_property(mobj, priv->colorkey_val_prop,
+				   0x0101fe);
+	drm_object_attach_property(mobj, priv->colorkey_alpha_prop,
+				   0x000000);
+	drm_object_attach_property(mobj, priv->colorkey_mode_prop,
+				   CKMODE_RGB);
+	drm_object_attach_property(mobj, priv->brightness_prop, 256);
+	drm_object_attach_property(mobj, priv->contrast_prop,
+				   dplane->prop.contrast);
+	drm_object_attach_property(mobj, priv->saturation_prop,
+				   dplane->prop.saturation);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/armada/armada_slave.c b/drivers/gpu/drm/armada/armada_slave.c
new file mode 100644
index 0000000..00d0fac
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_slave.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  Rewritten from the dovefb driver, and Armada510 manuals.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_encoder_slave.h>
+#include "armada_drm.h"
+#include "armada_output.h"
+#include "armada_slave.h"
+
+static int armada_drm_slave_get_modes(struct drm_connector *conn)
+{
+	struct drm_encoder *enc = armada_drm_connector_encoder(conn);
+	int count = 0;
+
+	if (enc) {
+		struct drm_encoder_slave *slave = to_encoder_slave(enc);
+
+		count = slave->slave_funcs->get_modes(enc, conn);
+	}
+
+	return count;
+}
+
+static void armada_drm_slave_destroy(struct drm_encoder *enc)
+{
+	struct drm_encoder_slave *slave = to_encoder_slave(enc);
+	struct i2c_client *client = drm_i2c_encoder_get_client(enc);
+
+	if (slave->slave_funcs)
+		slave->slave_funcs->destroy(enc);
+	if (client)
+		i2c_put_adapter(client->adapter);
+
+	drm_encoder_cleanup(&slave->base);
+	kfree(slave);
+}
+
+static const struct drm_encoder_funcs armada_drm_slave_encoder_funcs = {
+	.destroy	= armada_drm_slave_destroy,
+};
+
+static const struct drm_connector_helper_funcs armada_drm_slave_helper_funcs = {
+	.get_modes	= armada_drm_slave_get_modes,
+	.mode_valid	= armada_drm_slave_encoder_mode_valid,
+	.best_encoder	= armada_drm_connector_encoder,
+};
+
+static const struct drm_encoder_helper_funcs drm_slave_encoder_helpers = {
+	.dpms = drm_i2c_encoder_dpms,
+	.save = drm_i2c_encoder_save,
+	.restore = drm_i2c_encoder_restore,
+	.mode_fixup = drm_i2c_encoder_mode_fixup,
+	.prepare = drm_i2c_encoder_prepare,
+	.commit = drm_i2c_encoder_commit,
+	.mode_set = drm_i2c_encoder_mode_set,
+	.detect = drm_i2c_encoder_detect,
+};
+
+static int
+armada_drm_conn_slave_create(struct drm_connector *conn, const void *data)
+{
+	const struct armada_drm_slave_config *config = data;
+	struct drm_encoder_slave *slave;
+	struct i2c_adapter *adap;
+	int ret;
+
+	conn->interlace_allowed = config->interlace_allowed;
+	conn->doublescan_allowed = config->doublescan_allowed;
+	conn->polled = config->polled;
+
+	drm_connector_helper_add(conn, &armada_drm_slave_helper_funcs);
+
+	slave = kzalloc(sizeof(*slave), GFP_KERNEL);
+	if (!slave)
+		return -ENOMEM;
+
+	slave->base.possible_crtcs = config->crtcs;
+
+	adap = i2c_get_adapter(config->i2c_adapter_id);
+	if (!adap) {
+		kfree(slave);
+		return -EPROBE_DEFER;
+	}
+
+	ret = drm_encoder_init(conn->dev, &slave->base,
+			       &armada_drm_slave_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS);
+	if (ret) {
+		DRM_ERROR("unable to init encoder\n");
+		i2c_put_adapter(adap);
+		kfree(slave);
+		return ret;
+	}
+
+	ret = drm_i2c_encoder_init(conn->dev, slave, adap, &config->info);
+	i2c_put_adapter(adap);
+	if (ret) {
+		DRM_ERROR("unable to init encoder slave\n");
+		armada_drm_slave_destroy(&slave->base);
+		return ret;
+	}
+
+	drm_encoder_helper_add(&slave->base, &drm_slave_encoder_helpers);
+
+	ret = slave->slave_funcs->create_resources(&slave->base, conn);
+	if (ret) {
+		armada_drm_slave_destroy(&slave->base);
+		return ret;
+	}
+
+	ret = drm_mode_connector_attach_encoder(conn, &slave->base);
+	if (ret) {
+		armada_drm_slave_destroy(&slave->base);
+		return ret;
+	}
+
+	conn->encoder = &slave->base;
+
+	return ret;
+}
+
+static const struct armada_output_type armada_drm_conn_slave = {
+	.connector_type	= DRM_MODE_CONNECTOR_HDMIA,
+	.create		= armada_drm_conn_slave_create,
+	.set_property	= armada_drm_slave_encoder_set_property,
+};
+
+int armada_drm_connector_slave_create(struct drm_device *dev,
+	const struct armada_drm_slave_config *config)
+{
+	return armada_output_create(dev, &armada_drm_conn_slave, config);
+}
diff --git a/drivers/gpu/drm/armada/armada_slave.h b/drivers/gpu/drm/armada/armada_slave.h
new file mode 100644
index 0000000..bf2374c
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_slave.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ARMADA_SLAVE_H
+#define ARMADA_SLAVE_H
+
+#include <linux/i2c.h>
+#include <drm/drmP.h>
+
+struct armada_drm_slave_config {
+	int i2c_adapter_id;
+	uint32_t crtcs;
+	uint8_t polled;
+	bool interlace_allowed;
+	bool doublescan_allowed;
+	struct i2c_board_info info;
+};
+
+int armada_drm_connector_slave_create(struct drm_device *dev,
+	const struct armada_drm_slave_config *);
+
+#endif
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 24f4995..e5e6e91 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1135,4 +1135,21 @@ extern int drm_format_horz_chroma_subsampling(uint32_t format);
 extern int drm_format_vert_chroma_subsampling(uint32_t format);
 extern const char *drm_get_format_name(uint32_t format);
 
+/* Helpers */
+static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
+	uint32_t id)
+{
+	struct drm_mode_object *mo;
+	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CRTC);
+	return mo ? obj_to_crtc(mo) : NULL;
+}
+
+static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
+	uint32_t id)
+{
+	struct drm_mode_object *mo;
+	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
+	return mo ? obj_to_encoder(mo) : NULL;
+}
+
 #endif /* __DRM_CRTC_H__ */
diff --git a/include/uapi/drm/armada_drm.h b/include/uapi/drm/armada_drm.h
new file mode 100644
index 0000000..8dec3fd
--- /dev/null
+++ b/include/uapi/drm/armada_drm.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 Russell King
+ *  With inspiration from the i915 driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef DRM_ARMADA_IOCTL_H
+#define DRM_ARMADA_IOCTL_H
+
+#define DRM_ARMADA_GEM_CREATE		0x00
+#define DRM_ARMADA_GEM_MMAP		0x02
+#define DRM_ARMADA_GEM_PWRITE		0x03
+
+#define ARMADA_IOCTL(dir, name, str) \
+	DRM_##dir(DRM_COMMAND_BASE + DRM_ARMADA_##name, struct drm_armada_##str)
+
+struct drm_armada_gem_create {
+	uint32_t handle;
+	uint32_t size;
+};
+#define DRM_IOCTL_ARMADA_GEM_CREATE \
+	ARMADA_IOCTL(IOWR, GEM_CREATE, gem_create)
+
+struct drm_armada_gem_mmap {
+	uint32_t handle;
+	uint32_t pad;
+	uint64_t offset;
+	uint64_t size;
+	uint64_t addr;
+};
+#define DRM_IOCTL_ARMADA_GEM_MMAP \
+	ARMADA_IOCTL(IOWR, GEM_MMAP, gem_mmap)
+
+struct drm_armada_gem_pwrite {
+	uint64_t ptr;
+	uint32_t handle;
+	uint32_t offset;
+	uint32_t size;
+};
+#define DRM_IOCTL_ARMADA_GEM_PWRITE \
+	ARMADA_IOCTL(IOW, GEM_PWRITE, gem_pwrite)
+
+#endif
-- 
1.7.4.4

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Jean-Francois Moine <moinejf@free.fr>
Subject: Re: [PATCH 1/5] drm/i2c: tda998x: set VIF for full range,
 underscanned display
Date: Mon, 7 Oct 2013 10:59:44 +0200
Message-ID: <20131007105944.6746352b@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwUV-0000hl-Rw@rmk-PC.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <E1VSwUV-0000hl-Rw@rmk-PC.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

T24gU3VuLCAwNiBPY3QgMjAxMyAyMzowNzo1NSArMDEwMApSdXNzZWxsIEtpbmcgPHJtaytrZXJu
ZWxAYXJtLmxpbnV4Lm9yZy51az4gd3JvdGU6Cgo+IFNpZ25lZC1vZmYtYnk6IFJ1c3NlbGwgS2lu
ZyA8cm1rK2tlcm5lbEBhcm0ubGludXgub3JnLnVrPgo+IC0tLQo+ICBkcml2ZXJzL2dwdS9kcm0v
aTJjL3RkYTk5OHhfZHJ2LmMgfCAgICAyICsrCj4gIDEgZmlsZXMgY2hhbmdlZCwgMiBpbnNlcnRp
b25zKCspLCAwIGRlbGV0aW9ucygtKQo+IAo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0v
aTJjL3RkYTk5OHhfZHJ2LmMgYi9kcml2ZXJzL2dwdS9kcm0vaTJjL3RkYTk5OHhfZHJ2LmMKPiBp
bmRleCA2MGU4NDA0Li43MDQwNDBiNSAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL2dwdS9kcm0vaTJj
L3RkYTk5OHhfZHJ2LmMKPiArKysgYi9kcml2ZXJzL2dwdS9kcm0vaTJjL3RkYTk5OHhfZHJ2LmMK
PiBAQCAtNTQ5LDYgKzU0OSw4IEBAIHRkYTk5OHhfd3JpdGVfYXZpKHN0cnVjdCBkcm1fZW5jb2Rl
ciAqZW5jb2Rlciwgc3RydWN0IGRybV9kaXNwbGF5X21vZGUgKm1vZGUpCj4gIAlidWZbSEIoMCld
ID0gMHg4MjsKPiAgCWJ1ZltIQigxKV0gPSAweDAyOwo+ICAJYnVmW0hCKDIpXSA9IDEzOwo+ICsJ
YnVmW1BCKDEpXSA9IDI7IC8qIHVuZGVyc2Nhbm5lZCBkaXNwbGF5ICovCj4gKwlidWZbUEIoMyld
ID0gMiA8PCAyOyAvKiBmdWxsIHJhbmdlICovCj4gIAlidWZbUEIoNCldID0gZHJtX21hdGNoX2Nl
YV9tb2RlKG1vZGUpOwo+ICAKPiAgCXRkYTk5OHhfd3JpdGVfaWYoZW5jb2RlciwgRElQX0lGX0ZM
QUdTX0lGMiwgUkVHX0lGMl9IQjAsIGJ1ZiwKCllvdSBzaG91bGQgdXNlIHRoZSAnaGRtaS5oJyBj
b25zdGFudHMgd2hpY2ggYXJlIG1lYW5pbmdmdWwgZW5vdWdoOgoKCWJ1ZltQQigxKV0gPSBIRE1J
X1NDQU5fTU9ERV9VTkRFUlNDQU47CglidWZbUEIoMyldID0gSERNSV9RVUFOVElaQVRJT05fUkFO
R0VfRlVMTCA8PCAyOwoKLS0gCktlbiBhciBjJ2hlbnRhw7EJfAkgICAgICAqKiBCcmVpemggaGEg
TGludXggYXRhdiEgKioKSmVmCQl8CQlodHRwOi8vbW9pbmVqZi5mcmVlLmZyLwoKX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbGludXgtYXJtLWtlcm5lbCBt
YWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9s
aXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5lbAo=

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Jean-Francois Moine <moinejf@free.fr>
Subject: Re: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
Date: Mon, 7 Oct 2013 11:01:41 +0200
Message-ID: <20131007110141.27f1ac25@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

T24gU3VuLCAwNiBPY3QgMjAxMyAyMzowOTo1NiArMDEwMApSdXNzZWxsIEtpbmcgPHJtaytrZXJu
ZWxAYXJtLmxpbnV4Lm9yZy51az4gd3JvdGU6Cgo+IFRoaXMgcGF0Y2ggYWRkcyBBUkdCIGhhcmR3
YXJlIGN1cnNvciBzdXBwb3J0IHRvIHRoZSBEUk0gZHJpdmVyIGZvciB0aGUKPiBNYXJ2ZWxsIEFy
bWFkYSBTb0NzLiAgQVJHQiBjdXJzb3JzIGFyZSBzdXBwb3J0ZWQgYXQgZWl0aGVyIDMyeDY0IG9y
Cj4gNjR4MzIgcmVzb2x1dGlvbnMuCglbc25pcF0KCkkgZG9uJ3Qgc2VlIHRoZSBpbnRlcmVzdCBv
ZiBzdWNoIGN1cnNvcnMuIEFjdHVhbGx5LCBtb3N0IG9mdGVuLCB0aGUKY3Vyc29ycyBhcmUgNjR4
NjQgYW5kICdBJyBpcyBlaXRoZXIgMCBvciAweGZmLiBBcyB0aGUgQXJtYWRhIDUxMApzdXBwb3J0
cyA2NHg2NCBjdXJzb3JzIHdpdGggdHJhbnNwYXJlbmN5LCBpdCB3b3VsZCBiZSBtb3JlIHVzZWZ1
bCB0bwppbXBsZW1lbnQgdGhlc2Ugb25lcy4uLgoKLS0gCktlbiBhciBjJ2hlbnRhw7EJfAkgICAg
ICAqKiBCcmVpemggaGEgTGludXggYXRhdiEgKioKSmVmCQl8CQlodHRwOi8vbW9pbmVqZi5mcmVl
LmZyLwoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbGlu
dXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRl
YWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgt
YXJtLWtlcm5lbAo=

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Jean-Francois Moine <moinejf@free.fr>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Mon, 7 Oct 2013 11:18:07 +0200
Message-ID: <20131007111807.5e86ea6e@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

T24gU3VuLCAwNiBPY3QgMjAxMyAyMzoxMTo1NiArMDEwMApSdXNzZWxsIEtpbmcgPHJtaytrZXJu
ZWxAYXJtLmxpbnV4Lm9yZy51az4gd3JvdGU6Cgo+IFNpZ25lZC1vZmYtYnk6IFJ1c3NlbGwgS2lu
ZyA8cm1rK2tlcm5lbEBhcm0ubGludXgub3JnLnVrPgo+IC0tLQo+ICBkcml2ZXJzL2dwdS9kcm0v
YXJtYWRhL0tjb25maWcgICAgICB8ICAgIDkgKysrKysrKwo+ICBkcml2ZXJzL2dwdS9kcm0vYXJt
YWRhL2FybWFkYV9kcnYuYyB8ICAgNDIgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysKPiAgMiBmaWxlcyBjaGFuZ2VkLCA1MSBpbnNlcnRpb25zKCspLCAwIGRlbGV0aW9ucygtKQo+
IAo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vYXJtYWRhL0tjb25maWcgYi9kcml2ZXJz
L2dwdS9kcm0vYXJtYWRhL0tjb25maWcKPiBpbmRleCBjN2EwYTk0Li44N2U2MmRkIDEwMDY0NAo+
IC0tLSBhL2RyaXZlcnMvZ3B1L2RybS9hcm1hZGEvS2NvbmZpZwo+ICsrKyBiL2RyaXZlcnMvZ3B1
L2RybS9hcm1hZGEvS2NvbmZpZwo+IEBAIC0xMywzICsxMywxMiBAQCBjb25maWcgRFJNX0FSTUFE
QQo+ICAJICBUaGlzIGRyaXZlciBwcm92aWRlcyBubyBidWlsdC1pbiBhY2NlbGVyYXRpb247IGFj
Y2VsZXJhdGlvbiBpcwo+ICAJICBwZXJmb3JtZWQgYnkgb3RoZXIgSVAgZm91bmQgb24gdGhlIFNv
Qy4gIFRoaXMgZHJpdmVyIHByb3ZpZGVzCj4gIAkgIGtlcm5lbCBtb2RlIHNldHRpbmcgYW5kIGJ1
ZmZlciBtYW5hZ2VtZW50IHRvIHVzZXJzcGFjZS4KPiArCj4gK2NvbmZpZyBEUk1fQVJNQURBX1RE
QTE5OThYCj4gKwlib29sICJTdXBwb3J0IFREQTE5OThYIEhETUkgb3V0cHV0Igo+ICsJZGVwZW5k
cyBvbiBEUk1fQVJNQURBICE9IG4KPiArCWRlcGVuZHMgb24gSTJDICYmIERSTV9JMkNfTlhQX1RE
QTk5OFggPSB5Cj4gKwlkZWZhdWx0IHkKPiArCWhlbHAKPiArCSAgU3VwcG9ydCB0aGUgVERBMTk5
OHggSERNSSBvdXRwdXQgZGV2aWNlIGZvdW5kIG9uIHRoZSBTb2xpZC1SdW4KPiArCSAgQ3VCb3gu
CgpJdCBzZWVtcyB3ZSBhcmUgZ29pbmcgYmFja3dhcmRzOiBhcyB0aGUgQXJtYWRhIGJhc2VkIGJv
YXJkcyB3aWxsIHNvb24KbW92ZSB0byBmdWxsIERUIChtdmVidSksIHlvdSBhcmUgbWFraW5nIGFu
IGV4Y2VwdGlvbiBmb3IgdGhlIEN1Ym94LCBzbwp0aGF0IHRoZXJlIHNob3VsZCBiZSBDdWJveCBz
cGVjaWZpYyBrZXJuZWxzLiBJIGRvbid0IGxpa2UgdGhhdC4uLgoKPiBkaWZmIC0tZ2l0IGEvZHJp
dmVycy9ncHUvZHJtL2FybWFkYS9hcm1hZGFfZHJ2LmMgYi9kcml2ZXJzL2dwdS9kcm0vYXJtYWRh
L2FybWFkYV9kcnYuYwo+IGluZGV4IGRiNjJmMWIuLjY5NTE3Y2YgMTAwNjQ0Cj4gLS0tIGEvZHJp
dmVycy9ncHUvZHJtL2FybWFkYS9hcm1hZGFfZHJ2LmMKPiArKysgYi9kcml2ZXJzL2dwdS9kcm0v
YXJtYWRhL2FybWFkYV9kcnYuYwo+IEBAIC0xNiw2ICsxNiw0MiBAQAo+ICAjaW5jbHVkZSA8ZHJt
L2FybWFkYV9kcm0uaD4KPiAgI2luY2x1ZGUgImFybWFkYV9pb2N0bFAuaCIKPiAgCj4gKyNpZmRl
ZiBDT05GSUdfRFJNX0FSTUFEQV9UREExOTk4WAo+ICsjaW5jbHVkZSA8ZHJtL2kyYy90ZGE5OTh4
Lmg+Cj4gKyNpbmNsdWRlICJhcm1hZGFfc2xhdmUuaCIKPiArCj4gK3N0YXRpYyBzdHJ1Y3QgdGRh
OTk4eF9lbmNvZGVyX3BhcmFtcyBwYXJhbXMgPSB7Cj4gKwkvKiBXaXRoIDB4MjQsIHRoZXJlIGlz
IG5vIHRyYW5zbGF0aW9uIGJldHdlZW4gdnBfb3V0IGFuZCBpbnRfdnAKPiArCUZCCUxDRCBvdXQJ
UGlucwlWSVAJSW50IFZwCj4gKwlSOjIzOjE2CVI6NzowCVZQQzc6MAk3OjAJNzowW1JdCj4gKwlH
OjE1OjgJRzoxNTo4CVZQQjc6MAkyMzoxNgkyMzoxNltHXQo+ICsJQjo3OjAJQjoyMzoxNglWUEE3
OjAJMTU6OAkxNTo4W0JdCj4gKwkqLwo+ICsJLnN3YXBfYSA9IDIsCj4gKwkuc3dhcF9iID0gMywK
PiArCS5zd2FwX2MgPSA0LAo+ICsJLnN3YXBfZCA9IDUsCj4gKwkuc3dhcF9lID0gMCwKPiArCS5z
d2FwX2YgPSAxLAoKSSBzdGlsbCBkb24ndCBhZ3JlZS4gWW91IGRvbid0IG5lZWQgdG8gaW52ZXJ0
IFIgPC0+IEIgZm9yIHRoZSBDdWJveCBhdAp0aGUgdGRhOTk4eCBsZXZlbDogdGhpcyBtYXkgYmUg
ZG9uZSBzZXR0aW5nIGFzIGl0IHNob3VsZCBiZSB0aGUKQ0ZHX0dSQV9TV0FQUkIgZmxhZyBvZiB0
aGUgbGNkIHJlZ2lzdGVyIExDRF9TUFVfRE1BX0NUUkwwLgoKPiArCS5hdWRpb19jZmcgPSBCSVQo
MiksCj4gKwkuYXVkaW9fZnJhbWVbMV0gPSAxLAo+ICsJLmF1ZGlvX2Zvcm1hdCA9IEFGTVRfU1BE
SUYsCj4gKwkuYXVkaW9fc2FtcGxlX3JhdGUgPSA0NDEwMCwKClRoZXNlIHZhbHVlcyBhcmUgcmF0
aGVyIG15c3RlcmlvdXMhCgpMb29raW5nIGF0IHRoZSB0ZGE5OTh4IGRyaXZlciwgSSBmb3VuZCB0
aGF0OgotIGF1ZGlvX2NmZyBjYW4gYmUgMHgwMyBmb3IgaTJzIGlucHV0IGFuZCAweDA0IGZvciBz
cGRpZiBpbnB1dAotIGF1ZGlvX2ZyYW1lWzFdIGlzIHRoZSAoY2hhbm5lbCBjb3VudCAtIDEpCi0g
YXVkaW9fZm9ybWF0IGFuZCBhdWRpb19zYW1wbGVfcmF0ZSBhcmUgaGFyZGNvZGluZyB0aGUgYXVk
aW8gaW5wdXQgdG8KICBzcGRpZiBhbmQgdGhlIHNhbXBsZSByYXRlIHRvIDQ0LjFrSHoKCkkgZG9u
J3QgdGhpbmsgdGhhdCB0aGVzZSBwYXJhbWV0ZXJzIGFyZSBuZWVkZWQ6CgotIHRoZSB0ZGE5OTh4
IG11c3QgYmUgcHJlcGFyZWQgdG8gZ2V0IGVpdGhlciBpMnMgb3Igc3BkaWYgYXMgdGhlIGF1ZGlv
CiAgaW5wdXQgYXQgYW55IHRpbWUuIFRoZSBjaG9pY2Ugb2YgdGhpcyBpbnB1dCByZXN1bHRzIGZy
b20gdGhlIGF1ZGlvCiAgc3Vic3lzdGVtIGNvbnN0cmFpbnRzIChjb2RlYykgZm91bmQgYXQgYXVk
aW8gc3RyZWFtaW5nIHN0YXJ0IHRpbWUuCgotIHRoZSBjaGFubmVsIGNvdW50IGlzIGFsd2F5cyAy
IGZvciBzcGRpZi4gRG8gd2UgbmVlZCB0byBhY2NlcHQgZm91cgogIGNoYW5uZWxzIGZvciBpMnM/
CgotIGF1ZGlvIG9uIGhkbWkgd29ya3MgZmluZSBmb3IgbWUgYXQgYW55IGlucHV0IHJhdGUgc2V0
dGluZyB0aGUgdGRhOTk4eAogIHNhbXBsZSByYXRlIHRvIDk2IGtIei4gQW55d2F5LCBpbiB0aGUg
YWN0dWFsIHRkYTk5OHggZHJpdmVyLCB0aGlzCiAgYXVkaW9fc2FtcGxlX3JhdGUgdmFsdWUgaXMg
anVzdCB1c2VkIHRvIHNldCBhbiBhcHByb3hpbWF0ZSB2YWx1ZSBvZgogIEFDUi4gQnV0IHRoaXMg
dmFsdWUgaXMgbm90IHVzZWQgYmVjYXVzZSBhbiBvcHRpbWFsIHZhbHVlIGlzIGNvbXB1dGVkCiAg
YnkgdGhlIGhhcmR3YXJlIHRoYW5rcyB0byB0aGUgZmxhZyBBSVBfQ05UUkxfMF9BQ1JfTUFOIQoK
CVtzbmlwXQoKVGhlIHJlbWFpbmluZyBwYXRjaCBpcyBDdWJveCBzcGVjaWZpYy4KCi0tIApLZW4g
YXIgYydoZW50YcOxCXwJICAgICAgKiogQnJlaXpoIGhhIExpbnV4IGF0YXYhICoqCkplZgkJfAkJ
aHR0cDovL21vaW5lamYuZnJlZS5mci8KCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1r
ZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWls
bWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: Re: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
Date: Mon, 7 Oct 2013 10:40:08 +0100
Message-ID: <20131007094008.GH12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk> <20131007110141.27f1ac25@armhf>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
In-Reply-To: <20131007110141.27f1ac25@armhf>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Jean-Francois Moine <moinejf@free.fr>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Mon, Oct 07, 2013 at 11:01:41AM +0200, Jean-Francois Moine wrote:
> On Sun, 06 Oct 2013 23:09:56 +0100
> Russell King <rmk+kernel@arm.linux.org.uk> wrote:
> 
> > This patch adds ARGB hardware cursor support to the DRM driver for the
> > Marvell Armada SoCs.  ARGB cursors are supported at either 32x64 or
> > 64x32 resolutions.
> 	[snip]
> 
> I don't see the interest of such cursors. Actually, most often, the
> cursors are 64x64 and 'A' is either 0 or 0xff. As the Armada 510
> supports 64x64 cursors with transparency, it would be more useful to
> implement these ones...

Sorry, you're completely wrong there.  Xorg uses an alphablended cursor.
This patch is a result of trialling each of the Armada's cursor options
and this is the only one which results in a reasonable looking cursor.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Mon, 7 Oct 2013 10:44:04 +0100
Message-ID: <20131007094404.GI12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk> <20131007111807.5e86ea6e@armhf>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
In-Reply-To: <20131007111807.5e86ea6e@armhf>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Jean-Francois Moine <moinejf@free.fr>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Mon, Oct 07, 2013 at 11:18:07AM +0200, Jean-Francois Moine wrote:
> On Sun, 06 Oct 2013 23:11:56 +0100
> Russell King <rmk+kernel@arm.linux.org.uk> wrote:
> 
> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> > ---
> >  drivers/gpu/drm/armada/Kconfig      |    9 +++++++
> >  drivers/gpu/drm/armada/armada_drv.c |   42 +++++++++++++++++++++++++++++++++++
> >  2 files changed, 51 insertions(+), 0 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
> > index c7a0a94..87e62dd 100644
> > --- a/drivers/gpu/drm/armada/Kconfig
> > +++ b/drivers/gpu/drm/armada/Kconfig
> > @@ -13,3 +13,12 @@ config DRM_ARMADA
> >  	  This driver provides no built-in acceleration; acceleration is
> >  	  performed by other IP found on the SoC.  This driver provides
> >  	  kernel mode setting and buffer management to userspace.
> > +
> > +config DRM_ARMADA_TDA1998X
> > +	bool "Support TDA1998X HDMI output"
> > +	depends on DRM_ARMADA != n
> > +	depends on I2C && DRM_I2C_NXP_TDA998X = y
> > +	default y
> > +	help
> > +	  Support the TDA1998x HDMI output device found on the Solid-Run
> > +	  CuBox.
> 
> It seems we are going backwards: as the Armada based boards will soon
> move to full DT (mvebu), you are making an exception for the Cubox, so
> that there should be Cubox specific kernels. I don't like that...

*Ignored*.  You know why.

> > diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
> > index db62f1b..69517cf 100644
> > --- a/drivers/gpu/drm/armada/armada_drv.c
> > +++ b/drivers/gpu/drm/armada/armada_drv.c
> > @@ -16,6 +16,42 @@
> >  #include <drm/armada_drm.h>
> >  #include "armada_ioctlP.h"
> >  
> > +#ifdef CONFIG_DRM_ARMADA_TDA1998X
> > +#include <drm/i2c/tda998x.h>
> > +#include "armada_slave.h"
> > +
> > +static struct tda998x_encoder_params params = {
> > +	/* With 0x24, there is no translation between vp_out and int_vp
> > +	FB	LCD out	Pins	VIP	Int Vp
> > +	R:23:16	R:7:0	VPC7:0	7:0	7:0[R]
> > +	G:15:8	G:15:8	VPB7:0	23:16	23:16[G]
> > +	B:7:0	B:23:16	VPA7:0	15:8	15:8[B]
> > +	*/
> > +	.swap_a = 2,
> > +	.swap_b = 3,
> > +	.swap_c = 4,
> > +	.swap_d = 5,
> > +	.swap_e = 0,
> > +	.swap_f = 1,
> 
> I still don't agree. You don't need to invert R <-> B for the Cubox at
> the tda998x level: this may be done setting as it should be the
> CFG_GRA_SWAPRB flag of the lcd register LCD_SPU_DMA_CTRL0.

You are totally and utterly wrong there.  We need R and B presented on
their correct lanes to the TDA998x so that the Armadas YUV->RGB
conversion works.  Setting CFG_GRA_SWAPRB does not swap the YUV output
to match, neither does setting any of the other bits.

CFG_GRA_SWAPRB is all about the _graphics_ _framebuffer_ format, it's got
nothing to do at all with how the output is wired.

> > +	.audio_cfg = BIT(2),
> > +	.audio_frame[1] = 1,
> > +	.audio_format = AFMT_SPDIF,
> > +	.audio_sample_rate = 44100,
> 
> These values are rather mysterious!

Also I'm going to ignore this comment, because quite honestly, I think
this is worthless.  You haven't investigated how the TDA998x actually
gets setup by Rabeeh.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Jean-Francois Moine <moinejf@free.fr>
Subject: Re: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
Date: Mon, 7 Oct 2013 12:09:22 +0200
Message-ID: <20131007120922.47df03b6@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
 <20131007110141.27f1ac25@armhf>
 <20131007094008.GH12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131007094008.GH12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

T24gTW9uLCA3IE9jdCAyMDEzIDEwOjQwOjA4ICswMTAwClJ1c3NlbGwgS2luZyAtIEFSTSBMaW51
eCA8bGludXhAYXJtLmxpbnV4Lm9yZy51az4gd3JvdGU6Cgo+ID4gPiBUaGlzIHBhdGNoIGFkZHMg
QVJHQiBoYXJkd2FyZSBjdXJzb3Igc3VwcG9ydCB0byB0aGUgRFJNIGRyaXZlciBmb3IgdGhlCj4g
PiA+IE1hcnZlbGwgQXJtYWRhIFNvQ3MuICBBUkdCIGN1cnNvcnMgYXJlIHN1cHBvcnRlZCBhdCBl
aXRoZXIgMzJ4NjQgb3IKPiA+ID4gNjR4MzIgcmVzb2x1dGlvbnMuICAKPiA+IAlbc25pcF0KPiA+
IAo+ID4gSSBkb24ndCBzZWUgdGhlIGludGVyZXN0IG9mIHN1Y2ggY3Vyc29ycy4gQWN0dWFsbHks
IG1vc3Qgb2Z0ZW4sIHRoZQo+ID4gY3Vyc29ycyBhcmUgNjR4NjQgYW5kICdBJyBpcyBlaXRoZXIg
MCBvciAweGZmLiBBcyB0aGUgQXJtYWRhIDUxMAo+ID4gc3VwcG9ydHMgNjR4NjQgY3Vyc29ycyB3
aXRoIHRyYW5zcGFyZW5jeSwgaXQgd291bGQgYmUgbW9yZSB1c2VmdWwgdG8KPiA+IGltcGxlbWVu
dCB0aGVzZSBvbmVzLi4uICAKPiAKPiBTb3JyeSwgeW91J3JlIGNvbXBsZXRlbHkgd3JvbmcgdGhl
cmUuICBYb3JnIHVzZXMgYW4gYWxwaGFibGVuZGVkIGN1cnNvci4KPiBUaGlzIHBhdGNoIGlzIGEg
cmVzdWx0IG9mIHRyaWFsbGluZyBlYWNoIG9mIHRoZSBBcm1hZGEncyBjdXJzb3Igb3B0aW9ucwo+
IGFuZCB0aGlzIGlzIHRoZSBvbmx5IG9uZSB3aGljaCByZXN1bHRzIGluIGEgcmVhc29uYWJsZSBs
b29raW5nIGN1cnNvci4KClN0cmFuZ2UuIEkgYW0gdXNpbmcgdGhlIDY0eDY0IGN1cnNvciB3aXRo
IHRyYW5zcGFyZW5jeSBvZiB0aGUgNTEwIGZvcgptYW55IG1vbnRocyBhbmQgSSBuZXZlciBzYXcg
YW55IHByb2JsZW0uCgpJZiB5b3UgYWJzb2x1dGVseSB3YW50IHRvIGhhdmUgYWxsIHRyYW5zcGFy
ZW5jeSBzaGFkZXMsIHlvdSBzaG91bGQKYWNjZXB0IDY0eDY0IGN1cnNvcnMgYW5kIHRlc3QgaWYg
dGhleSBtYXkgYmUgcmVuZGVyZWQgYXMgNjR4MzIgb3IgMzJ4NjQsCmkuZS4gdGVzdCB0aGF0IHRo
ZXJlIGlzIG9ubHkgcHVyZSB0cmFuc3BhcmVuY3kgaW4gdGhlIG5vbi1yZW5kZXJlZApyZWN0YW5n
bGVzLi4uCgotLSAKS2VuIGFyIGMnaGVudGHDsQl8CSAgICAgICoqIEJyZWl6aCBoYSBMaW51eCBh
dGF2ISAqKgpKZWYJCXwJCWh0dHA6Ly9tb2luZWpmLmZyZWUuZnIvCgpfX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcg
bGlzdApsaW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmlu
ZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1hcm0ta2VybmVsCg==

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: Re: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
Date: Mon, 7 Oct 2013 11:32:50 +0100
Message-ID: <20131007103250.GJ12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk> <20131007110141.27f1ac25@armhf>
 <20131007094008.GH12758@n2100.arm.linux.org.uk>
 <20131007120922.47df03b6@armhf>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
In-Reply-To: <20131007120922.47df03b6@armhf>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Jean-Francois Moine <moinejf@free.fr>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Mon, Oct 07, 2013 at 12:09:22PM +0200, Jean-Francois Moine wrote:
> On Mon, 7 Oct 2013 10:40:08 +0100
> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
> 
> > > > This patch adds ARGB hardware cursor support to the DRM driver for the
> > > > Marvell Armada SoCs.  ARGB cursors are supported at either 32x64 or
> > > > 64x32 resolutions.  
> > > 	[snip]
> > > 
> > > I don't see the interest of such cursors. Actually, most often, the
> > > cursors are 64x64 and 'A' is either 0 or 0xff. As the Armada 510
> > > supports 64x64 cursors with transparency, it would be more useful to
> > > implement these ones...  
> > 
> > Sorry, you're completely wrong there.  Xorg uses an alphablended cursor.
> > This patch is a result of trialling each of the Armada's cursor options
> > and this is the only one which results in a reasonable looking cursor.
> 
> Strange. I am using the 64x64 cursor with transparency of the 510 for
> many months and I never saw any problem.

When I tried it, all cursors had variable alpha, and converting the
alpha to a single transparency bit made the cursor look rubbish against
certain backgrounds.

> If you absolutely want to have all transparency shades, you should
> accept 64x64 cursors and test if they may be rendered as 64x32 or
> 32x64, i.e. test that there is only pure transparency in the non-
> rendered rectangles...

That is policy, and that is something which can be done by the X server
rather than the kernel.  The kernel exposes the hardware capabilities,
which are to allow a 64x32 or a 32x64 cursor.  Userspace can make the
decision dynamically which it wishes to use.

However, what you're suggesting is dangerous.  What do you do when you're
presented with a cursor which is 64x64 ?  Do you:

(a) not display it
(b) crash the X server

There isn't a fallback to using software cursors available in the X server
because there's no error reporting for a failed hardware cursor update.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Jean-Francois Moine <moinejf@free.fr>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Mon, 7 Oct 2013 12:48:20 +0200
Message-ID: <20131007124820.2189a4c3@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
	<E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
	<20131007111807.5e86ea6e@armhf>
	<20131007094404.GI12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
Return-path: <dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org>
Received: from smtp4-g21.free.fr (smtp4-g21.free.fr [212.27.42.4])
	by gabe.freedesktop.org (Postfix) with ESMTP id 265C3E70E1
	for <dri-devel@lists.freedesktop.org>;
	Mon,  7 Oct 2013 03:44:58 -0700 (PDT)
In-Reply-To: <20131007094404.GI12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.freedesktop.org/mailman/options/dri-devel>,
	<mailto:dri-devel-request@lists.freedesktop.org?subject=unsubscribe>
List-Archive: <http://lists.freedesktop.org/archives/dri-devel>
List-Post: <mailto:dri-devel@lists.freedesktop.org>
List-Help: <mailto:dri-devel-request@lists.freedesktop.org?subject=help>
List-Subscribe: <http://lists.freedesktop.org/mailman/listinfo/dri-devel>,
	<mailto:dri-devel-request@lists.freedesktop.org?subject=subscribe>
Sender: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org
Errors-To: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

T24gTW9uLCA3IE9jdCAyMDEzIDEwOjQ0OjA0ICswMTAwClJ1c3NlbGwgS2luZyAtIEFSTSBMaW51
eCA8bGludXhAYXJtLmxpbnV4Lm9yZy51az4gd3JvdGU6Cgo+IE9uIE1vbiwgT2N0IDA3LCAyMDEz
IGF0IDExOjE4OjA3QU0gKzAyMDAsIEplYW4tRnJhbmNvaXMgTW9pbmUgd3JvdGU6Cglbc25pcF0K
PiA+IEl0IHNlZW1zIHdlIGFyZSBnb2luZyBiYWNrd2FyZHM6IGFzIHRoZSBBcm1hZGEgYmFzZWQg
Ym9hcmRzIHdpbGwgc29vbgo+ID4gbW92ZSB0byBmdWxsIERUIChtdmVidSksIHlvdSBhcmUgbWFr
aW5nIGFuIGV4Y2VwdGlvbiBmb3IgdGhlIEN1Ym94LCBzbwo+ID4gdGhhdCB0aGVyZSBzaG91bGQg
YmUgQ3Vib3ggc3BlY2lmaWMga2VybmVscy4gSSBkb24ndCBsaWtlIHRoYXQuLi4KPiAKPiAqSWdu
b3JlZCouICBZb3Uga25vdyB3aHkuCgpTb3JyeS4gSSBkb24ndCBzZWUgd2h5LiBNYXkgeW91IGV4
cGxhaW4gYWdhaW4/Cgo+ID4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2FybWFkYS9h
cm1hZGFfZHJ2LmMgYi9kcml2ZXJzL2dwdS9kcm0vYXJtYWRhL2FybWFkYV9kcnYuYwoJW3NuaXBd
Cj4gPiA+ICtzdGF0aWMgc3RydWN0IHRkYTk5OHhfZW5jb2Rlcl9wYXJhbXMgcGFyYW1zID0gewo+
ID4gPiArCS8qIFdpdGggMHgyNCwgdGhlcmUgaXMgbm8gdHJhbnNsYXRpb24gYmV0d2VlbiB2cF9v
dXQgYW5kIGludF92cAo+ID4gPiArCUZCCUxDRCBvdXQJUGlucwlWSVAJSW50IFZwCj4gPiA+ICsJ
UjoyMzoxNglSOjc6MAlWUEM3OjAJNzowCTc6MFtSXQo+ID4gPiArCUc6MTU6OAlHOjE1OjgJVlBC
NzowCTIzOjE2CTIzOjE2W0ddCj4gPiA+ICsJQjo3OjAJQjoyMzoxNglWUEE3OjAJMTU6OAkxNTo4
W0JdCj4gPiA+ICsJKi8KPiA+ID4gKwkuc3dhcF9hID0gMiwKPiA+ID4gKwkuc3dhcF9iID0gMywK
PiA+ID4gKwkuc3dhcF9jID0gNCwKPiA+ID4gKwkuc3dhcF9kID0gNSwKPiA+ID4gKwkuc3dhcF9l
ID0gMCwKPiA+ID4gKwkuc3dhcF9mID0gMSwKPiA+IAo+ID4gSSBzdGlsbCBkb24ndCBhZ3JlZS4g
WW91IGRvbid0IG5lZWQgdG8gaW52ZXJ0IFIgPC0+IEIgZm9yIHRoZSBDdWJveCBhdAo+ID4gdGhl
IHRkYTk5OHggbGV2ZWw6IHRoaXMgbWF5IGJlIGRvbmUgc2V0dGluZyBhcyBpdCBzaG91bGQgYmUg
dGhlCj4gPiBDRkdfR1JBX1NXQVBSQiBmbGFnIG9mIHRoZSBsY2QgcmVnaXN0ZXIgTENEX1NQVV9E
TUFfQ1RSTDAuCj4gCj4gWW91IGFyZSB0b3RhbGx5IGFuZCB1dHRlcmx5IHdyb25nIHRoZXJlLiAg
V2UgbmVlZCBSIGFuZCBCIHByZXNlbnRlZCBvbgo+IHRoZWlyIGNvcnJlY3QgbGFuZXMgdG8gdGhl
IFREQTk5OHggc28gdGhhdCB0aGUgQXJtYWRhcyBZVVYtPlJHQgo+IGNvbnZlcnNpb24gd29ya3Mu
ICBTZXR0aW5nIENGR19HUkFfU1dBUFJCIGRvZXMgbm90IHN3YXAgdGhlIFlVViBvdXRwdXQKPiB0
byBtYXRjaCwgbmVpdGhlciBkb2VzIHNldHRpbmcgYW55IG9mIHRoZSBvdGhlciBiaXRzLgo+IAo+
IENGR19HUkFfU1dBUFJCIGlzIGFsbCBhYm91dCB0aGUgX2dyYXBoaWNzXyBfZnJhbWVidWZmZXJf
IGZvcm1hdCwgaXQncyBnb3QKPiBub3RoaW5nIHRvIGRvIGF0IGFsbCB3aXRoIGhvdyB0aGUgb3V0
cHV0IGlzIHdpcmVkLgoKVGhlbiwgbWF5IHlvdSBleHBsYWluIHdoeSB5b3UgbXVzdCBzd2FwIFIv
QiBvbiBzaW1wbGUgUkdCIG91dHB1dD8KCkZyb20geW91ciBbUEFUQ0ggMi81XSBEUk06IEFybWFk
YTogQWRkIEFybWFkYSBEUk0gZHJpdmVyOgoKKwlGTVQoUkdCODg4LAk4ODhQQUNLLAlDRkdfU1dB
UFJCKTsKKwlGTVQoQkdSODg4LAk4ODhQQUNLLAkwKTsKCisJRk1UKFlVWVYsCTQyMlBBQ0ssCUNG
R19ZVVYyUkdCIHwgQ0ZHX1NXQVBZVSB8IENGR19TV0FQVVYpOwoKPiA+ID4gKwkuYXVkaW9fY2Zn
ID0gQklUKDIpLAo+ID4gPiArCS5hdWRpb19mcmFtZVsxXSA9IDEsCj4gPiA+ICsJLmF1ZGlvX2Zv
cm1hdCA9IEFGTVRfU1BESUYsCj4gPiA+ICsJLmF1ZGlvX3NhbXBsZV9yYXRlID0gNDQxMDAsCj4g
PiAKPiA+IFRoZXNlIHZhbHVlcyBhcmUgcmF0aGVyIG15c3RlcmlvdXMhCj4gCj4gQWxzbyBJJ20g
Z29pbmcgdG8gaWdub3JlIHRoaXMgY29tbWVudCwgYmVjYXVzZSBxdWl0ZSBob25lc3RseSwgSSB0
aGluawo+IHRoaXMgaXMgd29ydGhsZXNzLiAgWW91IGhhdmVuJ3QgaW52ZXN0aWdhdGVkIGhvdyB0
aGUgVERBOTk4eCBhY3R1YWxseQo+IGdldHMgc2V0dXAgYnkgUmFiZWVoLgoKUmFiZWVoIGRpZCB0
aGUgbW9zdCBoZSBjb3VsZCB0byBoYXZlIGEgd29ya2luZyBDdWJveC4gSGUgdXNlZCBiYWQKd3Jp
dHRlbiBkcml2ZXJzIGFuZCBoZSBoYWQgbm90IHRoZSB0aW1lIHRvIHRoaW5rIGFib3V0IGhvdyB0
aGUgZHJpdmVycwpjb3VsZCBiZSBlbmhhbmNlZC4KCkhlcmUgaXMgYSBzbWFsbCBzdG9yeSBhYm91
dCBpMnMvc3BkaWY6IG9uY2UsIEkgc2V0IHRoZSB0ZGE5OTh4IHRvIHVzZQp0aGUgc3BkaWYgaW5w
dXQsIGFuZCBhdCB0aGlzIHRpbWUsIEkgd2FzIHVzaW5nIHRoZSBkdW1teSBjb2RlYy4KVGhpcyBj
b2RlYyBhY2NlcHRzIHRoZSBmb3JtYXQgMzJfTEUsIGFzIGRvZXMgdGhlIGF1ZGlvIGRldmljZSwg
YnV0IHRoZQpvdXRwdXQgY2Fubm90IGdvIHRvIHNwZGlmLiBSZXN1bHQ6IG5vIGhkbWkgc291bmQu
CgpTaG91bGQgd2UgcmVzdHJpY3QgdGhlIGhkbWkgdHJhbnNtaXR0ZXIgdG8gc3BkaWYgKHRodXMg
J25vIDMyIGJpdHMKc3RyZWFtJykgb3IgdG8gaTJzICh0aHVzICdubyBjb21wcmVzc2VkIHN0cmVh
bScpIG9ubHksIG9yIGFjY2VwdCBib3RoCmkycyBhbmQgc3BkaWYgYW5kIGFsbG93IGEgZnVsbCBy
YW5nZSBvZiBzdXBwb3J0ZWQgYXVkaW8gc3RyZWFtcz8KCi0tIApLZW4gYXIgYydoZW50YcOxCXwJ
ICAgICAgKiogQnJlaXpoIGhhIExpbnV4IGF0YXYhICoqCkplZgkJfAkJaHR0cDovL21vaW5lamYu
ZnJlZS5mci8KKwpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
XwpkcmktZGV2ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcK
aHR0cDovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2RyaS1kZXZlbAo=

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Mon, 7 Oct 2013 12:09:02 +0100
Message-ID: <20131007110902.GL12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk> <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
In-Reply-To: <20131007124820.2189a4c3@armhf>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Jean-Francois Moine <moinejf@free.fr>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Mon, Oct 07, 2013 at 12:48:20PM +0200, Jean-Francois Moine wrote:
> On Mon, 7 Oct 2013 10:44:04 +0100
> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
> 
> > On Mon, Oct 07, 2013 at 11:18:07AM +0200, Jean-Francois Moine wrote:
> 	[snip]
> > > It seems we are going backwards: as the Armada based boards will soon
> > > move to full DT (mvebu), you are making an exception for the Cubox, so
> > > that there should be Cubox specific kernels. I don't like that...
> > 
> > *Ignored*.  You know why.
> 
> Sorry. I don't see why. May you explain again?

I don't run DT because DT lacks most of the features I require on the
cubox.  Therefore I can't develop for DT.  Simple.

> > > > diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
> 	[snip]
> > > > +static struct tda998x_encoder_params params = {
> > > > +	/* With 0x24, there is no translation between vp_out and int_vp
> > > > +	FB	LCD out	Pins	VIP	Int Vp
> > > > +	R:23:16	R:7:0	VPC7:0	7:0	7:0[R]
> > > > +	G:15:8	G:15:8	VPB7:0	23:16	23:16[G]
> > > > +	B:7:0	B:23:16	VPA7:0	15:8	15:8[B]
> > > > +	*/
> > > > +	.swap_a = 2,
> > > > +	.swap_b = 3,
> > > > +	.swap_c = 4,
> > > > +	.swap_d = 5,
> > > > +	.swap_e = 0,
> > > > +	.swap_f = 1,
> > > 
> > > I still don't agree. You don't need to invert R <-> B for the Cubox at
> > > the tda998x level: this may be done setting as it should be the
> > > CFG_GRA_SWAPRB flag of the lcd register LCD_SPU_DMA_CTRL0.
> > 
> > You are totally and utterly wrong there.  We need R and B presented on
> > their correct lanes to the TDA998x so that the Armadas YUV->RGB
> > conversion works.  Setting CFG_GRA_SWAPRB does not swap the YUV output
> > to match, neither does setting any of the other bits.
> > 
> > CFG_GRA_SWAPRB is all about the _graphics_ _framebuffer_ format, it's got
> > nothing to do at all with how the output is wired.
> 
> Then, may you explain why you must swap R/B on simple RGB output?
> 
> From your [PATCH 2/5] DRM: Armada: Add Armada DRM driver:
> 
> +	FMT(RGB888,	888PACK,	CFG_SWAPRB);
> +	FMT(BGR888,	888PACK,	0);

I think I explained above.  This is to do with the *graphics* *framebuffer*
*format* in *memory*.  This has nothing to do with how the hardware is
wired up.

With no swapping, the 888 format is defined by the documentation to be:

	[7:0] = red
	[15:8] = green
	[23:16] = blue

Now, if you look this up in the drm_fourcc.h header file, this corresponds
with this entry:

#define DRM_FORMAT_BGR888       fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */

Hence, this is the BGR888 format with no swapping.  Therefore, my second
line is correct.

With CFG_SWAPRB set, the format in hardware becomes:

	[7:0] = blue
	[15:8] = green
	[23:16] = red

Again, if you look this up in the drm_fourcc.h header, you get:

#define DRM_FORMAT_RGB888       fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */

So, the two entries you quote above are 100% correct.

> +	FMT(YUYV,	422PACK,	CFG_YUV2RGB | CFG_SWAPYU | CFG_SWAPUV);

Where is the RGB swap there?  Again, this is to do with swapping the
format to match the hardware.  Please read the documentation on the
framebuffer formats.

The native 422PACK format is:
	[7:0] = U
	[15:8] = Y0
	[23:16] = V
	[31:24] = Y1

and we need to set both CFG_SWAPYU and CFG_SWAPUV to get this to be:
	[7:0] = V
	[15:8] = Y1
	[23:16] = U
	[31:24] = Y0

which is what the YUYV format wants.

> Rabeeh did the most he could to have a working Cubox. He used bad
> written drivers and he had not the time to think about how the drivers
> could be enhanced.

What does I2S give us in terms of "enhancement" which SPDIF does not,
remembering that audio is transmitted over HDMI in a format which closely
resembles SPDIF (but with a 28-bit subframe size.)

> Here is a small story about i2s/spdif: once, I set the tda998x to use
> the spdif input, and at this time, I was using the dummy codec.
> This codec accepts the format 32_LE, as does the audio device, but the
> output cannot go to spdif. Result: no hdmi sound.

How ASoC works in this regard is that the capabilities are the _union_ of
the codec and the cpu DAIs.

The SPDIF transmitter codec supports 16, 20 and 24 bits per sample but not
32.  Quite simply, that's because the SPDIF format does not allow 32-bits
per sample.  Therefore, 32_LE is not available for use with audio output,
and userspace must convert down to something which the hardware does
support.

"Because I2S can support 32-bit audio" is a poor reason, because you can't
pass 32-bit audio via HDMI due to a subframe being limited to 28 bits - up
to 24 bits for the sample and 4 bits of control/status information.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Mon, 07 Oct 2013 13:29:30 +0200
Message-ID: <52529B1A.7060306@gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk> <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"; Format="flowed"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131007110902.GL12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Russell King - ARM Linux <linux@arm.linux.org.uk>, Jean-Francois Moine <moinejf@free.fr>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org
List-Id: dri-devel@lists.freedesktop.org

On 10/07/2013 01:09 PM, Russell King - ARM Linux wrote:
> On Mon, Oct 07, 2013 at 12:48:20PM +0200, Jean-Francois Moine wrote:
>> On Mon, 7 Oct 2013 10:44:04 +0100
>> Rabeeh did the most he could to have a working Cubox. He used bad
>> written drivers and he had not the time to think about how the drivers
>> could be enhanced.
>
> What does I2S give us in terms of "enhancement" which SPDIF does not,
> remembering that audio is transmitted over HDMI in a format which closely
> resembles SPDIF (but with a 28-bit subframe size.)

With respect to what _most_ users want, we should use SPDIF and ignore
I2S. Consumer audio fits well into SPDIF and we get pass-through, which
we loose on I2S.

I2S _can_ support more than two channels, but only if you wire up more
DATA lines. Those are not available on Dove, so its I2S is limited to
two channel audio.

The CuBox is simply not designed for HBR or multi-channel PCM, it is a
_consumer_ settop box replacement.

Sebastian

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Jean-Francois Moine <moinejf@free.fr>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Mon, 7 Oct 2013 14:03:27 +0200
Message-ID: <20131007140327.5bb4863b@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131007110902.GL12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

T24gTW9uLCA3IE9jdCAyMDEzIDEyOjA5OjAyICswMTAwClJ1c3NlbGwgS2luZyAtIEFSTSBMaW51
eCA8bGludXhAYXJtLmxpbnV4Lm9yZy51az4gd3JvdGU6Cgo+ID4gSGVyZSBpcyBhIHNtYWxsIHN0
b3J5IGFib3V0IGkycy9zcGRpZjogb25jZSwgSSBzZXQgdGhlIHRkYTk5OHggdG8gdXNlCj4gPiB0
aGUgc3BkaWYgaW5wdXQsIGFuZCBhdCB0aGlzIHRpbWUsIEkgd2FzIHVzaW5nIHRoZSBkdW1teSBj
b2RlYy4KPiA+IFRoaXMgY29kZWMgYWNjZXB0cyB0aGUgZm9ybWF0IDMyX0xFLCBhcyBkb2VzIHRo
ZSBhdWRpbyBkZXZpY2UsIGJ1dCB0aGUKPiA+IG91dHB1dCBjYW5ub3QgZ28gdG8gc3BkaWYuIFJl
c3VsdDogbm8gaGRtaSBzb3VuZC4gIAo+IAo+IEhvdyBBU29DIHdvcmtzIGluIHRoaXMgcmVnYXJk
IGlzIHRoYXQgdGhlIGNhcGFiaWxpdGllcyBhcmUgdGhlIF91bmlvbl8gb2YKPiB0aGUgY29kZWMg
YW5kIHRoZSBjcHUgREFJcy4KPiAKPiBUaGUgU1BESUYgdHJhbnNtaXR0ZXIgY29kZWMgc3VwcG9y
dHMgMTYsIDIwIGFuZCAyNCBiaXRzIHBlciBzYW1wbGUgYnV0IG5vdAo+IDMyLiAgUXVpdGUgc2lt
cGx5LCB0aGF0J3MgYmVjYXVzZSB0aGUgU1BESUYgZm9ybWF0IGRvZXMgbm90IGFsbG93IDMyLWJp
dHMKPiBwZXIgc2FtcGxlLiAgVGhlcmVmb3JlLCAzMl9MRSBpcyBub3QgYXZhaWxhYmxlIGZvciB1
c2Ugd2l0aCBhdWRpbyBvdXRwdXQsCj4gYW5kIHVzZXJzcGFjZSBtdXN0IGNvbnZlcnQgZG93biB0
byBzb21ldGhpbmcgd2hpY2ggdGhlIGhhcmR3YXJlIGRvZXMKPiBzdXBwb3J0Lgo+IAo+ICJCZWNh
dXNlIEkyUyBjYW4gc3VwcG9ydCAzMi1iaXQgYXVkaW8iIGlzIGEgcG9vciByZWFzb24sIGJlY2F1
c2UgeW91IGNhbid0Cj4gcGFzcyAzMi1iaXQgYXVkaW8gdmlhIEhETUkgZHVlIHRvIGEgc3ViZnJh
bWUgYmVpbmcgbGltaXRlZCB0byAyOCBiaXRzIC0gdXAKPiB0byAyNCBiaXRzIGZvciB0aGUgc2Ft
cGxlIGFuZCA0IGJpdHMgb2YgY29udHJvbC9zdGF0dXMgaW5mb3JtYXRpb24uCgpPSy4gU28sIHRv
IHJlc3VtZSwgaWYgYm90aCBpMnMgYW5kIHNwZGlmIGFyZSBmdXJuaXNoZWQgYnkgdGhlIGF1ZGlv
CnN1YnN5c3RlbSwgdGhlIHRkYTk5OHggbXVzdCB1c2Ugc3BkaWYgb25seSAod2l0aCB0aGUgc3Bk
aWYgY29kZWMpLgoKVGhlbiwgdGhlIGRlY2xhcmF0aW9uIG9mIHRoZSB0ZGE5OTh4IGluIHRoZSBE
VCB3aWxsIGluY2x1ZGUgYW4Kb3B0aW9uYWwgYXVkaW8gcHJvcGVydHksIHNheSAnYXVkaW8taW5w
dXQnIHdpdGggdGhlIHZhbHVlcyAiaTJzIiBvcgoic3BkaWYiIHdoaWNoIGNvcnJlc3BvbmRzIHRv
IHlvdXIgcGFyYW1ldGVyICdhdWRpb19mb3JtYXQnLgoKQWxzbywgZnJvbSB5b3VyIHZpZGVvIHN3
YXAgZXhwbGFuYXRpb24sIHRoZSBEVCB3aWxsIGNvbnRhaW4gc29tZSB2aWRlbwpwcm9wZXJ0eShp
ZXMpIFRCRC4KClRoZSByZW1haW5pbmcgcXVlc3Rpb24gaXM6IGRvIHdlIG5lZWQgbW9yZSBhdWRp
byBwYXJhbWV0ZXJzPwoKLSB0aGUgYXVkaW9fY2ZnIHZhbHVlIGlzIGRlZmluZWQgYnkgaTJzL3Nw
ZGlmICgzIG9yIDQpCi0gdGhlIGF1ZGlvX2ZyYW1lWzFdIHZhbHVlIGlzIGFsd2F5cyAxICgyIGNo
YW5uZWxzKQotIGF1ZGlvX3NhbXBsZV9yYXRlIGlzIHVzZWxlc3MKCi0tIApLZW4gYXIgYydoZW50
YcOxCXwJICAgICAgKiogQnJlaXpoIGhhIExpbnV4IGF0YXYhICoqCkplZgkJfAkJaHR0cDovL21v
aW5lamYuZnJlZS5mci8KCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlz
dHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3Rp
bmZvL2xpbnV4LWFybS1rZXJuZWwK

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Siarhei Siamashka <siarhei.siamashka@gmail.com>
Subject: Re: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
	hardware cursors
Date: Mon, 7 Oct 2013 15:29:15 +0300
Message-ID: <20131007152915.352cc4b2@i7>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
	<E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
	<20131007110141.27f1ac25@armhf>
	<20131007094008.GH12758@n2100.arm.linux.org.uk>
	<20131007120922.47df03b6@armhf>
	<20131007103250.GJ12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org>
Received: from mail-la0-f41.google.com (mail-la0-f41.google.com
	[209.85.215.41])
	by gabe.freedesktop.org (Postfix) with ESMTP id C58FAE6EDD
	for <dri-devel@lists.freedesktop.org>;
	Mon,  7 Oct 2013 05:29:23 -0700 (PDT)
Received: by mail-la0-f41.google.com with SMTP id ec20so5620662lab.28
	for <dri-devel@lists.freedesktop.org>;
	Mon, 07 Oct 2013 05:29:22 -0700 (PDT)
In-Reply-To: <20131007103250.GJ12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.freedesktop.org/mailman/options/dri-devel>,
	<mailto:dri-devel-request@lists.freedesktop.org?subject=unsubscribe>
List-Archive: <http://lists.freedesktop.org/archives/dri-devel>
List-Post: <mailto:dri-devel@lists.freedesktop.org>
List-Help: <mailto:dri-devel-request@lists.freedesktop.org?subject=help>
List-Subscribe: <http://lists.freedesktop.org/mailman/listinfo/dri-devel>,
	<mailto:dri-devel-request@lists.freedesktop.org?subject=subscribe>
Sender: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org
Errors-To: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Mon, 7 Oct 2013 11:32:50 +0100
Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:

> On Mon, Oct 07, 2013 at 12:09:22PM +0200, Jean-Francois Moine wrote:
> > On Mon, 7 Oct 2013 10:40:08 +0100
> > Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
> > 
> > > > > This patch adds ARGB hardware cursor support to the DRM driver for the
> > > > > Marvell Armada SoCs.  ARGB cursors are supported at either 32x64 or
> > > > > 64x32 resolutions.  
> > > > 	[snip]
> > > > 
> > > > I don't see the interest of such cursors. Actually, most often, the
> > > > cursors are 64x64 and 'A' is either 0 or 0xff. As the Armada 510
> > > > supports 64x64 cursors with transparency, it would be more useful to
> > > > implement these ones...  
> > > 
> > > Sorry, you're completely wrong there.  Xorg uses an alphablended cursor.
> > > This patch is a result of trialling each of the Armada's cursor options
> > > and this is the only one which results in a reasonable looking cursor.
> > 
> > Strange. I am using the 64x64 cursor with transparency of the 510 for
> > many months and I never saw any problem.
> 
> When I tried it, all cursors had variable alpha, and converting the
> alpha to a single transparency bit made the cursor look rubbish against
> certain backgrounds.
> 
> > If you absolutely want to have all transparency shades, you should
> > accept 64x64 cursors and test if they may be rendered as 64x32 or
> > 32x64, i.e. test that there is only pure transparency in the non-
> > rendered rectangles...
> 
> That is policy, and that is something which can be done by the X server
> rather than the kernel.  The kernel exposes the hardware capabilities,
> which are to allow a 64x32 or a 32x64 cursor.  Userspace can make the
> decision dynamically which it wishes to use.
> 
> However, what you're suggesting is dangerous.  What do you do when you're
> presented with a cursor which is 64x64 ?  Do you:
> 
> (a) not display it
> (b) crash the X server
> 
> There isn't a fallback to using software cursors available in the X server
> because there's no error reporting for a failed hardware cursor update.

Hmm, maybe I'm missing something, but doesn't returning FALSE from
UseHWCursorARGB just make the X server fallback to using a software
cursor?

https://github.com/ssvb/xf86-video-fbturbo/blob/689c08256555/src/sunxi_disp_hwcursor.c#L72

I'm just doing this. And also have hooks to notify the DRI2 code about
the status of the cursor. In the case if the hardware cursor is not
enabled, hardware overlays can't be safely used with the software
cursor and we need to fallback to CPU/GPU copy instead of zero-copy
buffers swapping.

And I fully agree that it is the responsibility of the kernel to expose
as much of the hardware capabilities as possible (without compromising
reliability and/or security).

-- 
Best regards,
Siarhei Siamashka

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Mon, 7 Oct 2013 13:36:50 +0100
Message-ID: <20131007123650.GN12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk> <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <20131007140327.5bb4863b@armhf>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
In-Reply-To: <20131007140327.5bb4863b@armhf>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Jean-Francois Moine <moinejf@free.fr>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Mon, Oct 07, 2013 at 02:03:27PM +0200, Jean-Francois Moine wrote:
> On Mon, 7 Oct 2013 12:09:02 +0100
> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
> 
> > > Here is a small story about i2s/spdif: once, I set the tda998x to use
> > > the spdif input, and at this time, I was using the dummy codec.
> > > This codec accepts the format 32_LE, as does the audio device, but the
> > > output cannot go to spdif. Result: no hdmi sound.  
> > 
> > How ASoC works in this regard is that the capabilities are the _union_ of
> > the codec and the cpu DAIs.
> > 
> > The SPDIF transmitter codec supports 16, 20 and 24 bits per sample but not
> > 32.  Quite simply, that's because the SPDIF format does not allow 32-bits
> > per sample.  Therefore, 32_LE is not available for use with audio output,
> > and userspace must convert down to something which the hardware does
> > support.
> > 
> > "Because I2S can support 32-bit audio" is a poor reason, because you can't
> > pass 32-bit audio via HDMI due to a subframe being limited to 28 bits - up
> > to 24 bits for the sample and 4 bits of control/status information.
> 
> OK. So, to resume, if both i2s and spdif are furnished by the audio
> subsystem, the tda998x must use spdif only (with the spdif codec).

This is going off-topic because the TDA998x bindings are a subject for
the TDA998x driver, not the Armada driver.  This data structure merely
exists to provide the required data for the TDA998x in absence of DT
information.

To do the job properly - which is what should be done _whenever_ DT
bindings are being considered - you have to look at the hardware with
an overview of its capabilities, never at the implementation.

So, the TDA998x family needs to be looked at in isolation, and its DT
bindings need to be considered on its own merit.

The TDA998x can accept a SPDIF signal on a single pin (on AP6), with or
without a clock (on AP5), or it can accept I2S: I2S clock in APCLK, I2S
word select on AP0, and up to four I2S streams on AP1..4 and auxillary
("internal test") data in AP7.  AP7 should therefore not be used.

The TDA19988 is slightly different, because it doesn't have soo many
AP pins.  Here, SPDIF can be supplied on either AP1 or AP2 with the
optional clock on AP3.  I2S is similar to the above but only AP1 and
AP2 accept streams.

I think the I2S is a special case - I'm not aware of anything which
outputs _four_ synchronised I2S data streams with a common word select.
Nevertheless, it's something that needs to be considered when creating
DT bindings.

So, we have some quite different capabilities depending on the device.
For I2S, we can get away with this:

	tda998x {
		compatible = "nxp,tda19988", "nxp,tda998x";
		i2s-source = <&i2s_source N>;
	};

where N is the number of coherent I2S streams supplied.  For the TDA998x,
N can be 1 to 4.  For TDA19988, N can be 1 or 2 but no more.

For SPDIF, the situation is more complex.  The TDA19988 could in theory
have two streams connected, and one of those streams can be selected.
So, maybe:

	tda998x {
		compatible = "nxp,tda998x";
		spdif-source = <&spdif_source>;
		spdif-has-mclk;
	};

and for the 19988:

	tda19988 {
		compatible = "nxp,tda19988";
		spdif0-source = <&spdif_source0>;
		spdif0-has-mclk;
		spdif1-source = <&spdif_source1>;
		spdif1-has-mclk;
	};

> Also, from your video swap explanation, the DT will contain some video
> property(ies) TBD.

The TDA998x needs some properties to define how it is connected to the
rest of the hardware - which pins are connected to what in terms of the
colour channel information.  As I hope I've made clear to you, this has
no bearing on the settings in the Dove for the SWAPRB bits.  This is
purely only to do with the TDA998x.

So, this also needs to be presented as properties for the TDA998x driver.

> The remaining question is: do we need more audio parameters?
> 
> - the audio_cfg value is defined by i2s/spdif (3 or 4)

This should be discovered from the DT binding information, because which
AP pins get used depends on the signals being supplied to it.

> - the audio_frame[1] value is always 1 (2 channels)
> - audio_sample_rate is useless

audio_sample_rate comes in if we wish to use a fixed sample rate and
have coherent video and audio clocks derived from a common source.  That
allows fixed CTS and N values to be used based on the audio sample rate
being supplied as the clocks have a fixed known relationship (and aren't
going to drift.)

However, you are right that this should not be specified in DT - it
should come from the audio subsystem.  However, that's something which
is a very very long way away from being possible (if ever) with Linux
since I don't see the DPCM issues ever getting resolved.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: Re: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
Date: Mon, 7 Oct 2013 13:50:34 +0100
Message-ID: <20131007125034.GO12758@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk> <20131007110141.27f1ac25@armhf>
 <20131007094008.GH12758@n2100.arm.linux.org.uk>
 <20131007120922.47df03b6@armhf>
 <20131007103250.GJ12758@n2100.arm.linux.org.uk> <20131007152915.352cc4b2@i7>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
In-Reply-To: <20131007152915.352cc4b2@i7>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Siarhei Siamashka <siarhei.siamashka@gmail.com>
Cc: Jean-Francois Moine <moinejf@free.fr>, Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Mon, Oct 07, 2013 at 03:29:15PM +0300, Siarhei Siamashka wrote:
> On Mon, 7 Oct 2013 11:32:50 +0100
> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
> > However, what you're suggesting is dangerous.  What do you do when you're
> > presented with a cursor which is 64x64 ?  Do you:
> > 
> > (a) not display it
> > (b) crash the X server
> > 
> > There isn't a fallback to using software cursors available in the X server
> > because there's no error reporting for a failed hardware cursor update.
> 
> Hmm, maybe I'm missing something, but doesn't returning FALSE from
> UseHWCursorARGB just make the X server fallback to using a software
> cursor?
> 
> https://github.com/ssvb/xf86-video-fbturbo/blob/689c08256555/src/sunxi_disp_hwcursor.c#L72
> 
> I'm just doing this. And also have hooks to notify the DRI2 code about
> the status of the cursor. In the case if the hardware cursor is not
> enabled, hardware overlays can't be safely used with the software
> cursor and we need to fallback to CPU/GPU copy instead of zero-copy
> buffers swapping.
> 
> And I fully agree that it is the responsibility of the kernel to expose
> as much of the hardware capabilities as possible (without compromising
> reliability and/or security).

If you wish to go in below the level presented by
hw/xfree86/modes/xf86Cursors.c (as you are doing), then yes you can do
this, and it's something which maybe should be looked into.  You have a
good reason to do this (due to your hardware cursor being incompatible
with overlays).

We have no such restriction - the only issue here is the "odd" size of
cursors.  Practically, choosing one or other of 64x32 or 32x64 works
fine for the cases I've seen.  I haven't seen any cursors which are
64x64 yet.  I'm not saying they don't exist though!  I can imagine that
some accessibility options might want to display a large cursor.

Now, the way I handle this is that the kernel allows _either_ a
(1 to 32)x(1 to 64) or (1 to 64)x(1 to 32) cursor.  Both width and
height larger than 32 gets rejected with -EINVAL:

+               /* maximum size is 64x32 or 32x64 */
+               if (w > 64 || h > 64 || (w > 32 && h > 32))
+                       return -ENOMEM;

which is quite reasonable for this hardware.  However, there is no way
to export this from DRM - adding maximum cursor size properties wouldn't
really represent this.

The only question is whether DRM should export some capabilities to
indicate what's possible with the cursor, so that X knows about this
quirk of this hardware.  Overall, I suspect that it's just rare and
not worth the effort.  I think it's just easier to pick one of these
and stick with it, and if we happen to encounter a cursor larger than
our chosen dimentions, XFree86 will already automatically fall back
to s/w cursor.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Rob Clark <robdclark@gmail.com>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Mon, 7 Oct 2013 10:59:39 -0400
Message-ID: <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131007110902.GL12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Jean-Francois Moine <moinejf@free.fr>, Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Daniel Vetter <daniel@ffwll.ch>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Mon, Oct 7, 2013 at 7:09 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Oct 07, 2013 at 12:48:20PM +0200, Jean-Francois Moine wrote:
>> On Mon, 7 Oct 2013 10:44:04 +0100
>> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
>>
>> > On Mon, Oct 07, 2013 at 11:18:07AM +0200, Jean-Francois Moine wrote:
>>       [snip]
>> > > It seems we are going backwards: as the Armada based boards will soon
>> > > move to full DT (mvebu), you are making an exception for the Cubox, =
so
>> > > that there should be Cubox specific kernels. I don't like that...
>> >
>> > *Ignored*.  You know why.
>>
>> Sorry. I don't see why. May you explain again?
>
> I don't run DT because DT lacks most of the features I require on the
> cubox.  Therefore I can't develop for DT.  Simple.

Jean-Fran=E7ois, just as an aside, I really don't think code that can be
shared, like tda998x, should encode a DT requirement.. there are
plenty of platforms that don't use DT (arm isn't everything, and last
I heard aarch64 was going to be ACPI).

Beyond that, it is a driver decision whether or not to support only-DT
or DT + other.. and as long as there is a common board which can use
the driver but which is not DT, there is probably a compelling reason
to still support the non-DT case.

BR,
-R

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Mark Brown <broonie@kernel.org>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Mon, 7 Oct 2013 16:53:26 +0100
Message-ID: <20131007155326.GP21581@sirena.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <52529B1A.7060306@gmail.com>
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="===============9028014244165203053=="
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <52529B1A.7060306@gmail.com>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Jean-Francois Moine <moinejf@free.fr>, Russell King - ARM Linux <linux@arm.linux.org.uk>, Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org
List-Id: dri-devel@lists.freedesktop.org


--===============9028014244165203053==
Content-Type: multipart/signed; micalg=pgp-sha1;
	protocol="application/pgp-signature"; boundary="/NwG7NuG0/W8LcLh"
Content-Disposition: inline


--/NwG7NuG0/W8LcLh
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Mon, Oct 07, 2013 at 01:29:30PM +0200, Sebastian Hesselbarth wrote:

> I2S _can_ support more than two channels, but only if you wire up more
> DATA lines. Those are not available on Dove, so its I2S is limited to
> two channel audio.

A lot of devices implement extra channels with TDM rather than with
extra wires - you get all the left channels and all the right channels
grouped together (like with DSP/PCM modes except the channels are
ordered differently).  I'm never sure that's actually useful, though,
since it's not something that just works with most hosts that don't
understand it in hardware and most of those can do DSP/PCM anyway.

--/NwG7NuG0/W8LcLh
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)

iQIcBAEBAgAGBQJSUtjzAAoJELSic+t+oim9p0AP/0uO3qa074CmeF/JL440aC2D
YYZydx3gbk2WI8f8qBiPu8//zzPcE8xoy38fOd2kETS3zZMSC+8qHup8c1qeZybL
vv4d/uMcq+J2sHWgA5uFaOPtOP3fthwlmd7d2m4ZWUjzZTAqb8CMqDhDYJqp58w3
HbHRf42YnIxyuQKKXbmv9pdN2o+OBWEt/kEK6Msyz/NX3ZuiLFUqgMxVJhRjKRsD
JBDrMIHCz4T8pggJXX4EZUhcQcNFC9EgO4mzVhKA0JekqCyCl2R9MuNp3Mr8Wspy
ktzA3bnfIR1hoIVCXwJQ8K4LRE04Y71ArCXsHzNa6Dau2YpzPp2UvX6xQRCX8uA9
uO2kSGIKRIDWWIWafXEtf7VvRpW6Fx66aZJ0OgX+DG5LqpZb7u5EBEIjedQ9JH9n
yg9Tse13JcXpN2aVR0qe1lPCepQ3VKkJld5MdhiwpeP/AOzQThMcTYQ5YR6WKjPy
+t9Zogwtwnx333fSjl2ZWdTl6jQGjbFTVY3d7F9A87bEoNQcKRbRhlJKG+SEGvJj
xoADpDv4e/MdhPKOrSdbXwdApt2eubvJJcjhBHmDF2wbIP07QwWiGkghdwxmgt7H
mwgjyHLZzuQD1BHWNDPnWwTd68wMFkgopv+pF4+kcVIOCal/DKOmMXwVknctmBLd
LPUC5WSy+2VTS4wQb0uS
=7r9r
-----END PGP SIGNATURE-----

--/NwG7NuG0/W8LcLh--


--===============9028014244165203053==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

--===============9028014244165203053==--

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Mon, 07 Oct 2013 18:08:12 +0200
Message-ID: <5252DC6C.9060503@gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk> <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk> <52529B1A.7060306@gmail.com>
 <20131007155326.GP21581@sirena.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"; Format="flowed"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131007155326.GP21581@sirena.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Mark Brown <broonie@kernel.org>
Cc: Jean-Francois Moine <moinejf@free.fr>, Russell King - ARM Linux <linux@arm.linux.org.uk>, Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org
List-Id: dri-devel@lists.freedesktop.org

On 10/07/2013 05:53 PM, Mark Brown wrote:
> On Mon, Oct 07, 2013 at 01:29:30PM +0200, Sebastian Hesselbarth wrote:
>
>> I2S _can_ support more than two channels, but only if you wire up more
>> DATA lines. Those are not available on Dove, so its I2S is limited to
>> two channel audio.
>
> A lot of devices implement extra channels with TDM rather than with
> extra wires - you get all the left channels and all the right channels
> grouped together (like with DSP/PCM modes except the channels are
> ordered differently).  I'm never sure that's actually useful, though,
> since it's not something that just works with most hosts that don't
> understand it in hardware and most of those can do DSP/PCM anyway.

True, I didn't mention TDM modes squeezing multiple channels into one
L/R frame. Neither Dove nor TDA998x support this, but thanks for the
clarification.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Mark Brown <broonie@kernel.org>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Mon, 7 Oct 2013 18:05:48 +0100
Message-ID: <20131007170548.GR21581@sirena.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <52529B1A.7060306@gmail.com> <20131007155326.GP21581@sirena.org.uk>
 <5252DC6C.9060503@gmail.com>
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="===============2034043626992817237=="
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <5252DC6C.9060503@gmail.com>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Jean-Francois Moine <moinejf@free.fr>, Russell King - ARM Linux <linux@arm.linux.org.uk>, Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org
List-Id: dri-devel@lists.freedesktop.org


--===============2034043626992817237==
Content-Type: multipart/signed; micalg=pgp-sha1;
	protocol="application/pgp-signature"; boundary="YkilVOb9qhI0mB+X"
Content-Disposition: inline


--YkilVOb9qhI0mB+X
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Mon, Oct 07, 2013 at 06:08:12PM +0200, Sebastian Hesselbarth wrote:

> True, I didn't mention TDM modes squeezing multiple channels into one
> L/R frame. Neither Dove nor TDA998x support this, but thanks for the
> clarification.

Depending on how the DMA and so on is done you can sometimes still do it
on the CPU side by lying to the CPU about the data format (eg, tell it
that two 16 bit samples are actually a 32 bit one) though it gets messy
for I2S since you need to be able to gather all the left samples and all
the right samples.  Though given that your CODEC doesn't support it it's
still all moot anyway as you say.

--YkilVOb9qhI0mB+X
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)

iQIcBAEBAgAGBQJSUunpAAoJELSic+t+oim9uZkQAJhOMmza1NPOtZfaUyFxrzrK
oVcD3nQPnlq62LJUcInB/daitNWkGRXOdGr7ulktnGeRntobbS77CnRhXNfrfI8h
JfwesyRJHc5O4rhWaYczaZhNeOSDjLCtFdtQqxknMCWo4tP+gTBSCv9VkDjCRBg9
PI8Urif3oi2zgO34KAC+vuLsY/Pw6Ror2ORub9RI4Oky8ryX5hrm2irvi7jFzNn0
rEcMByDYC0lWfJn2cqBqmsvl/NmQOza661EMFsTTS46MkLLTSmllr6GEy0ArMhb3
ZA0LYoJDMa4kOpMluY6tU43DNj+sgeBtzHqZMvbisN+cFdILnluDwHjJfBQTUEGi
pHuPVVHFE8YbhjMH4SOBwFjJImiSpo8eQVrQk4kuxoTFHCYS71NkuZRtTD0lL02B
FToRH06o9ho88uIcaBszp8P75kF0OiF64IjmegLMCsfnUwahNTOH7cenqcQcV8av
2M+GuhLB83LTSbDaRUg11MI5DLnOIRBtca76kZu4npVh1g5ZGDy40ZiCI66MVaiK
s8vkHjzGq3FzuiQuKCwjM5AiJrEzITT9Cv2MQ9QYUOw97r8ESV2Nvl+iRyUXIpkq
GnpKSvN6jkD0VCX7ZcRf6ePmQw0XkUF32LPFMi0J9JS+owvMaLcrWaZqNRn8hvg/
L8P56MIMQ5vDiHXCwglb
=EQ7x
-----END PGP SIGNATURE-----

--YkilVOb9qhI0mB+X--


--===============2034043626992817237==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

--===============2034043626992817237==--

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Subject: Re: [PATCH 0/5] Armada DRM stuff
Date: Mon, 07 Oct 2013 23:47:55 +0200
Message-ID: <52532C0B.3090503@gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"; Format="flowed"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Russell King - ARM Linux <linux@arm.linux.org.uk>, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org
Cc: David Airlie <airlied@linux.ie>, Rob Clark <robdclark@gmail.com>, Jason Cooper <jason@lakedaemon.net>, Daniel Vetter <daniel@ffwll.ch>
List-Id: dri-devel@lists.freedesktop.org

On 10/07/2013 12:07 AM, Russell King - ARM Linux wrote:
> The Armada DRM drivers again, along with the TDA998x HDMI output support,
> and an illustration to show how to add Armada 610 support (and others.)
>
> Rob has looked at this a couple of times since its last posting, and
> has provided additional useful feedback which has been incorporated.
> I believe all the major issues have been addressed now.

Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>

on Marvell Armada 510, SolidRun CuBox with quick-hack DT support added.

Let's please get this driver mainlined and start working on proper DT
support for it. Thanks for driver and the patience to work out all
issues!

Sebastian

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Jean-Francois Moine <moinejf@free.fr>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Tue, 8 Oct 2013 11:19:13 +0200
Message-ID: <20131008111913.09bfe93e@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
Mime-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Rob Clark <robdclark@gmail.com>
Cc: Russell King - ARM Linux <linux@arm.linux.org.uk>, Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Daniel Vetter <daniel@ffwll.ch>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

T24gTW9uLCA3IE9jdCAyMDEzIDEwOjU5OjM5IC0wNDAwClJvYiBDbGFyayA8cm9iZGNsYXJrQGdt
YWlsLmNvbT4gd3JvdGU6Cgo+IEplYW4tRnJhbsOnb2lzLCBqdXN0IGFzIGFuIGFzaWRlLCBJIHJl
YWxseSBkb24ndCB0aGluayBjb2RlIHRoYXQgY2FuIGJlCj4gc2hhcmVkLCBsaWtlIHRkYTk5OHgs
IHNob3VsZCBlbmNvZGUgYSBEVCByZXF1aXJlbWVudC4uIHRoZXJlIGFyZQo+IHBsZW50eSBvZiBw
bGF0Zm9ybXMgdGhhdCBkb24ndCB1c2UgRFQgKGFybSBpc24ndCBldmVyeXRoaW5nLCBhbmQgbGFz
dAo+IEkgaGVhcmQgYWFyY2g2NCB3YXMgZ29pbmcgdG8gYmUgQUNQSSkuCj4gCj4gQmV5b25kIHRo
YXQsIGl0IGlzIGEgZHJpdmVyIGRlY2lzaW9uIHdoZXRoZXIgb3Igbm90IHRvIHN1cHBvcnQgb25s
eS1EVAo+IG9yIERUICsgb3RoZXIuLiBhbmQgYXMgbG9uZyBhcyB0aGVyZSBpcyBhIGNvbW1vbiBi
b2FyZCB3aGljaCBjYW4gdXNlCj4gdGhlIGRyaXZlciBidXQgd2hpY2ggaXMgbm90IERULCB0aGVy
ZSBpcyBwcm9iYWJseSBhIGNvbXBlbGxpbmcgcmVhc29uCj4gdG8gc3RpbGwgc3VwcG9ydCB0aGUg
bm9uLURUIGNhc2UuCgpSb2IsCgpUaGUgQ3Vib3ggaXMgYW4gb3BlbiBwbGF0Zm9ybSwgYW5kIEkg
dXNlIGl0IGp1c3QgbGlrZSBhIGRlc2t0b3AgUEMuCldoZW4gaXRzIHJlcXVpcmVkIGRyaXZlcnMg
d2lsbCBiZSBpbiB0aGUgbWFpbmxpbmUsIEkgd2lsbCBkbyB0aGUgc2FtZQphcyBJIGRvIHdpdGgg
UENzOiBJIHdpbGwgbm90IHJlY29tcGlsZSBhIHNwZWNpZmljIGtlcm5lbCBlYWNoIHRpbWUKdGhl
cmUgYXJlIGtlcm5lbCBidWdzIG9yIHNlY3VyaXR5IGlzc3Vlcy4gSW5zdGVhZCwgSSB3aWxsIGp1
c3QgdXBncmFkZQpteSBzeXN0ZW0gZnJvbSBteSBkaXN0cmlidXRvciAoRGViaWFuKSwgYW5kLCBp
biB0aGUgcGFja2FnZXMsIHRoZXJlCndpbGwgYmUgYSBnZW5lcmljIG12ZWJ1IGtlcm5lbCBhcyB0
aGVyZSBpcyBhbHJlYWR5IG9uZSBmb3IgTWFydmVsbApBcm1hZGEgMzcwL3hwLCBGcmVlc2NhbGUg
aU1YNXgvaU1YNiAobGludXgtaW1hZ2UtMy4xMC0zLWFybW1wKS4KQnV0LCBmb3IgdGhhdCwgYWxs
IHRoZSBDdWJveCBzcGVjaWZpYyBzdHVmZiBtdXN0IGJlIGRlc2NyaWJlZCBpbiBhIERULgoKLS0g
CktlbiBhciBjJ2hlbnRhw7EJfAkgICAgICAqKiBCcmVpemggaGEgTGludXggYXRhdiEgKioKSmVm
CQl8CQlodHRwOi8vbW9pbmVqZi5mcmVlLmZyLwoKX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX18KbGludXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QKbGludXgt
YXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3Jn
L21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5lbAo=

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Tue, 8 Oct 2013 10:49:39 +0100
Message-ID: <20131008094939.GD25034@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk> <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
 <20131008111913.09bfe93e@armhf>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
In-Reply-To: <20131008111913.09bfe93e@armhf>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Jean-Francois Moine <moinejf@free.fr>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Tue, Oct 08, 2013 at 11:19:13AM +0200, Jean-Francois Moine wrote:
> The Cubox is an open platform, and I use it just like a desktop PC.
> When its required drivers will be in the mainline, I will do the same
> as I do with PCs: I will not recompile a specific kernel each time
> there are kernel bugs or security issues. Instead, I will just upgrade
> my system from my distributor (Debian), and, in the packages, there
> will be a generic mvebu kernel as there is already one for Marvell
> Armada 370/xp, Freescale iMX5x/iMX6 (linux-image-3.10-3-armmp).
> But, for that, all the Cubox specific stuff must be described in a DT.

Which scenario is better:

1. To have something in mainline which is capable of driving the hardware,
   but may need some additional work to make it useful for DT based setups.

or

2. To have nothing.

Now, you may prefer to have nothing, but personally, I prefer there to be
forward progress.  Forward progress means getting some kind of DRM driver
into mainline.  Yes, it may not work with DT setups yet, but - as per
the discussions that have happened _endlessly_ on this topic, it's
something that can be resolved at a later date.

We _still_ haven't worked out how to properly deal with the TDA998x
driver (or indeed any DRM based outputs) in a DT based setup, and all
the time that problem exists, it won't be possible to write a proper
stable DT binding for this.

So please, get off your hobby horse about this and allow us to make some
modicum of progress.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Rob Clark <robdclark@gmail.com>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Tue, 8 Oct 2013 08:07:23 -0400
Message-ID: <CAF6AEGtQLL_c3zLS+S83jm505O_fcCm2mKW+Kd-oWP8EgpwzSw@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
 <20131008111913.09bfe93e@armhf>
Mime-Version: 1.0
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131008111913.09bfe93e@armhf>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Jean-Francois Moine <moinejf@free.fr>
Cc: Russell King - ARM Linux <linux@arm.linux.org.uk>, Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Daniel Vetter <daniel@ffwll.ch>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Tue, Oct 8, 2013 at 5:19 AM, Jean-Francois Moine <moinejf@free.fr> wrote:
> On Mon, 7 Oct 2013 10:59:39 -0400
> Rob Clark <robdclark@gmail.com> wrote:
>
>> Jean-Fran=E7ois, just as an aside, I really don't think code that can be
>> shared, like tda998x, should encode a DT requirement.. there are
>> plenty of platforms that don't use DT (arm isn't everything, and last
>> I heard aarch64 was going to be ACPI).
>>
>> Beyond that, it is a driver decision whether or not to support only-DT
>> or DT + other.. and as long as there is a common board which can use
>> the driver but which is not DT, there is probably a compelling reason
>> to still support the non-DT case.
>
> Rob,
>
> The Cubox is an open platform, and I use it just like a desktop PC.
> When its required drivers will be in the mainline, I will do the same
> as I do with PCs: I will not recompile a specific kernel each time
> there are kernel bugs or security issues. Instead, I will just upgrade
> my system from my distributor (Debian), and, in the packages, there
> will be a generic mvebu kernel as there is already one for Marvell
> Armada 370/xp, Freescale iMX5x/iMX6 (linux-image-3.10-3-armmp).
> But, for that, all the Cubox specific stuff must be described in a DT.

sure, I'm not saying *not* to support DT (send patches if need be).
I'm just saying that it should be ok to also support non-DT case and
that shared components (like tda998x) should also still work in non-DT
case.

BR,
-R

> --
> Ken ar c'henta=F1 |             ** Breizh ha Linux atav! **
> Jef             |               http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Jean-Francois Moine <moinejf@free.fr>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Tue, 8 Oct 2013 17:34:18 +0200
Message-ID: <20131008173418.0fc21d60@armhf>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
	<E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
	<20131007111807.5e86ea6e@armhf>
	<20131007094404.GI12758@n2100.arm.linux.org.uk>
	<20131007124820.2189a4c3@armhf>
	<20131007110902.GL12758@n2100.arm.linux.org.uk>
	<CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
	<20131008111913.09bfe93e@armhf>
	<20131008094939.GD25034@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
Return-path: <dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org>
Received: from smtp3-g21.free.fr (smtp3-g21.free.fr [212.27.42.3])
	by gabe.freedesktop.org (Postfix) with ESMTP id 5E5E8E5CC6
	for <dri-devel@lists.freedesktop.org>;
	Tue,  8 Oct 2013 08:30:52 -0700 (PDT)
In-Reply-To: <20131008094939.GD25034@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.freedesktop.org/mailman/options/dri-devel>,
	<mailto:dri-devel-request@lists.freedesktop.org?subject=unsubscribe>
List-Archive: <http://lists.freedesktop.org/archives/dri-devel>
List-Post: <mailto:dri-devel@lists.freedesktop.org>
List-Help: <mailto:dri-devel-request@lists.freedesktop.org?subject=help>
List-Subscribe: <http://lists.freedesktop.org/mailman/listinfo/dri-devel>,
	<mailto:dri-devel-request@lists.freedesktop.org?subject=subscribe>
Sender: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org
Errors-To: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

T24gVHVlLCA4IE9jdCAyMDEzIDEwOjQ5OjM5ICswMTAwClJ1c3NlbGwgS2luZyAtIEFSTSBMaW51
eCA8bGludXhAYXJtLmxpbnV4Lm9yZy51az4gd3JvdGU6Cgo+IE9uIFR1ZSwgT2N0IDA4LCAyMDEz
IGF0IDExOjE5OjEzQU0gKzAyMDAsIEplYW4tRnJhbmNvaXMgTW9pbmUgd3JvdGU6Cj4gPiBUaGUg
Q3Vib3ggaXMgYW4gb3BlbiBwbGF0Zm9ybSwgYW5kIEkgdXNlIGl0IGp1c3QgbGlrZSBhIGRlc2t0
b3AgUEMuCj4gPiBXaGVuIGl0cyByZXF1aXJlZCBkcml2ZXJzIHdpbGwgYmUgaW4gdGhlIG1haW5s
aW5lLCBJIHdpbGwgZG8gdGhlIHNhbWUKPiA+IGFzIEkgZG8gd2l0aCBQQ3M6IEkgd2lsbCBub3Qg
cmVjb21waWxlIGEgc3BlY2lmaWMga2VybmVsIGVhY2ggdGltZQo+ID4gdGhlcmUgYXJlIGtlcm5l
bCBidWdzIG9yIHNlY3VyaXR5IGlzc3Vlcy4gSW5zdGVhZCwgSSB3aWxsIGp1c3QgdXBncmFkZQo+
ID4gbXkgc3lzdGVtIGZyb20gbXkgZGlzdHJpYnV0b3IgKERlYmlhbiksIGFuZCwgaW4gdGhlIHBh
Y2thZ2VzLCB0aGVyZQo+ID4gd2lsbCBiZSBhIGdlbmVyaWMgbXZlYnUga2VybmVsIGFzIHRoZXJl
IGlzIGFscmVhZHkgb25lIGZvciBNYXJ2ZWxsCj4gPiBBcm1hZGEgMzcwL3hwLCBGcmVlc2NhbGUg
aU1YNXgvaU1YNiAobGludXgtaW1hZ2UtMy4xMC0zLWFybW1wKS4KPiA+IEJ1dCwgZm9yIHRoYXQs
IGFsbCB0aGUgQ3Vib3ggc3BlY2lmaWMgc3R1ZmYgbXVzdCBiZSBkZXNjcmliZWQgaW4gYSBEVC4K
PiAKPiBXaGljaCBzY2VuYXJpbyBpcyBiZXR0ZXI6Cj4gCj4gMS4gVG8gaGF2ZSBzb21ldGhpbmcg
aW4gbWFpbmxpbmUgd2hpY2ggaXMgY2FwYWJsZSBvZiBkcml2aW5nIHRoZSBoYXJkd2FyZSwKPiAg
ICBidXQgbWF5IG5lZWQgc29tZSBhZGRpdGlvbmFsIHdvcmsgdG8gbWFrZSBpdCB1c2VmdWwgZm9y
IERUIGJhc2VkIHNldHVwcy4KPiAKPiBvcgo+IAo+IDIuIFRvIGhhdmUgbm90aGluZy4KPiAKPiBO
b3csIHlvdSBtYXkgcHJlZmVyIHRvIGhhdmUgbm90aGluZywgYnV0IHBlcnNvbmFsbHksIEkgcHJl
ZmVyIHRoZXJlIHRvIGJlCj4gZm9yd2FyZCBwcm9ncmVzcy4gIEZvcndhcmQgcHJvZ3Jlc3MgbWVh
bnMgZ2V0dGluZyBzb21lIGtpbmQgb2YgRFJNIGRyaXZlcgo+IGludG8gbWFpbmxpbmUuICBZZXMs
IGl0IG1heSBub3Qgd29yayB3aXRoIERUIHNldHVwcyB5ZXQsIGJ1dCAtIGFzIHBlcgo+IHRoZSBk
aXNjdXNzaW9ucyB0aGF0IGhhdmUgaGFwcGVuZWQgX2VuZGxlc3NseV8gb24gdGhpcyB0b3BpYywg
aXQncwo+IHNvbWV0aGluZyB0aGF0IGNhbiBiZSByZXNvbHZlZCBhdCBhIGxhdGVyIGRhdGUuCj4g
Cj4gV2UgX3N0aWxsXyBoYXZlbid0IHdvcmtlZCBvdXQgaG93IHRvIHByb3Blcmx5IGRlYWwgd2l0
aCB0aGUgVERBOTk4eAo+IGRyaXZlciAob3IgaW5kZWVkIGFueSBEUk0gYmFzZWQgb3V0cHV0cykg
aW4gYSBEVCBiYXNlZCBzZXR1cCwgYW5kIGFsbAo+IHRoZSB0aW1lIHRoYXQgcHJvYmxlbSBleGlz
dHMsIGl0IHdvbid0IGJlIHBvc3NpYmxlIHRvIHdyaXRlIGEgcHJvcGVyCj4gc3RhYmxlIERUIGJp
bmRpbmcgZm9yIHRoaXMuCj4gCj4gU28gcGxlYXNlLCBnZXQgb2ZmIHlvdXIgaG9iYnkgaG9yc2Ug
YWJvdXQgdGhpcyBhbmQgYWxsb3cgdXMgdG8gbWFrZSBzb21lCj4gbW9kaWN1bSBvZiBwcm9ncmVz
cy4KCllvdSBmb3Jnb3Q6CgozLiBUbyBoYXZlIGFsbCBwYXRjaGVzIHJlYWR5IGZvciBzdWJtaXNz
aW9uIGFuZCBoYXZlIGEgd29ya2luZyBEVCBkcml2ZW4KICAgQ3Vib3gga2VybmVsLgoKSSB3aWxs
IHN1Ym1pdCBhIHBhdGNoIHRvIGFkZCBEVCB0byB0aGUgdGRhOTk4eCBkcml2ZXIgYXMgc29vbiBh
cyBJIGhhdmUKY2hlY2tlZCB0aGUgbmV3IGF1ZGlvIHByb3BlcnRpZXMgd2UgdGFsa2VkIGFib3V0
IHllc3RlcmRheS4KCk5vcm1hbGx5LCB0aGlzIHNob3VsZCBoYXZlIG5vIGltcGFjdCBvbiB5b3Vy
IEFybWFkYSBkcm0gZHJpdmVyLCBhbmQsCnllcywgSSB3aWxsIGFkZCBEVCB0byB5b3VyIGRyaXZl
ciBhcyBzb29uIGFzIGl0IHdpbGwgYmUgYWNjZXB0ZWQKKHNvcnJ5IHRvIG5vdCBhY2sgaXQgbm93
OiBJIGhhZCBubyB0aW1lIHlldCB0byBoYXZlIGEgbG9vayBhdCBpdCkuCgotLSAKS2VuIGFyIGMn
aGVudGHDsQl8CSAgICAgICoqIEJyZWl6aCBoYSBMaW51eCBhdGF2ISAqKgpKZWYJCXwJCWh0dHA6
Ly9tb2luZWpmLmZyZWUuZnIvCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fCmRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRldmVsQGxpc3RzLmZyZWVkZXNr
dG9wLm9yZwpodHRwOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vZHJp
LWRldmVsCg==

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Rob Clark <robdclark@gmail.com>
Subject: Re: [PATCH 0/5] Armada DRM stuff
Date: Wed, 9 Oct 2013 10:48:34 -0400
Message-ID: <CAF6AEGtPtLHZiJbTFJ5BDpWzfD-o3cH=FHnQAg9TPs0p_ZKQEw@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <52532C0B.3090503@gmail.com>
 <20131009143120.GI25034@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131009143120.GI25034@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Daniel Vetter <daniel@ffwll.ch>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Wed, Oct 9, 2013 at 10:31 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Oct 07, 2013 at 11:47:55PM +0200, Sebastian Hesselbarth wrote:
>> On 10/07/2013 12:07 AM, Russell King - ARM Linux wrote:
>>> The Armada DRM drivers again, along with the TDA998x HDMI output support,
>>> and an illustration to show how to add Armada 610 support (and others.)
>>>
>>> Rob has looked at this a couple of times since its last posting, and
>>> has provided additional useful feedback which has been incorporated.
>>> I believe all the major issues have been addressed now.
>>
>> Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>>
>> on Marvell Armada 510, SolidRun CuBox with quick-hack DT support added.
>>
>> Let's please get this driver mainlined and start working on proper DT
>> support for it. Thanks for driver and the patience to work out all
>> issues!
>
> Sebastian,
>
> I've added your tested-by now, and also updated the TDA998x patch to use
> the HDMI definitions that Jean-Francois pointed out (which is a really
> small delta, so isn't worth resending the patch set just for that).
> Thanks.
>
> All the points brought up in previous reviews concerning the physical
> address exposure, and the location of the DRM helpers have all been
> addressed, so it is now ready to be merged into mainline.  So now the
> question is how to proceed with it.
>
> However, I see no response from any DRM developers, even though they are
> around - they've been responding on a different thread about driver
> model/sysfs abuse by DRM.
>
> I'm going to pull it into my nightly build tree so it can have some
> testing with non-dove builds, and if there's still no response from
> DRM people next week, I'll put it in to linux-next via my tree so at
> least it can get some exposure and integration validation there.

fyi, I think this is in pretty good shape.. I've reviewed earlier
versions, and had an initial look at this version which addresses my
concerns, although I still intend to give a closer review of the final
version (still on my TODO list, but we have a bit of time before 3.13
merge window.. I should at least get to it by the weekend)

BR,
-R

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: Re: [PATCH 0/5] Armada DRM stuff
Date: Wed, 9 Oct 2013 15:31:20 +0100
Message-ID: <20131009143120.GI25034@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <52532C0B.3090503@gmail.com>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
In-Reply-To: <52532C0B.3090503@gmail.com>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org
List-Id: dri-devel@lists.freedesktop.org

On Mon, Oct 07, 2013 at 11:47:55PM +0200, Sebastian Hesselbarth wrote:
> On 10/07/2013 12:07 AM, Russell King - ARM Linux wrote:
>> The Armada DRM drivers again, along with the TDA998x HDMI output support,
>> and an illustration to show how to add Armada 610 support (and others.)
>>
>> Rob has looked at this a couple of times since its last posting, and
>> has provided additional useful feedback which has been incorporated.
>> I believe all the major issues have been addressed now.
>
> Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>
> on Marvell Armada 510, SolidRun CuBox with quick-hack DT support added.
>
> Let's please get this driver mainlined and start working on proper DT
> support for it. Thanks for driver and the patience to work out all
> issues!

Sebastian,

I've added your tested-by now, and also updated the TDA998x patch to use
the HDMI definitions that Jean-Francois pointed out (which is a really
small delta, so isn't worth resending the patch set just for that).
Thanks.

All the points brought up in previous reviews concerning the physical
address exposure, and the location of the DRM helpers have all been
addressed, so it is now ready to be merged into mainline.  So now the
question is how to proceed with it.

However, I see no response from any DRM developers, even though they are
around - they've been responding on a different thread about driver
model/sysfs abuse by DRM.

I'm going to pull it into my nightly build tree so it can have some
testing with non-dove builds, and if there's still no response from
DRM people next week, I'll put it in to linux-next via my tree so at
least it can get some exposure and integration validation there.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Rob Clark <robdclark@gmail.com>
Subject: Re: [PATCH 2/5] DRM: Armada: Add Armada DRM driver
Date: Thu, 10 Oct 2013 17:25:15 -0400
Message-ID: <CAF6AEGsvBaX5+c1P=ups+k=d1F3r+JphgYOt5wb7pEM3mihOQw@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Daniel Vetter <daniel@ffwll.ch>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Sun, Oct 6, 2013 at 6:08 PM, Russell King
<rmk+kernel@arm.linux.org.uk> wrote:
> This patch adds support for the pair of LCD controllers on the Marvell
> Armada 510 SoCs.  This driver supports:
> - multiple contiguous scanout buffers for video and graphics
> - shm backed cacheable buffer objects for X pixmaps for Vivante GPU
>   acceleration
> - dual lcd0 and lcd1 crt operation
> - video overlay on each LCD crt via DRM planes
> - page flipping of the main scanout buffers
> - DRM prime for buffer export/import
>
> This driver is trivial to extend to other Armada SoCs.
>
> Included in this commit is the core driver with no output support; output
> support is platform and encoder driver dependent.

w/ a couple minor comments below:

Reviewed-by: Rob Clark <robdclark@gmail.com>


> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  drivers/gpu/drm/Kconfig                 |    2 +
>  drivers/gpu/drm/Makefile                |    1 +
>  drivers/gpu/drm/armada/Kconfig          |   15 +
>  drivers/gpu/drm/armada/Makefile         |    7 +
>  drivers/gpu/drm/armada/armada_510.c     |   86 +++
>  drivers/gpu/drm/armada/armada_crtc.c    |  861 +++++++++++++++++++++++++++++++
>  drivers/gpu/drm/armada/armada_crtc.h    |   74 +++
>  drivers/gpu/drm/armada/armada_debugfs.c |  183 +++++++
>  drivers/gpu/drm/armada/armada_drm.h     |  112 ++++
>  drivers/gpu/drm/armada/armada_drv.c     |  380 ++++++++++++++
>  drivers/gpu/drm/armada/armada_fb.c      |  170 ++++++
>  drivers/gpu/drm/armada/armada_fb.h      |   24 +
>  drivers/gpu/drm/armada/armada_fbdev.c   |  202 ++++++++
>  drivers/gpu/drm/armada/armada_gem.c     |  616 ++++++++++++++++++++++
>  drivers/gpu/drm/armada/armada_gem.h     |   52 ++
>  drivers/gpu/drm/armada/armada_hw.h      |  316 +++++++++++
>  drivers/gpu/drm/armada/armada_ioctlP.h  |   18 +
>  drivers/gpu/drm/armada/armada_output.c  |  158 ++++++
>  drivers/gpu/drm/armada/armada_output.h  |   39 ++
>  drivers/gpu/drm/armada/armada_overlay.c |  477 +++++++++++++++++
>  drivers/gpu/drm/armada/armada_slave.c   |  139 +++++
>  drivers/gpu/drm/armada/armada_slave.h   |   26 +
>  include/drm/drm_crtc.h                  |   17 +
>  include/uapi/drm/armada_drm.h           |   45 ++
>  24 files changed, 4020 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/gpu/drm/armada/Kconfig
>  create mode 100644 drivers/gpu/drm/armada/Makefile
>  create mode 100644 drivers/gpu/drm/armada/armada_510.c
>  create mode 100644 drivers/gpu/drm/armada/armada_crtc.c
>  create mode 100644 drivers/gpu/drm/armada/armada_crtc.h
>  create mode 100644 drivers/gpu/drm/armada/armada_debugfs.c
>  create mode 100644 drivers/gpu/drm/armada/armada_drm.h
>  create mode 100644 drivers/gpu/drm/armada/armada_drv.c
>  create mode 100644 drivers/gpu/drm/armada/armada_fb.c
>  create mode 100644 drivers/gpu/drm/armada/armada_fb.h
>  create mode 100644 drivers/gpu/drm/armada/armada_fbdev.c
>  create mode 100644 drivers/gpu/drm/armada/armada_gem.c
>  create mode 100644 drivers/gpu/drm/armada/armada_gem.h
>  create mode 100644 drivers/gpu/drm/armada/armada_hw.h
>  create mode 100644 drivers/gpu/drm/armada/armada_ioctlP.h
>  create mode 100644 drivers/gpu/drm/armada/armada_output.c
>  create mode 100644 drivers/gpu/drm/armada/armada_output.h
>  create mode 100644 drivers/gpu/drm/armada/armada_overlay.c
>  create mode 100644 drivers/gpu/drm/armada/armada_slave.c
>  create mode 100644 drivers/gpu/drm/armada/armada_slave.h
>  create mode 100644 include/uapi/drm/armada_drm.h
>
[snip]
> +/*
> + * Prepare for a mode set.  Turn off overlay to ensure that we don't end
> + * up with the overlay size being bigger than the active screen size.
> + * We rely upon X refreshing this state after the mode set has completed.
> + *
> + * The mode_config.mutex will be held for this call
> + */
> +static void armada_drm_crtc_prepare(struct drm_crtc *crtc)
> +{
> +       struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
> +       struct drm_plane *plane;
> +
> +       /*
> +        * If we have an overlay plane associated with this CRTC, disable
> +        * it before the modeset to avoid its coordinates being outside
> +        * the new mode parameters.  DRM doesn't provide help with this.
> +        */

Getting a bit off topic, but yeah.. I'd be in favor of "clarifying"
things by having crtc helpers disable planes on setcrtc (rather than
only doing this on fbdev/lastclose restore).  I
don't know of any userspace that this would cause problems for.  But
not really sure if it would be considered an interface break or just
"fixing a bug".. since we have different behavior on different
drivers, I'd lean towards the latter.

> +       plane = dcrtc->plane;
> +       if (plane) {
> +               struct drm_framebuffer *fb = plane->fb;
> +
> +               plane->funcs->disable_plane(plane);
> +               plane->fb = NULL;
> +               plane->crtc = NULL;
> +               drm_framebuffer_unreference(fb);
> +       }
> +}


> diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
> new file mode 100644
> index 0000000..c865a9a
> --- /dev/null
> +++ b/drivers/gpu/drm/armada/armada_gem.c
> @@ -0,0 +1,616 @@
> +/*
> + * Copyright (C) 2012 Russell King
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#include <linux/dma-buf.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/shmem_fs.h>
> +#include <drm/drmP.h>
> +#include "armada_drm.h"
> +#include "armada_gem.h"
> +#include <drm/armada_drm.h>
> +#include "armada_ioctlP.h"
> +
> +static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
> +{
> +       struct armada_gem_object *obj = drm_to_armada_gem(vma->vm_private_data);
> +       unsigned long addr = (unsigned long)vmf->virtual_address;
> +       unsigned long pfn = obj->phys_addr >> PAGE_SHIFT;
> +       int ret;
> +
> +       pfn += (addr - vma->vm_start) >> PAGE_SHIFT;
> +       ret = vm_insert_pfn(vma, addr, pfn);
> +
> +       switch (ret) {
> +       case -EIO:
> +       case -EAGAIN:
> +               set_need_resched();

probably this thread is applicable here too?

https://lkml.org/lkml/2013/9/12/417

(although.. we have at least a few  slightly differet variants on the
same errno -> VM_FAULT_x switch in different drivers.. maybe we should
do something better)

> +       case 0:
> +       case -ERESTARTSYS:
> +       case -EINTR:
> +       case -EBUSY:
> +               return VM_FAULT_NOPAGE;
> +       case -ENOMEM:
> +               return VM_FAULT_OOM;
> +       default:
> +               return VM_FAULT_SIGBUS;
> +       }
> +}
> +

[snip]

> +/* Prime support */
> +struct sg_table *
> +armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
> +       enum dma_data_direction dir)
> +{
> +       struct drm_gem_object *obj = attach->dmabuf->priv;
> +       struct armada_gem_object *dobj = drm_to_armada_gem(obj);
> +       struct scatterlist *sg;
> +       struct sg_table *sgt;
> +       int i, num;
> +
> +       sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
> +       if (!sgt)
> +               return NULL;
> +
> +       if (dobj->obj.filp) {
> +               struct address_space *mapping;
> +               gfp_t gfp;
> +               int count;
> +
> +               count = dobj->obj.size / PAGE_SIZE;
> +               if (sg_alloc_table(sgt, count, GFP_KERNEL))
> +                       goto free_sgt;
> +
> +               mapping = file_inode(dobj->obj.filp)->i_mapping;
> +               gfp = mapping_gfp_mask(mapping);
> +
> +               for_each_sg(sgt->sgl, sg, count, i) {
> +                       struct page *page;
> +
> +                       page = shmem_read_mapping_page_gfp(mapping, i, gfp);

you could almost use drm_gem_get_pages().. although I guess you
otherwise have no need for the page[] array?

(the page array would be handy if you supported mmap on shmem backed
files.. which as long as they are cached should be the easy case)

> +                       if (IS_ERR(page)) {
> +                               num = i;
> +                               goto release;
> +                       }
> +
> +                       sg_set_page(sg, page, PAGE_SIZE, 0);
> +               }
> +
> +               if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0) {
> +                       num = sgt->nents;
> +                       goto release;
> +               }
> +       } else if (dobj->page) {
> +               /* Single contiguous page */
> +               if (sg_alloc_table(sgt, 1, GFP_KERNEL))
> +                       goto free_sgt;
> +
> +               sg_set_page(sgt->sgl, dobj->page, dobj->obj.size, 0);
> +
> +               if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0)
> +                       goto free_table;
> +       } else if (dobj->linear) {
> +               /* Single contiguous physical region - no struct page */
> +               if (sg_alloc_table(sgt, 1, GFP_KERNEL))
> +                       goto free_sgt;
> +               sg_dma_address(sgt->sgl) = dobj->dev_addr;
> +               sg_dma_len(sgt->sgl) = dobj->obj.size;
> +       } else {
> +               goto free_sgt;
> +       }
> +       return sgt;
> +
> + release:
> +       for_each_sg(sgt->sgl, sg, num, i)
> +               page_cache_release(sg_page(sg));
> + free_table:
> +       sg_free_table(sgt);
> + free_sgt:
> +       kfree(sgt);
> +       return NULL;
> +}
[snip]
> +> diff --git a/include/uapi/drm/armada_drm.h b/include/uapi/drm/armada_drm.h
> new file mode 100644
> index 0000000..8dec3fd
> --- /dev/null
> +++ b/include/uapi/drm/armada_drm.h
> @@ -0,0 +1,45 @@
> +/*
> + * Copyright (C) 2012 Russell King
> + *  With inspiration from the i915 driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#ifndef DRM_ARMADA_IOCTL_H
> +#define DRM_ARMADA_IOCTL_H
> +
> +#define DRM_ARMADA_GEM_CREATE          0x00
> +#define DRM_ARMADA_GEM_MMAP            0x02
> +#define DRM_ARMADA_GEM_PWRITE          0x03
> +
> +#define ARMADA_IOCTL(dir, name, str) \
> +       DRM_##dir(DRM_COMMAND_BASE + DRM_ARMADA_##name, struct drm_armada_##str)
> +
> +struct drm_armada_gem_create {

Any reason not to throw in a 'uint32_t flags' field?  At least then
you could indicate what sort of backing memory you want, and do things
like allocate linear scanout buffer w/ your gem_create rather than
having to use dumb_create.  Maybe not something you need now, but
seems like eventually you'll come up with some reason or another to
want to pass some flags into gem_create.

> +       uint32_t handle;
> +       uint32_t size;
> +};
> +#define DRM_IOCTL_ARMADA_GEM_CREATE \
> +       ARMADA_IOCTL(IOWR, GEM_CREATE, gem_create)
> +
> +struct drm_armada_gem_mmap {
> +       uint32_t handle;
> +       uint32_t pad;
> +       uint64_t offset;
> +       uint64_t size;
> +       uint64_t addr;
> +};
> +#define DRM_IOCTL_ARMADA_GEM_MMAP \
> +       ARMADA_IOCTL(IOWR, GEM_MMAP, gem_mmap)
> +
> +struct drm_armada_gem_pwrite {
> +       uint64_t ptr;
> +       uint32_t handle;
> +       uint32_t offset;
> +       uint32_t size;
> +};
> +#define DRM_IOCTL_ARMADA_GEM_PWRITE \
> +       ARMADA_IOCTL(IOW, GEM_PWRITE, gem_pwrite)
> +
> +#endif
> --
> 1.7.4.4
>

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: Re: [PATCH 2/5] DRM: Armada: Add Armada DRM driver
Date: Thu, 10 Oct 2013 22:59:51 +0100
Message-ID: <20131010215951.GS25034@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
 <CAF6AEGsvBaX5+c1P=ups+k=d1F3r+JphgYOt5wb7pEM3mihOQw@mail.gmail.com>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
In-Reply-To: <CAF6AEGsvBaX5+c1P=ups+k=d1F3r+JphgYOt5wb7pEM3mihOQw@mail.gmail.com>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Rob Clark <robdclark@gmail.com>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Daniel Vetter <daniel@ffwll.ch>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Thu, Oct 10, 2013 at 05:25:15PM -0400, Rob Clark wrote:
> On Sun, Oct 6, 2013 at 6:08 PM, Russell King
> <rmk+kernel@arm.linux.org.uk> wrote:
> > +       /*
> > +        * If we have an overlay plane associated with this CRTC, disable
> > +        * it before the modeset to avoid its coordinates being outside
> > +        * the new mode parameters.  DRM doesn't provide help with this.
> > +        */
> 
> Getting a bit off topic, but yeah.. I'd be in favor of "clarifying"
> things by having crtc helpers disable planes on setcrtc (rather than
> only doing this on fbdev/lastclose restore).  I
> don't know of any userspace that this would cause problems for.  But
> not really sure if it would be considered an interface break or just
> "fixing a bug".. since we have different behavior on different
> drivers, I'd lean towards the latter.

The reasoning here is if the overlay plane is larger than the mode being
set, we will end up having the hardware programmed in an inconsistent
state - the overlay plane position/width/height can be outside of the
active region, which is invalid for the hardware.  So, it's safer to
disable the plane and wait for the next plane to be sent and have that
validated against the new mode.

It's not like you would be able to see the plane immediately, because
most monitors blank while they retrain to the new mode settings.

> > +static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
> > +{
> > +       struct armada_gem_object *obj = drm_to_armada_gem(vma->vm_private_data);
> > +       unsigned long addr = (unsigned long)vmf->virtual_address;
> > +       unsigned long pfn = obj->phys_addr >> PAGE_SHIFT;
> > +       int ret;
> > +
> > +       pfn += (addr - vma->vm_start) >> PAGE_SHIFT;
> > +       ret = vm_insert_pfn(vma, addr, pfn);
> > +
> > +       switch (ret) {
> > +       case -EIO:
> > +       case -EAGAIN:
> > +               set_need_resched();
> 
> probably this thread is applicable here too?
> 
> https://lkml.org/lkml/2013/9/12/417
> 
> (although.. we have at least a few  slightly differet variants on the
> same errno -> VM_FAULT_x switch in different drivers.. maybe we should
> do something better)

Hmm.  It seems today's vm_insert_pfn() has the following error return
values:

-EFAULT - virtual address outside vma
-EINVAL - track_pfn_insert() failure
-ENOMEM - failed to get locked pte
-EBUSY - entry already exists in pte

So it seems my handling -EIO, -EAGAIN, -ERESTARTSYS and -EINTR are all
redundant and can be removed.  I'm not sure if it makes sense for this
to be generic - it looks like it's only Intel, gma500 and me who use
this, and Intel handles more error codes (due to it calling other
functions.)

I'll respin dropping those four unnecessary error codes, and post the
delta for this.

> > +/* Prime support */
> > +struct sg_table *
> > +armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
> > +       enum dma_data_direction dir)
> > +{
> > +       struct drm_gem_object *obj = attach->dmabuf->priv;
> > +       struct armada_gem_object *dobj = drm_to_armada_gem(obj);
> > +       struct scatterlist *sg;
> > +       struct sg_table *sgt;
> > +       int i, num;
> > +
> > +       sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
> > +       if (!sgt)
> > +               return NULL;
> > +
> > +       if (dobj->obj.filp) {
> > +               struct address_space *mapping;
> > +               gfp_t gfp;
> > +               int count;
> > +
> > +               count = dobj->obj.size / PAGE_SIZE;
> > +               if (sg_alloc_table(sgt, count, GFP_KERNEL))
> > +                       goto free_sgt;
> > +
> > +               mapping = file_inode(dobj->obj.filp)->i_mapping;
> > +               gfp = mapping_gfp_mask(mapping);
> > +
> > +               for_each_sg(sgt->sgl, sg, count, i) {
> > +                       struct page *page;
> > +
> > +                       page = shmem_read_mapping_page_gfp(mapping, i, gfp);
> 
> you could almost use drm_gem_get_pages().. although I guess you
> otherwise have no need for the page[] array?

Correct.  The page[] array would just be an additional unnecessary
allocation, and therefore would be an additional unnecessary point of
failure.

> > +#define DRM_ARMADA_GEM_CREATE          0x00
> > +#define DRM_ARMADA_GEM_MMAP            0x02
> > +#define DRM_ARMADA_GEM_PWRITE          0x03
> > +
> > +#define ARMADA_IOCTL(dir, name, str) \
> > +       DRM_##dir(DRM_COMMAND_BASE + DRM_ARMADA_##name, struct drm_armada_##str)
> > +
> > +struct drm_armada_gem_create {
> 
> Any reason not to throw in a 'uint32_t flags' field?  At least then
> you could indicate what sort of backing memory you want, and do things
> like allocate linear scanout buffer w/ your gem_create rather than
> having to use dumb_create.  Maybe not something you need now, but
> seems like eventually you'll come up with some reason or another to
> want to pass some flags into gem_create.

I thought one of the points of the dumb_create stuff was so that there
is a standard API for dumb scanout buffers across all DRM drivers.  It
has that advantage, and as I understand it, a generic KMS driver for X
is on the cards.

Thanks for the review.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Rob Clark <robdclark@gmail.com>
Subject: Re: [PATCH 2/5] DRM: Armada: Add Armada DRM driver
Date: Thu, 10 Oct 2013 18:23:26 -0400
Message-ID: <CAF6AEGvNyD8-_t2y69a5Gjey7Jg_LXVYNgpYW1rsFFyTkABg=Q@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
	<E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
	<CAF6AEGsvBaX5+c1P=ups+k=d1F3r+JphgYOt5wb7pEM3mihOQw@mail.gmail.com>
	<20131010215951.GS25034@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org>
Received: from mail-pd0-f173.google.com (mail-pd0-f173.google.com
	[209.85.192.173])
	by gabe.freedesktop.org (Postfix) with ESMTP id 27AC7E66D1
	for <dri-devel@lists.freedesktop.org>;
	Thu, 10 Oct 2013 15:23:27 -0700 (PDT)
Received: by mail-pd0-f173.google.com with SMTP id p10so3306782pdj.18
	for <dri-devel@lists.freedesktop.org>;
	Thu, 10 Oct 2013 15:23:27 -0700 (PDT)
In-Reply-To: <20131010215951.GS25034@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.freedesktop.org/mailman/options/dri-devel>,
	<mailto:dri-devel-request@lists.freedesktop.org?subject=unsubscribe>
List-Archive: <http://lists.freedesktop.org/archives/dri-devel>
List-Post: <mailto:dri-devel@lists.freedesktop.org>
List-Help: <mailto:dri-devel-request@lists.freedesktop.org?subject=help>
List-Subscribe: <http://lists.freedesktop.org/mailman/listinfo/dri-devel>,
	<mailto:dri-devel-request@lists.freedesktop.org?subject=subscribe>
Sender: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org
Errors-To: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Thu, Oct 10, 2013 at 5:59 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Oct 10, 2013 at 05:25:15PM -0400, Rob Clark wrote:
>> On Sun, Oct 6, 2013 at 6:08 PM, Russell King
>> <rmk+kernel@arm.linux.org.uk> wrote:
>> > +       /*
>> > +        * If we have an overlay plane associated with this CRTC, disable
>> > +        * it before the modeset to avoid its coordinates being outside
>> > +        * the new mode parameters.  DRM doesn't provide help with this.
>> > +        */
>>
>> Getting a bit off topic, but yeah.. I'd be in favor of "clarifying"
>> things by having crtc helpers disable planes on setcrtc (rather than
>> only doing this on fbdev/lastclose restore).  I
>> don't know of any userspace that this would cause problems for.  But
>> not really sure if it would be considered an interface break or just
>> "fixing a bug".. since we have different behavior on different
>> drivers, I'd lean towards the latter.
>
> The reasoning here is if the overlay plane is larger than the mode being
> set, we will end up having the hardware programmed in an inconsistent
> state - the overlay plane position/width/height can be outside of the
> active region, which is invalid for the hardware.  So, it's safer to
> disable the plane and wait for the next plane to be sent and have that
> validated against the new mode.

right.  I think disabling the planes is the correct behavior.  So
nothing to do here for armada.  I mostly just wanted to get some
opinions about making the crtc helpers do this automatically for us.

> It's not like you would be able to see the plane immediately, because
> most monitors blank while they retrain to the new mode settings.
>
>> > +static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
>> > +{
>> > +       struct armada_gem_object *obj = drm_to_armada_gem(vma->vm_private_data);
>> > +       unsigned long addr = (unsigned long)vmf->virtual_address;
>> > +       unsigned long pfn = obj->phys_addr >> PAGE_SHIFT;
>> > +       int ret;
>> > +
>> > +       pfn += (addr - vma->vm_start) >> PAGE_SHIFT;
>> > +       ret = vm_insert_pfn(vma, addr, pfn);
>> > +
>> > +       switch (ret) {
>> > +       case -EIO:
>> > +       case -EAGAIN:
>> > +               set_need_resched();
>>
>> probably this thread is applicable here too?
>>
>> https://lkml.org/lkml/2013/9/12/417
>>
>> (although.. we have at least a few  slightly differet variants on the
>> same errno -> VM_FAULT_x switch in different drivers.. maybe we should
>> do something better)
>
> Hmm.  It seems today's vm_insert_pfn() has the following error return
> values:
>
> -EFAULT - virtual address outside vma
> -EINVAL - track_pfn_insert() failure
> -ENOMEM - failed to get locked pte
> -EBUSY - entry already exists in pte
>
> So it seems my handling -EIO, -EAGAIN, -ERESTARTSYS and -EINTR are all
> redundant and can be removed.  I'm not sure if it makes sense for this
> to be generic - it looks like it's only Intel, gma500 and me who use
> this, and Intel handles more error codes (due to it calling other
> functions.)

I just noticed msm and omapdrm are missing the -EBUSY case (have some
patches I need to send), which was why I mentioned this.  They do have
other error cases from other fxns, so maybe something generic/common
doesn't make sense..  but I realized i915 fixed the same issue a while
back, so somewhere common has the advantage of somehow not forgetting
to fix other drivers ;-)

> I'll respin dropping those four unnecessary error codes, and post the
> delta for this.
>
>> > +/* Prime support */
>> > +struct sg_table *
>> > +armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
>> > +       enum dma_data_direction dir)
>> > +{
>> > +       struct drm_gem_object *obj = attach->dmabuf->priv;
>> > +       struct armada_gem_object *dobj = drm_to_armada_gem(obj);
>> > +       struct scatterlist *sg;
>> > +       struct sg_table *sgt;
>> > +       int i, num;
>> > +
>> > +       sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
>> > +       if (!sgt)
>> > +               return NULL;
>> > +
>> > +       if (dobj->obj.filp) {
>> > +               struct address_space *mapping;
>> > +               gfp_t gfp;
>> > +               int count;
>> > +
>> > +               count = dobj->obj.size / PAGE_SIZE;
>> > +               if (sg_alloc_table(sgt, count, GFP_KERNEL))
>> > +                       goto free_sgt;
>> > +
>> > +               mapping = file_inode(dobj->obj.filp)->i_mapping;
>> > +               gfp = mapping_gfp_mask(mapping);
>> > +
>> > +               for_each_sg(sgt->sgl, sg, count, i) {
>> > +                       struct page *page;
>> > +
>> > +                       page = shmem_read_mapping_page_gfp(mapping, i, gfp);
>>
>> you could almost use drm_gem_get_pages().. although I guess you
>> otherwise have no need for the page[] array?
>
> Correct.  The page[] array would just be an additional unnecessary
> allocation, and therefore would be an additional unnecessary point of
> failure.
>
>> > +#define DRM_ARMADA_GEM_CREATE          0x00
>> > +#define DRM_ARMADA_GEM_MMAP            0x02
>> > +#define DRM_ARMADA_GEM_PWRITE          0x03
>> > +
>> > +#define ARMADA_IOCTL(dir, name, str) \
>> > +       DRM_##dir(DRM_COMMAND_BASE + DRM_ARMADA_##name, struct drm_armada_##str)
>> > +
>> > +struct drm_armada_gem_create {
>>
>> Any reason not to throw in a 'uint32_t flags' field?  At least then
>> you could indicate what sort of backing memory you want, and do things
>> like allocate linear scanout buffer w/ your gem_create rather than
>> having to use dumb_create.  Maybe not something you need now, but
>> seems like eventually you'll come up with some reason or another to
>> want to pass some flags into gem_create.
>
> I thought one of the points of the dumb_create stuff was so that there
> is a standard API for dumb scanout buffers across all DRM drivers.  It
> has that advantage, and as I understand it, a generic KMS driver for X
> is on the cards.

Yeah, xf86-video-modesetting currently uses dumb allocation.  So you
definitely want to continue to support the dumb buffer path.

I can't really think of any immediate need for 'flags'..  but seems
like sooner or later someone will come up with some need for it, so it
seemed like a convenient placeholder to have.

Well, technically you can get away w/ adding new fields to the end of
the ioctl struct, and drm_ioctl() will take care of zero'ing that out
for you with an old userspace.  So I guess you could just rely on that
if you ever need to add 'flags' or some other fields.

> Thanks for the review.

no prob

BR,
-R

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: Re: [PATCH 2/5] DRM: Armada: Add Armada DRM driver
Date: Thu, 10 Oct 2013 23:53:31 +0100
Message-ID: <20131010225331.GT25034@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
 <CAF6AEGsvBaX5+c1P=ups+k=d1F3r+JphgYOt5wb7pEM3mihOQw@mail.gmail.com>
 <20131010215951.GS25034@n2100.arm.linux.org.uk>
 <CAF6AEGvNyD8-_t2y69a5Gjey7Jg_LXVYNgpYW1rsFFyTkABg=Q@mail.gmail.com>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
In-Reply-To: <CAF6AEGvNyD8-_t2y69a5Gjey7Jg_LXVYNgpYW1rsFFyTkABg=Q@mail.gmail.com>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Rob Clark <robdclark@gmail.com>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Daniel Vetter <daniel@ffwll.ch>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Thu, Oct 10, 2013 at 06:23:26PM -0400, Rob Clark wrote:
> On Thu, Oct 10, 2013 at 5:59 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Thu, Oct 10, 2013 at 05:25:15PM -0400, Rob Clark wrote:
> >> probably this thread is applicable here too?
> >>
> >> https://lkml.org/lkml/2013/9/12/417
> >>
> >> (although.. we have at least a few  slightly differet variants on the
> >> same errno -> VM_FAULT_x switch in different drivers.. maybe we should
> >> do something better)
> >
> > Hmm.  It seems today's vm_insert_pfn() has the following error return
> > values:
> >
> > -EFAULT - virtual address outside vma
> > -EINVAL - track_pfn_insert() failure
> > -ENOMEM - failed to get locked pte
> > -EBUSY - entry already exists in pte
> >
> > So it seems my handling -EIO, -EAGAIN, -ERESTARTSYS and -EINTR are all
> > redundant and can be removed.  I'm not sure if it makes sense for this
> > to be generic - it looks like it's only Intel, gma500 and me who use
> > this, and Intel handles more error codes (due to it calling other
> > functions.)
> 
> I just noticed msm and omapdrm are missing the -EBUSY case (have some
> patches I need to send), which was why I mentioned this.  They do have
> other error cases from other fxns, so maybe something generic/common
> doesn't make sense..  but I realized i915 fixed the same issue a while
> back, so somewhere common has the advantage of somehow not forgetting
> to fix other drivers ;-)

Here's the promised delta:

 drivers/gpu/drm/armada/armada_gem.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index 02de7a4..1e74f70 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -25,12 +25,7 @@ static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	ret = vm_insert_pfn(vma, addr, pfn);
 
 	switch (ret) {
-	case -EIO:
-	case -EAGAIN:
-		set_need_resched();
 	case 0:
-	case -ERESTARTSYS:
-	case -EINTR:
 	case -EBUSY:
 		return VM_FAULT_NOPAGE;
 	case -ENOMEM:

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Rob Clark <robdclark@gmail.com>
Subject: Re: [PATCH 2/5] DRM: Armada: Add Armada DRM driver
Date: Thu, 10 Oct 2013 20:10:58 -0400
Message-ID: <CAF6AEGvb-oeQqYF-XyZ1PjCaqojJ=DurLVGkZxUFwC_WveoTwg@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
	<E1VSwVU-0000hu-09@rmk-PC.arm.linux.org.uk>
	<CAF6AEGsvBaX5+c1P=ups+k=d1F3r+JphgYOt5wb7pEM3mihOQw@mail.gmail.com>
	<20131010215951.GS25034@n2100.arm.linux.org.uk>
	<CAF6AEGvNyD8-_t2y69a5Gjey7Jg_LXVYNgpYW1rsFFyTkABg=Q@mail.gmail.com>
	<20131010225331.GT25034@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org>
Received: from mail-ie0-f180.google.com (mail-ie0-f180.google.com
	[209.85.223.180])
	by gabe.freedesktop.org (Postfix) with ESMTP id ED5B2E5CFD
	for <dri-devel@lists.freedesktop.org>;
	Thu, 10 Oct 2013 17:10:58 -0700 (PDT)
Received: by mail-ie0-f180.google.com with SMTP id e14so2282221iej.39
	for <dri-devel@lists.freedesktop.org>;
	Thu, 10 Oct 2013 17:10:58 -0700 (PDT)
In-Reply-To: <20131010225331.GT25034@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.freedesktop.org/mailman/options/dri-devel>,
	<mailto:dri-devel-request@lists.freedesktop.org?subject=unsubscribe>
List-Archive: <http://lists.freedesktop.org/archives/dri-devel>
List-Post: <mailto:dri-devel@lists.freedesktop.org>
List-Help: <mailto:dri-devel-request@lists.freedesktop.org?subject=help>
List-Subscribe: <http://lists.freedesktop.org/mailman/listinfo/dri-devel>,
	<mailto:dri-devel-request@lists.freedesktop.org?subject=subscribe>
Sender: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org
Errors-To: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Thu, Oct 10, 2013 at 6:53 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Oct 10, 2013 at 06:23:26PM -0400, Rob Clark wrote:
>> On Thu, Oct 10, 2013 at 5:59 PM, Russell King - ARM Linux
>> <linux@arm.linux.org.uk> wrote:
>> > On Thu, Oct 10, 2013 at 05:25:15PM -0400, Rob Clark wrote:
>> >> probably this thread is applicable here too?
>> >>
>> >> https://lkml.org/lkml/2013/9/12/417
>> >>
>> >> (although.. we have at least a few  slightly differet variants on the
>> >> same errno -> VM_FAULT_x switch in different drivers.. maybe we should
>> >> do something better)
>> >
>> > Hmm.  It seems today's vm_insert_pfn() has the following error return
>> > values:
>> >
>> > -EFAULT - virtual address outside vma
>> > -EINVAL - track_pfn_insert() failure
>> > -ENOMEM - failed to get locked pte
>> > -EBUSY - entry already exists in pte
>> >
>> > So it seems my handling -EIO, -EAGAIN, -ERESTARTSYS and -EINTR are all
>> > redundant and can be removed.  I'm not sure if it makes sense for this
>> > to be generic - it looks like it's only Intel, gma500 and me who use
>> > this, and Intel handles more error codes (due to it calling other
>> > functions.)
>>
>> I just noticed msm and omapdrm are missing the -EBUSY case (have some
>> patches I need to send), which was why I mentioned this.  They do have
>> other error cases from other fxns, so maybe something generic/common
>> doesn't make sense..  but I realized i915 fixed the same issue a while
>> back, so somewhere common has the advantage of somehow not forgetting
>> to fix other drivers ;-)
>
> Here's the promised delta:

looks good.. I'll try to get to reviewing the rest of the series
tomorrow, or at least before the end of the weekend

Reviewed-by: Rob Clark <robdclark@gmail.com>

BR,
-R

>  drivers/gpu/drm/armada/armada_gem.c |    5 -----
>  1 files changed, 0 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
> index 02de7a4..1e74f70 100644
> --- a/drivers/gpu/drm/armada/armada_gem.c
> +++ b/drivers/gpu/drm/armada/armada_gem.c
> @@ -25,12 +25,7 @@ static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
>         ret = vm_insert_pfn(vma, addr, pfn);
>
>         switch (ret) {
> -       case -EIO:
> -       case -EAGAIN:
> -               set_need_resched();
>         case 0:
> -       case -ERESTARTSYS:
> -       case -EINTR:
>         case -EBUSY:
>                 return VM_FAULT_NOPAGE;
>         case -ENOMEM:
>

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Rob Clark <robdclark@gmail.com>
Subject: Re: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
Date: Thu, 17 Oct 2013 19:58:32 -0400
Message-ID: <CAF6AEGt1uOsE5V6rAtxpLNNaYkaKiw9G8CNdt31JZVdS6TX-hA@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
 <20131007110141.27f1ac25@armhf>
 <20131007094008.GH12758@n2100.arm.linux.org.uk>
 <20131007120922.47df03b6@armhf>
 <20131007103250.GJ12758@n2100.arm.linux.org.uk>
 <20131007152915.352cc4b2@i7>
 <20131007125034.GO12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131007125034.GO12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Siarhei Siamashka <siarhei.siamashka@gmail.com>, Jason Cooper <jason@lakedaemon.net>, Jean-Francois Moine <moinejf@free.fr>, David Airlie <airlied@linux.ie>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Daniel Vetter <daniel@ffwll.ch>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Mon, Oct 7, 2013 at 8:50 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Oct 07, 2013 at 03:29:15PM +0300, Siarhei Siamashka wrote:
>> On Mon, 7 Oct 2013 11:32:50 +0100
>> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
>> > However, what you're suggesting is dangerous.  What do you do when you're
>> > presented with a cursor which is 64x64 ?  Do you:
>> >
>> > (a) not display it
>> > (b) crash the X server
>> >
>> > There isn't a fallback to using software cursors available in the X server
>> > because there's no error reporting for a failed hardware cursor update.
>>
>> Hmm, maybe I'm missing something, but doesn't returning FALSE from
>> UseHWCursorARGB just make the X server fallback to using a software
>> cursor?
>>
>> https://github.com/ssvb/xf86-video-fbturbo/blob/689c08256555/src/sunxi_disp_hwcursor.c#L72
>>
>> I'm just doing this. And also have hooks to notify the DRI2 code about
>> the status of the cursor. In the case if the hardware cursor is not
>> enabled, hardware overlays can't be safely used with the software
>> cursor and we need to fallback to CPU/GPU copy instead of zero-copy
>> buffers swapping.
>>
>> And I fully agree that it is the responsibility of the kernel to expose
>> as much of the hardware capabilities as possible (without compromising
>> reliability and/or security).
>
> If you wish to go in below the level presented by
> hw/xfree86/modes/xf86Cursors.c (as you are doing), then yes you can do
> this, and it's something which maybe should be looked into.  You have a
> good reason to do this (due to your hardware cursor being incompatible
> with overlays).
>
> We have no such restriction - the only issue here is the "odd" size of
> cursors.  Practically, choosing one or other of 64x32 or 32x64 works
> fine for the cases I've seen.  I haven't seen any cursors which are
> 64x64 yet.  I'm not saying they don't exist though!  I can imagine that
> some accessibility options might want to display a large cursor.
>
> Now, the way I handle this is that the kernel allows _either_ a
> (1 to 32)x(1 to 64) or (1 to 64)x(1 to 32) cursor.  Both width and
> height larger than 32 gets rejected with -EINVAL:
>
> +               /* maximum size is 64x32 or 32x64 */
> +               if (w > 64 || h > 64 || (w > 32 && h > 32))
> +                       return -ENOMEM;
>
> which is quite reasonable for this hardware.  However, there is no way
> to export this from DRM - adding maximum cursor size properties wouldn't
> really represent this.

Until relatively recently, it had always been a device specific ddx
which would somehow know what w/h values to pass to
xf86_cursors_init().  I think for xf86-video-modesetting and wayland
compositors, we probably need to come up with something better.
Although off the top of my head I can't think of a good way to express
64x32 or 32x64.. that is a weird restriction.

Anyways, right now I don't think there is anything different that I'd
do in the kernel part.  I *suppose* you could try and figure out that
all the alpha values are either 0x00 or 0xff and support 64x64 in that
special case.  I'm not sure that is actually better.. it at least
makes the failure vs success cases more confusing.  And unless you are
rockin' the twm+xterm+xcalc setup, I doubt you will see many cursors
with only 0x00 or 0xff alpha.

So,

Signed-off-by: Rob Clark <robdclark@gmail.com>


> The only question is whether DRM should export some capabilities to
> indicate what's possible with the cursor, so that X knows about this
> quirk of this hardware.  Overall, I suspect that it's just rare and
> not worth the effort.  I think it's just easier to pick one of these
> and stick with it, and if we happen to encounter a cursor larger than
> our chosen dimentions, XFree86 will already automatically fall back
> to s/w cursor.

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Rob Clark <robdclark@gmail.com>
Subject: Re: [PATCH 4/5] DRM: Armada: start of MMP2/MMP3 support
Date: Thu, 17 Oct 2013 20:11:35 -0400
Message-ID: <CAF6AEGtTdmdTE_qeojTkPY8WYv86TRuzX-ms3Nb3UQHfvoWRwg@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwXQ-0000iL-8N@rmk-PC.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <E1VSwXQ-0000iL-8N@rmk-PC.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Daniel Vetter <daniel@ffwll.ch>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Sun, Oct 6, 2013 at 6:10 PM, Russell King
<rmk+kernel@arm.linux.org.uk> wrote:
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  drivers/gpu/drm/armada/Makefile      |    1 +
>  drivers/gpu/drm/armada/armada_610.c  |   49 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/armada/armada_crtc.c |    1 +
>  drivers/gpu/drm/armada/armada_drm.h  |    1 +
>  drivers/gpu/drm/armada/armada_drv.c  |    6 ++++
>  drivers/gpu/drm/armada/armada_hw.h   |    8 +++++
>  6 files changed, 66 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/gpu/drm/armada/armada_610.c
>
> diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile
> index d6f43e0..088db4a 100644
> --- a/drivers/gpu/drm/armada/Makefile
> +++ b/drivers/gpu/drm/armada/Makefile
> @@ -2,6 +2,7 @@ armada-y        := armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
>                    armada_gem.o armada_output.o armada_overlay.o \
>                    armada_slave.o
>  armada-y       += armada_510.o
> +armada-y       += armada_610.o
>  armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
>
>  obj-$(CONFIG_DRM_ARMADA) := armada.o
> diff --git a/drivers/gpu/drm/armada/armada_610.c b/drivers/gpu/drm/armada/armada_610.c
> new file mode 100644
> index 0000000..36a10e3
> --- /dev/null
> +++ b/drivers/gpu/drm/armada/armada_610.c
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright (C) 2012 Russell King
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Armada 610/MMP2/MMP3 variant support
> + */
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc_helper.h>
> +#include "armada_crtc.h"
> +#include "armada_drm.h"
> +#include "armada_hw.h"
> +
> +static int mmp23_init(struct armada_private *priv, struct device *dev)
> +{
> +       priv->extclk[0] = devm_clk_get(dev, NULL);
> +
> +       if (IS_ERR(priv->extclk[0]) && PTR_ERR(priv->extclk[0]) == -ENOENT)
> +               priv->extclk[0] = ERR_PTR(-EPROBE_DEFER);
> +
> +       return PTR_RET(priv->extclk[0]);
> +}
> +
> +/*
> + * This gets called with sclk = NULL to test whether the mode is
> + * supportable, and again with sclk != NULL to set the clocks up for
> + * that.  The former can return an error, but the latter is expected
> + * not to.
> + */
> +static int mmp23_crtc_compute_clock(struct armada_crtc *dcrtc,
> +       const struct drm_display_mode *mode, uint32_t *sclk)
> +{
> +       /*
> +        * on MMP3 bits 31:29 select the clock, OLPC wants 0x1 here, LCD clock 1
> +        * on MMP2 bits 31:30 select the clock, OLPC wants 0x1 here, LCD clock 1
> +        */
> +       *sclk = 0x20001100; // FIXME hardcoded mmp3 value
> +

maybe fix this?  Or comment out for now mmp2 below in armada_drm_platform_ids?

BR,
-R

> +       return 0;
> +}
> +
> +const struct armada_variant mmp23_ops = {
> +       .init = mmp23_init,
> +       .crtc_compute_clock = mmp23_crtc_compute_clock,
> +};
> diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
> index e8605bf..b5877ee 100644
> --- a/drivers/gpu/drm/armada/armada_crtc.c
> +++ b/drivers/gpu/drm/armada/armada_crtc.c
> @@ -1054,6 +1054,7 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
>         dcrtc->clk = ERR_PTR(-EINVAL);
>         dcrtc->csc_yuv_mode = CSC_AUTO;
>         dcrtc->csc_rgb_mode = CSC_AUTO;
> +       /* FIXME: MMP2/MMP3: OLPC panel is RGB666 */
>         dcrtc->cfg_dumb_ctrl = DUMB24_RGB888_0;
>         dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
>         spin_lock_init(&dcrtc->irq_lock);
> diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
> index eef09ec..f52fccb 100644
> --- a/drivers/gpu/drm/armada/armada_drm.h
> +++ b/drivers/gpu/drm/armada/armada_drm.h
> @@ -70,6 +70,7 @@ struct armada_variant {
>
>  /* Variant ops */
>  extern const struct armada_variant armada510_ops;
> +extern const struct armada_variant mmp23_ops;
>
>  struct armada_private {
>         const struct armada_variant *variant;
> diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
> index 7bfab9a..db62f1b 100644
> --- a/drivers/gpu/drm/armada/armada_drv.c
> +++ b/drivers/gpu/drm/armada/armada_drv.c
> @@ -344,6 +344,12 @@ static const struct platform_device_id armada_drm_platform_ids[] = {
>                 .name           = "armada-drm",
>                 .driver_data    = (unsigned long)&armada510_ops,
>         }, {
> +               .name           = "armada-610-drm", /* aka MMP2 */
> +               .driver_data    = (unsigned long)&mmp23_ops,
> +       }, {
> +               .name           = "mmp3-drm",
> +               .driver_data    = (unsigned long)&mmp23_ops,
> +       }, {
>                 .name           = "armada-510-drm",
>                 .driver_data    = (unsigned long)&armada510_ops,
>         },
> diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
> index 27319a8..1688716 100644
> --- a/drivers/gpu/drm/armada/armada_hw.h
> +++ b/drivers/gpu/drm/armada/armada_hw.h
> @@ -74,6 +74,7 @@ enum {
>         LCD_SPU_IOPAD_CONTROL           = 0x01bc,
>         LCD_SPU_IRQ_ENA                 = 0x01c0,
>         LCD_SPU_IRQ_ISR                 = 0x01c4,
> +       LCD_MISC_CNTL                   = 0x01c8,       /* Armada 168 */
>  };
>
>  /* For LCD_SPU_ADV_REG */
> @@ -211,6 +212,13 @@ enum {
>         SCLK_16X_PLL            = 0x8 << 28,
>         SCLK_16X_FRAC_DIV_MASK  = 0xfff << 16,
>         SCLK_16X_INT_DIV_MASK   = 0xffff << 0,
> +
> +       /* PXA910 / MMP2 (Armada 610) / MMP3 / PXA988 */
> +       SCLK_MMP_SRC_SEL        = 1 << 31,
> +       SCLK_MMP_DISABLE        = 1 << 28,
> +       SCLK_MMP_FRAC_DIV_MASK  = 0xfff << 16,
> +       SCLK_MMP_DSI_DIV_MASK   = 0xf << 8,
> +       SCLK_MMP_INT_DIV_MASK   = 0xff << 0,
>  };
>
>  /* For LCD_SPU_DUMB_CTRL */
> --
> 1.7.4.4
>

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Rob Clark <robdclark@gmail.com>
Subject: Re: [PATCH 5/5] DRM: Armada: add support for drm tda19988 driver
Date: Thu, 17 Oct 2013 20:20:45 -0400
Message-ID: <CAF6AEGsGMzc8iUZMFqsWdhbS_fSwg38eLfaOG515WNxXg029FA@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwYO-0000iT-CU@rmk-PC.arm.linux.org.uk>
 <20131007111807.5e86ea6e@armhf>
 <20131007094404.GI12758@n2100.arm.linux.org.uk>
 <20131007124820.2189a4c3@armhf>
 <20131007110902.GL12758@n2100.arm.linux.org.uk>
 <CAF6AEGsqGYj7_tZdzrsmUxExs6wm838dYPFhBdc8wqVC6mTxmg@mail.gmail.com>
 <20131008111913.09bfe93e@armhf>
 <20131008094939.GD25034@n2100.arm.linux.org.uk>
 <20131008173418.0fc21d60@armhf>
Mime-Version: 1.0
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131008173418.0fc21d60@armhf>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Jean-Francois Moine <moinejf@free.fr>
Cc: Russell King - ARM Linux <linux@arm.linux.org.uk>, Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Daniel Vetter <daniel@ffwll.ch>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Tue, Oct 8, 2013 at 11:34 AM, Jean-Francois Moine <moinejf@free.fr> wrot=
e:
> On Tue, 8 Oct 2013 10:49:39 +0100
> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
>
>> On Tue, Oct 08, 2013 at 11:19:13AM +0200, Jean-Francois Moine wrote:
>> > The Cubox is an open platform, and I use it just like a desktop PC.
>> > When its required drivers will be in the mainline, I will do the same
>> > as I do with PCs: I will not recompile a specific kernel each time
>> > there are kernel bugs or security issues. Instead, I will just upgrade
>> > my system from my distributor (Debian), and, in the packages, there
>> > will be a generic mvebu kernel as there is already one for Marvell
>> > Armada 370/xp, Freescale iMX5x/iMX6 (linux-image-3.10-3-armmp).
>> > But, for that, all the Cubox specific stuff must be described in a DT.
>>
>> Which scenario is better:
>>
>> 1. To have something in mainline which is capable of driving the hardwar=
e,
>>    but may need some additional work to make it useful for DT based setu=
ps.
>>
>> or
>>
>> 2. To have nothing.
>>
>> Now, you may prefer to have nothing, but personally, I prefer there to be
>> forward progress.  Forward progress means getting some kind of DRM driver
>> into mainline.  Yes, it may not work with DT setups yet, but - as per
>> the discussions that have happened _endlessly_ on this topic, it's
>> something that can be resolved at a later date.
>>
>> We _still_ haven't worked out how to properly deal with the TDA998x
>> driver (or indeed any DRM based outputs) in a DT based setup, and all
>> the time that problem exists, it won't be possible to write a proper
>> stable DT binding for this.
>>
>> So please, get off your hobby horse about this and allow us to make some
>> modicum of progress.
>
> You forgot:
>
> 3. To have all patches ready for submission and have a working DT driven
>    Cubox kernel.

No need to block this patch on DT support for all platforms that can
use this driver.  I don't see an issue with removing non-DT support
later if it is no longer needed, or adding DT support in a future
patch for platforms which can use it.  So this patch looks fine to me.

Signed-off-by: Rob Clark <robdclark@gmail.com


> I will submit a patch to add DT to the tda998x driver as soon as I have
> checked the new audio properties we talked about yesterday.
>
> Normally, this should have no impact on your Armada drm driver, and,
> yes, I will add DT to your driver as soon as it will be accepted
> (sorry to not ack it now: I had no time yet to have a look at it).
>
> --
> Ken ar c'henta=F1 |             ** Breizh ha Linux atav! **
> Jef             |               http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Alex Deucher <alexdeucher@gmail.com>
Subject: Re: [PATCH 3/5] DRM: Armada: Add support for ARGB 32x64 or 64x32
 hardware cursors
Date: Fri, 18 Oct 2013 10:31:57 -0400
Message-ID: <CADnq5_Nc9ZK94BO=S7wK=nVoKVUFkJowxo2MvBNMSj+6-cPHUw@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwWS-0000i7-4f@rmk-PC.arm.linux.org.uk>
 <20131007110141.27f1ac25@armhf>
 <20131007094008.GH12758@n2100.arm.linux.org.uk>
 <20131007120922.47df03b6@armhf>
 <20131007103250.GJ12758@n2100.arm.linux.org.uk>
 <20131007152915.352cc4b2@i7>
 <20131007125034.GO12758@n2100.arm.linux.org.uk>
 <CAF6AEGt1uOsE5V6rAtxpLNNaYkaKiw9G8CNdt31JZVdS6TX-hA@mail.gmail.com>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <CAF6AEGt1uOsE5V6rAtxpLNNaYkaKiw9G8CNdt31JZVdS6TX-hA@mail.gmail.com>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Rob Clark <robdclark@gmail.com>
Cc: "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Russell King - ARM Linux <linux@arm.linux.org.uk>, Jason Cooper <jason@lakedaemon.net>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Thu, Oct 17, 2013 at 7:58 PM, Rob Clark <robdclark@gmail.com> wrote:
> On Mon, Oct 7, 2013 at 8:50 AM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
>> On Mon, Oct 07, 2013 at 03:29:15PM +0300, Siarhei Siamashka wrote:
>>> On Mon, 7 Oct 2013 11:32:50 +0100
>>> Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:
>>> > However, what you're suggesting is dangerous.  What do you do when you're
>>> > presented with a cursor which is 64x64 ?  Do you:
>>> >
>>> > (a) not display it
>>> > (b) crash the X server
>>> >
>>> > There isn't a fallback to using software cursors available in the X server
>>> > because there's no error reporting for a failed hardware cursor update.
>>>
>>> Hmm, maybe I'm missing something, but doesn't returning FALSE from
>>> UseHWCursorARGB just make the X server fallback to using a software
>>> cursor?
>>>
>>> https://github.com/ssvb/xf86-video-fbturbo/blob/689c08256555/src/sunxi_disp_hwcursor.c#L72
>>>
>>> I'm just doing this. And also have hooks to notify the DRI2 code about
>>> the status of the cursor. In the case if the hardware cursor is not
>>> enabled, hardware overlays can't be safely used with the software
>>> cursor and we need to fallback to CPU/GPU copy instead of zero-copy
>>> buffers swapping.
>>>
>>> And I fully agree that it is the responsibility of the kernel to expose
>>> as much of the hardware capabilities as possible (without compromising
>>> reliability and/or security).
>>
>> If you wish to go in below the level presented by
>> hw/xfree86/modes/xf86Cursors.c (as you are doing), then yes you can do
>> this, and it's something which maybe should be looked into.  You have a
>> good reason to do this (due to your hardware cursor being incompatible
>> with overlays).
>>
>> We have no such restriction - the only issue here is the "odd" size of
>> cursors.  Practically, choosing one or other of 64x32 or 32x64 works
>> fine for the cases I've seen.  I haven't seen any cursors which are
>> 64x64 yet.  I'm not saying they don't exist though!  I can imagine that
>> some accessibility options might want to display a large cursor.
>>
>> Now, the way I handle this is that the kernel allows _either_ a
>> (1 to 32)x(1 to 64) or (1 to 64)x(1 to 32) cursor.  Both width and
>> height larger than 32 gets rejected with -EINVAL:
>>
>> +               /* maximum size is 64x32 or 32x64 */
>> +               if (w > 64 || h > 64 || (w > 32 && h > 32))
>> +                       return -ENOMEM;
>>
>> which is quite reasonable for this hardware.  However, there is no way
>> to export this from DRM - adding maximum cursor size properties wouldn't
>> really represent this.
>
> Until relatively recently, it had always been a device specific ddx
> which would somehow know what w/h values to pass to
> xf86_cursors_init().  I think for xf86-video-modesetting and wayland
> compositors, we probably need to come up with something better.
> Although off the top of my head I can't think of a good way to express
> 64x32 or 32x64.. that is a weird restriction.
>

We have a similar problem on our newer asics.  They require a 128x128
cursors so when you use xf86-video-modesetting, you end up with messed
up cursors because it assumes 64x64.  We could add cursor size to drm
caps.

Alex

> Anyways, right now I don't think there is anything different that I'd
> do in the kernel part.  I *suppose* you could try and figure out that
> all the alpha values are either 0x00 or 0xff and support 64x64 in that
> special case.  I'm not sure that is actually better.. it at least
> makes the failure vs success cases more confusing.  And unless you are
> rockin' the twm+xterm+xcalc setup, I doubt you will see many cursors
> with only 0x00 or 0xff alpha.
>
> So,
>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
>
>
>> The only question is whether DRM should export some capabilities to
>> indicate what's possible with the cursor, so that X knows about this
>> quirk of this hardware.  Overall, I suspect that it's just rare and
>> not worth the effort.  I think it's just easier to pick one of these
>> and stick with it, and if we happen to encounter a cursor larger than
>> our chosen dimentions, XFree86 will already automatically fall back
>> to s/w cursor.
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Rob Clark <robdclark@gmail.com>
Subject: Re: [PATCH 1/5] drm/i2c: tda998x: set VIF for full range,
 underscanned display
Date: Fri, 18 Oct 2013 11:00:34 -0400
Message-ID: <CAF6AEGt_gn2EYhMq5xA4RFbFmmFuYr5_yTXeK-9MkmRpJS85-w@mail.gmail.com>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <E1VSwUV-0000hl-Rw@rmk-PC.arm.linux.org.uk>
 <20131007105944.6746352b@armhf>
Mime-Version: 1.0
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
In-Reply-To: <20131007105944.6746352b@armhf>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: Jean-Francois Moine <moinejf@free.fr>
Cc: Jason Cooper <jason@lakedaemon.net>, David Airlie <airlied@linux.ie>, "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>, Daniel Vetter <daniel@ffwll.ch>, Russell King <rmk+kernel@arm.linux.org.uk>, "linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Mon, Oct 7, 2013 at 4:59 AM, Jean-Francois Moine <moinejf@free.fr> wrote:
> On Sun, 06 Oct 2013 23:07:55 +0100
> Russell King <rmk+kernel@arm.linux.org.uk> wrote:
>
>> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
>> ---
>>  drivers/gpu/drm/i2c/tda998x_drv.c |    2 ++
>>  1 files changed, 2 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda=
998x_drv.c
>> index 60e8404..704040b5 100644
>> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
>> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
>> @@ -549,6 +549,8 @@ tda998x_write_avi(struct drm_encoder *encoder, struc=
t drm_display_mode *mode)
>>       buf[HB(0)] =3D 0x82;
>>       buf[HB(1)] =3D 0x02;
>>       buf[HB(2)] =3D 13;
>> +     buf[PB(1)] =3D 2; /* underscanned display */
>> +     buf[PB(3)] =3D 2 << 2; /* full range */
>>       buf[PB(4)] =3D drm_match_cea_mode(mode);
>>
>>       tda998x_write_if(encoder, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf,
>
> You should use the 'hdmi.h' constants which are meaningful enough:
>
>         buf[PB(1)] =3D HDMI_SCAN_MODE_UNDERSCAN;
>         buf[PB(3)] =3D HDMI_QUANTIZATION_RANGE_FULL << 2;
>

with the update to use hdmi.h const, this has my

Reviewed-by: Rob Clark <robdclark@gmail.com>

(and other ones I replied last night, s/s-o-b/r-b/)

> --
> Ken ar c'henta=F1 |             ** Breizh ha Linux atav! **
> Jef             |               http://moinejf.free.fr/

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: [GIT PULL] Armada DRM support
Date: Fri, 18 Oct 2013 16:15:57 +0100
Message-ID: <20131018151557.GA25034@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
In-Reply-To: <20131006220728.GG12758@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: David Airlie <airlied@linux.ie>
Cc: Jason Cooper <jason@lakedaemon.net>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

David,

Rob Clark has now reviewed this and has given his blessing for it to be
pulled for the coming merge window.

This adds support for the Armada 510 display subsystem found on the
Marvell Dove devices.  This IP is re-used across several different Marvell
SoCs with various tweaks, and this driver has been structured to allow
the other IPs to re-use the bulk of this code; further work in this area
is expected from interested parties.

This has been extensively tested on the SolidRun Cubox platform and
appears to work well there.

Please pull this driver for the next merge window.  Thanks.

The following changes since commit 15c03dd4859ab16f9212238f29dd315654aa94f6:

  Linux 3.12-rc3 (2013-09-29 15:02:38 -0700)

are available in the git repository at:

  git://ftp.arm.linux.org.uk/~rmk/linux-cubox.git drm-tda998x-3.12

which is commit: 585b691e2180e1501637050290292f77f5c30c7b

Russell King (5):
      DRM: Armada: Add Armada DRM driver
      DRM: Armada: Add support for ARGB 32x64 or 64x32 hardware cursors
      drm/i2c: tda998x: set VIF for full range, underscanned display
      Merge branches 'drm-3.12' and 'tda998x-3.12' into drm-tda998x-3.12
      DRM: Armada: add support for drm tda19988 driver

 drivers/gpu/drm/Kconfig                 |    2 +
 drivers/gpu/drm/Makefile                |    1 +
 drivers/gpu/drm/armada/Kconfig          |   24 +
 drivers/gpu/drm/armada/Makefile         |    7 +
 drivers/gpu/drm/armada/armada_510.c     |   87 +++
 drivers/gpu/drm/armada/armada_crtc.c    | 1098 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_crtc.h    |   83 +++
 drivers/gpu/drm/armada/armada_debugfs.c |  183 +++++
 drivers/gpu/drm/armada/armada_drm.h     |  113 ++++
 drivers/gpu/drm/armada/armada_drv.c     |  422 ++++++++++++
 drivers/gpu/drm/armada/armada_fb.c      |  170 +++++
 drivers/gpu/drm/armada/armada_fb.h      |   24 +
 drivers/gpu/drm/armada/armada_fbdev.c   |  202 ++++++
 drivers/gpu/drm/armada/armada_gem.c     |  611 +++++++++++++++++
 drivers/gpu/drm/armada/armada_gem.h     |   52 ++
 drivers/gpu/drm/armada/armada_hw.h      |  318 +++++++++
 drivers/gpu/drm/armada/armada_ioctlP.h  |   18 +
 drivers/gpu/drm/armada/armada_output.c  |  158 +++++
 drivers/gpu/drm/armada/armada_output.h  |   39 ++
 drivers/gpu/drm/armada/armada_overlay.c |  477 ++++++++++++++
 drivers/gpu/drm/armada/armada_slave.c   |  139 ++++
 drivers/gpu/drm/armada/armada_slave.h   |   26 +
 drivers/gpu/drm/i2c/tda998x_drv.c       |    3 +
 include/drm/drm_crtc.h                  |   17 +
 include/uapi/drm/armada_drm.h           |   45 ++
 25 files changed, 4319 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/armada/Kconfig
 create mode 100644 drivers/gpu/drm/armada/Makefile
 create mode 100644 drivers/gpu/drm/armada/armada_510.c
 create mode 100644 drivers/gpu/drm/armada/armada_crtc.c
 create mode 100644 drivers/gpu/drm/armada/armada_crtc.h
 create mode 100644 drivers/gpu/drm/armada/armada_debugfs.c
 create mode 100644 drivers/gpu/drm/armada/armada_drm.h
 create mode 100644 drivers/gpu/drm/armada/armada_drv.c
 create mode 100644 drivers/gpu/drm/armada/armada_fb.c
 create mode 100644 drivers/gpu/drm/armada/armada_fb.h
 create mode 100644 drivers/gpu/drm/armada/armada_fbdev.c
 create mode 100644 drivers/gpu/drm/armada/armada_gem.c
 create mode 100644 drivers/gpu/drm/armada/armada_gem.h
 create mode 100644 drivers/gpu/drm/armada/armada_hw.h
 create mode 100644 drivers/gpu/drm/armada/armada_ioctlP.h
 create mode 100644 drivers/gpu/drm/armada/armada_output.c
 create mode 100644 drivers/gpu/drm/armada/armada_output.h
 create mode 100644 drivers/gpu/drm/armada/armada_overlay.c
 create mode 100644 drivers/gpu/drm/armada/armada_slave.c
 create mode 100644 drivers/gpu/drm/armada/armada_slave.h
 create mode 100644 include/uapi/drm/armada_drm.h

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Subject: Re: [GIT PULL] Armada DRM support
Date: Tue, 22 Oct 2013 14:36:52 +0100
Message-ID: <20131022133652.GC25034@n2100.arm.linux.org.uk>
References: <20131006220728.GG12758@n2100.arm.linux.org.uk>
 <20131018151557.GA25034@n2100.arm.linux.org.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org>
Content-Disposition: inline
In-Reply-To: <20131018151557.GA25034@n2100.arm.linux.org.uk>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
 <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org
To: David Airlie <airlied@linux.ie>
Cc: Jason Cooper <jason@lakedaemon.net>, dri-devel@lists.freedesktop.org, Rob Clark <robdclark@gmail.com>, Daniel Vetter <daniel@ffwll.ch>, linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
List-Id: dri-devel@lists.freedesktop.org

On Fri, Oct 18, 2013 at 04:15:57PM +0100, Russell King - ARM Linux wrote:
> David,
> 
> Rob Clark has now reviewed this and has given his blessing for it to be
> pulled for the coming merge window.
> 
> This adds support for the Armada 510 display subsystem found on the
> Marvell Dove devices.  This IP is re-used across several different Marvell
> SoCs with various tweaks, and this driver has been structured to allow
> the other IPs to re-use the bulk of this code; further work in this area
> is expected from interested parties.
> 
> This has been extensively tested on the SolidRun Cubox platform and
> appears to work well there.

David,

The zero day tester found a problem with this building on some non-ARM.
Please add this fix to it, which Rob Clark has acked.  It's a small patch
to add a dependency on ARM.

Thanks.

The following changes since commit 585b691e2180e1501637050290292f77f5c30c7b:

  DRM: Armada: add support for drm tda19988 driver (2013-10-18 16:00:33 +0100)

are available in the git repository at:
  git://ftp.arm.linux.org.uk/~rmk/linux-cubox.git drm-tda998x-3.12-fixes

Russell King (1):
      DRM: Armada: depend on ARM

 drivers/gpu/drm/armada/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

