All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
@ 2015-03-13  9:44 ` Jianwei Wang
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei Wang @ 2015-03-13  9:44 UTC (permalink / raw)
  To: scottwood, airlied, jbarnes, dri-devel
  Cc: linux-kernel, linux-arm-kernel, Jason.Jin, Jianwei Wang,
	Alison Wang, Xiubo Li

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="y", Size: 42888 bytes --]

This patch add support for Two Dimensional Animation and Compositing
Engine (2D-ACE) on Freescale SoCs.

2D-ACE is a Freescale display controller. It provide an hardware
cursor.

This is a simplified version, only a primary plane, a fb created for
fbdev, a crtc, a connector for TFT LCD panel, an encoder, and the
encoder is not in use.

Signed-off-by: Alison Wang <b18965@freescale.com>
Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Jianwei Wang <b52261@freescale.com>
---

Changed in v2: 
- Add atomic support
- Modify bindings file
- Rename node for compatibility
- Move platform related code out for compatibility

Added in v1: 
- Add support for DCU display controller on the Freescale LS102x SoCs.
- Create a primary plane, a fb created for fbdev, a crtc, a connector
for TFT LCD panel, an encoder.

 arch/arm/mach-imx/mach-ls1021a.c            |  36 ++++
 drivers/gpu/drm/Kconfig                     |   2 +
 drivers/gpu/drm/Makefile                    |   1 +
 drivers/gpu/drm/fsl/Kconfig                 |  17 ++
 drivers/gpu/drm/fsl/Makefile                |   8 +
 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c | 203 ++++++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h |  28 +++
 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c      | 164 ++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h      |  26 +++
 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c       | 288 ++++++++++++++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h       | 168 ++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c     |  26 +++
 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c       |  42 ++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h       |  17 ++
 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c     | 187 ++++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h     |  23 +++
 include/linux/fsl/dcu.h                     |  22 +++
 17 files changed, 1258 insertions(+)
 create mode 100644 drivers/gpu/drm/fsl/Kconfig
 create mode 100644 drivers/gpu/drm/fsl/Makefile
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
 create mode 100644 include/linux/fsl/dcu.h

diff --git a/arch/arm/mach-imx/mach-ls1021a.c b/arch/arm/mach-imx/mach-ls1021a.c
index b89c858..4fb346d 100644
--- a/arch/arm/mach-imx/mach-ls1021a.c
+++ b/arch/arm/mach-imx/mach-ls1021a.c
@@ -8,9 +8,44 @@
  */
 
 #include <asm/mach/arch.h>
+#include <linux/of_platform.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/fsl/dcu.h>
 
 #include "common.h"
 
+void dcu_pixclk_disable(void)
+{
+	struct regmap *scfg_regmap;
+
+	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
+	if (IS_ERR(scfg_regmap)) {
+		pr_err("No syscfg phandle specified\n");
+		return;
+	}
+
+	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_DISABLE);
+}
+
+void dcu_pixclk_enable(void)
+{
+	struct regmap *scfg_regmap;
+
+	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
+	if (IS_ERR(scfg_regmap)) {
+		pr_err("No syscfg phandle specified\n");
+		return;
+	}
+
+	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_ENABLE);
+}
+
+static void __init ls1021a_init_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	dcu_pixclk_enable();
+}
 static const char * const ls1021a_dt_compat[] __initconst = {
 	"fsl,ls1021a",
 	NULL,
@@ -18,5 +53,6 @@ static const char * const ls1021a_dt_compat[] __initconst = {
 
 DT_MACHINE_START(LS1021A, "Freescale LS1021A")
 	.smp		= smp_ops(ls1021a_smp_ops),
+	.init_machine	= ls1021a_init_machine,
 	.dt_compat	= ls1021a_dt_compat,
 MACHINE_END
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 151a050..a6957aa 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -199,6 +199,8 @@ source "drivers/gpu/drm/bochs/Kconfig"
 
 source "drivers/gpu/drm/msm/Kconfig"
 
+source "drivers/gpu/drm/fsl/Kconfig"
+
 source "drivers/gpu/drm/tegra/Kconfig"
 
 source "drivers/gpu/drm/panel/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 2c239b9..ab5b9ef 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_DRM_UDL) += udl/
 obj-$(CONFIG_DRM_AST) += ast/
 obj-$(CONFIG_DRM_ARMADA) += armada/
 obj-$(CONFIG_DRM_ATMEL_HLCDC)	+= atmel-hlcdc/
+obj-$(CONFIG_DRM_FSL_DCU) += fsl/
 obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
 obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
 obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
diff --git a/drivers/gpu/drm/fsl/Kconfig b/drivers/gpu/drm/fsl/Kconfig
new file mode 100644
index 0000000..e4f8df0
--- /dev/null
+++ b/drivers/gpu/drm/fsl/Kconfig
@@ -0,0 +1,17 @@
+config DRM_FSL_DCU
+	tristate "DRM Support for Freescale DCU"
+	depends on DRM && OF && ARM
+	select DRM_KMS_HELPER
+	select DRM_KMS_CMA_HELPER
+	select VIDEOMODE_HELPERS
+	select BACKLIGHT_CLASS_DEVICE
+	select BACKLIGHT_LCD_SUPPORT
+	select REGMAP_MMIO
+	select DRM_KMS_FB_HELPER
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	help
+	  Choose this option if you have an Freescale DCU chipset.
+	  If M is selected the module will be called fsl-dcu-drm.
diff --git a/drivers/gpu/drm/fsl/Makefile b/drivers/gpu/drm/fsl/Makefile
new file mode 100644
index 0000000..5f74aee
--- /dev/null
+++ b/drivers/gpu/drm/fsl/Makefile
@@ -0,0 +1,8 @@
+fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
+	       fsl_dcu_drm_kms.o \
+	       fsl_dcu_drm_connector.o \
+	       fsl_dcu_drm_plane.o \
+	       fsl_dcu_drm_crtc.o \
+	       fsl_dcu_drm_fbdev.o \
+
+obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
new file mode 100644
index 0000000..178d647
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/backlight.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <video/of_display_timing.h>
+
+#include "fsl_dcu_drm_drv.h"
+#include "fsl_dcu_drm_connector.h"
+
+static void fsl_dcu_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+}
+
+/* Disable the encoders as the first thing we do. */
+static void fsl_dcu_drm_encoder_mode_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void fsl_dcu_drm_encoder_mode_set(struct drm_encoder *encoder,
+					 struct drm_display_mode *mode,
+					 struct drm_display_mode *adjusted_mode)
+{
+}
+
+static void fsl_dcu_drm_encoder_mode_commit(struct drm_encoder *encoder)
+{
+}
+
+static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
+static int
+fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
+				 struct drm_crtc_state *crtc_state,
+				 struct drm_connector_state *conn_state)
+{
+	return 0;
+}
+
+static bool
+fsl_dcu_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+			       const struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
+	.dpms = fsl_dcu_drm_encoder_dpms,
+	.prepare = fsl_dcu_drm_encoder_mode_prepare,
+	.commit = fsl_dcu_drm_encoder_mode_commit,
+	.mode_set = fsl_dcu_drm_encoder_mode_set,
+	.disable = fsl_dcu_drm_encoder_disable,
+	.atomic_check = fsl_dcu_drm_encoder_atomic_check,
+	.mode_fixup = fsl_dcu_drm_encoder_mode_fixup,
+};
+
+static const struct drm_encoder_funcs encoder_funcs = {
+	.destroy = fsl_dcu_drm_encoder_destroy,
+};
+
+int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev)
+{
+	struct drm_encoder *encoder = &fsl_dev->encoder;
+	int ret;
+
+	encoder->possible_crtcs = 1;
+
+	ret = drm_encoder_init(fsl_dev->ddev, encoder, &encoder_funcs,
+			       DRM_MODE_ENCODER_LVDS);
+	if (ret < 0)
+		return ret;
+
+	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
+
+	return 0;
+}
+
+#define to_fsl_dcu_connector(connector) \
+	container_of(connector, struct fsl_dcu_drm_connector, connector)
+
+static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct device_node *display_np, *np = dev->dev->of_node;
+	struct drm_display_mode *mode = drm_mode_create(connector->dev);
+	int num_modes = 0;
+
+	if (np) {
+		display_np = of_parse_phandle(np, "display", 0);
+		if (!display_np) {
+			dev_err(dev->dev, "failed to find display phandle\n");
+			return num_modes;
+		}
+		of_get_drm_display_mode(display_np, mode, OF_USE_NATIVE_MODE);
+		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+		drm_mode_probed_add(connector, mode);
+		num_modes++;
+	}
+
+	return num_modes;
+}
+
+static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
+					    struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static struct drm_encoder *
+fsl_dcu_drm_connector_best_encoder(struct drm_connector *connector)
+{
+	struct fsl_dcu_drm_connector *fsl_con = to_fsl_dcu_connector(connector);
+
+	return fsl_con->encoder;
+}
+
+static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static enum drm_connector_status
+fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = fsl_dcu_drm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = fsl_dcu_drm_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_connector_helper_funcs connector_helper_funcs = {
+	.get_modes = fsl_dcu_drm_connector_get_modes,
+	.mode_valid = fsl_dcu_drm_connector_mode_valid,
+	.best_encoder = fsl_dcu_drm_connector_best_encoder,
+};
+
+int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
+				 struct drm_encoder *encoder)
+{
+	struct drm_connector *connector = &fsl_dev->connector.connector;
+	int ret;
+
+	fsl_dev->connector.encoder = encoder;
+
+	connector->display_info.width_mm = 0;
+	connector->display_info.height_mm = 0;
+
+	ret = drm_connector_init(fsl_dev->ddev, connector,
+				 &fsl_dcu_drm_connector_funcs,
+				 DRM_MODE_CONNECTOR_LVDS);
+	if (ret < 0)
+		return ret;
+
+	connector->dpms = DRM_MODE_DPMS_OFF;
+	drm_connector_helper_add(connector, &connector_helper_funcs);
+	ret = drm_connector_register(connector);
+	if (ret < 0)
+		goto err_cleanup;
+
+	ret = drm_mode_connector_attach_encoder(connector, encoder);
+	if (ret < 0)
+		goto err_sysfs;
+
+	connector->encoder = encoder;
+
+	drm_object_property_set_value
+		(&connector->base, fsl_dev->ddev->mode_config.dpms_property,
+		DRM_MODE_DPMS_OFF);
+
+	return 0;
+
+err_sysfs:
+	drm_connector_unregister(connector);
+err_cleanup:
+	drm_connector_cleanup(connector);
+	return ret;
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
new file mode 100644
index 0000000..afe44ab
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_CONNECTOR_H__
+#define __FSL_DCU_DRM_CONNECTOR_H__
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+
+struct fsl_dcu_drm_device;
+struct fsl_dcu_drm_connector {
+	struct drm_connector connector;
+	struct drm_encoder *encoder;
+};
+
+int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev);
+int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
+				 struct drm_encoder *encoder);
+
+#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
new file mode 100644
index 0000000..a43e7ce
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/regmap.h>
+#include <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+
+#include "fsl_dcu_drm_crtc.h"
+#include "fsl_dcu_drm_drv.h"
+#include "fsl_dcu_drm_plane.h"
+
+#define to_fsl_dcu_crtc(c)	container_of(c, struct fsl_dcu_drm_crtc, crtc)
+
+void fsl_dcu_drm_crtc_suspend(struct drm_crtc *crtc)
+{
+}
+
+static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+	struct drm_display_mode *mode = &crtc->state->mode;
+	uint32_t hbp, hfp, hsw, vbp, vfp, vsw, div, index;
+
+	DBG(": set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+	    mode->base.id, mode->name,
+	    mode->vrefresh, mode->clock,
+	    mode->hdisplay, mode->hsync_start,
+	    mode->hsync_end, mode->htotal,
+	    mode->vdisplay, mode->vsync_start,
+	    mode->vsync_end, mode->vtotal,
+	    mode->type, mode->flags);
+
+	index = drm_crtc_index(crtc);
+	div = (uint32_t)clk_get_rate(fsl_dev->clk) / mode->clock / 1000;
+
+	/* Configure timings: */
+	hbp = mode->htotal - mode->hsync_end;
+	hfp = mode->hsync_start - mode->hdisplay;
+	hsw = mode->hsync_end - mode->hsync_start;
+	vbp = mode->vtotal - mode->vsync_end;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vsw = mode->vsync_end - mode->vsync_start;
+
+	regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
+		     DCU_HSYN_PARA_BP(hbp) |
+		     DCU_HSYN_PARA_PW(hsw) |
+		     DCU_HSYN_PARA_FP(hfp));
+	regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
+		     DCU_VSYN_PARA_BP(vbp) |
+		     DCU_VSYN_PARA_PW(vsw) |
+		     DCU_VSYN_PARA_FP(vfp));
+	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
+		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
+		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
+	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
+	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
+}
+
+static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+					const struct drm_display_mode *mode,
+					struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void fsl_dcu_drm_crtc_prepare(struct drm_crtc *crtc)
+{
+}
+
+/* Now enable the clocks, plane, pipe, and connectors that we set up. */
+static void fsl_dcu_drm_crtc_mode_commit(struct drm_crtc *crtc)
+{
+}
+
+static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
+					 struct drm_crtc_state *state)
+{
+	return 0;
+}
+
+static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc)
+{
+}
+
+static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc)
+{
+}
+
+static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
+{
+}
+
+static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
+	.page_flip = drm_atomic_helper_page_flip,
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = drm_crtc_cleanup,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static void fsl_dcu_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+}
+
+static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
+	.disable = fsl_dcu_drm_disable_crtc,
+	.mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
+	.mode_set = drm_helper_crtc_mode_set,
+	.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
+	.mode_set_base = drm_helper_crtc_mode_set_base,
+	.prepare = fsl_dcu_drm_crtc_prepare,
+	.commit = fsl_dcu_drm_crtc_mode_commit,
+	.atomic_check = fsl_dcu_drm_crtc_atomic_check,
+	.atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
+	.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
+	.dpms = fsl_dcu_drm_crtc_dpms,
+};
+
+int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
+{
+	struct drm_plane *primary;
+	struct drm_crtc *crtc = &fsl_dev->crtc.crtc;
+	int ret;
+
+	fsl_dev->crtc.dpms = DRM_MODE_DPMS_OFF;
+
+	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->ddev);
+	ret = drm_crtc_init_with_planes(fsl_dev->ddev, crtc, primary, NULL,
+					&fsl_dcu_drm_crtc_funcs);
+	if (ret < 0)
+		return ret;
+
+	drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
+
+	regmap_write(fsl_dev->regmap, DCU_SYN_POL,
+		     DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
+	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
+		     DCU_BGND_G(0) | DCU_BGND_B(0));
+	regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
+		     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
+	regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
+		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
+		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
+		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
+	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
+			   DCU_MODE_DCU_MODE_MASK,
+			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
+	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
+	return 0;
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
new file mode 100644
index 0000000..d44b564
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_CRTC_H__
+#define __FSL_DCU_DRM_CRTC_H__
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+
+struct fsl_dcu_drm_device;
+struct fsl_dcu_drm_crtc {
+	struct drm_crtc crtc;
+	int dpms;
+};
+
+int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev);
+
+#endif /* __FSL_DCU_DRM_CRTC_H__ */
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
new file mode 100644
index 0000000..10975ee
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <drm/drmP.h>
+#include <linux/fsl/dcu.h>
+
+#include "fsl_dcu_drm_drv.h"
+#include "fsl_dcu_drm_kms.h"
+
+static int fsl_dcu_unload(struct drm_device *dev)
+{
+	drm_mode_config_cleanup(dev);
+	drm_vblank_cleanup(dev);
+	drm_irq_uninstall(dev);
+
+	dev->dev_private = NULL;
+
+	return 0;
+}
+
+static struct regmap_config fsl_dcu_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+};
+
+static int fsl_dcu_bypass_tcon(struct fsl_dcu_drm_device *fsl_dev,
+			       struct device_node *np)
+{
+	struct device_node *tcon_np;
+	struct platform_device *pdev;
+	struct clk *tcon_clk;
+	struct resource *res;
+	void __iomem *base;
+
+	tcon_np = of_parse_phandle(np, "tcon-controller", 0);
+	if (!tcon_np)
+		return -EINVAL;
+
+	pdev = of_find_device_by_node(tcon_np);
+	if (!pdev)
+		return -EINVAL;
+
+	tcon_clk = devm_clk_get(&pdev->dev, "tcon");
+	if (IS_ERR(tcon_clk))
+		return PTR_ERR(tcon_clk);
+	clk_prepare_enable(tcon_clk);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	fsl_dev->tcon_regmap = devm_regmap_init_mmio_clk(&pdev->dev,
+			"tcon", base, &fsl_dcu_regmap_config);
+	if (IS_ERR(fsl_dev->tcon_regmap)) {
+		dev_err(&pdev->dev, "regmap init failed\n");
+		return PTR_ERR(fsl_dev->tcon_regmap);
+	}
+
+	regmap_write(fsl_dev->tcon_regmap, TCON_CTRL1, TCON_BYPASS_ENABLE);
+	return 0;
+}
+
+static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
+{
+	struct platform_device *pdev = dev->platformdev;
+	struct fsl_dcu_drm_device *fsl_dev;
+	struct resource *res;
+	void __iomem *base;
+	int ret;
+
+	fsl_dev = devm_kzalloc(&pdev->dev, sizeof(*fsl_dev), GFP_KERNEL);
+	if (!fsl_dev)
+		return -ENOMEM;
+
+	fsl_dev->dev = &pdev->dev;
+	fsl_dev->ddev = dev;
+	dev->dev_private = fsl_dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base)) {
+		ret = PTR_ERR(base);
+		return ret;
+	}
+
+	fsl_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
+			base, &fsl_dcu_regmap_config);
+	if (IS_ERR(fsl_dev->regmap)) {
+		dev_err(&pdev->dev, "regmap init failed\n");
+		return PTR_ERR(fsl_dev->regmap);
+	}
+
+	ret = fsl_dcu_drm_modeset_init(fsl_dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to initialize mode setting\n");
+		return ret;
+	}
+
+	ret = drm_vblank_init(dev, 1);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to initialize vblank\n");
+		goto done;
+	}
+
+	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to install IRQ handler\n");
+		goto done;
+	}
+
+	/* Put TCON in bypass mode, so the input signals from DCU are passed
+	 * through TCON unchanged */
+	fsl_dcu_bypass_tcon(fsl_dev, pdev->dev.of_node);
+
+	fsl_dev->clk = devm_clk_get(&pdev->dev, "dcu");
+	if (IS_ERR(fsl_dev->clk)) {
+		ret = PTR_ERR(fsl_dev->clk);
+		dev_err(&pdev->dev, "could not get clock\n");
+		return ret;
+	}
+	clk_prepare_enable(fsl_dev->clk);
+
+	dev_set_drvdata(dev->dev, fsl_dev);
+
+	fsl_dcu_fbdev_init(dev);
+
+	return 0;
+done:
+	if (ret)
+		fsl_dcu_unload(dev);
+
+	return ret;
+}
+
+static void fsl_dcu_drm_preclose(struct drm_device *dev, struct drm_file *file)
+{
+	;
+}
+
+static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
+{
+	return IRQ_HANDLED;
+}
+
+static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int crtc)
+{
+	return 0;
+}
+
+static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int crtc)
+{
+	;
+}
+
+static const struct file_operations fsl_dcu_drm_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= drm_compat_ioctl,
+#endif
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+	.mmap		= drm_gem_cma_mmap,
+};
+
+static struct drm_driver fsl_dcu_drm_driver = {
+	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
+				| DRIVER_PRIME,
+	.load			= fsl_dcu_load,
+	.unload			= fsl_dcu_unload,
+	.preclose		= fsl_dcu_drm_preclose,
+	.irq_handler		= fsl_dcu_drm_irq,
+	.get_vblank_counter	= drm_vblank_count,
+	.enable_vblank		= fsl_dcu_drm_enable_vblank,
+	.disable_vblank		= fsl_dcu_drm_disable_vblank,
+	.gem_free_object	= drm_gem_cma_free_object,
+	.gem_vm_ops		= &drm_gem_cma_vm_ops,
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_export	= drm_gem_prime_export,
+	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
+	.dumb_create		= drm_gem_cma_dumb_create,
+	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
+	.dumb_destroy		= drm_gem_dumb_destroy,
+	.fops			= &fsl_dcu_drm_fops,
+	.name			= "fsl-dcu-drm",
+	.desc			= "Freescale DCU DRM",
+	.date			= "20150213",
+	.major			= 1,
+	.minor			= 0,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int fsl_dcu_drm_pm_suspend(struct device *dev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
+
+	dcu_pixclk_disable();
+	drm_kms_helper_poll_disable(fsl_dev->ddev);
+	fsl_dcu_drm_crtc_suspend(&fsl_dev->crtc);
+
+	return 0;
+}
+
+static int fsl_dcu_drm_pm_resume(struct device *dev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
+
+	drm_modeset_lock_all(fsl_dev->ddev);
+	fsl_dcu_drm_crtc_resume(&fsl_dev->crtc);
+	drm_modeset_unlock_all(fsl_dev->ddev);
+	drm_kms_helper_poll_enable(fsl_dev->ddev);
+	dcu_pixclk_enable();
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops fsl_dcu_drm_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_drm_pm_suspend, fsl_dcu_drm_pm_resume)
+};
+
+static int fsl_dcu_drm_probe(struct platform_device *pdev)
+{
+	return drm_platform_init(&fsl_dcu_drm_driver, pdev);
+}
+
+static int fsl_dcu_drm_remove(struct platform_device *pdev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
+
+	drm_put_dev(fsl_dev->ddev);
+
+	return 0;
+}
+
+static const struct of_device_id fsl_dcu_of_match[] = {
+		{ .compatible = "fsl,dcu", },
+		{ },
+};
+MODULE_DEVICE_TABLE(of, fsl_dcu_of_match);
+
+static struct platform_driver fsl_dcu_drm_platform_driver = {
+	.probe		= fsl_dcu_drm_probe,
+	.remove		= fsl_dcu_drm_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "fsl,dcu",
+		.pm	= &fsl_dcu_drm_pm_ops,
+		.of_match_table = fsl_dcu_of_match,
+	},
+};
+
+module_platform_driver(fsl_dcu_drm_platform_driver);
+
+MODULE_ALIAS("platform:fsl-dcu-drm");
+MODULE_DESCRIPTION("Freescale DCU DRM Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
new file mode 100644
index 0000000..cbdfefc
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_DRV_H__
+#define __FSL_DCU_DRM_DRV_H__
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <stddef.h>
+#include <drm/drm.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "fsl_dcu_drm_crtc.h"
+#include "fsl_dcu_drm_plane.h"
+#include "fsl_dcu_drm_connector.h"
+#define DRIVER_NAME			"fsl-dcu-fb"
+
+#define DCU_DCU_MODE			0x0010
+#define DCU_MODE_BLEND_ITER(x)		((x) << 20)
+#define DCU_MODE_RASTER_EN		BIT(14)
+#define DCU_MODE_DCU_MODE(x)		(x)
+#define DCU_MODE_DCU_MODE_MASK		0x03
+#define DCU_MODE_OFF			0
+#define DCU_MODE_NORMAL			1
+#define DCU_MODE_TEST			2
+#define DCU_MODE_COLORBAR		3
+
+#define DCU_BGND			0x0014
+#define DCU_BGND_R(x)			((x) << 16)
+#define DCU_BGND_G(x)			((x) << 8)
+#define DCU_BGND_B(x)			(x)
+
+#define DCU_DISP_SIZE			0x0018
+#define DCU_DISP_SIZE_DELTA_Y(x)	((x) << 16)
+/*Regisiter value 1/16 of horizontal resolution*/
+#define DCU_DISP_SIZE_DELTA_X(x)	((x) >> 4)
+
+#define DCU_HSYN_PARA			0x001c
+#define DCU_HSYN_PARA_BP(x)		((x) << 22)
+#define DCU_HSYN_PARA_PW(x)		((x) << 11)
+#define DCU_HSYN_PARA_FP(x)		(x)
+
+#define DCU_VSYN_PARA			0x0020
+#define DCU_VSYN_PARA_BP(x)		((x) << 22)
+#define DCU_VSYN_PARA_PW(x)		((x) << 11)
+#define DCU_VSYN_PARA_FP(x)		(x)
+
+#define DCU_SYN_POL			0x0024
+#define DCU_SYN_POL_INV_PXCK_FALL	(0 << 6)
+#define DCU_SYN_POL_NEG_REMAIN		(0 << 5)
+#define DCU_SYN_POL_INV_VS_LOW		BIT(1)
+#define DCU_SYN_POL_INV_HS_LOW		(1)
+
+#define DCU_THRESHOLD			0x0028
+#define DCU_THRESHOLD_LS_BF_VS(x)	((x) << 16)
+#define DCU_THRESHOLD_OUT_BUF_HIGH(x)	((x) << 8)
+#define DCU_THRESHOLD_OUT_BUF_LOW(x)	(x)
+#define BF_VS_VAL			0x03
+#define BUF_MAX_VAL			0x78
+#define BUF_MIN_VAL			0x0a
+
+#define DCU_INT_STATUS			0x002C
+#define DCU_INT_STATUS_UNDRUN		BIT(1)
+
+#define DCU_INT_MASK			0x0030
+#define DCU_INT_MASK_UNDRUN		BIT(1)
+#define DCU_INT_MASK_VBLANK		BIT(3)
+
+#define DCU_DIV_RATIO			0x0054
+
+#define DCU_UPDATE_MODE			0x00cc
+#define DCU_UPDATE_MODE_MODE		BIT(31)
+#define DCU_UPDATE_MODE_READREG		BIT(30)
+
+#define DCU_DCFB_MAX			0x300
+
+#define DCU_CTRLDESCLN_1(x)		(0x200 + (x) * 0x40)
+#define DCU_CTRLDESCLN_1_HEIGHT(x)	((x) << 16)
+#define DCU_CTRLDESCLN_1_WIDTH(x)	(x)
+
+#define DCU_CTRLDESCLN_2(x)		(0x204 + (x) * 0x40)
+#define DCU_CTRLDESCLN_2_POSY(x)	((x) << 16)
+#define DCU_CTRLDESCLN_2_POSX(x)	(x)
+
+#define DCU_CTRLDESCLN_3(x)		(0x208 + (x) * 0x40)
+
+#define DCU_CTRLDESCLN_4(x)		(0x20c + (x) * 0x40)
+#define DCU_CTRLDESCLN_4_EN		BIT(31)
+#define DCU_CTRLDESCLN_4_TILE_EN	BIT(30)
+#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT	BIT(29)
+#define DCU_CTRLDESCLN_4_SAFETY_EN	BIT(28)
+#define DCU_CTRLDESCLN_4_TRANS(x)	((x) << 20)
+#define DCU_CTRLDESCLN_4_BPP(x)		((x) << 16)
+#define DCU_CTRLDESCLN_4_RLE_EN		BIT(15)
+#define DCU_CTRLDESCLN_4_LUOFFS(x)	((x) << 4)
+#define DCU_CTRLDESCLN_4_BB_ON		BIT(2)
+#define DCU_CTRLDESCLN_4_AB(x)		(x)
+
+#define DCU_CTRLDESCLN_5(x)		(0x210 + (x) * 0x40)
+#define DCU_CTRLDESCLN_5_CKMAX_R(x)	((x) << 16)
+#define DCU_CTRLDESCLN_5_CKMAX_G(x)	((x) << 8)
+#define DCU_CTRLDESCLN_5_CKMAX_B(x)	(x)
+
+#define DCU_CTRLDESCLN_6(x)		(0x214 + (x) * 0x40)
+#define DCU_CTRLDESCLN_6_CKMIN_R(x)	((x) << 16)
+#define DCU_CTRLDESCLN_6_CKMIN_G(x)	((x) << 8)
+#define DCU_CTRLDESCLN_6_CKMIN_B(x)	(x)
+
+#define DCU_CTRLDESCLN_7(x)		(0x218 + (x) * 0x40)
+#define DCU_CTRLDESCLN_7_TILE_VER(x)	((x) << 16)
+#define DCU_CTRLDESCLN_7_TILE_HOR(x)	(x)
+
+#define DCU_CTRLDESCLN_8(x)		(0x21c + (x) * 0x40)
+#define DCU_CTRLDESCLN_8_FG_FCOLOR(x)	(x)
+
+#define DCU_CTRLDESCLN_9(x)		(0x220 + (x) * 0x40)
+#define DCU_CTRLDESCLN_9_BG_BCOLOR(x)	(x)
+
+#define DCU_CTRLDESCLN_10(x)		(0x224 + (x) * 0x40)
+#define DCU_CTRLDESCLN_10_POST_SKIP(x)	((x) << 16)
+#define DCU_CTRLDESCLN_10_PRE_SKIP(x)	(x)
+
+#define FSL_DCU_RGB565			4
+#define FSL_DCU_RGB888			5
+#define FSL_DCU_ARGB8888		6
+#define FSL_DCU_ARGB1555		11
+#define FSL_DCU_ARGB4444		12
+#define FSL_DCU_YUV422			14
+
+#define TCON_CTRL1			0x0000
+#define TCON_BYPASS_ENABLE		BIT(29)
+
+#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+
+struct clk;
+struct device;
+struct drm_device;
+
+struct fsl_dcu_drm_device {
+	struct device *dev;
+	struct regmap *regmap;
+	struct regmap *tcon_regmap;
+	unsigned int irq;
+	struct clk *clk;
+	/*protects hardware register*/
+	spinlock_t irq_lock;
+	struct drm_device *ddev;
+	struct drm_fbdev_cma *fbdev;
+	struct fsl_dcu_drm_crtc crtc;
+	struct drm_encoder encoder;
+	struct fsl_dcu_drm_connector connector;
+};
+
+void fsl_dcu_fbdev_init(struct drm_device *dev);
+
+#endif /* __FSL_DCU_DRM_DRV_H__ */
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
new file mode 100644
index 0000000..f8ef0e1
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "fsl_dcu_drm_drv.h"
+
+/* initialize fbdev helper */
+void fsl_dcu_fbdev_init(struct drm_device *dev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
+
+	fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1);
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
new file mode 100644
index 0000000..4a840fb
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "fsl_dcu_drm_crtc.h"
+#include "fsl_dcu_drm_connector.h"
+#include "fsl_dcu_drm_drv.h"
+
+static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
+{
+	drm_mode_config_init(fsl_dev->ddev);
+
+	fsl_dev->ddev->mode_config.min_width = 0;
+	fsl_dev->ddev->mode_config.min_height = 0;
+	fsl_dev->ddev->mode_config.max_width = 2031;
+	fsl_dev->ddev->mode_config.max_height = 2047;
+	fsl_dev->ddev->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;
+
+	drm_kms_helper_poll_init(fsl_dev->ddev);
+	fsl_dcu_drm_crtc_create(fsl_dev);
+	fsl_dcu_drm_encoder_create(fsl_dev);
+	fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
+	drm_mode_config_reset(fsl_dev->ddev);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
new file mode 100644
index 0000000..b9bd299
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_KMS_H__
+#define __FSL_DCU_DRM_KMS_H__
+
+int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
+
+#endif /* __FSL_DCU_DRM_KMS_H__ */
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
new file mode 100644
index 0000000..b7b4405
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <linux/regmap.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "fsl_dcu_drm_drv.h"
+#include "fsl_dcu_drm_kms.h"
+#include "fsl_dcu_drm_plane.h"
+
+#define to_fsl_dcu_plane(plane) \
+	container_of(plane, struct fsl_dcu_drm_plane, plane)
+
+static int
+fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
+			     struct drm_framebuffer *fb,
+			     const struct drm_plane_state *new_state)
+{
+	return 0;
+}
+
+static void
+fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
+			     struct drm_framebuffer *fb,
+			     const struct drm_plane_state *new_state)
+{
+}
+
+static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
+					  struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
+					     struct drm_plane_state *old_state)
+{
+}
+
+void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
+				     struct drm_plane_state *old_state)
+{
+	struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = plane->state->fb;
+	u32 index, alpha, bpp;
+	struct drm_gem_cma_object *gem;
+	struct fsl_dcu_drm_plane *fsl_plane = to_fsl_dcu_plane(plane);
+
+	index = fsl_plane->index;
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_RGB565:
+		bpp = FSL_DCU_RGB565;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_RGB888:
+		bpp = FSL_DCU_RGB888;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_ARGB8888:
+		bpp = FSL_DCU_ARGB8888;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_BGRA4444:
+		bpp = FSL_DCU_ARGB4444;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_ARGB1555:
+		bpp = FSL_DCU_ARGB1555;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_YUV422:
+		bpp = FSL_DCU_YUV422;
+		alpha = 0xff;
+		break;
+	default:
+		return;
+	}
+
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_1(index),
+		     DCU_CTRLDESCLN_1_HEIGHT(state->crtc_h) |
+		     DCU_CTRLDESCLN_1_WIDTH(state->crtc_w));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_2(index),
+		     DCU_CTRLDESCLN_2_POSY(state->crtc_y) |
+		     DCU_CTRLDESCLN_2_POSX(state->crtc_x));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_3(index), gem->paddr);
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_4(index),
+		     DCU_CTRLDESCLN_4_EN |
+		     DCU_CTRLDESCLN_4_TRANS(alpha) |
+		     DCU_CTRLDESCLN_4_BPP(bpp) |
+		     DCU_CTRLDESCLN_4_AB(2));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_5(index),
+		     DCU_CTRLDESCLN_5_CKMAX_R(0xFF) |
+		     DCU_CTRLDESCLN_5_CKMAX_G(0xFF) |
+		     DCU_CTRLDESCLN_5_CKMAX_B(0xFF));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_6(index),
+		     DCU_CTRLDESCLN_6_CKMIN_R(0) |
+		     DCU_CTRLDESCLN_6_CKMIN_G(0) |
+		     DCU_CTRLDESCLN_6_CKMIN_B(0));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_8(index),
+		     DCU_CTRLDESCLN_8_FG_FCOLOR(0));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_9(index),
+		     DCU_CTRLDESCLN_9_BG_BCOLOR(0));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_10(index),
+		     DCU_CTRLDESCLN_10_POST_SKIP(0) |
+		     DCU_CTRLDESCLN_10_PRE_SKIP(0));
+	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
+}
+
+int fsl_dcu_drm_plane_disable(struct drm_plane *plane)
+{
+	return 0;
+}
+
+void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
+{
+	fsl_dcu_drm_plane_disable(plane);
+	drm_plane_cleanup(plane);
+}
+
+static const uint32_t fsl_dcu_drm_plane_formats[] = {
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_YUV422,
+};
+
+static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
+	.update_plane = drm_plane_helper_update,
+	.disable_plane = drm_plane_helper_disable,
+	.destroy = fsl_dcu_drm_plane_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+	.reset = drm_atomic_helper_plane_reset,
+};
+
+static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
+	.prepare_fb = fsl_dcu_drm_plane_prepare_fb,
+	.cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
+	.atomic_check = fsl_dcu_drm_plane_atomic_check,
+	.atomic_update = fsl_dcu_drm_plane_atomic_update,
+	.atomic_disable = fsl_dcu_drm_plane_atomic_disable,
+};
+
+struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
+{
+	struct drm_plane *primary;
+	int ret;
+
+	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
+	if (!primary) {
+		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
+		return NULL;
+	}
+
+	/* possible_crtc's will be filled in later by crtc_init */
+	ret = drm_universal_plane_init(dev, primary, 0,
+				       &fsl_dcu_drm_plane_funcs,
+				       fsl_dcu_drm_plane_formats,
+				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
+				       DRM_PLANE_TYPE_PRIMARY);
+	if (ret) {
+		kfree(primary);
+		primary = NULL;
+	}
+	drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
+
+	return primary;
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
new file mode 100644
index 0000000..ccbfa61
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_PLANE_H__
+#define __FSL_DCU_DRM_PLANE_H__
+
+struct fsl_dcu_drm_device;
+struct fsl_dcu_drm_plane {
+	struct drm_plane plane;
+	unsigned int index;
+};
+
+struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev);
+
+#endif /* __FSL_DCU_DRM_PLANE_H__ */
diff --git a/include/linux/fsl/dcu.h b/include/linux/fsl/dcu.h
new file mode 100644
index 0000000..1873057
--- /dev/null
+++ b/include/linux/fsl/dcu.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_H__
+#define __FSL_DCU_H__
+
+#define SCFG_PIXCLKCR			0x28
+#define PXCK_ENABLE			BIT(31)
+#define PXCK_DISABLE			0
+
+void dcu_pixclk_enable(void);
+void dcu_pixclk_disable(void);
+
+#endif /* __FSL_DCU_H__ */
-- 
2.1.0.27.g96db324


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

* [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
@ 2015-03-13  9:44 ` Jianwei Wang
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei Wang @ 2015-03-13  9:44 UTC (permalink / raw)
  To: linux-arm-kernel

This patch add support for Two Dimensional Animation and Compositing
Engine (2D-ACE) on Freescale SoCs.

2D-ACE is a Freescale display controller. It provide an hardware
cursor.

This is a simplified version, only a primary plane, a fb created for
fbdev, a crtc, a connector for TFT LCD panel, an encoder, and the
encoder is not in use.

Signed-off-by: Alison Wang <b18965@freescale.com>
Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Jianwei Wang <b52261@freescale.com>
---

Changed in v2:??
- Add atomic support
- Modify bindings file
- Rename node for compatibility
- Move platform related code out for compatibility

Added in v1:??
-??Add support for DCU display controller on the Freescale LS102x SoCs.
- Create a primary plane, a fb created for fbdev, a crtc, a connector
for TFT LCD panel, an encoder.

 arch/arm/mach-imx/mach-ls1021a.c            |  36 ++++
 drivers/gpu/drm/Kconfig                     |   2 +
 drivers/gpu/drm/Makefile                    |   1 +
 drivers/gpu/drm/fsl/Kconfig                 |  17 ++
 drivers/gpu/drm/fsl/Makefile                |   8 +
 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c | 203 ++++++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h |  28 +++
 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c      | 164 ++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h      |  26 +++
 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c       | 288 ++++++++++++++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h       | 168 ++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c     |  26 +++
 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c       |  42 ++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h       |  17 ++
 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c     | 187 ++++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h     |  23 +++
 include/linux/fsl/dcu.h                     |  22 +++
 17 files changed, 1258 insertions(+)
 create mode 100644 drivers/gpu/drm/fsl/Kconfig
 create mode 100644 drivers/gpu/drm/fsl/Makefile
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
 create mode 100644 include/linux/fsl/dcu.h

diff --git a/arch/arm/mach-imx/mach-ls1021a.c b/arch/arm/mach-imx/mach-ls1021a.c
index b89c858..4fb346d 100644
--- a/arch/arm/mach-imx/mach-ls1021a.c
+++ b/arch/arm/mach-imx/mach-ls1021a.c
@@ -8,9 +8,44 @@
  */
 
 #include <asm/mach/arch.h>
+#include <linux/of_platform.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/fsl/dcu.h>
 
 #include "common.h"
 
+void dcu_pixclk_disable(void)
+{
+	struct regmap *scfg_regmap;
+
+	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
+	if (IS_ERR(scfg_regmap)) {
+		pr_err("No syscfg phandle specified\n");
+		return;
+	}
+
+	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_DISABLE);
+}
+
+void dcu_pixclk_enable(void)
+{
+	struct regmap *scfg_regmap;
+
+	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
+	if (IS_ERR(scfg_regmap)) {
+		pr_err("No syscfg phandle specified\n");
+		return;
+	}
+
+	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_ENABLE);
+}
+
+static void __init ls1021a_init_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	dcu_pixclk_enable();
+}
 static const char * const ls1021a_dt_compat[] __initconst = {
 	"fsl,ls1021a",
 	NULL,
@@ -18,5 +53,6 @@ static const char * const ls1021a_dt_compat[] __initconst = {
 
 DT_MACHINE_START(LS1021A, "Freescale LS1021A")
 	.smp		= smp_ops(ls1021a_smp_ops),
+	.init_machine	= ls1021a_init_machine,
 	.dt_compat	= ls1021a_dt_compat,
 MACHINE_END
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 151a050..a6957aa 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -199,6 +199,8 @@ source "drivers/gpu/drm/bochs/Kconfig"
 
 source "drivers/gpu/drm/msm/Kconfig"
 
+source "drivers/gpu/drm/fsl/Kconfig"
+
 source "drivers/gpu/drm/tegra/Kconfig"
 
 source "drivers/gpu/drm/panel/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 2c239b9..ab5b9ef 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_DRM_UDL) += udl/
 obj-$(CONFIG_DRM_AST) += ast/
 obj-$(CONFIG_DRM_ARMADA) += armada/
 obj-$(CONFIG_DRM_ATMEL_HLCDC)	+= atmel-hlcdc/
+obj-$(CONFIG_DRM_FSL_DCU) += fsl/
 obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
 obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
 obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
diff --git a/drivers/gpu/drm/fsl/Kconfig b/drivers/gpu/drm/fsl/Kconfig
new file mode 100644
index 0000000..e4f8df0
--- /dev/null
+++ b/drivers/gpu/drm/fsl/Kconfig
@@ -0,0 +1,17 @@
+config DRM_FSL_DCU
+	tristate "DRM Support for Freescale DCU"
+	depends on DRM && OF && ARM
+	select DRM_KMS_HELPER
+	select DRM_KMS_CMA_HELPER
+	select VIDEOMODE_HELPERS
+	select BACKLIGHT_CLASS_DEVICE
+	select BACKLIGHT_LCD_SUPPORT
+	select REGMAP_MMIO
+	select DRM_KMS_FB_HELPER
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	help
+	  Choose this option if you have an Freescale DCU chipset.
+	  If M is selected the module will be called fsl-dcu-drm.
diff --git a/drivers/gpu/drm/fsl/Makefile b/drivers/gpu/drm/fsl/Makefile
new file mode 100644
index 0000000..5f74aee
--- /dev/null
+++ b/drivers/gpu/drm/fsl/Makefile
@@ -0,0 +1,8 @@
+fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
+	       fsl_dcu_drm_kms.o \
+	       fsl_dcu_drm_connector.o \
+	       fsl_dcu_drm_plane.o \
+	       fsl_dcu_drm_crtc.o \
+	       fsl_dcu_drm_fbdev.o \
+
+obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
new file mode 100644
index 0000000..178d647
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/backlight.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <video/of_display_timing.h>
+
+#include "fsl_dcu_drm_drv.h"
+#include "fsl_dcu_drm_connector.h"
+
+static void fsl_dcu_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+}
+
+/* Disable the encoders as the first thing we do. */
+static void fsl_dcu_drm_encoder_mode_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void fsl_dcu_drm_encoder_mode_set(struct drm_encoder *encoder,
+					 struct drm_display_mode *mode,
+					 struct drm_display_mode *adjusted_mode)
+{
+}
+
+static void fsl_dcu_drm_encoder_mode_commit(struct drm_encoder *encoder)
+{
+}
+
+static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
+static int
+fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
+				 struct drm_crtc_state *crtc_state,
+				 struct drm_connector_state *conn_state)
+{
+	return 0;
+}
+
+static bool
+fsl_dcu_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+			       const struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
+	.dpms = fsl_dcu_drm_encoder_dpms,
+	.prepare = fsl_dcu_drm_encoder_mode_prepare,
+	.commit = fsl_dcu_drm_encoder_mode_commit,
+	.mode_set = fsl_dcu_drm_encoder_mode_set,
+	.disable = fsl_dcu_drm_encoder_disable,
+	.atomic_check = fsl_dcu_drm_encoder_atomic_check,
+	.mode_fixup = fsl_dcu_drm_encoder_mode_fixup,
+};
+
+static const struct drm_encoder_funcs encoder_funcs = {
+	.destroy = fsl_dcu_drm_encoder_destroy,
+};
+
+int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev)
+{
+	struct drm_encoder *encoder = &fsl_dev->encoder;
+	int ret;
+
+	encoder->possible_crtcs = 1;
+
+	ret = drm_encoder_init(fsl_dev->ddev, encoder, &encoder_funcs,
+			       DRM_MODE_ENCODER_LVDS);
+	if (ret < 0)
+		return ret;
+
+	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
+
+	return 0;
+}
+
+#define to_fsl_dcu_connector(connector) \
+	container_of(connector, struct fsl_dcu_drm_connector, connector)
+
+static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct device_node *display_np, *np = dev->dev->of_node;
+	struct drm_display_mode *mode = drm_mode_create(connector->dev);
+	int num_modes = 0;
+
+	if (np) {
+		display_np = of_parse_phandle(np, "display", 0);
+		if (!display_np) {
+			dev_err(dev->dev, "failed to find display phandle\n");
+			return num_modes;
+		}
+		of_get_drm_display_mode(display_np, mode, OF_USE_NATIVE_MODE);
+		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+		drm_mode_probed_add(connector, mode);
+		num_modes++;
+	}
+
+	return num_modes;
+}
+
+static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
+					    struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static struct drm_encoder *
+fsl_dcu_drm_connector_best_encoder(struct drm_connector *connector)
+{
+	struct fsl_dcu_drm_connector *fsl_con = to_fsl_dcu_connector(connector);
+
+	return fsl_con->encoder;
+}
+
+static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static enum drm_connector_status
+fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = fsl_dcu_drm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = fsl_dcu_drm_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_connector_helper_funcs connector_helper_funcs = {
+	.get_modes = fsl_dcu_drm_connector_get_modes,
+	.mode_valid = fsl_dcu_drm_connector_mode_valid,
+	.best_encoder = fsl_dcu_drm_connector_best_encoder,
+};
+
+int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
+				 struct drm_encoder *encoder)
+{
+	struct drm_connector *connector = &fsl_dev->connector.connector;
+	int ret;
+
+	fsl_dev->connector.encoder = encoder;
+
+	connector->display_info.width_mm = 0;
+	connector->display_info.height_mm = 0;
+
+	ret = drm_connector_init(fsl_dev->ddev, connector,
+				 &fsl_dcu_drm_connector_funcs,
+				 DRM_MODE_CONNECTOR_LVDS);
+	if (ret < 0)
+		return ret;
+
+	connector->dpms = DRM_MODE_DPMS_OFF;
+	drm_connector_helper_add(connector, &connector_helper_funcs);
+	ret = drm_connector_register(connector);
+	if (ret < 0)
+		goto err_cleanup;
+
+	ret = drm_mode_connector_attach_encoder(connector, encoder);
+	if (ret < 0)
+		goto err_sysfs;
+
+	connector->encoder = encoder;
+
+	drm_object_property_set_value
+		(&connector->base, fsl_dev->ddev->mode_config.dpms_property,
+		DRM_MODE_DPMS_OFF);
+
+	return 0;
+
+err_sysfs:
+	drm_connector_unregister(connector);
+err_cleanup:
+	drm_connector_cleanup(connector);
+	return ret;
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
new file mode 100644
index 0000000..afe44ab
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_CONNECTOR_H__
+#define __FSL_DCU_DRM_CONNECTOR_H__
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+
+struct fsl_dcu_drm_device;
+struct fsl_dcu_drm_connector {
+	struct drm_connector connector;
+	struct drm_encoder *encoder;
+};
+
+int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev);
+int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
+				 struct drm_encoder *encoder);
+
+#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
new file mode 100644
index 0000000..a43e7ce
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/regmap.h>
+#include <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+
+#include "fsl_dcu_drm_crtc.h"
+#include "fsl_dcu_drm_drv.h"
+#include "fsl_dcu_drm_plane.h"
+
+#define to_fsl_dcu_crtc(c)	container_of(c, struct fsl_dcu_drm_crtc, crtc)
+
+void fsl_dcu_drm_crtc_suspend(struct drm_crtc *crtc)
+{
+}
+
+static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+	struct drm_display_mode *mode = &crtc->state->mode;
+	uint32_t hbp, hfp, hsw, vbp, vfp, vsw, div, index;
+
+	DBG(": set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+	    mode->base.id, mode->name,
+	    mode->vrefresh, mode->clock,
+	    mode->hdisplay, mode->hsync_start,
+	    mode->hsync_end, mode->htotal,
+	    mode->vdisplay, mode->vsync_start,
+	    mode->vsync_end, mode->vtotal,
+	    mode->type, mode->flags);
+
+	index = drm_crtc_index(crtc);
+	div = (uint32_t)clk_get_rate(fsl_dev->clk) / mode->clock / 1000;
+
+	/* Configure timings: */
+	hbp = mode->htotal - mode->hsync_end;
+	hfp = mode->hsync_start - mode->hdisplay;
+	hsw = mode->hsync_end - mode->hsync_start;
+	vbp = mode->vtotal - mode->vsync_end;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vsw = mode->vsync_end - mode->vsync_start;
+
+	regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
+		     DCU_HSYN_PARA_BP(hbp) |
+		     DCU_HSYN_PARA_PW(hsw) |
+		     DCU_HSYN_PARA_FP(hfp));
+	regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
+		     DCU_VSYN_PARA_BP(vbp) |
+		     DCU_VSYN_PARA_PW(vsw) |
+		     DCU_VSYN_PARA_FP(vfp));
+	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
+		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
+		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
+	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
+	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
+}
+
+static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+					const struct drm_display_mode *mode,
+					struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void fsl_dcu_drm_crtc_prepare(struct drm_crtc *crtc)
+{
+}
+
+/* Now enable the clocks, plane, pipe, and connectors that we set up. */
+static void fsl_dcu_drm_crtc_mode_commit(struct drm_crtc *crtc)
+{
+}
+
+static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
+					 struct drm_crtc_state *state)
+{
+	return 0;
+}
+
+static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc)
+{
+}
+
+static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc)
+{
+}
+
+static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
+{
+}
+
+static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
+	.page_flip = drm_atomic_helper_page_flip,
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = drm_crtc_cleanup,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static void fsl_dcu_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+}
+
+static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
+	.disable = fsl_dcu_drm_disable_crtc,
+	.mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
+	.mode_set = drm_helper_crtc_mode_set,
+	.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
+	.mode_set_base = drm_helper_crtc_mode_set_base,
+	.prepare = fsl_dcu_drm_crtc_prepare,
+	.commit = fsl_dcu_drm_crtc_mode_commit,
+	.atomic_check = fsl_dcu_drm_crtc_atomic_check,
+	.atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
+	.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
+	.dpms = fsl_dcu_drm_crtc_dpms,
+};
+
+int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
+{
+	struct drm_plane *primary;
+	struct drm_crtc *crtc = &fsl_dev->crtc.crtc;
+	int ret;
+
+	fsl_dev->crtc.dpms = DRM_MODE_DPMS_OFF;
+
+	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->ddev);
+	ret = drm_crtc_init_with_planes(fsl_dev->ddev, crtc, primary, NULL,
+					&fsl_dcu_drm_crtc_funcs);
+	if (ret < 0)
+		return ret;
+
+	drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
+
+	regmap_write(fsl_dev->regmap, DCU_SYN_POL,
+		     DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
+	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
+		     DCU_BGND_G(0) | DCU_BGND_B(0));
+	regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
+		     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
+	regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
+		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
+		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
+		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
+	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
+			   DCU_MODE_DCU_MODE_MASK,
+			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
+	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
+	return 0;
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
new file mode 100644
index 0000000..d44b564
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_CRTC_H__
+#define __FSL_DCU_DRM_CRTC_H__
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+
+struct fsl_dcu_drm_device;
+struct fsl_dcu_drm_crtc {
+	struct drm_crtc crtc;
+	int dpms;
+};
+
+int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev);
+
+#endif /* __FSL_DCU_DRM_CRTC_H__ */
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
new file mode 100644
index 0000000..10975ee
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <drm/drmP.h>
+#include <linux/fsl/dcu.h>
+
+#include "fsl_dcu_drm_drv.h"
+#include "fsl_dcu_drm_kms.h"
+
+static int fsl_dcu_unload(struct drm_device *dev)
+{
+	drm_mode_config_cleanup(dev);
+	drm_vblank_cleanup(dev);
+	drm_irq_uninstall(dev);
+
+	dev->dev_private = NULL;
+
+	return 0;
+}
+
+static struct regmap_config fsl_dcu_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+};
+
+static int fsl_dcu_bypass_tcon(struct fsl_dcu_drm_device *fsl_dev,
+			       struct device_node *np)
+{
+	struct device_node *tcon_np;
+	struct platform_device *pdev;
+	struct clk *tcon_clk;
+	struct resource *res;
+	void __iomem *base;
+
+	tcon_np = of_parse_phandle(np, "tcon-controller", 0);
+	if (!tcon_np)
+		return -EINVAL;
+
+	pdev = of_find_device_by_node(tcon_np);
+	if (!pdev)
+		return -EINVAL;
+
+	tcon_clk = devm_clk_get(&pdev->dev, "tcon");
+	if (IS_ERR(tcon_clk))
+		return PTR_ERR(tcon_clk);
+	clk_prepare_enable(tcon_clk);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	fsl_dev->tcon_regmap = devm_regmap_init_mmio_clk(&pdev->dev,
+			"tcon", base, &fsl_dcu_regmap_config);
+	if (IS_ERR(fsl_dev->tcon_regmap)) {
+		dev_err(&pdev->dev, "regmap init failed\n");
+		return PTR_ERR(fsl_dev->tcon_regmap);
+	}
+
+	regmap_write(fsl_dev->tcon_regmap, TCON_CTRL1, TCON_BYPASS_ENABLE);
+	return 0;
+}
+
+static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
+{
+	struct platform_device *pdev = dev->platformdev;
+	struct fsl_dcu_drm_device *fsl_dev;
+	struct resource *res;
+	void __iomem *base;
+	int ret;
+
+	fsl_dev = devm_kzalloc(&pdev->dev, sizeof(*fsl_dev), GFP_KERNEL);
+	if (!fsl_dev)
+		return -ENOMEM;
+
+	fsl_dev->dev = &pdev->dev;
+	fsl_dev->ddev = dev;
+	dev->dev_private = fsl_dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base)) {
+		ret = PTR_ERR(base);
+		return ret;
+	}
+
+	fsl_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
+			base, &fsl_dcu_regmap_config);
+	if (IS_ERR(fsl_dev->regmap)) {
+		dev_err(&pdev->dev, "regmap init failed\n");
+		return PTR_ERR(fsl_dev->regmap);
+	}
+
+	ret = fsl_dcu_drm_modeset_init(fsl_dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to initialize mode setting\n");
+		return ret;
+	}
+
+	ret = drm_vblank_init(dev, 1);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to initialize vblank\n");
+		goto done;
+	}
+
+	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to install IRQ handler\n");
+		goto done;
+	}
+
+	/* Put TCON in bypass mode, so the input signals from DCU are passed
+	 * through TCON unchanged */
+	fsl_dcu_bypass_tcon(fsl_dev, pdev->dev.of_node);
+
+	fsl_dev->clk = devm_clk_get(&pdev->dev, "dcu");
+	if (IS_ERR(fsl_dev->clk)) {
+		ret = PTR_ERR(fsl_dev->clk);
+		dev_err(&pdev->dev, "could not get clock\n");
+		return ret;
+	}
+	clk_prepare_enable(fsl_dev->clk);
+
+	dev_set_drvdata(dev->dev, fsl_dev);
+
+	fsl_dcu_fbdev_init(dev);
+
+	return 0;
+done:
+	if (ret)
+		fsl_dcu_unload(dev);
+
+	return ret;
+}
+
+static void fsl_dcu_drm_preclose(struct drm_device *dev, struct drm_file *file)
+{
+	;
+}
+
+static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
+{
+	return IRQ_HANDLED;
+}
+
+static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int crtc)
+{
+	return 0;
+}
+
+static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int crtc)
+{
+	;
+}
+
+static const struct file_operations fsl_dcu_drm_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= drm_compat_ioctl,
+#endif
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+	.mmap		= drm_gem_cma_mmap,
+};
+
+static struct drm_driver fsl_dcu_drm_driver = {
+	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
+				| DRIVER_PRIME,
+	.load			= fsl_dcu_load,
+	.unload			= fsl_dcu_unload,
+	.preclose		= fsl_dcu_drm_preclose,
+	.irq_handler		= fsl_dcu_drm_irq,
+	.get_vblank_counter	= drm_vblank_count,
+	.enable_vblank		= fsl_dcu_drm_enable_vblank,
+	.disable_vblank		= fsl_dcu_drm_disable_vblank,
+	.gem_free_object	= drm_gem_cma_free_object,
+	.gem_vm_ops		= &drm_gem_cma_vm_ops,
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_export	= drm_gem_prime_export,
+	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
+	.dumb_create		= drm_gem_cma_dumb_create,
+	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
+	.dumb_destroy		= drm_gem_dumb_destroy,
+	.fops			= &fsl_dcu_drm_fops,
+	.name			= "fsl-dcu-drm",
+	.desc			= "Freescale DCU DRM",
+	.date			= "20150213",
+	.major			= 1,
+	.minor			= 0,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int fsl_dcu_drm_pm_suspend(struct device *dev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
+
+	dcu_pixclk_disable();
+	drm_kms_helper_poll_disable(fsl_dev->ddev);
+	fsl_dcu_drm_crtc_suspend(&fsl_dev->crtc);
+
+	return 0;
+}
+
+static int fsl_dcu_drm_pm_resume(struct device *dev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
+
+	drm_modeset_lock_all(fsl_dev->ddev);
+	fsl_dcu_drm_crtc_resume(&fsl_dev->crtc);
+	drm_modeset_unlock_all(fsl_dev->ddev);
+	drm_kms_helper_poll_enable(fsl_dev->ddev);
+	dcu_pixclk_enable();
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops fsl_dcu_drm_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_drm_pm_suspend, fsl_dcu_drm_pm_resume)
+};
+
+static int fsl_dcu_drm_probe(struct platform_device *pdev)
+{
+	return drm_platform_init(&fsl_dcu_drm_driver, pdev);
+}
+
+static int fsl_dcu_drm_remove(struct platform_device *pdev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
+
+	drm_put_dev(fsl_dev->ddev);
+
+	return 0;
+}
+
+static const struct of_device_id fsl_dcu_of_match[] = {
+		{ .compatible = "fsl,dcu", },
+		{ },
+};
+MODULE_DEVICE_TABLE(of, fsl_dcu_of_match);
+
+static struct platform_driver fsl_dcu_drm_platform_driver = {
+	.probe		= fsl_dcu_drm_probe,
+	.remove		= fsl_dcu_drm_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "fsl,dcu",
+		.pm	= &fsl_dcu_drm_pm_ops,
+		.of_match_table = fsl_dcu_of_match,
+	},
+};
+
+module_platform_driver(fsl_dcu_drm_platform_driver);
+
+MODULE_ALIAS("platform:fsl-dcu-drm");
+MODULE_DESCRIPTION("Freescale DCU DRM Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
new file mode 100644
index 0000000..cbdfefc
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_DRV_H__
+#define __FSL_DCU_DRM_DRV_H__
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <stddef.h>
+#include <drm/drm.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "fsl_dcu_drm_crtc.h"
+#include "fsl_dcu_drm_plane.h"
+#include "fsl_dcu_drm_connector.h"
+#define DRIVER_NAME			"fsl-dcu-fb"
+
+#define DCU_DCU_MODE			0x0010
+#define DCU_MODE_BLEND_ITER(x)		((x) << 20)
+#define DCU_MODE_RASTER_EN		BIT(14)
+#define DCU_MODE_DCU_MODE(x)		(x)
+#define DCU_MODE_DCU_MODE_MASK		0x03
+#define DCU_MODE_OFF			0
+#define DCU_MODE_NORMAL			1
+#define DCU_MODE_TEST			2
+#define DCU_MODE_COLORBAR		3
+
+#define DCU_BGND			0x0014
+#define DCU_BGND_R(x)			((x) << 16)
+#define DCU_BGND_G(x)			((x) << 8)
+#define DCU_BGND_B(x)			(x)
+
+#define DCU_DISP_SIZE			0x0018
+#define DCU_DISP_SIZE_DELTA_Y(x)	((x) << 16)
+/*Regisiter value 1/16 of horizontal resolution*/
+#define DCU_DISP_SIZE_DELTA_X(x)	((x) >> 4)
+
+#define DCU_HSYN_PARA			0x001c
+#define DCU_HSYN_PARA_BP(x)		((x) << 22)
+#define DCU_HSYN_PARA_PW(x)		((x) << 11)
+#define DCU_HSYN_PARA_FP(x)		(x)
+
+#define DCU_VSYN_PARA			0x0020
+#define DCU_VSYN_PARA_BP(x)		((x) << 22)
+#define DCU_VSYN_PARA_PW(x)		((x) << 11)
+#define DCU_VSYN_PARA_FP(x)		(x)
+
+#define DCU_SYN_POL			0x0024
+#define DCU_SYN_POL_INV_PXCK_FALL	(0 << 6)
+#define DCU_SYN_POL_NEG_REMAIN		(0 << 5)
+#define DCU_SYN_POL_INV_VS_LOW		BIT(1)
+#define DCU_SYN_POL_INV_HS_LOW		(1)
+
+#define DCU_THRESHOLD			0x0028
+#define DCU_THRESHOLD_LS_BF_VS(x)	((x) << 16)
+#define DCU_THRESHOLD_OUT_BUF_HIGH(x)	((x) << 8)
+#define DCU_THRESHOLD_OUT_BUF_LOW(x)	(x)
+#define BF_VS_VAL			0x03
+#define BUF_MAX_VAL			0x78
+#define BUF_MIN_VAL			0x0a
+
+#define DCU_INT_STATUS			0x002C
+#define DCU_INT_STATUS_UNDRUN		BIT(1)
+
+#define DCU_INT_MASK			0x0030
+#define DCU_INT_MASK_UNDRUN		BIT(1)
+#define DCU_INT_MASK_VBLANK		BIT(3)
+
+#define DCU_DIV_RATIO			0x0054
+
+#define DCU_UPDATE_MODE			0x00cc
+#define DCU_UPDATE_MODE_MODE		BIT(31)
+#define DCU_UPDATE_MODE_READREG		BIT(30)
+
+#define DCU_DCFB_MAX			0x300
+
+#define DCU_CTRLDESCLN_1(x)		(0x200 + (x) * 0x40)
+#define DCU_CTRLDESCLN_1_HEIGHT(x)	((x) << 16)
+#define DCU_CTRLDESCLN_1_WIDTH(x)	(x)
+
+#define DCU_CTRLDESCLN_2(x)		(0x204 + (x) * 0x40)
+#define DCU_CTRLDESCLN_2_POSY(x)	((x) << 16)
+#define DCU_CTRLDESCLN_2_POSX(x)	(x)
+
+#define DCU_CTRLDESCLN_3(x)		(0x208 + (x) * 0x40)
+
+#define DCU_CTRLDESCLN_4(x)		(0x20c + (x) * 0x40)
+#define DCU_CTRLDESCLN_4_EN		BIT(31)
+#define DCU_CTRLDESCLN_4_TILE_EN	BIT(30)
+#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT	BIT(29)
+#define DCU_CTRLDESCLN_4_SAFETY_EN	BIT(28)
+#define DCU_CTRLDESCLN_4_TRANS(x)	((x) << 20)
+#define DCU_CTRLDESCLN_4_BPP(x)		((x) << 16)
+#define DCU_CTRLDESCLN_4_RLE_EN		BIT(15)
+#define DCU_CTRLDESCLN_4_LUOFFS(x)	((x) << 4)
+#define DCU_CTRLDESCLN_4_BB_ON		BIT(2)
+#define DCU_CTRLDESCLN_4_AB(x)		(x)
+
+#define DCU_CTRLDESCLN_5(x)		(0x210 + (x) * 0x40)
+#define DCU_CTRLDESCLN_5_CKMAX_R(x)	((x) << 16)
+#define DCU_CTRLDESCLN_5_CKMAX_G(x)	((x) << 8)
+#define DCU_CTRLDESCLN_5_CKMAX_B(x)	(x)
+
+#define DCU_CTRLDESCLN_6(x)		(0x214 + (x) * 0x40)
+#define DCU_CTRLDESCLN_6_CKMIN_R(x)	((x) << 16)
+#define DCU_CTRLDESCLN_6_CKMIN_G(x)	((x) << 8)
+#define DCU_CTRLDESCLN_6_CKMIN_B(x)	(x)
+
+#define DCU_CTRLDESCLN_7(x)		(0x218 + (x) * 0x40)
+#define DCU_CTRLDESCLN_7_TILE_VER(x)	((x) << 16)
+#define DCU_CTRLDESCLN_7_TILE_HOR(x)	(x)
+
+#define DCU_CTRLDESCLN_8(x)		(0x21c + (x) * 0x40)
+#define DCU_CTRLDESCLN_8_FG_FCOLOR(x)	(x)
+
+#define DCU_CTRLDESCLN_9(x)		(0x220 + (x) * 0x40)
+#define DCU_CTRLDESCLN_9_BG_BCOLOR(x)	(x)
+
+#define DCU_CTRLDESCLN_10(x)		(0x224 + (x) * 0x40)
+#define DCU_CTRLDESCLN_10_POST_SKIP(x)	((x) << 16)
+#define DCU_CTRLDESCLN_10_PRE_SKIP(x)	(x)
+
+#define FSL_DCU_RGB565			4
+#define FSL_DCU_RGB888			5
+#define FSL_DCU_ARGB8888		6
+#define FSL_DCU_ARGB1555		11
+#define FSL_DCU_ARGB4444		12
+#define FSL_DCU_YUV422			14
+
+#define TCON_CTRL1			0x0000
+#define TCON_BYPASS_ENABLE		BIT(29)
+
+#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+
+struct clk;
+struct device;
+struct drm_device;
+
+struct fsl_dcu_drm_device {
+	struct device *dev;
+	struct regmap *regmap;
+	struct regmap *tcon_regmap;
+	unsigned int irq;
+	struct clk *clk;
+	/*protects hardware register*/
+	spinlock_t irq_lock;
+	struct drm_device *ddev;
+	struct drm_fbdev_cma *fbdev;
+	struct fsl_dcu_drm_crtc crtc;
+	struct drm_encoder encoder;
+	struct fsl_dcu_drm_connector connector;
+};
+
+void fsl_dcu_fbdev_init(struct drm_device *dev);
+
+#endif /* __FSL_DCU_DRM_DRV_H__ */
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
new file mode 100644
index 0000000..f8ef0e1
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "fsl_dcu_drm_drv.h"
+
+/* initialize fbdev helper */
+void fsl_dcu_fbdev_init(struct drm_device *dev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
+
+	fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1);
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
new file mode 100644
index 0000000..4a840fb
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "fsl_dcu_drm_crtc.h"
+#include "fsl_dcu_drm_connector.h"
+#include "fsl_dcu_drm_drv.h"
+
+static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
+{
+	drm_mode_config_init(fsl_dev->ddev);
+
+	fsl_dev->ddev->mode_config.min_width = 0;
+	fsl_dev->ddev->mode_config.min_height = 0;
+	fsl_dev->ddev->mode_config.max_width = 2031;
+	fsl_dev->ddev->mode_config.max_height = 2047;
+	fsl_dev->ddev->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;
+
+	drm_kms_helper_poll_init(fsl_dev->ddev);
+	fsl_dcu_drm_crtc_create(fsl_dev);
+	fsl_dcu_drm_encoder_create(fsl_dev);
+	fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
+	drm_mode_config_reset(fsl_dev->ddev);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
new file mode 100644
index 0000000..b9bd299
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_KMS_H__
+#define __FSL_DCU_DRM_KMS_H__
+
+int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
+
+#endif /* __FSL_DCU_DRM_KMS_H__ */
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
new file mode 100644
index 0000000..b7b4405
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <linux/regmap.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "fsl_dcu_drm_drv.h"
+#include "fsl_dcu_drm_kms.h"
+#include "fsl_dcu_drm_plane.h"
+
+#define to_fsl_dcu_plane(plane) \
+	container_of(plane, struct fsl_dcu_drm_plane, plane)
+
+static int
+fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
+			     struct drm_framebuffer *fb,
+			     const struct drm_plane_state *new_state)
+{
+	return 0;
+}
+
+static void
+fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
+			     struct drm_framebuffer *fb,
+			     const struct drm_plane_state *new_state)
+{
+}
+
+static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
+					  struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
+					     struct drm_plane_state *old_state)
+{
+}
+
+void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
+				     struct drm_plane_state *old_state)
+{
+	struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = plane->state->fb;
+	u32 index, alpha, bpp;
+	struct drm_gem_cma_object *gem;
+	struct fsl_dcu_drm_plane *fsl_plane = to_fsl_dcu_plane(plane);
+
+	index = fsl_plane->index;
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_RGB565:
+		bpp = FSL_DCU_RGB565;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_RGB888:
+		bpp = FSL_DCU_RGB888;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_ARGB8888:
+		bpp = FSL_DCU_ARGB8888;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_BGRA4444:
+		bpp = FSL_DCU_ARGB4444;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_ARGB1555:
+		bpp = FSL_DCU_ARGB1555;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_YUV422:
+		bpp = FSL_DCU_YUV422;
+		alpha = 0xff;
+		break;
+	default:
+		return;
+	}
+
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_1(index),
+		     DCU_CTRLDESCLN_1_HEIGHT(state->crtc_h) |
+		     DCU_CTRLDESCLN_1_WIDTH(state->crtc_w));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_2(index),
+		     DCU_CTRLDESCLN_2_POSY(state->crtc_y) |
+		     DCU_CTRLDESCLN_2_POSX(state->crtc_x));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_3(index), gem->paddr);
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_4(index),
+		     DCU_CTRLDESCLN_4_EN |
+		     DCU_CTRLDESCLN_4_TRANS(alpha) |
+		     DCU_CTRLDESCLN_4_BPP(bpp) |
+		     DCU_CTRLDESCLN_4_AB(2));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_5(index),
+		     DCU_CTRLDESCLN_5_CKMAX_R(0xFF) |
+		     DCU_CTRLDESCLN_5_CKMAX_G(0xFF) |
+		     DCU_CTRLDESCLN_5_CKMAX_B(0xFF));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_6(index),
+		     DCU_CTRLDESCLN_6_CKMIN_R(0) |
+		     DCU_CTRLDESCLN_6_CKMIN_G(0) |
+		     DCU_CTRLDESCLN_6_CKMIN_B(0));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_8(index),
+		     DCU_CTRLDESCLN_8_FG_FCOLOR(0));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_9(index),
+		     DCU_CTRLDESCLN_9_BG_BCOLOR(0));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_10(index),
+		     DCU_CTRLDESCLN_10_POST_SKIP(0) |
+		     DCU_CTRLDESCLN_10_PRE_SKIP(0));
+	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
+}
+
+int fsl_dcu_drm_plane_disable(struct drm_plane *plane)
+{
+	return 0;
+}
+
+void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
+{
+	fsl_dcu_drm_plane_disable(plane);
+	drm_plane_cleanup(plane);
+}
+
+static const uint32_t fsl_dcu_drm_plane_formats[] = {
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_YUV422,
+};
+
+static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
+	.update_plane = drm_plane_helper_update,
+	.disable_plane = drm_plane_helper_disable,
+	.destroy = fsl_dcu_drm_plane_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+	.reset = drm_atomic_helper_plane_reset,
+};
+
+static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
+	.prepare_fb = fsl_dcu_drm_plane_prepare_fb,
+	.cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
+	.atomic_check = fsl_dcu_drm_plane_atomic_check,
+	.atomic_update = fsl_dcu_drm_plane_atomic_update,
+	.atomic_disable = fsl_dcu_drm_plane_atomic_disable,
+};
+
+struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
+{
+	struct drm_plane *primary;
+	int ret;
+
+	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
+	if (!primary) {
+		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
+		return NULL;
+	}
+
+	/* possible_crtc's will be filled in later by crtc_init */
+	ret = drm_universal_plane_init(dev, primary, 0,
+				       &fsl_dcu_drm_plane_funcs,
+				       fsl_dcu_drm_plane_formats,
+				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
+				       DRM_PLANE_TYPE_PRIMARY);
+	if (ret) {
+		kfree(primary);
+		primary = NULL;
+	}
+	drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
+
+	return primary;
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
new file mode 100644
index 0000000..ccbfa61
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_PLANE_H__
+#define __FSL_DCU_DRM_PLANE_H__
+
+struct fsl_dcu_drm_device;
+struct fsl_dcu_drm_plane {
+	struct drm_plane plane;
+	unsigned int index;
+};
+
+struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev);
+
+#endif /* __FSL_DCU_DRM_PLANE_H__ */
diff --git a/include/linux/fsl/dcu.h b/include/linux/fsl/dcu.h
new file mode 100644
index 0000000..1873057
--- /dev/null
+++ b/include/linux/fsl/dcu.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_H__
+#define __FSL_DCU_H__
+
+#define SCFG_PIXCLKCR			0x28
+#define PXCK_ENABLE			BIT(31)
+#define PXCK_DISABLE			0
+
+void dcu_pixclk_enable(void);
+void dcu_pixclk_disable(void);
+
+#endif /* __FSL_DCU_H__ */
-- 
2.1.0.27.g96db324

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

* [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
@ 2015-03-13  9:44 ` Jianwei Wang
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei Wang @ 2015-03-13  9:44 UTC (permalink / raw)
  To: scottwood, airlied, jbarnes, dri-devel
  Cc: Xiubo Li, Alison Wang, linux-kernel, Jianwei Wang, Jason.Jin,
	linux-arm-kernel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="y", Size: 42889 bytes --]

This patch add support for Two Dimensional Animation and Compositing
Engine (2D-ACE) on Freescale SoCs.

2D-ACE is a Freescale display controller. It provide an hardware
cursor.

This is a simplified version, only a primary plane, a fb created for
fbdev, a crtc, a connector for TFT LCD panel, an encoder, and the
encoder is not in use.

Signed-off-by: Alison Wang <b18965@freescale.com>
Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Jianwei Wang <b52261@freescale.com>
---

Changed in v2: 
- Add atomic support
- Modify bindings file
- Rename node for compatibility
- Move platform related code out for compatibility

Added in v1: 
- Add support for DCU display controller on the Freescale LS102x SoCs.
- Create a primary plane, a fb created for fbdev, a crtc, a connector
for TFT LCD panel, an encoder.

 arch/arm/mach-imx/mach-ls1021a.c            |  36 ++++
 drivers/gpu/drm/Kconfig                     |   2 +
 drivers/gpu/drm/Makefile                    |   1 +
 drivers/gpu/drm/fsl/Kconfig                 |  17 ++
 drivers/gpu/drm/fsl/Makefile                |   8 +
 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c | 203 ++++++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h |  28 +++
 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c      | 164 ++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h      |  26 +++
 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c       | 288 ++++++++++++++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h       | 168 ++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c     |  26 +++
 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c       |  42 ++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h       |  17 ++
 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c     | 187 ++++++++++++++++++
 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h     |  23 +++
 include/linux/fsl/dcu.h                     |  22 +++
 17 files changed, 1258 insertions(+)
 create mode 100644 drivers/gpu/drm/fsl/Kconfig
 create mode 100644 drivers/gpu/drm/fsl/Makefile
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
 create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
 create mode 100644 include/linux/fsl/dcu.h

diff --git a/arch/arm/mach-imx/mach-ls1021a.c b/arch/arm/mach-imx/mach-ls1021a.c
index b89c858..4fb346d 100644
--- a/arch/arm/mach-imx/mach-ls1021a.c
+++ b/arch/arm/mach-imx/mach-ls1021a.c
@@ -8,9 +8,44 @@
  */
 
 #include <asm/mach/arch.h>
+#include <linux/of_platform.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/fsl/dcu.h>
 
 #include "common.h"
 
+void dcu_pixclk_disable(void)
+{
+	struct regmap *scfg_regmap;
+
+	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
+	if (IS_ERR(scfg_regmap)) {
+		pr_err("No syscfg phandle specified\n");
+		return;
+	}
+
+	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_DISABLE);
+}
+
+void dcu_pixclk_enable(void)
+{
+	struct regmap *scfg_regmap;
+
+	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
+	if (IS_ERR(scfg_regmap)) {
+		pr_err("No syscfg phandle specified\n");
+		return;
+	}
+
+	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_ENABLE);
+}
+
+static void __init ls1021a_init_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	dcu_pixclk_enable();
+}
 static const char * const ls1021a_dt_compat[] __initconst = {
 	"fsl,ls1021a",
 	NULL,
@@ -18,5 +53,6 @@ static const char * const ls1021a_dt_compat[] __initconst = {
 
 DT_MACHINE_START(LS1021A, "Freescale LS1021A")
 	.smp		= smp_ops(ls1021a_smp_ops),
+	.init_machine	= ls1021a_init_machine,
 	.dt_compat	= ls1021a_dt_compat,
 MACHINE_END
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 151a050..a6957aa 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -199,6 +199,8 @@ source "drivers/gpu/drm/bochs/Kconfig"
 
 source "drivers/gpu/drm/msm/Kconfig"
 
+source "drivers/gpu/drm/fsl/Kconfig"
+
 source "drivers/gpu/drm/tegra/Kconfig"
 
 source "drivers/gpu/drm/panel/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 2c239b9..ab5b9ef 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_DRM_UDL) += udl/
 obj-$(CONFIG_DRM_AST) += ast/
 obj-$(CONFIG_DRM_ARMADA) += armada/
 obj-$(CONFIG_DRM_ATMEL_HLCDC)	+= atmel-hlcdc/
+obj-$(CONFIG_DRM_FSL_DCU) += fsl/
 obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
 obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
 obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
diff --git a/drivers/gpu/drm/fsl/Kconfig b/drivers/gpu/drm/fsl/Kconfig
new file mode 100644
index 0000000..e4f8df0
--- /dev/null
+++ b/drivers/gpu/drm/fsl/Kconfig
@@ -0,0 +1,17 @@
+config DRM_FSL_DCU
+	tristate "DRM Support for Freescale DCU"
+	depends on DRM && OF && ARM
+	select DRM_KMS_HELPER
+	select DRM_KMS_CMA_HELPER
+	select VIDEOMODE_HELPERS
+	select BACKLIGHT_CLASS_DEVICE
+	select BACKLIGHT_LCD_SUPPORT
+	select REGMAP_MMIO
+	select DRM_KMS_FB_HELPER
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	help
+	  Choose this option if you have an Freescale DCU chipset.
+	  If M is selected the module will be called fsl-dcu-drm.
diff --git a/drivers/gpu/drm/fsl/Makefile b/drivers/gpu/drm/fsl/Makefile
new file mode 100644
index 0000000..5f74aee
--- /dev/null
+++ b/drivers/gpu/drm/fsl/Makefile
@@ -0,0 +1,8 @@
+fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
+	       fsl_dcu_drm_kms.o \
+	       fsl_dcu_drm_connector.o \
+	       fsl_dcu_drm_plane.o \
+	       fsl_dcu_drm_crtc.o \
+	       fsl_dcu_drm_fbdev.o \
+
+obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
new file mode 100644
index 0000000..178d647
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/backlight.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <video/of_display_timing.h>
+
+#include "fsl_dcu_drm_drv.h"
+#include "fsl_dcu_drm_connector.h"
+
+static void fsl_dcu_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+}
+
+/* Disable the encoders as the first thing we do. */
+static void fsl_dcu_drm_encoder_mode_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void fsl_dcu_drm_encoder_mode_set(struct drm_encoder *encoder,
+					 struct drm_display_mode *mode,
+					 struct drm_display_mode *adjusted_mode)
+{
+}
+
+static void fsl_dcu_drm_encoder_mode_commit(struct drm_encoder *encoder)
+{
+}
+
+static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
+static int
+fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
+				 struct drm_crtc_state *crtc_state,
+				 struct drm_connector_state *conn_state)
+{
+	return 0;
+}
+
+static bool
+fsl_dcu_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+			       const struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
+	.dpms = fsl_dcu_drm_encoder_dpms,
+	.prepare = fsl_dcu_drm_encoder_mode_prepare,
+	.commit = fsl_dcu_drm_encoder_mode_commit,
+	.mode_set = fsl_dcu_drm_encoder_mode_set,
+	.disable = fsl_dcu_drm_encoder_disable,
+	.atomic_check = fsl_dcu_drm_encoder_atomic_check,
+	.mode_fixup = fsl_dcu_drm_encoder_mode_fixup,
+};
+
+static const struct drm_encoder_funcs encoder_funcs = {
+	.destroy = fsl_dcu_drm_encoder_destroy,
+};
+
+int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev)
+{
+	struct drm_encoder *encoder = &fsl_dev->encoder;
+	int ret;
+
+	encoder->possible_crtcs = 1;
+
+	ret = drm_encoder_init(fsl_dev->ddev, encoder, &encoder_funcs,
+			       DRM_MODE_ENCODER_LVDS);
+	if (ret < 0)
+		return ret;
+
+	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
+
+	return 0;
+}
+
+#define to_fsl_dcu_connector(connector) \
+	container_of(connector, struct fsl_dcu_drm_connector, connector)
+
+static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct device_node *display_np, *np = dev->dev->of_node;
+	struct drm_display_mode *mode = drm_mode_create(connector->dev);
+	int num_modes = 0;
+
+	if (np) {
+		display_np = of_parse_phandle(np, "display", 0);
+		if (!display_np) {
+			dev_err(dev->dev, "failed to find display phandle\n");
+			return num_modes;
+		}
+		of_get_drm_display_mode(display_np, mode, OF_USE_NATIVE_MODE);
+		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+		drm_mode_probed_add(connector, mode);
+		num_modes++;
+	}
+
+	return num_modes;
+}
+
+static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
+					    struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static struct drm_encoder *
+fsl_dcu_drm_connector_best_encoder(struct drm_connector *connector)
+{
+	struct fsl_dcu_drm_connector *fsl_con = to_fsl_dcu_connector(connector);
+
+	return fsl_con->encoder;
+}
+
+static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static enum drm_connector_status
+fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = fsl_dcu_drm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = fsl_dcu_drm_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_connector_helper_funcs connector_helper_funcs = {
+	.get_modes = fsl_dcu_drm_connector_get_modes,
+	.mode_valid = fsl_dcu_drm_connector_mode_valid,
+	.best_encoder = fsl_dcu_drm_connector_best_encoder,
+};
+
+int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
+				 struct drm_encoder *encoder)
+{
+	struct drm_connector *connector = &fsl_dev->connector.connector;
+	int ret;
+
+	fsl_dev->connector.encoder = encoder;
+
+	connector->display_info.width_mm = 0;
+	connector->display_info.height_mm = 0;
+
+	ret = drm_connector_init(fsl_dev->ddev, connector,
+				 &fsl_dcu_drm_connector_funcs,
+				 DRM_MODE_CONNECTOR_LVDS);
+	if (ret < 0)
+		return ret;
+
+	connector->dpms = DRM_MODE_DPMS_OFF;
+	drm_connector_helper_add(connector, &connector_helper_funcs);
+	ret = drm_connector_register(connector);
+	if (ret < 0)
+		goto err_cleanup;
+
+	ret = drm_mode_connector_attach_encoder(connector, encoder);
+	if (ret < 0)
+		goto err_sysfs;
+
+	connector->encoder = encoder;
+
+	drm_object_property_set_value
+		(&connector->base, fsl_dev->ddev->mode_config.dpms_property,
+		DRM_MODE_DPMS_OFF);
+
+	return 0;
+
+err_sysfs:
+	drm_connector_unregister(connector);
+err_cleanup:
+	drm_connector_cleanup(connector);
+	return ret;
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
new file mode 100644
index 0000000..afe44ab
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_CONNECTOR_H__
+#define __FSL_DCU_DRM_CONNECTOR_H__
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+
+struct fsl_dcu_drm_device;
+struct fsl_dcu_drm_connector {
+	struct drm_connector connector;
+	struct drm_encoder *encoder;
+};
+
+int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev);
+int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
+				 struct drm_encoder *encoder);
+
+#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
new file mode 100644
index 0000000..a43e7ce
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/regmap.h>
+#include <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+
+#include "fsl_dcu_drm_crtc.h"
+#include "fsl_dcu_drm_drv.h"
+#include "fsl_dcu_drm_plane.h"
+
+#define to_fsl_dcu_crtc(c)	container_of(c, struct fsl_dcu_drm_crtc, crtc)
+
+void fsl_dcu_drm_crtc_suspend(struct drm_crtc *crtc)
+{
+}
+
+static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+	struct drm_display_mode *mode = &crtc->state->mode;
+	uint32_t hbp, hfp, hsw, vbp, vfp, vsw, div, index;
+
+	DBG(": set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+	    mode->base.id, mode->name,
+	    mode->vrefresh, mode->clock,
+	    mode->hdisplay, mode->hsync_start,
+	    mode->hsync_end, mode->htotal,
+	    mode->vdisplay, mode->vsync_start,
+	    mode->vsync_end, mode->vtotal,
+	    mode->type, mode->flags);
+
+	index = drm_crtc_index(crtc);
+	div = (uint32_t)clk_get_rate(fsl_dev->clk) / mode->clock / 1000;
+
+	/* Configure timings: */
+	hbp = mode->htotal - mode->hsync_end;
+	hfp = mode->hsync_start - mode->hdisplay;
+	hsw = mode->hsync_end - mode->hsync_start;
+	vbp = mode->vtotal - mode->vsync_end;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vsw = mode->vsync_end - mode->vsync_start;
+
+	regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
+		     DCU_HSYN_PARA_BP(hbp) |
+		     DCU_HSYN_PARA_PW(hsw) |
+		     DCU_HSYN_PARA_FP(hfp));
+	regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
+		     DCU_VSYN_PARA_BP(vbp) |
+		     DCU_VSYN_PARA_PW(vsw) |
+		     DCU_VSYN_PARA_FP(vfp));
+	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
+		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
+		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
+	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
+	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
+}
+
+static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+					const struct drm_display_mode *mode,
+					struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void fsl_dcu_drm_crtc_prepare(struct drm_crtc *crtc)
+{
+}
+
+/* Now enable the clocks, plane, pipe, and connectors that we set up. */
+static void fsl_dcu_drm_crtc_mode_commit(struct drm_crtc *crtc)
+{
+}
+
+static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
+					 struct drm_crtc_state *state)
+{
+	return 0;
+}
+
+static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc)
+{
+}
+
+static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc)
+{
+}
+
+static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
+{
+}
+
+static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
+	.page_flip = drm_atomic_helper_page_flip,
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = drm_crtc_cleanup,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static void fsl_dcu_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+}
+
+static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
+	.disable = fsl_dcu_drm_disable_crtc,
+	.mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
+	.mode_set = drm_helper_crtc_mode_set,
+	.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
+	.mode_set_base = drm_helper_crtc_mode_set_base,
+	.prepare = fsl_dcu_drm_crtc_prepare,
+	.commit = fsl_dcu_drm_crtc_mode_commit,
+	.atomic_check = fsl_dcu_drm_crtc_atomic_check,
+	.atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
+	.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
+	.dpms = fsl_dcu_drm_crtc_dpms,
+};
+
+int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
+{
+	struct drm_plane *primary;
+	struct drm_crtc *crtc = &fsl_dev->crtc.crtc;
+	int ret;
+
+	fsl_dev->crtc.dpms = DRM_MODE_DPMS_OFF;
+
+	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->ddev);
+	ret = drm_crtc_init_with_planes(fsl_dev->ddev, crtc, primary, NULL,
+					&fsl_dcu_drm_crtc_funcs);
+	if (ret < 0)
+		return ret;
+
+	drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
+
+	regmap_write(fsl_dev->regmap, DCU_SYN_POL,
+		     DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
+	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
+		     DCU_BGND_G(0) | DCU_BGND_B(0));
+	regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
+		     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
+	regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
+		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
+		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
+		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
+	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
+			   DCU_MODE_DCU_MODE_MASK,
+			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
+	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
+	return 0;
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
new file mode 100644
index 0000000..d44b564
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_CRTC_H__
+#define __FSL_DCU_DRM_CRTC_H__
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+
+struct fsl_dcu_drm_device;
+struct fsl_dcu_drm_crtc {
+	struct drm_crtc crtc;
+	int dpms;
+};
+
+int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev);
+
+#endif /* __FSL_DCU_DRM_CRTC_H__ */
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
new file mode 100644
index 0000000..10975ee
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <drm/drmP.h>
+#include <linux/fsl/dcu.h>
+
+#include "fsl_dcu_drm_drv.h"
+#include "fsl_dcu_drm_kms.h"
+
+static int fsl_dcu_unload(struct drm_device *dev)
+{
+	drm_mode_config_cleanup(dev);
+	drm_vblank_cleanup(dev);
+	drm_irq_uninstall(dev);
+
+	dev->dev_private = NULL;
+
+	return 0;
+}
+
+static struct regmap_config fsl_dcu_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+};
+
+static int fsl_dcu_bypass_tcon(struct fsl_dcu_drm_device *fsl_dev,
+			       struct device_node *np)
+{
+	struct device_node *tcon_np;
+	struct platform_device *pdev;
+	struct clk *tcon_clk;
+	struct resource *res;
+	void __iomem *base;
+
+	tcon_np = of_parse_phandle(np, "tcon-controller", 0);
+	if (!tcon_np)
+		return -EINVAL;
+
+	pdev = of_find_device_by_node(tcon_np);
+	if (!pdev)
+		return -EINVAL;
+
+	tcon_clk = devm_clk_get(&pdev->dev, "tcon");
+	if (IS_ERR(tcon_clk))
+		return PTR_ERR(tcon_clk);
+	clk_prepare_enable(tcon_clk);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	fsl_dev->tcon_regmap = devm_regmap_init_mmio_clk(&pdev->dev,
+			"tcon", base, &fsl_dcu_regmap_config);
+	if (IS_ERR(fsl_dev->tcon_regmap)) {
+		dev_err(&pdev->dev, "regmap init failed\n");
+		return PTR_ERR(fsl_dev->tcon_regmap);
+	}
+
+	regmap_write(fsl_dev->tcon_regmap, TCON_CTRL1, TCON_BYPASS_ENABLE);
+	return 0;
+}
+
+static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
+{
+	struct platform_device *pdev = dev->platformdev;
+	struct fsl_dcu_drm_device *fsl_dev;
+	struct resource *res;
+	void __iomem *base;
+	int ret;
+
+	fsl_dev = devm_kzalloc(&pdev->dev, sizeof(*fsl_dev), GFP_KERNEL);
+	if (!fsl_dev)
+		return -ENOMEM;
+
+	fsl_dev->dev = &pdev->dev;
+	fsl_dev->ddev = dev;
+	dev->dev_private = fsl_dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base)) {
+		ret = PTR_ERR(base);
+		return ret;
+	}
+
+	fsl_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
+			base, &fsl_dcu_regmap_config);
+	if (IS_ERR(fsl_dev->regmap)) {
+		dev_err(&pdev->dev, "regmap init failed\n");
+		return PTR_ERR(fsl_dev->regmap);
+	}
+
+	ret = fsl_dcu_drm_modeset_init(fsl_dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to initialize mode setting\n");
+		return ret;
+	}
+
+	ret = drm_vblank_init(dev, 1);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to initialize vblank\n");
+		goto done;
+	}
+
+	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to install IRQ handler\n");
+		goto done;
+	}
+
+	/* Put TCON in bypass mode, so the input signals from DCU are passed
+	 * through TCON unchanged */
+	fsl_dcu_bypass_tcon(fsl_dev, pdev->dev.of_node);
+
+	fsl_dev->clk = devm_clk_get(&pdev->dev, "dcu");
+	if (IS_ERR(fsl_dev->clk)) {
+		ret = PTR_ERR(fsl_dev->clk);
+		dev_err(&pdev->dev, "could not get clock\n");
+		return ret;
+	}
+	clk_prepare_enable(fsl_dev->clk);
+
+	dev_set_drvdata(dev->dev, fsl_dev);
+
+	fsl_dcu_fbdev_init(dev);
+
+	return 0;
+done:
+	if (ret)
+		fsl_dcu_unload(dev);
+
+	return ret;
+}
+
+static void fsl_dcu_drm_preclose(struct drm_device *dev, struct drm_file *file)
+{
+	;
+}
+
+static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
+{
+	return IRQ_HANDLED;
+}
+
+static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int crtc)
+{
+	return 0;
+}
+
+static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int crtc)
+{
+	;
+}
+
+static const struct file_operations fsl_dcu_drm_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= drm_compat_ioctl,
+#endif
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+	.mmap		= drm_gem_cma_mmap,
+};
+
+static struct drm_driver fsl_dcu_drm_driver = {
+	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
+				| DRIVER_PRIME,
+	.load			= fsl_dcu_load,
+	.unload			= fsl_dcu_unload,
+	.preclose		= fsl_dcu_drm_preclose,
+	.irq_handler		= fsl_dcu_drm_irq,
+	.get_vblank_counter	= drm_vblank_count,
+	.enable_vblank		= fsl_dcu_drm_enable_vblank,
+	.disable_vblank		= fsl_dcu_drm_disable_vblank,
+	.gem_free_object	= drm_gem_cma_free_object,
+	.gem_vm_ops		= &drm_gem_cma_vm_ops,
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_export	= drm_gem_prime_export,
+	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
+	.dumb_create		= drm_gem_cma_dumb_create,
+	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
+	.dumb_destroy		= drm_gem_dumb_destroy,
+	.fops			= &fsl_dcu_drm_fops,
+	.name			= "fsl-dcu-drm",
+	.desc			= "Freescale DCU DRM",
+	.date			= "20150213",
+	.major			= 1,
+	.minor			= 0,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int fsl_dcu_drm_pm_suspend(struct device *dev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
+
+	dcu_pixclk_disable();
+	drm_kms_helper_poll_disable(fsl_dev->ddev);
+	fsl_dcu_drm_crtc_suspend(&fsl_dev->crtc);
+
+	return 0;
+}
+
+static int fsl_dcu_drm_pm_resume(struct device *dev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
+
+	drm_modeset_lock_all(fsl_dev->ddev);
+	fsl_dcu_drm_crtc_resume(&fsl_dev->crtc);
+	drm_modeset_unlock_all(fsl_dev->ddev);
+	drm_kms_helper_poll_enable(fsl_dev->ddev);
+	dcu_pixclk_enable();
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops fsl_dcu_drm_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_drm_pm_suspend, fsl_dcu_drm_pm_resume)
+};
+
+static int fsl_dcu_drm_probe(struct platform_device *pdev)
+{
+	return drm_platform_init(&fsl_dcu_drm_driver, pdev);
+}
+
+static int fsl_dcu_drm_remove(struct platform_device *pdev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
+
+	drm_put_dev(fsl_dev->ddev);
+
+	return 0;
+}
+
+static const struct of_device_id fsl_dcu_of_match[] = {
+		{ .compatible = "fsl,dcu", },
+		{ },
+};
+MODULE_DEVICE_TABLE(of, fsl_dcu_of_match);
+
+static struct platform_driver fsl_dcu_drm_platform_driver = {
+	.probe		= fsl_dcu_drm_probe,
+	.remove		= fsl_dcu_drm_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "fsl,dcu",
+		.pm	= &fsl_dcu_drm_pm_ops,
+		.of_match_table = fsl_dcu_of_match,
+	},
+};
+
+module_platform_driver(fsl_dcu_drm_platform_driver);
+
+MODULE_ALIAS("platform:fsl-dcu-drm");
+MODULE_DESCRIPTION("Freescale DCU DRM Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
new file mode 100644
index 0000000..cbdfefc
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_DRV_H__
+#define __FSL_DCU_DRM_DRV_H__
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <stddef.h>
+#include <drm/drm.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "fsl_dcu_drm_crtc.h"
+#include "fsl_dcu_drm_plane.h"
+#include "fsl_dcu_drm_connector.h"
+#define DRIVER_NAME			"fsl-dcu-fb"
+
+#define DCU_DCU_MODE			0x0010
+#define DCU_MODE_BLEND_ITER(x)		((x) << 20)
+#define DCU_MODE_RASTER_EN		BIT(14)
+#define DCU_MODE_DCU_MODE(x)		(x)
+#define DCU_MODE_DCU_MODE_MASK		0x03
+#define DCU_MODE_OFF			0
+#define DCU_MODE_NORMAL			1
+#define DCU_MODE_TEST			2
+#define DCU_MODE_COLORBAR		3
+
+#define DCU_BGND			0x0014
+#define DCU_BGND_R(x)			((x) << 16)
+#define DCU_BGND_G(x)			((x) << 8)
+#define DCU_BGND_B(x)			(x)
+
+#define DCU_DISP_SIZE			0x0018
+#define DCU_DISP_SIZE_DELTA_Y(x)	((x) << 16)
+/*Regisiter value 1/16 of horizontal resolution*/
+#define DCU_DISP_SIZE_DELTA_X(x)	((x) >> 4)
+
+#define DCU_HSYN_PARA			0x001c
+#define DCU_HSYN_PARA_BP(x)		((x) << 22)
+#define DCU_HSYN_PARA_PW(x)		((x) << 11)
+#define DCU_HSYN_PARA_FP(x)		(x)
+
+#define DCU_VSYN_PARA			0x0020
+#define DCU_VSYN_PARA_BP(x)		((x) << 22)
+#define DCU_VSYN_PARA_PW(x)		((x) << 11)
+#define DCU_VSYN_PARA_FP(x)		(x)
+
+#define DCU_SYN_POL			0x0024
+#define DCU_SYN_POL_INV_PXCK_FALL	(0 << 6)
+#define DCU_SYN_POL_NEG_REMAIN		(0 << 5)
+#define DCU_SYN_POL_INV_VS_LOW		BIT(1)
+#define DCU_SYN_POL_INV_HS_LOW		(1)
+
+#define DCU_THRESHOLD			0x0028
+#define DCU_THRESHOLD_LS_BF_VS(x)	((x) << 16)
+#define DCU_THRESHOLD_OUT_BUF_HIGH(x)	((x) << 8)
+#define DCU_THRESHOLD_OUT_BUF_LOW(x)	(x)
+#define BF_VS_VAL			0x03
+#define BUF_MAX_VAL			0x78
+#define BUF_MIN_VAL			0x0a
+
+#define DCU_INT_STATUS			0x002C
+#define DCU_INT_STATUS_UNDRUN		BIT(1)
+
+#define DCU_INT_MASK			0x0030
+#define DCU_INT_MASK_UNDRUN		BIT(1)
+#define DCU_INT_MASK_VBLANK		BIT(3)
+
+#define DCU_DIV_RATIO			0x0054
+
+#define DCU_UPDATE_MODE			0x00cc
+#define DCU_UPDATE_MODE_MODE		BIT(31)
+#define DCU_UPDATE_MODE_READREG		BIT(30)
+
+#define DCU_DCFB_MAX			0x300
+
+#define DCU_CTRLDESCLN_1(x)		(0x200 + (x) * 0x40)
+#define DCU_CTRLDESCLN_1_HEIGHT(x)	((x) << 16)
+#define DCU_CTRLDESCLN_1_WIDTH(x)	(x)
+
+#define DCU_CTRLDESCLN_2(x)		(0x204 + (x) * 0x40)
+#define DCU_CTRLDESCLN_2_POSY(x)	((x) << 16)
+#define DCU_CTRLDESCLN_2_POSX(x)	(x)
+
+#define DCU_CTRLDESCLN_3(x)		(0x208 + (x) * 0x40)
+
+#define DCU_CTRLDESCLN_4(x)		(0x20c + (x) * 0x40)
+#define DCU_CTRLDESCLN_4_EN		BIT(31)
+#define DCU_CTRLDESCLN_4_TILE_EN	BIT(30)
+#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT	BIT(29)
+#define DCU_CTRLDESCLN_4_SAFETY_EN	BIT(28)
+#define DCU_CTRLDESCLN_4_TRANS(x)	((x) << 20)
+#define DCU_CTRLDESCLN_4_BPP(x)		((x) << 16)
+#define DCU_CTRLDESCLN_4_RLE_EN		BIT(15)
+#define DCU_CTRLDESCLN_4_LUOFFS(x)	((x) << 4)
+#define DCU_CTRLDESCLN_4_BB_ON		BIT(2)
+#define DCU_CTRLDESCLN_4_AB(x)		(x)
+
+#define DCU_CTRLDESCLN_5(x)		(0x210 + (x) * 0x40)
+#define DCU_CTRLDESCLN_5_CKMAX_R(x)	((x) << 16)
+#define DCU_CTRLDESCLN_5_CKMAX_G(x)	((x) << 8)
+#define DCU_CTRLDESCLN_5_CKMAX_B(x)	(x)
+
+#define DCU_CTRLDESCLN_6(x)		(0x214 + (x) * 0x40)
+#define DCU_CTRLDESCLN_6_CKMIN_R(x)	((x) << 16)
+#define DCU_CTRLDESCLN_6_CKMIN_G(x)	((x) << 8)
+#define DCU_CTRLDESCLN_6_CKMIN_B(x)	(x)
+
+#define DCU_CTRLDESCLN_7(x)		(0x218 + (x) * 0x40)
+#define DCU_CTRLDESCLN_7_TILE_VER(x)	((x) << 16)
+#define DCU_CTRLDESCLN_7_TILE_HOR(x)	(x)
+
+#define DCU_CTRLDESCLN_8(x)		(0x21c + (x) * 0x40)
+#define DCU_CTRLDESCLN_8_FG_FCOLOR(x)	(x)
+
+#define DCU_CTRLDESCLN_9(x)		(0x220 + (x) * 0x40)
+#define DCU_CTRLDESCLN_9_BG_BCOLOR(x)	(x)
+
+#define DCU_CTRLDESCLN_10(x)		(0x224 + (x) * 0x40)
+#define DCU_CTRLDESCLN_10_POST_SKIP(x)	((x) << 16)
+#define DCU_CTRLDESCLN_10_PRE_SKIP(x)	(x)
+
+#define FSL_DCU_RGB565			4
+#define FSL_DCU_RGB888			5
+#define FSL_DCU_ARGB8888		6
+#define FSL_DCU_ARGB1555		11
+#define FSL_DCU_ARGB4444		12
+#define FSL_DCU_YUV422			14
+
+#define TCON_CTRL1			0x0000
+#define TCON_BYPASS_ENABLE		BIT(29)
+
+#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+
+struct clk;
+struct device;
+struct drm_device;
+
+struct fsl_dcu_drm_device {
+	struct device *dev;
+	struct regmap *regmap;
+	struct regmap *tcon_regmap;
+	unsigned int irq;
+	struct clk *clk;
+	/*protects hardware register*/
+	spinlock_t irq_lock;
+	struct drm_device *ddev;
+	struct drm_fbdev_cma *fbdev;
+	struct fsl_dcu_drm_crtc crtc;
+	struct drm_encoder encoder;
+	struct fsl_dcu_drm_connector connector;
+};
+
+void fsl_dcu_fbdev_init(struct drm_device *dev);
+
+#endif /* __FSL_DCU_DRM_DRV_H__ */
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
new file mode 100644
index 0000000..f8ef0e1
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "fsl_dcu_drm_drv.h"
+
+/* initialize fbdev helper */
+void fsl_dcu_fbdev_init(struct drm_device *dev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
+
+	fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1);
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
new file mode 100644
index 0000000..4a840fb
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "fsl_dcu_drm_crtc.h"
+#include "fsl_dcu_drm_connector.h"
+#include "fsl_dcu_drm_drv.h"
+
+static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
+{
+	drm_mode_config_init(fsl_dev->ddev);
+
+	fsl_dev->ddev->mode_config.min_width = 0;
+	fsl_dev->ddev->mode_config.min_height = 0;
+	fsl_dev->ddev->mode_config.max_width = 2031;
+	fsl_dev->ddev->mode_config.max_height = 2047;
+	fsl_dev->ddev->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;
+
+	drm_kms_helper_poll_init(fsl_dev->ddev);
+	fsl_dcu_drm_crtc_create(fsl_dev);
+	fsl_dcu_drm_encoder_create(fsl_dev);
+	fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
+	drm_mode_config_reset(fsl_dev->ddev);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
new file mode 100644
index 0000000..b9bd299
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_KMS_H__
+#define __FSL_DCU_DRM_KMS_H__
+
+int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
+
+#endif /* __FSL_DCU_DRM_KMS_H__ */
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
new file mode 100644
index 0000000..b7b4405
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <linux/regmap.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "fsl_dcu_drm_drv.h"
+#include "fsl_dcu_drm_kms.h"
+#include "fsl_dcu_drm_plane.h"
+
+#define to_fsl_dcu_plane(plane) \
+	container_of(plane, struct fsl_dcu_drm_plane, plane)
+
+static int
+fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
+			     struct drm_framebuffer *fb,
+			     const struct drm_plane_state *new_state)
+{
+	return 0;
+}
+
+static void
+fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
+			     struct drm_framebuffer *fb,
+			     const struct drm_plane_state *new_state)
+{
+}
+
+static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
+					  struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
+					     struct drm_plane_state *old_state)
+{
+}
+
+void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
+				     struct drm_plane_state *old_state)
+{
+	struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = plane->state->fb;
+	u32 index, alpha, bpp;
+	struct drm_gem_cma_object *gem;
+	struct fsl_dcu_drm_plane *fsl_plane = to_fsl_dcu_plane(plane);
+
+	index = fsl_plane->index;
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_RGB565:
+		bpp = FSL_DCU_RGB565;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_RGB888:
+		bpp = FSL_DCU_RGB888;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_ARGB8888:
+		bpp = FSL_DCU_ARGB8888;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_BGRA4444:
+		bpp = FSL_DCU_ARGB4444;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_ARGB1555:
+		bpp = FSL_DCU_ARGB1555;
+		alpha = 0xff;
+		break;
+	case DRM_FORMAT_YUV422:
+		bpp = FSL_DCU_YUV422;
+		alpha = 0xff;
+		break;
+	default:
+		return;
+	}
+
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_1(index),
+		     DCU_CTRLDESCLN_1_HEIGHT(state->crtc_h) |
+		     DCU_CTRLDESCLN_1_WIDTH(state->crtc_w));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_2(index),
+		     DCU_CTRLDESCLN_2_POSY(state->crtc_y) |
+		     DCU_CTRLDESCLN_2_POSX(state->crtc_x));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_3(index), gem->paddr);
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_4(index),
+		     DCU_CTRLDESCLN_4_EN |
+		     DCU_CTRLDESCLN_4_TRANS(alpha) |
+		     DCU_CTRLDESCLN_4_BPP(bpp) |
+		     DCU_CTRLDESCLN_4_AB(2));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_5(index),
+		     DCU_CTRLDESCLN_5_CKMAX_R(0xFF) |
+		     DCU_CTRLDESCLN_5_CKMAX_G(0xFF) |
+		     DCU_CTRLDESCLN_5_CKMAX_B(0xFF));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_6(index),
+		     DCU_CTRLDESCLN_6_CKMIN_R(0) |
+		     DCU_CTRLDESCLN_6_CKMIN_G(0) |
+		     DCU_CTRLDESCLN_6_CKMIN_B(0));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_8(index),
+		     DCU_CTRLDESCLN_8_FG_FCOLOR(0));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_9(index),
+		     DCU_CTRLDESCLN_9_BG_BCOLOR(0));
+	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_10(index),
+		     DCU_CTRLDESCLN_10_POST_SKIP(0) |
+		     DCU_CTRLDESCLN_10_PRE_SKIP(0));
+	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
+}
+
+int fsl_dcu_drm_plane_disable(struct drm_plane *plane)
+{
+	return 0;
+}
+
+void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
+{
+	fsl_dcu_drm_plane_disable(plane);
+	drm_plane_cleanup(plane);
+}
+
+static const uint32_t fsl_dcu_drm_plane_formats[] = {
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_YUV422,
+};
+
+static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
+	.update_plane = drm_plane_helper_update,
+	.disable_plane = drm_plane_helper_disable,
+	.destroy = fsl_dcu_drm_plane_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+	.reset = drm_atomic_helper_plane_reset,
+};
+
+static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
+	.prepare_fb = fsl_dcu_drm_plane_prepare_fb,
+	.cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
+	.atomic_check = fsl_dcu_drm_plane_atomic_check,
+	.atomic_update = fsl_dcu_drm_plane_atomic_update,
+	.atomic_disable = fsl_dcu_drm_plane_atomic_disable,
+};
+
+struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
+{
+	struct drm_plane *primary;
+	int ret;
+
+	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
+	if (!primary) {
+		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
+		return NULL;
+	}
+
+	/* possible_crtc's will be filled in later by crtc_init */
+	ret = drm_universal_plane_init(dev, primary, 0,
+				       &fsl_dcu_drm_plane_funcs,
+				       fsl_dcu_drm_plane_formats,
+				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
+				       DRM_PLANE_TYPE_PRIMARY);
+	if (ret) {
+		kfree(primary);
+		primary = NULL;
+	}
+	drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
+
+	return primary;
+}
diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
new file mode 100644
index 0000000..ccbfa61
--- /dev/null
+++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_DRM_PLANE_H__
+#define __FSL_DCU_DRM_PLANE_H__
+
+struct fsl_dcu_drm_device;
+struct fsl_dcu_drm_plane {
+	struct drm_plane plane;
+	unsigned int index;
+};
+
+struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev);
+
+#endif /* __FSL_DCU_DRM_PLANE_H__ */
diff --git a/include/linux/fsl/dcu.h b/include/linux/fsl/dcu.h
new file mode 100644
index 0000000..1873057
--- /dev/null
+++ b/include/linux/fsl/dcu.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU drm device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_DCU_H__
+#define __FSL_DCU_H__
+
+#define SCFG_PIXCLKCR			0x28
+#define PXCK_ENABLE			BIT(31)
+#define PXCK_DISABLE			0
+
+void dcu_pixclk_enable(void);
+void dcu_pixclk_disable(void);
+
+#endif /* __FSL_DCU_H__ */
-- 
2.1.0.27.g96db324



[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

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

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

* [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node
  2015-03-13  9:44 ` Jianwei Wang
  (?)
@ 2015-03-13  9:44   ` Jianwei Wang
  -1 siblings, 0 replies; 26+ messages in thread
From: Jianwei Wang @ 2015-03-13  9:44 UTC (permalink / raw)
  To: scottwood, airlied, jbarnes, dri-devel
  Cc: linux-kernel, linux-arm-kernel, Jason.Jin, Jianwei Wang,
	Alison Wang, Xiubo Li

Add DCU node, DCU is a display controller of Freescale
named 2D-ACE.

Signed-off-by: Alison Wang <b18965@freescale.com>
Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Jianwei Wang <b52261@freescale.com>
---
 arch/arm/boot/dts/ls1021a.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index c70bb27..ea83bdc 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -383,6 +383,16 @@
 				 <&platform_clk 1>;
 		};
 
+		dcu: dcu@2ce0000 {
+			compatible = "fsl,dcu";
+			reg = <0x0 0x2ce0000 0x0 0x10000>;
+			interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&platform_clk 0>;
+			clock-names = "dcu";
+			big-endian;
+			status = "disabled";
+		};
+
 		mdio0: mdio@2d24000 {
 			compatible = "gianfar";
 			device_type = "mdio";
-- 
2.1.0.27.g96db324


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

* [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node
@ 2015-03-13  9:44   ` Jianwei Wang
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei Wang @ 2015-03-13  9:44 UTC (permalink / raw)
  To: linux-arm-kernel

Add DCU node, DCU is a display controller of Freescale
named 2D-ACE.

Signed-off-by: Alison Wang <b18965@freescale.com>
Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Jianwei Wang <b52261@freescale.com>
---
 arch/arm/boot/dts/ls1021a.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index c70bb27..ea83bdc 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -383,6 +383,16 @@
 				 <&platform_clk 1>;
 		};
 
+		dcu: dcu at 2ce0000 {
+			compatible = "fsl,dcu";
+			reg = <0x0 0x2ce0000 0x0 0x10000>;
+			interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&platform_clk 0>;
+			clock-names = "dcu";
+			big-endian;
+			status = "disabled";
+		};
+
 		mdio0: mdio at 2d24000 {
 			compatible = "gianfar";
 			device_type = "mdio";
-- 
2.1.0.27.g96db324

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

* [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node
@ 2015-03-13  9:44   ` Jianwei Wang
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei Wang @ 2015-03-13  9:44 UTC (permalink / raw)
  To: scottwood, airlied, jbarnes, dri-devel
  Cc: linux-kernel, linux-arm-kernel, Jason.Jin, Jianwei Wang,
	Alison Wang, Xiubo Li

Add DCU node, DCU is a display controller of Freescale
named 2D-ACE.

Signed-off-by: Alison Wang <b18965@freescale.com>
Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Jianwei Wang <b52261@freescale.com>
---
 arch/arm/boot/dts/ls1021a.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index c70bb27..ea83bdc 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -383,6 +383,16 @@
 				 <&platform_clk 1>;
 		};
 
+		dcu: dcu@2ce0000 {
+			compatible = "fsl,dcu";
+			reg = <0x0 0x2ce0000 0x0 0x10000>;
+			interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&platform_clk 0>;
+			clock-names = "dcu";
+			big-endian;
+			status = "disabled";
+		};
+
 		mdio0: mdio@2d24000 {
 			compatible = "gianfar";
 			device_type = "mdio";
-- 
2.1.0.27.g96db324

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

* [PATCH 3/3] arm/dts/ls1021a: Add a TFT LCD panel dts node for DCU
  2015-03-13  9:44 ` Jianwei Wang
  (?)
@ 2015-03-13  9:44   ` Jianwei Wang
  -1 siblings, 0 replies; 26+ messages in thread
From: Jianwei Wang @ 2015-03-13  9:44 UTC (permalink / raw)
  To: scottwood, airlied, jbarnes, dri-devel
  Cc: linux-kernel, linux-arm-kernel, Jason.Jin, Jianwei Wang,
	Alison Wang, Xiubo Li

Add a required display-timings node for the TFT LCD panel
the TFT LCD panel is WQVGA "480x272", and the bpp is 24.

Signed-off-by: Alison Wang <b18965@freescale.com>
Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Jianwei Wang <b52261@freescale.com>
---
 arch/arm/boot/dts/ls1021a-twr.dts | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts
index a2c591e..4780b11 100644
--- a/arch/arm/boot/dts/ls1021a-twr.dts
+++ b/arch/arm/boot/dts/ls1021a-twr.dts
@@ -58,6 +58,32 @@
 	};
 };
 
+&dcu {
+	display = <&display>;
+	status = "okay";
+
+	display: display@0 {
+		bits-per-pixel = <24>;
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: nl4827hc19 {
+				clock-frequency = <10870000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vfront-porch = <2>;
+				hsync-len = <41>;
+				vsync-len = <4>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+			};
+		};
+	};
+};
+
 &dspi1 {
 	bus-num = <0>;
 	status = "okay";
-- 
2.1.0.27.g96db324


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

* [PATCH 3/3] arm/dts/ls1021a: Add a TFT LCD panel dts node for DCU
@ 2015-03-13  9:44   ` Jianwei Wang
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei Wang @ 2015-03-13  9:44 UTC (permalink / raw)
  To: linux-arm-kernel

Add a required display-timings node for the TFT LCD panel
the TFT LCD panel is WQVGA "480x272", and the bpp is 24.

Signed-off-by: Alison Wang <b18965@freescale.com>
Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Jianwei Wang <b52261@freescale.com>
---
 arch/arm/boot/dts/ls1021a-twr.dts | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts
index a2c591e..4780b11 100644
--- a/arch/arm/boot/dts/ls1021a-twr.dts
+++ b/arch/arm/boot/dts/ls1021a-twr.dts
@@ -58,6 +58,32 @@
 	};
 };
 
+&dcu {
+	display = <&display>;
+	status = "okay";
+
+	display: display at 0 {
+		bits-per-pixel = <24>;
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: nl4827hc19 {
+				clock-frequency = <10870000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vfront-porch = <2>;
+				hsync-len = <41>;
+				vsync-len = <4>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+			};
+		};
+	};
+};
+
 &dspi1 {
 	bus-num = <0>;
 	status = "okay";
-- 
2.1.0.27.g96db324

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

* [PATCH 3/3] arm/dts/ls1021a: Add a TFT LCD panel dts node for DCU
@ 2015-03-13  9:44   ` Jianwei Wang
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei Wang @ 2015-03-13  9:44 UTC (permalink / raw)
  To: scottwood, airlied, jbarnes, dri-devel
  Cc: linux-kernel, linux-arm-kernel, Jason.Jin, Jianwei Wang,
	Alison Wang, Xiubo Li

Add a required display-timings node for the TFT LCD panel
the TFT LCD panel is WQVGA "480x272", and the bpp is 24.

Signed-off-by: Alison Wang <b18965@freescale.com>
Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Jianwei Wang <b52261@freescale.com>
---
 arch/arm/boot/dts/ls1021a-twr.dts | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts
index a2c591e..4780b11 100644
--- a/arch/arm/boot/dts/ls1021a-twr.dts
+++ b/arch/arm/boot/dts/ls1021a-twr.dts
@@ -58,6 +58,32 @@
 	};
 };
 
+&dcu {
+	display = <&display>;
+	status = "okay";
+
+	display: display@0 {
+		bits-per-pixel = <24>;
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: nl4827hc19 {
+				clock-frequency = <10870000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vfront-porch = <2>;
+				hsync-len = <41>;
+				vsync-len = <4>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+			};
+		};
+	};
+};
+
 &dspi1 {
 	bus-num = <0>;
 	status = "okay";
-- 
2.1.0.27.g96db324

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

* Re: [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
  2015-03-13  9:44 ` Jianwei Wang
@ 2015-03-18 22:58   ` Stefan Agner
  -1 siblings, 0 replies; 26+ messages in thread
From: Stefan Agner @ 2015-03-18 22:58 UTC (permalink / raw)
  To: Jianwei Wang
  Cc: scottwood, airlied, jbarnes, dri-devel, Xiubo Li, Alison Wang,
	linux-kernel, Jason.Jin, linux-arm-kernel

Hi Jianwei,

Normally, for the second and higher iteration of a patchset, developers
add the version to the subject (e.g. PATCH v2). You can use the
--reroll-count option when creating the patches with git format-patch.

On 2015-03-13 10:44, Jianwei Wang wrote:
> This patch add support for Two Dimensional Animation and Compositing
> Engine (2D-ACE) on Freescale SoCs.
> 
> 2D-ACE is a Freescale display controller. It provide an hardware
> cursor.
> 
> This is a simplified version, only a primary plane, a fb created for
> fbdev, a crtc, a connector for TFT LCD panel, an encoder, and the
> encoder is not in use.
> 
> Signed-off-by: Alison Wang <b18965@freescale.com>
> Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> Signed-off-by: Jianwei Wang <b52261@freescale.com>
> ---
> 
> Changed in v2: 
> - Add atomic support
> - Modify bindings file
> - Rename node for compatibility
> - Move platform related code out for compatibility
> 
> Added in v1: 
> - Add support for DCU display controller on the Freescale LS102x SoCs.
> - Create a primary plane, a fb created for fbdev, a crtc, a connector
> for TFT LCD panel, an encoder.
> 
>  arch/arm/mach-imx/mach-ls1021a.c            |  36 ++++
>  drivers/gpu/drm/Kconfig                     |   2 +
>  drivers/gpu/drm/Makefile                    |   1 +
>  drivers/gpu/drm/fsl/Kconfig                 |  17 ++
>  drivers/gpu/drm/fsl/Makefile                |   8 +
>  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c | 203 ++++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h |  28 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c      | 164 ++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h      |  26 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c       | 288 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h       | 168 ++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c     |  26 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c       |  42 ++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h       |  17 ++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c     | 187 ++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h     |  23 +++
>  include/linux/fsl/dcu.h                     |  22 +++
>  17 files changed, 1258 insertions(+)
>  create mode 100644 drivers/gpu/drm/fsl/Kconfig
>  create mode 100644 drivers/gpu/drm/fsl/Makefile
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
>  create mode 100644 include/linux/fsl/dcu.h
> 
> diff --git a/arch/arm/mach-imx/mach-ls1021a.c b/arch/arm/mach-imx/mach-ls1021a.c
> index b89c858..4fb346d 100644
> --- a/arch/arm/mach-imx/mach-ls1021a.c
> +++ b/arch/arm/mach-imx/mach-ls1021a.c
> @@ -8,9 +8,44 @@
>   */
>  
>  #include <asm/mach/arch.h>
> +#include <linux/of_platform.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <linux/fsl/dcu.h>
>  
>  #include "common.h"
>  
> +void dcu_pixclk_disable(void)
> +{
> +	struct regmap *scfg_regmap;
> +
> +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> +	if (IS_ERR(scfg_regmap)) {
> +		pr_err("No syscfg phandle specified\n");
> +		return;
> +	}
> +
> +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_DISABLE);
> +}
> +
> +void dcu_pixclk_enable(void)
> +{
> +	struct regmap *scfg_regmap;
> +
> +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> +	if (IS_ERR(scfg_regmap)) {
> +		pr_err("No syscfg phandle specified\n");
> +		return;
> +	}
> +
> +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_ENABLE);
> +}
> +
> +static void __init ls1021a_init_machine(void)
> +{
> +	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> +	dcu_pixclk_enable();
> +}

This change should be in a separate patch. However, I'm not convinced
that the current code is the right solution. You should try to avoid
calling from the driver directly into arch code.

I don't have access to the reference manual, hence I can't lookup that
module. But this register looks just like a clock gate...

On Vybrid, the Pixelclock is enabled through CCM_CSCDR3 and friends, and
the CCM module makes use of the common clock framework. In the end, the
clock is assigned to the nodes (e.g. DCU node in this case) and
requested during runtime. The framework makes sure the clock and the
relevant gates get enabled. See:
http://lxr.free-electrons.com/source/arch/arm/mach-imx/clk-vf610.c?v=3.12#L241

--
Stefan

>  static const char * const ls1021a_dt_compat[] __initconst = {
>  	"fsl,ls1021a",
>  	NULL,
> @@ -18,5 +53,6 @@ static const char * const ls1021a_dt_compat[] __initconst = {
>  
>  DT_MACHINE_START(LS1021A, "Freescale LS1021A")
>  	.smp		= smp_ops(ls1021a_smp_ops),
> +	.init_machine	= ls1021a_init_machine,
>  	.dt_compat	= ls1021a_dt_compat,
>  MACHINE_END
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index 151a050..a6957aa 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -199,6 +199,8 @@ source "drivers/gpu/drm/bochs/Kconfig"
>  
>  source "drivers/gpu/drm/msm/Kconfig"
>  
> +source "drivers/gpu/drm/fsl/Kconfig"
> +
>  source "drivers/gpu/drm/tegra/Kconfig"
>  
>  source "drivers/gpu/drm/panel/Kconfig"
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 2c239b9..ab5b9ef 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -56,6 +56,7 @@ obj-$(CONFIG_DRM_UDL) += udl/
>  obj-$(CONFIG_DRM_AST) += ast/
>  obj-$(CONFIG_DRM_ARMADA) += armada/
>  obj-$(CONFIG_DRM_ATMEL_HLCDC)	+= atmel-hlcdc/
> +obj-$(CONFIG_DRM_FSL_DCU) += fsl/
>  obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
>  obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
>  obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
> diff --git a/drivers/gpu/drm/fsl/Kconfig b/drivers/gpu/drm/fsl/Kconfig
> new file mode 100644
> index 0000000..e4f8df0
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/Kconfig
> @@ -0,0 +1,17 @@
> +config DRM_FSL_DCU
> +	tristate "DRM Support for Freescale DCU"
> +	depends on DRM && OF && ARM
> +	select DRM_KMS_HELPER
> +	select DRM_KMS_CMA_HELPER
> +	select VIDEOMODE_HELPERS
> +	select BACKLIGHT_CLASS_DEVICE
> +	select BACKLIGHT_LCD_SUPPORT
> +	select REGMAP_MMIO
> +	select DRM_KMS_FB_HELPER
> +	select FB_SYS_FILLRECT
> +	select FB_SYS_COPYAREA
> +	select FB_SYS_IMAGEBLIT
> +	select FB_SYS_FOPS
> +	help
> +	  Choose this option if you have an Freescale DCU chipset.
> +	  If M is selected the module will be called fsl-dcu-drm.
> diff --git a/drivers/gpu/drm/fsl/Makefile b/drivers/gpu/drm/fsl/Makefile
> new file mode 100644
> index 0000000..5f74aee
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/Makefile
> @@ -0,0 +1,8 @@
> +fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
> +	       fsl_dcu_drm_kms.o \
> +	       fsl_dcu_drm_connector.o \
> +	       fsl_dcu_drm_plane.o \
> +	       fsl_dcu_drm_crtc.o \
> +	       fsl_dcu_drm_fbdev.o \
> +
> +obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> new file mode 100644
> index 0000000..178d647
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> @@ -0,0 +1,203 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/backlight.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <video/of_display_timing.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_connector.h"
> +
> +static void fsl_dcu_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
> +{
> +}
> +
> +/* Disable the encoders as the first thing we do. */
> +static void fsl_dcu_drm_encoder_mode_prepare(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_mode_set(struct drm_encoder *encoder,
> +					 struct drm_display_mode *mode,
> +					 struct drm_display_mode *adjusted_mode)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_mode_commit(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
> +{
> +}
> +
> +static int
> +fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
> +				 struct drm_crtc_state *crtc_state,
> +				 struct drm_connector_state *conn_state)
> +{
> +	return 0;
> +}
> +
> +static bool
> +fsl_dcu_drm_encoder_mode_fixup(struct drm_encoder *encoder,
> +			       const struct drm_display_mode *mode,
> +			       struct drm_display_mode *adjusted_mode)
> +{
> +	return true;
> +}
> +
> +static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
> +{
> +	drm_encoder_cleanup(encoder);
> +}
> +
> +static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
> +	.dpms = fsl_dcu_drm_encoder_dpms,
> +	.prepare = fsl_dcu_drm_encoder_mode_prepare,
> +	.commit = fsl_dcu_drm_encoder_mode_commit,
> +	.mode_set = fsl_dcu_drm_encoder_mode_set,
> +	.disable = fsl_dcu_drm_encoder_disable,
> +	.atomic_check = fsl_dcu_drm_encoder_atomic_check,
> +	.mode_fixup = fsl_dcu_drm_encoder_mode_fixup,
> +};
> +
> +static const struct drm_encoder_funcs encoder_funcs = {
> +	.destroy = fsl_dcu_drm_encoder_destroy,
> +};
> +
> +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	struct drm_encoder *encoder = &fsl_dev->encoder;
> +	int ret;
> +
> +	encoder->possible_crtcs = 1;
> +
> +	ret = drm_encoder_init(fsl_dev->ddev, encoder, &encoder_funcs,
> +			       DRM_MODE_ENCODER_LVDS);
> +	if (ret < 0)
> +		return ret;
> +
> +	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
> +
> +	return 0;
> +}
> +
> +#define to_fsl_dcu_connector(connector) \
> +	container_of(connector, struct fsl_dcu_drm_connector, connector)
> +
> +static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector)
> +{
> +	struct drm_device *dev = connector->dev;
> +	struct device_node *display_np, *np = dev->dev->of_node;
> +	struct drm_display_mode *mode = drm_mode_create(connector->dev);
> +	int num_modes = 0;
> +
> +	if (np) {
> +		display_np = of_parse_phandle(np, "display", 0);
> +		if (!display_np) {
> +			dev_err(dev->dev, "failed to find display phandle\n");
> +			return num_modes;
> +		}
> +		of_get_drm_display_mode(display_np, mode, OF_USE_NATIVE_MODE);
> +		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> +		drm_mode_probed_add(connector, mode);
> +		num_modes++;
> +	}
> +
> +	return num_modes;
> +}
> +
> +static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
> +					    struct drm_display_mode *mode)
> +{
> +	return MODE_OK;
> +}
> +
> +static struct drm_encoder *
> +fsl_dcu_drm_connector_best_encoder(struct drm_connector *connector)
> +{
> +	struct fsl_dcu_drm_connector *fsl_con = to_fsl_dcu_connector(connector);
> +
> +	return fsl_con->encoder;
> +}
> +
> +static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_connector_unregister(connector);
> +	drm_connector_cleanup(connector);
> +}
> +
> +static enum drm_connector_status
> +fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	return connector_status_connected;
> +}
> +
> +static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
> +	.dpms = drm_atomic_helper_connector_dpms,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.detect = fsl_dcu_drm_connector_detect,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.destroy = fsl_dcu_drm_connector_destroy,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static const struct drm_connector_helper_funcs connector_helper_funcs = {
> +	.get_modes = fsl_dcu_drm_connector_get_modes,
> +	.mode_valid = fsl_dcu_drm_connector_mode_valid,
> +	.best_encoder = fsl_dcu_drm_connector_best_encoder,
> +};
> +
> +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> +				 struct drm_encoder *encoder)
> +{
> +	struct drm_connector *connector = &fsl_dev->connector.connector;
> +	int ret;
> +
> +	fsl_dev->connector.encoder = encoder;
> +
> +	connector->display_info.width_mm = 0;
> +	connector->display_info.height_mm = 0;
> +
> +	ret = drm_connector_init(fsl_dev->ddev, connector,
> +				 &fsl_dcu_drm_connector_funcs,
> +				 DRM_MODE_CONNECTOR_LVDS);
> +	if (ret < 0)
> +		return ret;
> +
> +	connector->dpms = DRM_MODE_DPMS_OFF;
> +	drm_connector_helper_add(connector, &connector_helper_funcs);
> +	ret = drm_connector_register(connector);
> +	if (ret < 0)
> +		goto err_cleanup;
> +
> +	ret = drm_mode_connector_attach_encoder(connector, encoder);
> +	if (ret < 0)
> +		goto err_sysfs;
> +
> +	connector->encoder = encoder;
> +
> +	drm_object_property_set_value
> +		(&connector->base, fsl_dev->ddev->mode_config.dpms_property,
> +		DRM_MODE_DPMS_OFF);
> +
> +	return 0;
> +
> +err_sysfs:
> +	drm_connector_unregister(connector);
> +err_cleanup:
> +	drm_connector_cleanup(connector);
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> new file mode 100644
> index 0000000..afe44ab
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> @@ -0,0 +1,28 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_CONNECTOR_H__
> +#define __FSL_DCU_DRM_CONNECTOR_H__
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_connector {
> +	struct drm_connector connector;
> +	struct drm_encoder *encoder;
> +};
> +
> +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev);
> +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> +				 struct drm_encoder *encoder);
> +
> +#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> new file mode 100644
> index 0000000..a43e7ce
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> @@ -0,0 +1,164 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/regmap.h>
> +#include <linux/clk.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_plane.h"
> +
> +#define to_fsl_dcu_crtc(c)	container_of(c, struct fsl_dcu_drm_crtc, crtc)
> +
> +void fsl_dcu_drm_crtc_suspend(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
> +	struct drm_display_mode *mode = &crtc->state->mode;
> +	uint32_t hbp, hfp, hsw, vbp, vfp, vsw, div, index;
> +
> +	DBG(": set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
> +	    mode->base.id, mode->name,
> +	    mode->vrefresh, mode->clock,
> +	    mode->hdisplay, mode->hsync_start,
> +	    mode->hsync_end, mode->htotal,
> +	    mode->vdisplay, mode->vsync_start,
> +	    mode->vsync_end, mode->vtotal,
> +	    mode->type, mode->flags);
> +
> +	index = drm_crtc_index(crtc);
> +	div = (uint32_t)clk_get_rate(fsl_dev->clk) / mode->clock / 1000;
> +
> +	/* Configure timings: */
> +	hbp = mode->htotal - mode->hsync_end;
> +	hfp = mode->hsync_start - mode->hdisplay;
> +	hsw = mode->hsync_end - mode->hsync_start;
> +	vbp = mode->vtotal - mode->vsync_end;
> +	vfp = mode->vsync_start - mode->vdisplay;
> +	vsw = mode->vsync_end - mode->vsync_start;
> +
> +	regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
> +		     DCU_HSYN_PARA_BP(hbp) |
> +		     DCU_HSYN_PARA_PW(hsw) |
> +		     DCU_HSYN_PARA_FP(hfp));
> +	regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
> +		     DCU_VSYN_PARA_BP(vbp) |
> +		     DCU_VSYN_PARA_PW(vsw) |
> +		     DCU_VSYN_PARA_FP(vfp));
> +	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
> +		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
> +		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
> +	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +}
> +
> +static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
> +					const struct drm_display_mode *mode,
> +					struct drm_display_mode *adjusted_mode)
> +{
> +	return true;
> +}
> +
> +static void fsl_dcu_drm_crtc_prepare(struct drm_crtc *crtc)
> +{
> +}
> +
> +/* Now enable the clocks, plane, pipe, and connectors that we set up. */
> +static void fsl_dcu_drm_crtc_mode_commit(struct drm_crtc *crtc)
> +{
> +}
> +
> +static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
> +					 struct drm_crtc_state *state)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
> +{
> +}
> +
> +static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
> +	.page_flip = drm_atomic_helper_page_flip,
> +	.set_config = drm_crtc_helper_set_config,
> +	.destroy = drm_crtc_cleanup,
> +	.reset = drm_atomic_helper_crtc_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> +};
> +
> +static void fsl_dcu_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
> +{
> +}
> +
> +static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
> +	.disable = fsl_dcu_drm_disable_crtc,
> +	.mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
> +	.mode_set = drm_helper_crtc_mode_set,
> +	.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
> +	.mode_set_base = drm_helper_crtc_mode_set_base,
> +	.prepare = fsl_dcu_drm_crtc_prepare,
> +	.commit = fsl_dcu_drm_crtc_mode_commit,
> +	.atomic_check = fsl_dcu_drm_crtc_atomic_check,
> +	.atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
> +	.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
> +	.dpms = fsl_dcu_drm_crtc_dpms,
> +};
> +
> +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	struct drm_plane *primary;
> +	struct drm_crtc *crtc = &fsl_dev->crtc.crtc;
> +	int ret;
> +
> +	fsl_dev->crtc.dpms = DRM_MODE_DPMS_OFF;
> +
> +	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->ddev);
> +	ret = drm_crtc_init_with_planes(fsl_dev->ddev, crtc, primary, NULL,
> +					&fsl_dcu_drm_crtc_funcs);
> +	if (ret < 0)
> +		return ret;
> +
> +	drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
> +
> +	regmap_write(fsl_dev->regmap, DCU_SYN_POL,
> +		     DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
> +	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
> +		     DCU_BGND_G(0) | DCU_BGND_B(0));
> +	regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
> +		     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
> +	regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
> +		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
> +		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
> +		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
> +	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
> +			   DCU_MODE_DCU_MODE_MASK,
> +			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> new file mode 100644
> index 0000000..d44b564
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_CRTC_H__
> +#define __FSL_DCU_DRM_CRTC_H__
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_crtc {
> +	struct drm_crtc crtc;
> +	int dpms;
> +};
> +
> +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev);
> +
> +#endif /* __FSL_DCU_DRM_CRTC_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> new file mode 100644
> index 0000000..10975ee
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> @@ -0,0 +1,288 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/mm.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> +
> +#include <drm/drmP.h>
> +#include <linux/fsl/dcu.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_kms.h"
> +
> +static int fsl_dcu_unload(struct drm_device *dev)
> +{
> +	drm_mode_config_cleanup(dev);
> +	drm_vblank_cleanup(dev);
> +	drm_irq_uninstall(dev);
> +
> +	dev->dev_private = NULL;
> +
> +	return 0;
> +}
> +
> +static struct regmap_config fsl_dcu_regmap_config = {
> +	.reg_bits = 32,
> +	.reg_stride = 4,
> +	.val_bits = 32,
> +};
> +
> +static int fsl_dcu_bypass_tcon(struct fsl_dcu_drm_device *fsl_dev,
> +			       struct device_node *np)
> +{
> +	struct device_node *tcon_np;
> +	struct platform_device *pdev;
> +	struct clk *tcon_clk;
> +	struct resource *res;
> +	void __iomem *base;
> +
> +	tcon_np = of_parse_phandle(np, "tcon-controller", 0);
> +	if (!tcon_np)
> +		return -EINVAL;
> +
> +	pdev = of_find_device_by_node(tcon_np);
> +	if (!pdev)
> +		return -EINVAL;
> +
> +	tcon_clk = devm_clk_get(&pdev->dev, "tcon");
> +	if (IS_ERR(tcon_clk))
> +		return PTR_ERR(tcon_clk);
> +	clk_prepare_enable(tcon_clk);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -ENODEV;
> +
> +	base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	fsl_dev->tcon_regmap = devm_regmap_init_mmio_clk(&pdev->dev,
> +			"tcon", base, &fsl_dcu_regmap_config);
> +	if (IS_ERR(fsl_dev->tcon_regmap)) {
> +		dev_err(&pdev->dev, "regmap init failed\n");
> +		return PTR_ERR(fsl_dev->tcon_regmap);
> +	}
> +
> +	regmap_write(fsl_dev->tcon_regmap, TCON_CTRL1, TCON_BYPASS_ENABLE);
> +	return 0;
> +}
> +
> +static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
> +{
> +	struct platform_device *pdev = dev->platformdev;
> +	struct fsl_dcu_drm_device *fsl_dev;
> +	struct resource *res;
> +	void __iomem *base;
> +	int ret;
> +
> +	fsl_dev = devm_kzalloc(&pdev->dev, sizeof(*fsl_dev), GFP_KERNEL);
> +	if (!fsl_dev)
> +		return -ENOMEM;
> +
> +	fsl_dev->dev = &pdev->dev;
> +	fsl_dev->ddev = dev;
> +	dev->dev_private = fsl_dev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(base)) {
> +		ret = PTR_ERR(base);
> +		return ret;
> +	}
> +
> +	fsl_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
> +			base, &fsl_dcu_regmap_config);
> +	if (IS_ERR(fsl_dev->regmap)) {
> +		dev_err(&pdev->dev, "regmap init failed\n");
> +		return PTR_ERR(fsl_dev->regmap);
> +	}
> +
> +	ret = fsl_dcu_drm_modeset_init(fsl_dev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to initialize mode setting\n");
> +		return ret;
> +	}
> +
> +	ret = drm_vblank_init(dev, 1);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to initialize vblank\n");
> +		goto done;
> +	}
> +
> +	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to install IRQ handler\n");
> +		goto done;
> +	}
> +
> +	/* Put TCON in bypass mode, so the input signals from DCU are passed
> +	 * through TCON unchanged */
> +	fsl_dcu_bypass_tcon(fsl_dev, pdev->dev.of_node);
> +
> +	fsl_dev->clk = devm_clk_get(&pdev->dev, "dcu");
> +	if (IS_ERR(fsl_dev->clk)) {
> +		ret = PTR_ERR(fsl_dev->clk);
> +		dev_err(&pdev->dev, "could not get clock\n");
> +		return ret;
> +	}
> +	clk_prepare_enable(fsl_dev->clk);
> +
> +	dev_set_drvdata(dev->dev, fsl_dev);
> +
> +	fsl_dcu_fbdev_init(dev);
> +
> +	return 0;
> +done:
> +	if (ret)
> +		fsl_dcu_unload(dev);
> +
> +	return ret;
> +}
> +
> +static void fsl_dcu_drm_preclose(struct drm_device *dev, struct drm_file *file)
> +{
> +	;
> +}
> +
> +static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
> +{
> +	return IRQ_HANDLED;
> +}
> +
> +static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int crtc)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int crtc)
> +{
> +	;
> +}
> +
> +static const struct file_operations fsl_dcu_drm_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= drm_open,
> +	.release	= drm_release,
> +	.unlocked_ioctl	= drm_ioctl,
> +#ifdef CONFIG_COMPAT
> +	.compat_ioctl	= drm_compat_ioctl,
> +#endif
> +	.poll		= drm_poll,
> +	.read		= drm_read,
> +	.llseek		= no_llseek,
> +	.mmap		= drm_gem_cma_mmap,
> +};
> +
> +static struct drm_driver fsl_dcu_drm_driver = {
> +	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
> +				| DRIVER_PRIME,
> +	.load			= fsl_dcu_load,
> +	.unload			= fsl_dcu_unload,
> +	.preclose		= fsl_dcu_drm_preclose,
> +	.irq_handler		= fsl_dcu_drm_irq,
> +	.get_vblank_counter	= drm_vblank_count,
> +	.enable_vblank		= fsl_dcu_drm_enable_vblank,
> +	.disable_vblank		= fsl_dcu_drm_disable_vblank,
> +	.gem_free_object	= drm_gem_cma_free_object,
> +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
> +	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
> +	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
> +	.gem_prime_import	= drm_gem_prime_import,
> +	.gem_prime_export	= drm_gem_prime_export,
> +	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
> +	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> +	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
> +	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
> +	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
> +	.dumb_create		= drm_gem_cma_dumb_create,
> +	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
> +	.dumb_destroy		= drm_gem_dumb_destroy,
> +	.fops			= &fsl_dcu_drm_fops,
> +	.name			= "fsl-dcu-drm",
> +	.desc			= "Freescale DCU DRM",
> +	.date			= "20150213",
> +	.major			= 1,
> +	.minor			= 0,
> +};
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int fsl_dcu_drm_pm_suspend(struct device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> +
> +	dcu_pixclk_disable();
> +	drm_kms_helper_poll_disable(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_suspend(&fsl_dev->crtc);
> +
> +	return 0;
> +}
> +
> +static int fsl_dcu_drm_pm_resume(struct device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> +
> +	drm_modeset_lock_all(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_resume(&fsl_dev->crtc);
> +	drm_modeset_unlock_all(fsl_dev->ddev);
> +	drm_kms_helper_poll_enable(fsl_dev->ddev);
> +	dcu_pixclk_enable();
> +	return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops fsl_dcu_drm_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_drm_pm_suspend, fsl_dcu_drm_pm_resume)
> +};
> +
> +static int fsl_dcu_drm_probe(struct platform_device *pdev)
> +{
> +	return drm_platform_init(&fsl_dcu_drm_driver, pdev);
> +}
> +
> +static int fsl_dcu_drm_remove(struct platform_device *pdev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
> +
> +	drm_put_dev(fsl_dev->ddev);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id fsl_dcu_of_match[] = {
> +		{ .compatible = "fsl,dcu", },
> +		{ },
> +};
> +MODULE_DEVICE_TABLE(of, fsl_dcu_of_match);
> +
> +static struct platform_driver fsl_dcu_drm_platform_driver = {
> +	.probe		= fsl_dcu_drm_probe,
> +	.remove		= fsl_dcu_drm_remove,
> +	.driver		= {
> +		.owner	= THIS_MODULE,
> +		.name	= "fsl,dcu",
> +		.pm	= &fsl_dcu_drm_pm_ops,
> +		.of_match_table = fsl_dcu_of_match,
> +	},
> +};
> +
> +module_platform_driver(fsl_dcu_drm_platform_driver);
> +
> +MODULE_ALIAS("platform:fsl-dcu-drm");
> +MODULE_DESCRIPTION("Freescale DCU DRM Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> new file mode 100644
> index 0000000..cbdfefc
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> @@ -0,0 +1,168 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_DRV_H__
> +#define __FSL_DCU_DRM_DRV_H__
> +
> +#include <linux/kernel.h>
> +#include <linux/spinlock.h>
> +#include <stddef.h>
> +#include <drm/drm.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_plane.h"
> +#include "fsl_dcu_drm_connector.h"
> +#define DRIVER_NAME			"fsl-dcu-fb"
> +
> +#define DCU_DCU_MODE			0x0010
> +#define DCU_MODE_BLEND_ITER(x)		((x) << 20)
> +#define DCU_MODE_RASTER_EN		BIT(14)
> +#define DCU_MODE_DCU_MODE(x)		(x)
> +#define DCU_MODE_DCU_MODE_MASK		0x03
> +#define DCU_MODE_OFF			0
> +#define DCU_MODE_NORMAL			1
> +#define DCU_MODE_TEST			2
> +#define DCU_MODE_COLORBAR		3
> +
> +#define DCU_BGND			0x0014
> +#define DCU_BGND_R(x)			((x) << 16)
> +#define DCU_BGND_G(x)			((x) << 8)
> +#define DCU_BGND_B(x)			(x)
> +
> +#define DCU_DISP_SIZE			0x0018
> +#define DCU_DISP_SIZE_DELTA_Y(x)	((x) << 16)
> +/*Regisiter value 1/16 of horizontal resolution*/
> +#define DCU_DISP_SIZE_DELTA_X(x)	((x) >> 4)
> +
> +#define DCU_HSYN_PARA			0x001c
> +#define DCU_HSYN_PARA_BP(x)		((x) << 22)
> +#define DCU_HSYN_PARA_PW(x)		((x) << 11)
> +#define DCU_HSYN_PARA_FP(x)		(x)
> +
> +#define DCU_VSYN_PARA			0x0020
> +#define DCU_VSYN_PARA_BP(x)		((x) << 22)
> +#define DCU_VSYN_PARA_PW(x)		((x) << 11)
> +#define DCU_VSYN_PARA_FP(x)		(x)
> +
> +#define DCU_SYN_POL			0x0024
> +#define DCU_SYN_POL_INV_PXCK_FALL	(0 << 6)
> +#define DCU_SYN_POL_NEG_REMAIN		(0 << 5)
> +#define DCU_SYN_POL_INV_VS_LOW		BIT(1)
> +#define DCU_SYN_POL_INV_HS_LOW		(1)
> +
> +#define DCU_THRESHOLD			0x0028
> +#define DCU_THRESHOLD_LS_BF_VS(x)	((x) << 16)
> +#define DCU_THRESHOLD_OUT_BUF_HIGH(x)	((x) << 8)
> +#define DCU_THRESHOLD_OUT_BUF_LOW(x)	(x)
> +#define BF_VS_VAL			0x03
> +#define BUF_MAX_VAL			0x78
> +#define BUF_MIN_VAL			0x0a
> +
> +#define DCU_INT_STATUS			0x002C
> +#define DCU_INT_STATUS_UNDRUN		BIT(1)
> +
> +#define DCU_INT_MASK			0x0030
> +#define DCU_INT_MASK_UNDRUN		BIT(1)
> +#define DCU_INT_MASK_VBLANK		BIT(3)
> +
> +#define DCU_DIV_RATIO			0x0054
> +
> +#define DCU_UPDATE_MODE			0x00cc
> +#define DCU_UPDATE_MODE_MODE		BIT(31)
> +#define DCU_UPDATE_MODE_READREG		BIT(30)
> +
> +#define DCU_DCFB_MAX			0x300
> +
> +#define DCU_CTRLDESCLN_1(x)		(0x200 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_1_HEIGHT(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_1_WIDTH(x)	(x)
> +
> +#define DCU_CTRLDESCLN_2(x)		(0x204 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_2_POSY(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_2_POSX(x)	(x)
> +
> +#define DCU_CTRLDESCLN_3(x)		(0x208 + (x) * 0x40)
> +
> +#define DCU_CTRLDESCLN_4(x)		(0x20c + (x) * 0x40)
> +#define DCU_CTRLDESCLN_4_EN		BIT(31)
> +#define DCU_CTRLDESCLN_4_TILE_EN	BIT(30)
> +#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT	BIT(29)
> +#define DCU_CTRLDESCLN_4_SAFETY_EN	BIT(28)
> +#define DCU_CTRLDESCLN_4_TRANS(x)	((x) << 20)
> +#define DCU_CTRLDESCLN_4_BPP(x)		((x) << 16)
> +#define DCU_CTRLDESCLN_4_RLE_EN		BIT(15)
> +#define DCU_CTRLDESCLN_4_LUOFFS(x)	((x) << 4)
> +#define DCU_CTRLDESCLN_4_BB_ON		BIT(2)
> +#define DCU_CTRLDESCLN_4_AB(x)		(x)
> +
> +#define DCU_CTRLDESCLN_5(x)		(0x210 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_5_CKMAX_R(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_5_CKMAX_G(x)	((x) << 8)
> +#define DCU_CTRLDESCLN_5_CKMAX_B(x)	(x)
> +
> +#define DCU_CTRLDESCLN_6(x)		(0x214 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_6_CKMIN_R(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_6_CKMIN_G(x)	((x) << 8)
> +#define DCU_CTRLDESCLN_6_CKMIN_B(x)	(x)
> +
> +#define DCU_CTRLDESCLN_7(x)		(0x218 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_7_TILE_VER(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_7_TILE_HOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_8(x)		(0x21c + (x) * 0x40)
> +#define DCU_CTRLDESCLN_8_FG_FCOLOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_9(x)		(0x220 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_9_BG_BCOLOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_10(x)		(0x224 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_10_POST_SKIP(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_10_PRE_SKIP(x)	(x)
> +
> +#define FSL_DCU_RGB565			4
> +#define FSL_DCU_RGB888			5
> +#define FSL_DCU_ARGB8888		6
> +#define FSL_DCU_ARGB1555		11
> +#define FSL_DCU_ARGB4444		12
> +#define FSL_DCU_YUV422			14
> +
> +#define TCON_CTRL1			0x0000
> +#define TCON_BYPASS_ENABLE		BIT(29)
> +
> +#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
> +
> +struct clk;
> +struct device;
> +struct drm_device;
> +
> +struct fsl_dcu_drm_device {
> +	struct device *dev;
> +	struct regmap *regmap;
> +	struct regmap *tcon_regmap;
> +	unsigned int irq;
> +	struct clk *clk;
> +	/*protects hardware register*/
> +	spinlock_t irq_lock;
> +	struct drm_device *ddev;
> +	struct drm_fbdev_cma *fbdev;
> +	struct fsl_dcu_drm_crtc crtc;
> +	struct drm_encoder encoder;
> +	struct fsl_dcu_drm_connector connector;
> +};
> +
> +void fsl_dcu_fbdev_init(struct drm_device *dev);
> +
> +#endif /* __FSL_DCU_DRM_DRV_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> new file mode 100644
> index 0000000..f8ef0e1
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_cma_helper.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +
> +/* initialize fbdev helper */
> +void fsl_dcu_fbdev_init(struct drm_device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
> +
> +	fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1);
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> new file mode 100644
> index 0000000..4a840fb
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> @@ -0,0 +1,42 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_connector.h"
> +#include "fsl_dcu_drm_drv.h"
> +
> +static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs = {
> +	.fb_create = drm_fb_cma_create,
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	drm_mode_config_init(fsl_dev->ddev);
> +
> +	fsl_dev->ddev->mode_config.min_width = 0;
> +	fsl_dev->ddev->mode_config.min_height = 0;
> +	fsl_dev->ddev->mode_config.max_width = 2031;
> +	fsl_dev->ddev->mode_config.max_height = 2047;
> +	fsl_dev->ddev->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;
> +
> +	drm_kms_helper_poll_init(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_create(fsl_dev);
> +	fsl_dcu_drm_encoder_create(fsl_dev);
> +	fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
> +	drm_mode_config_reset(fsl_dev->ddev);
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> new file mode 100644
> index 0000000..b9bd299
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> @@ -0,0 +1,17 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_KMS_H__
> +#define __FSL_DCU_DRM_KMS_H__
> +
> +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
> +
> +#endif /* __FSL_DCU_DRM_KMS_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> new file mode 100644
> index 0000000..b7b4405
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> @@ -0,0 +1,187 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <linux/regmap.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_kms.h"
> +#include "fsl_dcu_drm_plane.h"
> +
> +#define to_fsl_dcu_plane(plane) \
> +	container_of(plane, struct fsl_dcu_drm_plane, plane)
> +
> +static int
> +fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
> +			     struct drm_framebuffer *fb,
> +			     const struct drm_plane_state *new_state)
> +{
> +	return 0;
> +}
> +
> +static void
> +fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
> +			     struct drm_framebuffer *fb,
> +			     const struct drm_plane_state *new_state)
> +{
> +}
> +
> +static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
> +					  struct drm_plane_state *state)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
> +					     struct drm_plane_state *old_state)
> +{
> +}
> +
> +void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
> +				     struct drm_plane_state *old_state)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = plane->state->fb;
> +	u32 index, alpha, bpp;
> +	struct drm_gem_cma_object *gem;
> +	struct fsl_dcu_drm_plane *fsl_plane = to_fsl_dcu_plane(plane);
> +
> +	index = fsl_plane->index;
> +	gem = drm_fb_cma_get_gem_obj(fb, 0);
> +
> +	switch (fb->pixel_format) {
> +	case DRM_FORMAT_RGB565:
> +		bpp = FSL_DCU_RGB565;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_RGB888:
> +		bpp = FSL_DCU_RGB888;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_ARGB8888:
> +		bpp = FSL_DCU_ARGB8888;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_BGRA4444:
> +		bpp = FSL_DCU_ARGB4444;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_ARGB1555:
> +		bpp = FSL_DCU_ARGB1555;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_YUV422:
> +		bpp = FSL_DCU_YUV422;
> +		alpha = 0xff;
> +		break;
> +	default:
> +		return;
> +	}
> +
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_1(index),
> +		     DCU_CTRLDESCLN_1_HEIGHT(state->crtc_h) |
> +		     DCU_CTRLDESCLN_1_WIDTH(state->crtc_w));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_2(index),
> +		     DCU_CTRLDESCLN_2_POSY(state->crtc_y) |
> +		     DCU_CTRLDESCLN_2_POSX(state->crtc_x));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_3(index), gem->paddr);
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_4(index),
> +		     DCU_CTRLDESCLN_4_EN |
> +		     DCU_CTRLDESCLN_4_TRANS(alpha) |
> +		     DCU_CTRLDESCLN_4_BPP(bpp) |
> +		     DCU_CTRLDESCLN_4_AB(2));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_5(index),
> +		     DCU_CTRLDESCLN_5_CKMAX_R(0xFF) |
> +		     DCU_CTRLDESCLN_5_CKMAX_G(0xFF) |
> +		     DCU_CTRLDESCLN_5_CKMAX_B(0xFF));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_6(index),
> +		     DCU_CTRLDESCLN_6_CKMIN_R(0) |
> +		     DCU_CTRLDESCLN_6_CKMIN_G(0) |
> +		     DCU_CTRLDESCLN_6_CKMIN_B(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_8(index),
> +		     DCU_CTRLDESCLN_8_FG_FCOLOR(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_9(index),
> +		     DCU_CTRLDESCLN_9_BG_BCOLOR(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_10(index),
> +		     DCU_CTRLDESCLN_10_POST_SKIP(0) |
> +		     DCU_CTRLDESCLN_10_PRE_SKIP(0));
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +}
> +
> +int fsl_dcu_drm_plane_disable(struct drm_plane *plane)
> +{
> +	return 0;
> +}
> +
> +void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
> +{
> +	fsl_dcu_drm_plane_disable(plane);
> +	drm_plane_cleanup(plane);
> +}
> +
> +static const uint32_t fsl_dcu_drm_plane_formats[] = {
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_RGB888,
> +	DRM_FORMAT_ARGB8888,
> +	DRM_FORMAT_ARGB4444,
> +	DRM_FORMAT_ARGB1555,
> +	DRM_FORMAT_YUV422,
> +};
> +
> +static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
> +	.update_plane = drm_plane_helper_update,
> +	.disable_plane = drm_plane_helper_disable,
> +	.destroy = fsl_dcu_drm_plane_destroy,
> +	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> +	.reset = drm_atomic_helper_plane_reset,
> +};
> +
> +static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
> +	.prepare_fb = fsl_dcu_drm_plane_prepare_fb,
> +	.cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
> +	.atomic_check = fsl_dcu_drm_plane_atomic_check,
> +	.atomic_update = fsl_dcu_drm_plane_atomic_update,
> +	.atomic_disable = fsl_dcu_drm_plane_atomic_disable,
> +};
> +
> +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
> +{
> +	struct drm_plane *primary;
> +	int ret;
> +
> +	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> +	if (!primary) {
> +		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
> +		return NULL;
> +	}
> +
> +	/* possible_crtc's will be filled in later by crtc_init */
> +	ret = drm_universal_plane_init(dev, primary, 0,
> +				       &fsl_dcu_drm_plane_funcs,
> +				       fsl_dcu_drm_plane_formats,
> +				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
> +				       DRM_PLANE_TYPE_PRIMARY);
> +	if (ret) {
> +		kfree(primary);
> +		primary = NULL;
> +	}
> +	drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
> +
> +	return primary;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> new file mode 100644
> index 0000000..ccbfa61
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> @@ -0,0 +1,23 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_PLANE_H__
> +#define __FSL_DCU_DRM_PLANE_H__
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_plane {
> +	struct drm_plane plane;
> +	unsigned int index;
> +};
> +
> +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev);
> +
> +#endif /* __FSL_DCU_DRM_PLANE_H__ */
> diff --git a/include/linux/fsl/dcu.h b/include/linux/fsl/dcu.h
> new file mode 100644
> index 0000000..1873057
> --- /dev/null
> +++ b/include/linux/fsl/dcu.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_H__
> +#define __FSL_DCU_H__
> +
> +#define SCFG_PIXCLKCR			0x28
> +#define PXCK_ENABLE			BIT(31)
> +#define PXCK_DISABLE			0
> +
> +void dcu_pixclk_enable(void);
> +void dcu_pixclk_disable(void);
> +
> +#endif /* __FSL_DCU_H__ */
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


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

* [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
@ 2015-03-18 22:58   ` Stefan Agner
  0 siblings, 0 replies; 26+ messages in thread
From: Stefan Agner @ 2015-03-18 22:58 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jianwei,

Normally, for the second and higher iteration of a patchset, developers
add the version to the subject (e.g. PATCH v2). You can use the
--reroll-count option when creating the patches with git format-patch.

On 2015-03-13 10:44, Jianwei Wang wrote:
> This patch add support for Two Dimensional Animation and Compositing
> Engine (2D-ACE) on Freescale SoCs.
> 
> 2D-ACE is a Freescale display controller. It provide an hardware
> cursor.
> 
> This is a simplified version, only a primary plane, a fb created for
> fbdev, a crtc, a connector for TFT LCD panel, an encoder, and the
> encoder is not in use.
> 
> Signed-off-by: Alison Wang <b18965@freescale.com>
> Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> Signed-off-by: Jianwei Wang <b52261@freescale.com>
> ---
> 
> Changed in v2:?
> - Add atomic support
> - Modify bindings file
> - Rename node for compatibility
> - Move platform related code out for compatibility
> 
> Added in v1:?
> -?Add support for DCU display controller on the Freescale LS102x SoCs.
> - Create a primary plane, a fb created for fbdev, a crtc, a connector
> for TFT LCD panel, an encoder.
> 
>  arch/arm/mach-imx/mach-ls1021a.c            |  36 ++++
>  drivers/gpu/drm/Kconfig                     |   2 +
>  drivers/gpu/drm/Makefile                    |   1 +
>  drivers/gpu/drm/fsl/Kconfig                 |  17 ++
>  drivers/gpu/drm/fsl/Makefile                |   8 +
>  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c | 203 ++++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h |  28 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c      | 164 ++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h      |  26 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c       | 288 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h       | 168 ++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c     |  26 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c       |  42 ++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h       |  17 ++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c     | 187 ++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h     |  23 +++
>  include/linux/fsl/dcu.h                     |  22 +++
>  17 files changed, 1258 insertions(+)
>  create mode 100644 drivers/gpu/drm/fsl/Kconfig
>  create mode 100644 drivers/gpu/drm/fsl/Makefile
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
>  create mode 100644 include/linux/fsl/dcu.h
> 
> diff --git a/arch/arm/mach-imx/mach-ls1021a.c b/arch/arm/mach-imx/mach-ls1021a.c
> index b89c858..4fb346d 100644
> --- a/arch/arm/mach-imx/mach-ls1021a.c
> +++ b/arch/arm/mach-imx/mach-ls1021a.c
> @@ -8,9 +8,44 @@
>   */
>  
>  #include <asm/mach/arch.h>
> +#include <linux/of_platform.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <linux/fsl/dcu.h>
>  
>  #include "common.h"
>  
> +void dcu_pixclk_disable(void)
> +{
> +	struct regmap *scfg_regmap;
> +
> +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> +	if (IS_ERR(scfg_regmap)) {
> +		pr_err("No syscfg phandle specified\n");
> +		return;
> +	}
> +
> +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_DISABLE);
> +}
> +
> +void dcu_pixclk_enable(void)
> +{
> +	struct regmap *scfg_regmap;
> +
> +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> +	if (IS_ERR(scfg_regmap)) {
> +		pr_err("No syscfg phandle specified\n");
> +		return;
> +	}
> +
> +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_ENABLE);
> +}
> +
> +static void __init ls1021a_init_machine(void)
> +{
> +	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> +	dcu_pixclk_enable();
> +}

This change should be in a separate patch. However, I'm not convinced
that the current code is the right solution. You should try to avoid
calling from the driver directly into arch code.

I don't have access to the reference manual, hence I can't lookup that
module. But this register looks just like a clock gate...

On Vybrid, the Pixelclock is enabled through CCM_CSCDR3 and friends, and
the CCM module makes use of the common clock framework. In the end, the
clock is assigned to the nodes (e.g. DCU node in this case) and
requested during runtime. The framework makes sure the clock and the
relevant gates get enabled. See:
http://lxr.free-electrons.com/source/arch/arm/mach-imx/clk-vf610.c?v=3.12#L241

--
Stefan

>  static const char * const ls1021a_dt_compat[] __initconst = {
>  	"fsl,ls1021a",
>  	NULL,
> @@ -18,5 +53,6 @@ static const char * const ls1021a_dt_compat[] __initconst = {
>  
>  DT_MACHINE_START(LS1021A, "Freescale LS1021A")
>  	.smp		= smp_ops(ls1021a_smp_ops),
> +	.init_machine	= ls1021a_init_machine,
>  	.dt_compat	= ls1021a_dt_compat,
>  MACHINE_END
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index 151a050..a6957aa 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -199,6 +199,8 @@ source "drivers/gpu/drm/bochs/Kconfig"
>  
>  source "drivers/gpu/drm/msm/Kconfig"
>  
> +source "drivers/gpu/drm/fsl/Kconfig"
> +
>  source "drivers/gpu/drm/tegra/Kconfig"
>  
>  source "drivers/gpu/drm/panel/Kconfig"
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 2c239b9..ab5b9ef 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -56,6 +56,7 @@ obj-$(CONFIG_DRM_UDL) += udl/
>  obj-$(CONFIG_DRM_AST) += ast/
>  obj-$(CONFIG_DRM_ARMADA) += armada/
>  obj-$(CONFIG_DRM_ATMEL_HLCDC)	+= atmel-hlcdc/
> +obj-$(CONFIG_DRM_FSL_DCU) += fsl/
>  obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
>  obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
>  obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
> diff --git a/drivers/gpu/drm/fsl/Kconfig b/drivers/gpu/drm/fsl/Kconfig
> new file mode 100644
> index 0000000..e4f8df0
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/Kconfig
> @@ -0,0 +1,17 @@
> +config DRM_FSL_DCU
> +	tristate "DRM Support for Freescale DCU"
> +	depends on DRM && OF && ARM
> +	select DRM_KMS_HELPER
> +	select DRM_KMS_CMA_HELPER
> +	select VIDEOMODE_HELPERS
> +	select BACKLIGHT_CLASS_DEVICE
> +	select BACKLIGHT_LCD_SUPPORT
> +	select REGMAP_MMIO
> +	select DRM_KMS_FB_HELPER
> +	select FB_SYS_FILLRECT
> +	select FB_SYS_COPYAREA
> +	select FB_SYS_IMAGEBLIT
> +	select FB_SYS_FOPS
> +	help
> +	  Choose this option if you have an Freescale DCU chipset.
> +	  If M is selected the module will be called fsl-dcu-drm.
> diff --git a/drivers/gpu/drm/fsl/Makefile b/drivers/gpu/drm/fsl/Makefile
> new file mode 100644
> index 0000000..5f74aee
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/Makefile
> @@ -0,0 +1,8 @@
> +fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
> +	       fsl_dcu_drm_kms.o \
> +	       fsl_dcu_drm_connector.o \
> +	       fsl_dcu_drm_plane.o \
> +	       fsl_dcu_drm_crtc.o \
> +	       fsl_dcu_drm_fbdev.o \
> +
> +obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> new file mode 100644
> index 0000000..178d647
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> @@ -0,0 +1,203 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/backlight.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <video/of_display_timing.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_connector.h"
> +
> +static void fsl_dcu_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
> +{
> +}
> +
> +/* Disable the encoders as the first thing we do. */
> +static void fsl_dcu_drm_encoder_mode_prepare(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_mode_set(struct drm_encoder *encoder,
> +					 struct drm_display_mode *mode,
> +					 struct drm_display_mode *adjusted_mode)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_mode_commit(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
> +{
> +}
> +
> +static int
> +fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
> +				 struct drm_crtc_state *crtc_state,
> +				 struct drm_connector_state *conn_state)
> +{
> +	return 0;
> +}
> +
> +static bool
> +fsl_dcu_drm_encoder_mode_fixup(struct drm_encoder *encoder,
> +			       const struct drm_display_mode *mode,
> +			       struct drm_display_mode *adjusted_mode)
> +{
> +	return true;
> +}
> +
> +static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
> +{
> +	drm_encoder_cleanup(encoder);
> +}
> +
> +static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
> +	.dpms = fsl_dcu_drm_encoder_dpms,
> +	.prepare = fsl_dcu_drm_encoder_mode_prepare,
> +	.commit = fsl_dcu_drm_encoder_mode_commit,
> +	.mode_set = fsl_dcu_drm_encoder_mode_set,
> +	.disable = fsl_dcu_drm_encoder_disable,
> +	.atomic_check = fsl_dcu_drm_encoder_atomic_check,
> +	.mode_fixup = fsl_dcu_drm_encoder_mode_fixup,
> +};
> +
> +static const struct drm_encoder_funcs encoder_funcs = {
> +	.destroy = fsl_dcu_drm_encoder_destroy,
> +};
> +
> +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	struct drm_encoder *encoder = &fsl_dev->encoder;
> +	int ret;
> +
> +	encoder->possible_crtcs = 1;
> +
> +	ret = drm_encoder_init(fsl_dev->ddev, encoder, &encoder_funcs,
> +			       DRM_MODE_ENCODER_LVDS);
> +	if (ret < 0)
> +		return ret;
> +
> +	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
> +
> +	return 0;
> +}
> +
> +#define to_fsl_dcu_connector(connector) \
> +	container_of(connector, struct fsl_dcu_drm_connector, connector)
> +
> +static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector)
> +{
> +	struct drm_device *dev = connector->dev;
> +	struct device_node *display_np, *np = dev->dev->of_node;
> +	struct drm_display_mode *mode = drm_mode_create(connector->dev);
> +	int num_modes = 0;
> +
> +	if (np) {
> +		display_np = of_parse_phandle(np, "display", 0);
> +		if (!display_np) {
> +			dev_err(dev->dev, "failed to find display phandle\n");
> +			return num_modes;
> +		}
> +		of_get_drm_display_mode(display_np, mode, OF_USE_NATIVE_MODE);
> +		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> +		drm_mode_probed_add(connector, mode);
> +		num_modes++;
> +	}
> +
> +	return num_modes;
> +}
> +
> +static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
> +					    struct drm_display_mode *mode)
> +{
> +	return MODE_OK;
> +}
> +
> +static struct drm_encoder *
> +fsl_dcu_drm_connector_best_encoder(struct drm_connector *connector)
> +{
> +	struct fsl_dcu_drm_connector *fsl_con = to_fsl_dcu_connector(connector);
> +
> +	return fsl_con->encoder;
> +}
> +
> +static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_connector_unregister(connector);
> +	drm_connector_cleanup(connector);
> +}
> +
> +static enum drm_connector_status
> +fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	return connector_status_connected;
> +}
> +
> +static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
> +	.dpms = drm_atomic_helper_connector_dpms,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.detect = fsl_dcu_drm_connector_detect,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.destroy = fsl_dcu_drm_connector_destroy,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static const struct drm_connector_helper_funcs connector_helper_funcs = {
> +	.get_modes = fsl_dcu_drm_connector_get_modes,
> +	.mode_valid = fsl_dcu_drm_connector_mode_valid,
> +	.best_encoder = fsl_dcu_drm_connector_best_encoder,
> +};
> +
> +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> +				 struct drm_encoder *encoder)
> +{
> +	struct drm_connector *connector = &fsl_dev->connector.connector;
> +	int ret;
> +
> +	fsl_dev->connector.encoder = encoder;
> +
> +	connector->display_info.width_mm = 0;
> +	connector->display_info.height_mm = 0;
> +
> +	ret = drm_connector_init(fsl_dev->ddev, connector,
> +				 &fsl_dcu_drm_connector_funcs,
> +				 DRM_MODE_CONNECTOR_LVDS);
> +	if (ret < 0)
> +		return ret;
> +
> +	connector->dpms = DRM_MODE_DPMS_OFF;
> +	drm_connector_helper_add(connector, &connector_helper_funcs);
> +	ret = drm_connector_register(connector);
> +	if (ret < 0)
> +		goto err_cleanup;
> +
> +	ret = drm_mode_connector_attach_encoder(connector, encoder);
> +	if (ret < 0)
> +		goto err_sysfs;
> +
> +	connector->encoder = encoder;
> +
> +	drm_object_property_set_value
> +		(&connector->base, fsl_dev->ddev->mode_config.dpms_property,
> +		DRM_MODE_DPMS_OFF);
> +
> +	return 0;
> +
> +err_sysfs:
> +	drm_connector_unregister(connector);
> +err_cleanup:
> +	drm_connector_cleanup(connector);
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> new file mode 100644
> index 0000000..afe44ab
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> @@ -0,0 +1,28 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_CONNECTOR_H__
> +#define __FSL_DCU_DRM_CONNECTOR_H__
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_connector {
> +	struct drm_connector connector;
> +	struct drm_encoder *encoder;
> +};
> +
> +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev);
> +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> +				 struct drm_encoder *encoder);
> +
> +#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> new file mode 100644
> index 0000000..a43e7ce
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> @@ -0,0 +1,164 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/regmap.h>
> +#include <linux/clk.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_plane.h"
> +
> +#define to_fsl_dcu_crtc(c)	container_of(c, struct fsl_dcu_drm_crtc, crtc)
> +
> +void fsl_dcu_drm_crtc_suspend(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
> +	struct drm_display_mode *mode = &crtc->state->mode;
> +	uint32_t hbp, hfp, hsw, vbp, vfp, vsw, div, index;
> +
> +	DBG(": set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
> +	    mode->base.id, mode->name,
> +	    mode->vrefresh, mode->clock,
> +	    mode->hdisplay, mode->hsync_start,
> +	    mode->hsync_end, mode->htotal,
> +	    mode->vdisplay, mode->vsync_start,
> +	    mode->vsync_end, mode->vtotal,
> +	    mode->type, mode->flags);
> +
> +	index = drm_crtc_index(crtc);
> +	div = (uint32_t)clk_get_rate(fsl_dev->clk) / mode->clock / 1000;
> +
> +	/* Configure timings: */
> +	hbp = mode->htotal - mode->hsync_end;
> +	hfp = mode->hsync_start - mode->hdisplay;
> +	hsw = mode->hsync_end - mode->hsync_start;
> +	vbp = mode->vtotal - mode->vsync_end;
> +	vfp = mode->vsync_start - mode->vdisplay;
> +	vsw = mode->vsync_end - mode->vsync_start;
> +
> +	regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
> +		     DCU_HSYN_PARA_BP(hbp) |
> +		     DCU_HSYN_PARA_PW(hsw) |
> +		     DCU_HSYN_PARA_FP(hfp));
> +	regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
> +		     DCU_VSYN_PARA_BP(vbp) |
> +		     DCU_VSYN_PARA_PW(vsw) |
> +		     DCU_VSYN_PARA_FP(vfp));
> +	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
> +		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
> +		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
> +	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +}
> +
> +static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
> +					const struct drm_display_mode *mode,
> +					struct drm_display_mode *adjusted_mode)
> +{
> +	return true;
> +}
> +
> +static void fsl_dcu_drm_crtc_prepare(struct drm_crtc *crtc)
> +{
> +}
> +
> +/* Now enable the clocks, plane, pipe, and connectors that we set up. */
> +static void fsl_dcu_drm_crtc_mode_commit(struct drm_crtc *crtc)
> +{
> +}
> +
> +static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
> +					 struct drm_crtc_state *state)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
> +{
> +}
> +
> +static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
> +	.page_flip = drm_atomic_helper_page_flip,
> +	.set_config = drm_crtc_helper_set_config,
> +	.destroy = drm_crtc_cleanup,
> +	.reset = drm_atomic_helper_crtc_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> +};
> +
> +static void fsl_dcu_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
> +{
> +}
> +
> +static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
> +	.disable = fsl_dcu_drm_disable_crtc,
> +	.mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
> +	.mode_set = drm_helper_crtc_mode_set,
> +	.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
> +	.mode_set_base = drm_helper_crtc_mode_set_base,
> +	.prepare = fsl_dcu_drm_crtc_prepare,
> +	.commit = fsl_dcu_drm_crtc_mode_commit,
> +	.atomic_check = fsl_dcu_drm_crtc_atomic_check,
> +	.atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
> +	.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
> +	.dpms = fsl_dcu_drm_crtc_dpms,
> +};
> +
> +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	struct drm_plane *primary;
> +	struct drm_crtc *crtc = &fsl_dev->crtc.crtc;
> +	int ret;
> +
> +	fsl_dev->crtc.dpms = DRM_MODE_DPMS_OFF;
> +
> +	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->ddev);
> +	ret = drm_crtc_init_with_planes(fsl_dev->ddev, crtc, primary, NULL,
> +					&fsl_dcu_drm_crtc_funcs);
> +	if (ret < 0)
> +		return ret;
> +
> +	drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
> +
> +	regmap_write(fsl_dev->regmap, DCU_SYN_POL,
> +		     DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
> +	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
> +		     DCU_BGND_G(0) | DCU_BGND_B(0));
> +	regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
> +		     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
> +	regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
> +		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
> +		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
> +		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
> +	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
> +			   DCU_MODE_DCU_MODE_MASK,
> +			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> new file mode 100644
> index 0000000..d44b564
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_CRTC_H__
> +#define __FSL_DCU_DRM_CRTC_H__
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_crtc {
> +	struct drm_crtc crtc;
> +	int dpms;
> +};
> +
> +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev);
> +
> +#endif /* __FSL_DCU_DRM_CRTC_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> new file mode 100644
> index 0000000..10975ee
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> @@ -0,0 +1,288 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/mm.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> +
> +#include <drm/drmP.h>
> +#include <linux/fsl/dcu.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_kms.h"
> +
> +static int fsl_dcu_unload(struct drm_device *dev)
> +{
> +	drm_mode_config_cleanup(dev);
> +	drm_vblank_cleanup(dev);
> +	drm_irq_uninstall(dev);
> +
> +	dev->dev_private = NULL;
> +
> +	return 0;
> +}
> +
> +static struct regmap_config fsl_dcu_regmap_config = {
> +	.reg_bits = 32,
> +	.reg_stride = 4,
> +	.val_bits = 32,
> +};
> +
> +static int fsl_dcu_bypass_tcon(struct fsl_dcu_drm_device *fsl_dev,
> +			       struct device_node *np)
> +{
> +	struct device_node *tcon_np;
> +	struct platform_device *pdev;
> +	struct clk *tcon_clk;
> +	struct resource *res;
> +	void __iomem *base;
> +
> +	tcon_np = of_parse_phandle(np, "tcon-controller", 0);
> +	if (!tcon_np)
> +		return -EINVAL;
> +
> +	pdev = of_find_device_by_node(tcon_np);
> +	if (!pdev)
> +		return -EINVAL;
> +
> +	tcon_clk = devm_clk_get(&pdev->dev, "tcon");
> +	if (IS_ERR(tcon_clk))
> +		return PTR_ERR(tcon_clk);
> +	clk_prepare_enable(tcon_clk);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -ENODEV;
> +
> +	base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	fsl_dev->tcon_regmap = devm_regmap_init_mmio_clk(&pdev->dev,
> +			"tcon", base, &fsl_dcu_regmap_config);
> +	if (IS_ERR(fsl_dev->tcon_regmap)) {
> +		dev_err(&pdev->dev, "regmap init failed\n");
> +		return PTR_ERR(fsl_dev->tcon_regmap);
> +	}
> +
> +	regmap_write(fsl_dev->tcon_regmap, TCON_CTRL1, TCON_BYPASS_ENABLE);
> +	return 0;
> +}
> +
> +static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
> +{
> +	struct platform_device *pdev = dev->platformdev;
> +	struct fsl_dcu_drm_device *fsl_dev;
> +	struct resource *res;
> +	void __iomem *base;
> +	int ret;
> +
> +	fsl_dev = devm_kzalloc(&pdev->dev, sizeof(*fsl_dev), GFP_KERNEL);
> +	if (!fsl_dev)
> +		return -ENOMEM;
> +
> +	fsl_dev->dev = &pdev->dev;
> +	fsl_dev->ddev = dev;
> +	dev->dev_private = fsl_dev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(base)) {
> +		ret = PTR_ERR(base);
> +		return ret;
> +	}
> +
> +	fsl_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
> +			base, &fsl_dcu_regmap_config);
> +	if (IS_ERR(fsl_dev->regmap)) {
> +		dev_err(&pdev->dev, "regmap init failed\n");
> +		return PTR_ERR(fsl_dev->regmap);
> +	}
> +
> +	ret = fsl_dcu_drm_modeset_init(fsl_dev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to initialize mode setting\n");
> +		return ret;
> +	}
> +
> +	ret = drm_vblank_init(dev, 1);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to initialize vblank\n");
> +		goto done;
> +	}
> +
> +	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to install IRQ handler\n");
> +		goto done;
> +	}
> +
> +	/* Put TCON in bypass mode, so the input signals from DCU are passed
> +	 * through TCON unchanged */
> +	fsl_dcu_bypass_tcon(fsl_dev, pdev->dev.of_node);
> +
> +	fsl_dev->clk = devm_clk_get(&pdev->dev, "dcu");
> +	if (IS_ERR(fsl_dev->clk)) {
> +		ret = PTR_ERR(fsl_dev->clk);
> +		dev_err(&pdev->dev, "could not get clock\n");
> +		return ret;
> +	}
> +	clk_prepare_enable(fsl_dev->clk);
> +
> +	dev_set_drvdata(dev->dev, fsl_dev);
> +
> +	fsl_dcu_fbdev_init(dev);
> +
> +	return 0;
> +done:
> +	if (ret)
> +		fsl_dcu_unload(dev);
> +
> +	return ret;
> +}
> +
> +static void fsl_dcu_drm_preclose(struct drm_device *dev, struct drm_file *file)
> +{
> +	;
> +}
> +
> +static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
> +{
> +	return IRQ_HANDLED;
> +}
> +
> +static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int crtc)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int crtc)
> +{
> +	;
> +}
> +
> +static const struct file_operations fsl_dcu_drm_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= drm_open,
> +	.release	= drm_release,
> +	.unlocked_ioctl	= drm_ioctl,
> +#ifdef CONFIG_COMPAT
> +	.compat_ioctl	= drm_compat_ioctl,
> +#endif
> +	.poll		= drm_poll,
> +	.read		= drm_read,
> +	.llseek		= no_llseek,
> +	.mmap		= drm_gem_cma_mmap,
> +};
> +
> +static struct drm_driver fsl_dcu_drm_driver = {
> +	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
> +				| DRIVER_PRIME,
> +	.load			= fsl_dcu_load,
> +	.unload			= fsl_dcu_unload,
> +	.preclose		= fsl_dcu_drm_preclose,
> +	.irq_handler		= fsl_dcu_drm_irq,
> +	.get_vblank_counter	= drm_vblank_count,
> +	.enable_vblank		= fsl_dcu_drm_enable_vblank,
> +	.disable_vblank		= fsl_dcu_drm_disable_vblank,
> +	.gem_free_object	= drm_gem_cma_free_object,
> +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
> +	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
> +	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
> +	.gem_prime_import	= drm_gem_prime_import,
> +	.gem_prime_export	= drm_gem_prime_export,
> +	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
> +	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> +	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
> +	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
> +	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
> +	.dumb_create		= drm_gem_cma_dumb_create,
> +	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
> +	.dumb_destroy		= drm_gem_dumb_destroy,
> +	.fops			= &fsl_dcu_drm_fops,
> +	.name			= "fsl-dcu-drm",
> +	.desc			= "Freescale DCU DRM",
> +	.date			= "20150213",
> +	.major			= 1,
> +	.minor			= 0,
> +};
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int fsl_dcu_drm_pm_suspend(struct device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> +
> +	dcu_pixclk_disable();
> +	drm_kms_helper_poll_disable(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_suspend(&fsl_dev->crtc);
> +
> +	return 0;
> +}
> +
> +static int fsl_dcu_drm_pm_resume(struct device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> +
> +	drm_modeset_lock_all(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_resume(&fsl_dev->crtc);
> +	drm_modeset_unlock_all(fsl_dev->ddev);
> +	drm_kms_helper_poll_enable(fsl_dev->ddev);
> +	dcu_pixclk_enable();
> +	return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops fsl_dcu_drm_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_drm_pm_suspend, fsl_dcu_drm_pm_resume)
> +};
> +
> +static int fsl_dcu_drm_probe(struct platform_device *pdev)
> +{
> +	return drm_platform_init(&fsl_dcu_drm_driver, pdev);
> +}
> +
> +static int fsl_dcu_drm_remove(struct platform_device *pdev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
> +
> +	drm_put_dev(fsl_dev->ddev);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id fsl_dcu_of_match[] = {
> +		{ .compatible = "fsl,dcu", },
> +		{ },
> +};
> +MODULE_DEVICE_TABLE(of, fsl_dcu_of_match);
> +
> +static struct platform_driver fsl_dcu_drm_platform_driver = {
> +	.probe		= fsl_dcu_drm_probe,
> +	.remove		= fsl_dcu_drm_remove,
> +	.driver		= {
> +		.owner	= THIS_MODULE,
> +		.name	= "fsl,dcu",
> +		.pm	= &fsl_dcu_drm_pm_ops,
> +		.of_match_table = fsl_dcu_of_match,
> +	},
> +};
> +
> +module_platform_driver(fsl_dcu_drm_platform_driver);
> +
> +MODULE_ALIAS("platform:fsl-dcu-drm");
> +MODULE_DESCRIPTION("Freescale DCU DRM Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> new file mode 100644
> index 0000000..cbdfefc
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> @@ -0,0 +1,168 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_DRV_H__
> +#define __FSL_DCU_DRM_DRV_H__
> +
> +#include <linux/kernel.h>
> +#include <linux/spinlock.h>
> +#include <stddef.h>
> +#include <drm/drm.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_plane.h"
> +#include "fsl_dcu_drm_connector.h"
> +#define DRIVER_NAME			"fsl-dcu-fb"
> +
> +#define DCU_DCU_MODE			0x0010
> +#define DCU_MODE_BLEND_ITER(x)		((x) << 20)
> +#define DCU_MODE_RASTER_EN		BIT(14)
> +#define DCU_MODE_DCU_MODE(x)		(x)
> +#define DCU_MODE_DCU_MODE_MASK		0x03
> +#define DCU_MODE_OFF			0
> +#define DCU_MODE_NORMAL			1
> +#define DCU_MODE_TEST			2
> +#define DCU_MODE_COLORBAR		3
> +
> +#define DCU_BGND			0x0014
> +#define DCU_BGND_R(x)			((x) << 16)
> +#define DCU_BGND_G(x)			((x) << 8)
> +#define DCU_BGND_B(x)			(x)
> +
> +#define DCU_DISP_SIZE			0x0018
> +#define DCU_DISP_SIZE_DELTA_Y(x)	((x) << 16)
> +/*Regisiter value 1/16 of horizontal resolution*/
> +#define DCU_DISP_SIZE_DELTA_X(x)	((x) >> 4)
> +
> +#define DCU_HSYN_PARA			0x001c
> +#define DCU_HSYN_PARA_BP(x)		((x) << 22)
> +#define DCU_HSYN_PARA_PW(x)		((x) << 11)
> +#define DCU_HSYN_PARA_FP(x)		(x)
> +
> +#define DCU_VSYN_PARA			0x0020
> +#define DCU_VSYN_PARA_BP(x)		((x) << 22)
> +#define DCU_VSYN_PARA_PW(x)		((x) << 11)
> +#define DCU_VSYN_PARA_FP(x)		(x)
> +
> +#define DCU_SYN_POL			0x0024
> +#define DCU_SYN_POL_INV_PXCK_FALL	(0 << 6)
> +#define DCU_SYN_POL_NEG_REMAIN		(0 << 5)
> +#define DCU_SYN_POL_INV_VS_LOW		BIT(1)
> +#define DCU_SYN_POL_INV_HS_LOW		(1)
> +
> +#define DCU_THRESHOLD			0x0028
> +#define DCU_THRESHOLD_LS_BF_VS(x)	((x) << 16)
> +#define DCU_THRESHOLD_OUT_BUF_HIGH(x)	((x) << 8)
> +#define DCU_THRESHOLD_OUT_BUF_LOW(x)	(x)
> +#define BF_VS_VAL			0x03
> +#define BUF_MAX_VAL			0x78
> +#define BUF_MIN_VAL			0x0a
> +
> +#define DCU_INT_STATUS			0x002C
> +#define DCU_INT_STATUS_UNDRUN		BIT(1)
> +
> +#define DCU_INT_MASK			0x0030
> +#define DCU_INT_MASK_UNDRUN		BIT(1)
> +#define DCU_INT_MASK_VBLANK		BIT(3)
> +
> +#define DCU_DIV_RATIO			0x0054
> +
> +#define DCU_UPDATE_MODE			0x00cc
> +#define DCU_UPDATE_MODE_MODE		BIT(31)
> +#define DCU_UPDATE_MODE_READREG		BIT(30)
> +
> +#define DCU_DCFB_MAX			0x300
> +
> +#define DCU_CTRLDESCLN_1(x)		(0x200 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_1_HEIGHT(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_1_WIDTH(x)	(x)
> +
> +#define DCU_CTRLDESCLN_2(x)		(0x204 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_2_POSY(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_2_POSX(x)	(x)
> +
> +#define DCU_CTRLDESCLN_3(x)		(0x208 + (x) * 0x40)
> +
> +#define DCU_CTRLDESCLN_4(x)		(0x20c + (x) * 0x40)
> +#define DCU_CTRLDESCLN_4_EN		BIT(31)
> +#define DCU_CTRLDESCLN_4_TILE_EN	BIT(30)
> +#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT	BIT(29)
> +#define DCU_CTRLDESCLN_4_SAFETY_EN	BIT(28)
> +#define DCU_CTRLDESCLN_4_TRANS(x)	((x) << 20)
> +#define DCU_CTRLDESCLN_4_BPP(x)		((x) << 16)
> +#define DCU_CTRLDESCLN_4_RLE_EN		BIT(15)
> +#define DCU_CTRLDESCLN_4_LUOFFS(x)	((x) << 4)
> +#define DCU_CTRLDESCLN_4_BB_ON		BIT(2)
> +#define DCU_CTRLDESCLN_4_AB(x)		(x)
> +
> +#define DCU_CTRLDESCLN_5(x)		(0x210 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_5_CKMAX_R(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_5_CKMAX_G(x)	((x) << 8)
> +#define DCU_CTRLDESCLN_5_CKMAX_B(x)	(x)
> +
> +#define DCU_CTRLDESCLN_6(x)		(0x214 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_6_CKMIN_R(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_6_CKMIN_G(x)	((x) << 8)
> +#define DCU_CTRLDESCLN_6_CKMIN_B(x)	(x)
> +
> +#define DCU_CTRLDESCLN_7(x)		(0x218 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_7_TILE_VER(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_7_TILE_HOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_8(x)		(0x21c + (x) * 0x40)
> +#define DCU_CTRLDESCLN_8_FG_FCOLOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_9(x)		(0x220 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_9_BG_BCOLOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_10(x)		(0x224 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_10_POST_SKIP(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_10_PRE_SKIP(x)	(x)
> +
> +#define FSL_DCU_RGB565			4
> +#define FSL_DCU_RGB888			5
> +#define FSL_DCU_ARGB8888		6
> +#define FSL_DCU_ARGB1555		11
> +#define FSL_DCU_ARGB4444		12
> +#define FSL_DCU_YUV422			14
> +
> +#define TCON_CTRL1			0x0000
> +#define TCON_BYPASS_ENABLE		BIT(29)
> +
> +#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
> +
> +struct clk;
> +struct device;
> +struct drm_device;
> +
> +struct fsl_dcu_drm_device {
> +	struct device *dev;
> +	struct regmap *regmap;
> +	struct regmap *tcon_regmap;
> +	unsigned int irq;
> +	struct clk *clk;
> +	/*protects hardware register*/
> +	spinlock_t irq_lock;
> +	struct drm_device *ddev;
> +	struct drm_fbdev_cma *fbdev;
> +	struct fsl_dcu_drm_crtc crtc;
> +	struct drm_encoder encoder;
> +	struct fsl_dcu_drm_connector connector;
> +};
> +
> +void fsl_dcu_fbdev_init(struct drm_device *dev);
> +
> +#endif /* __FSL_DCU_DRM_DRV_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> new file mode 100644
> index 0000000..f8ef0e1
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_cma_helper.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +
> +/* initialize fbdev helper */
> +void fsl_dcu_fbdev_init(struct drm_device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
> +
> +	fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1);
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> new file mode 100644
> index 0000000..4a840fb
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> @@ -0,0 +1,42 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_connector.h"
> +#include "fsl_dcu_drm_drv.h"
> +
> +static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs = {
> +	.fb_create = drm_fb_cma_create,
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	drm_mode_config_init(fsl_dev->ddev);
> +
> +	fsl_dev->ddev->mode_config.min_width = 0;
> +	fsl_dev->ddev->mode_config.min_height = 0;
> +	fsl_dev->ddev->mode_config.max_width = 2031;
> +	fsl_dev->ddev->mode_config.max_height = 2047;
> +	fsl_dev->ddev->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;
> +
> +	drm_kms_helper_poll_init(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_create(fsl_dev);
> +	fsl_dcu_drm_encoder_create(fsl_dev);
> +	fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
> +	drm_mode_config_reset(fsl_dev->ddev);
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> new file mode 100644
> index 0000000..b9bd299
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> @@ -0,0 +1,17 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_KMS_H__
> +#define __FSL_DCU_DRM_KMS_H__
> +
> +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
> +
> +#endif /* __FSL_DCU_DRM_KMS_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> new file mode 100644
> index 0000000..b7b4405
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> @@ -0,0 +1,187 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <linux/regmap.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_kms.h"
> +#include "fsl_dcu_drm_plane.h"
> +
> +#define to_fsl_dcu_plane(plane) \
> +	container_of(plane, struct fsl_dcu_drm_plane, plane)
> +
> +static int
> +fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
> +			     struct drm_framebuffer *fb,
> +			     const struct drm_plane_state *new_state)
> +{
> +	return 0;
> +}
> +
> +static void
> +fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
> +			     struct drm_framebuffer *fb,
> +			     const struct drm_plane_state *new_state)
> +{
> +}
> +
> +static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
> +					  struct drm_plane_state *state)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
> +					     struct drm_plane_state *old_state)
> +{
> +}
> +
> +void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
> +				     struct drm_plane_state *old_state)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = plane->state->fb;
> +	u32 index, alpha, bpp;
> +	struct drm_gem_cma_object *gem;
> +	struct fsl_dcu_drm_plane *fsl_plane = to_fsl_dcu_plane(plane);
> +
> +	index = fsl_plane->index;
> +	gem = drm_fb_cma_get_gem_obj(fb, 0);
> +
> +	switch (fb->pixel_format) {
> +	case DRM_FORMAT_RGB565:
> +		bpp = FSL_DCU_RGB565;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_RGB888:
> +		bpp = FSL_DCU_RGB888;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_ARGB8888:
> +		bpp = FSL_DCU_ARGB8888;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_BGRA4444:
> +		bpp = FSL_DCU_ARGB4444;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_ARGB1555:
> +		bpp = FSL_DCU_ARGB1555;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_YUV422:
> +		bpp = FSL_DCU_YUV422;
> +		alpha = 0xff;
> +		break;
> +	default:
> +		return;
> +	}
> +
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_1(index),
> +		     DCU_CTRLDESCLN_1_HEIGHT(state->crtc_h) |
> +		     DCU_CTRLDESCLN_1_WIDTH(state->crtc_w));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_2(index),
> +		     DCU_CTRLDESCLN_2_POSY(state->crtc_y) |
> +		     DCU_CTRLDESCLN_2_POSX(state->crtc_x));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_3(index), gem->paddr);
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_4(index),
> +		     DCU_CTRLDESCLN_4_EN |
> +		     DCU_CTRLDESCLN_4_TRANS(alpha) |
> +		     DCU_CTRLDESCLN_4_BPP(bpp) |
> +		     DCU_CTRLDESCLN_4_AB(2));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_5(index),
> +		     DCU_CTRLDESCLN_5_CKMAX_R(0xFF) |
> +		     DCU_CTRLDESCLN_5_CKMAX_G(0xFF) |
> +		     DCU_CTRLDESCLN_5_CKMAX_B(0xFF));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_6(index),
> +		     DCU_CTRLDESCLN_6_CKMIN_R(0) |
> +		     DCU_CTRLDESCLN_6_CKMIN_G(0) |
> +		     DCU_CTRLDESCLN_6_CKMIN_B(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_8(index),
> +		     DCU_CTRLDESCLN_8_FG_FCOLOR(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_9(index),
> +		     DCU_CTRLDESCLN_9_BG_BCOLOR(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_10(index),
> +		     DCU_CTRLDESCLN_10_POST_SKIP(0) |
> +		     DCU_CTRLDESCLN_10_PRE_SKIP(0));
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +}
> +
> +int fsl_dcu_drm_plane_disable(struct drm_plane *plane)
> +{
> +	return 0;
> +}
> +
> +void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
> +{
> +	fsl_dcu_drm_plane_disable(plane);
> +	drm_plane_cleanup(plane);
> +}
> +
> +static const uint32_t fsl_dcu_drm_plane_formats[] = {
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_RGB888,
> +	DRM_FORMAT_ARGB8888,
> +	DRM_FORMAT_ARGB4444,
> +	DRM_FORMAT_ARGB1555,
> +	DRM_FORMAT_YUV422,
> +};
> +
> +static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
> +	.update_plane = drm_plane_helper_update,
> +	.disable_plane = drm_plane_helper_disable,
> +	.destroy = fsl_dcu_drm_plane_destroy,
> +	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> +	.reset = drm_atomic_helper_plane_reset,
> +};
> +
> +static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
> +	.prepare_fb = fsl_dcu_drm_plane_prepare_fb,
> +	.cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
> +	.atomic_check = fsl_dcu_drm_plane_atomic_check,
> +	.atomic_update = fsl_dcu_drm_plane_atomic_update,
> +	.atomic_disable = fsl_dcu_drm_plane_atomic_disable,
> +};
> +
> +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
> +{
> +	struct drm_plane *primary;
> +	int ret;
> +
> +	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> +	if (!primary) {
> +		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
> +		return NULL;
> +	}
> +
> +	/* possible_crtc's will be filled in later by crtc_init */
> +	ret = drm_universal_plane_init(dev, primary, 0,
> +				       &fsl_dcu_drm_plane_funcs,
> +				       fsl_dcu_drm_plane_formats,
> +				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
> +				       DRM_PLANE_TYPE_PRIMARY);
> +	if (ret) {
> +		kfree(primary);
> +		primary = NULL;
> +	}
> +	drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
> +
> +	return primary;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> new file mode 100644
> index 0000000..ccbfa61
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> @@ -0,0 +1,23 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_PLANE_H__
> +#define __FSL_DCU_DRM_PLANE_H__
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_plane {
> +	struct drm_plane plane;
> +	unsigned int index;
> +};
> +
> +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev);
> +
> +#endif /* __FSL_DCU_DRM_PLANE_H__ */
> diff --git a/include/linux/fsl/dcu.h b/include/linux/fsl/dcu.h
> new file mode 100644
> index 0000000..1873057
> --- /dev/null
> +++ b/include/linux/fsl/dcu.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_H__
> +#define __FSL_DCU_H__
> +
> +#define SCFG_PIXCLKCR			0x28
> +#define PXCK_ENABLE			BIT(31)
> +#define PXCK_DISABLE			0
> +
> +void dcu_pixclk_enable(void);
> +void dcu_pixclk_disable(void);
> +
> +#endif /* __FSL_DCU_H__ */
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
  2015-03-18 22:58   ` Stefan Agner
  (?)
@ 2015-03-19  1:41     ` Jianwei.Wang at freescale.com
  -1 siblings, 0 replies; 26+ messages in thread
From: Jianwei.Wang @ 2015-03-19  1:41 UTC (permalink / raw)
  To: Stefan Agner
  Cc: Scott Wood, airlied, jbarnes, dri-devel, Xiubo Li, Huan Wang,
	linux-kernel, Jason.Jin, linux-arm-kernel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 50448 bytes --]

Hi Stefan,

Thank you for your comment. I'll correct this next time.


> -----Original Message-----
> From: Stefan Agner [mailto:stefan@agner.ch]
> Sent: Thursday, March 19, 2015 6:58 AM
> To: Wang Jianwei-B52261
> Cc: Wood Scott-B07421; airlied@linux.ie; jbarnes@virtuousgeek.org; dri-
> devel@lists.freedesktop.org; Xiubo Li; Wang Huan-B18965; linux-
> kernel@vger.kernel.org; Jin Zhengxiong-R64188; linux-arm-
> kernel@lists.infradead.org
> Subject: Re: [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
> 
> Hi Jianwei,
> 
> Normally, for the second and higher iteration of a patchset, developers
> add the version to the subject (e.g. PATCH v2). You can use the --reroll-
> count option when creating the patches with git format-patch.
> 
> On 2015-03-13 10:44, Jianwei Wang wrote:
> > This patch add support for Two Dimensional Animation and Compositing
> > Engine (2D-ACE) on Freescale SoCs.
> >
> > 2D-ACE is a Freescale display controller. It provide an hardware
> > cursor.
> >
> > This is a simplified version, only a primary plane, a fb created for
> > fbdev, a crtc, a connector for TFT LCD panel, an encoder, and the
> > encoder is not in use.
> >
> > Signed-off-by: Alison Wang <b18965@freescale.com>
> > Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> > Signed-off-by: Jianwei Wang <b52261@freescale.com>
> > ---
> >
> > Changed in v2:
> > - Add atomic support
> > - Modify bindings file
> > - Rename node for compatibility
> > - Move platform related code out for compatibility
> >
> > Added in v1:
> > - Add support for DCU display controller on the Freescale LS102x SoCs.
> > - Create a primary plane, a fb created for fbdev, a crtc, a connector
> > for TFT LCD panel, an encoder.
> >
> >  arch/arm/mach-imx/mach-ls1021a.c            |  36 ++++
> >  drivers/gpu/drm/Kconfig                     |   2 +
> >  drivers/gpu/drm/Makefile                    |   1 +
> >  drivers/gpu/drm/fsl/Kconfig                 |  17 ++
> >  drivers/gpu/drm/fsl/Makefile                |   8 +
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c | 203
> > ++++++++++++++++++++  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h |  28
> +++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c      | 164 ++++++++++++++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h      |  26 +++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c       | 288
> ++++++++++++++++++++++++++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h       | 168 ++++++++++++++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c     |  26 +++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c       |  42 ++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h       |  17 ++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c     | 187 ++++++++++++++++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h     |  23 +++
> >  include/linux/fsl/dcu.h                     |  22 +++
> >  17 files changed, 1258 insertions(+)
> >  create mode 100644 drivers/gpu/drm/fsl/Kconfig  create mode 100644
> > drivers/gpu/drm/fsl/Makefile  create mode 100644
> > drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> >  create mode 100644 include/linux/fsl/dcu.h
> >
> > diff --git a/arch/arm/mach-imx/mach-ls1021a.c
> > b/arch/arm/mach-imx/mach-ls1021a.c
> > index b89c858..4fb346d 100644
> > --- a/arch/arm/mach-imx/mach-ls1021a.c
> > +++ b/arch/arm/mach-imx/mach-ls1021a.c
> > @@ -8,9 +8,44 @@
> >   */
> >
> >  #include <asm/mach/arch.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/regmap.h>
> > +#include <linux/fsl/dcu.h>
> >
> >  #include "common.h"
> >
> > +void dcu_pixclk_disable(void)
> > +{
> > +	struct regmap *scfg_regmap;
> > +
> > +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> > +	if (IS_ERR(scfg_regmap)) {
> > +		pr_err("No syscfg phandle specified\n");
> > +		return;
> > +	}
> > +
> > +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_DISABLE); }
> > +
> > +void dcu_pixclk_enable(void)
> > +{
> > +	struct regmap *scfg_regmap;
> > +
> > +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> > +	if (IS_ERR(scfg_regmap)) {
> > +		pr_err("No syscfg phandle specified\n");
> > +		return;
> > +	}
> > +
> > +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_ENABLE); }
> > +
> > +static void __init ls1021a_init_machine(void) {
> > +	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> > +	dcu_pixclk_enable();
> > +}
> 
> This change should be in a separate patch. However, I'm not convinced that
> the current code is the right solution. You should try to avoid calling
> from the driver directly into arch code.
> 
> I don't have access to the reference manual, hence I can't lookup that
> module. But this register looks just like a clock gate...
> 
> On Vybrid, the Pixelclock is enabled through CCM_CSCDR3 and friends, and
> the CCM module makes use of the common clock framework. In the end, the
> clock is assigned to the nodes (e.g. DCU node in this case) and requested
> during runtime. The framework makes sure the clock and the relevant gates
> get enabled. See:
> http://lxr.free-electrons.com/source/arch/arm/mach-imx/clk-
> vf610.c?v=3.12#L241
> 
> --
> Stefan
> 
> >  static const char * const ls1021a_dt_compat[] __initconst = {
> >  	"fsl,ls1021a",
> >  	NULL,
> > @@ -18,5 +53,6 @@ static const char * const ls1021a_dt_compat[]
> > __initconst = {
> >
> >  DT_MACHINE_START(LS1021A, "Freescale LS1021A")
> >  	.smp		= smp_ops(ls1021a_smp_ops),
> > +	.init_machine	= ls1021a_init_machine,
> >  	.dt_compat	= ls1021a_dt_compat,
> >  MACHINE_END
> > diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index
> > 151a050..a6957aa 100644
> > --- a/drivers/gpu/drm/Kconfig
> > +++ b/drivers/gpu/drm/Kconfig
> > @@ -199,6 +199,8 @@ source "drivers/gpu/drm/bochs/Kconfig"
> >
> >  source "drivers/gpu/drm/msm/Kconfig"
> >
> > +source "drivers/gpu/drm/fsl/Kconfig"
> > +
> >  source "drivers/gpu/drm/tegra/Kconfig"
> >
> >  source "drivers/gpu/drm/panel/Kconfig"
> > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index
> > 2c239b9..ab5b9ef 100644
> > --- a/drivers/gpu/drm/Makefile
> > +++ b/drivers/gpu/drm/Makefile
> > @@ -56,6 +56,7 @@ obj-$(CONFIG_DRM_UDL) += udl/
> >  obj-$(CONFIG_DRM_AST) += ast/
> >  obj-$(CONFIG_DRM_ARMADA) += armada/
> >  obj-$(CONFIG_DRM_ATMEL_HLCDC)	+= atmel-hlcdc/
> > +obj-$(CONFIG_DRM_FSL_DCU) += fsl/
> >  obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
> >  obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
> >  obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
> > diff --git a/drivers/gpu/drm/fsl/Kconfig b/drivers/gpu/drm/fsl/Kconfig
> > new file mode 100644 index 0000000..e4f8df0
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/Kconfig
> > @@ -0,0 +1,17 @@
> > +config DRM_FSL_DCU
> > +	tristate "DRM Support for Freescale DCU"
> > +	depends on DRM && OF && ARM
> > +	select DRM_KMS_HELPER
> > +	select DRM_KMS_CMA_HELPER
> > +	select VIDEOMODE_HELPERS
> > +	select BACKLIGHT_CLASS_DEVICE
> > +	select BACKLIGHT_LCD_SUPPORT
> > +	select REGMAP_MMIO
> > +	select DRM_KMS_FB_HELPER
> > +	select FB_SYS_FILLRECT
> > +	select FB_SYS_COPYAREA
> > +	select FB_SYS_IMAGEBLIT
> > +	select FB_SYS_FOPS
> > +	help
> > +	  Choose this option if you have an Freescale DCU chipset.
> > +	  If M is selected the module will be called fsl-dcu-drm.
> > diff --git a/drivers/gpu/drm/fsl/Makefile
> > b/drivers/gpu/drm/fsl/Makefile new file mode 100644 index
> > 0000000..5f74aee
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/Makefile
> > @@ -0,0 +1,8 @@
> > +fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
> > +	       fsl_dcu_drm_kms.o \
> > +	       fsl_dcu_drm_connector.o \
> > +	       fsl_dcu_drm_plane.o \
> > +	       fsl_dcu_drm_crtc.o \
> > +	       fsl_dcu_drm_fbdev.o \
> > +
> > +obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> > new file mode 100644
> > index 0000000..178d647
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> > @@ -0,0 +1,203 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <linux/backlight.h>
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_atomic_helper.h>
> > +#include <video/of_display_timing.h>
> > +
> > +#include "fsl_dcu_drm_drv.h"
> > +#include "fsl_dcu_drm_connector.h"
> > +
> > +static void fsl_dcu_drm_encoder_dpms(struct drm_encoder *encoder, int
> > +mode) { }
> > +
> > +/* Disable the encoders as the first thing we do. */ static void
> > +fsl_dcu_drm_encoder_mode_prepare(struct drm_encoder *encoder) { }
> > +
> > +static void fsl_dcu_drm_encoder_mode_set(struct drm_encoder *encoder,
> > +					 struct drm_display_mode *mode,
> > +					 struct drm_display_mode *adjusted_mode) { }
> > +
> > +static void fsl_dcu_drm_encoder_mode_commit(struct drm_encoder
> > +*encoder) { }
> > +
> > +static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
> > +{ }
> > +
> > +static int
> > +fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
> > +				 struct drm_crtc_state *crtc_state,
> > +				 struct drm_connector_state *conn_state) {
> > +	return 0;
> > +}
> > +
> > +static bool
> > +fsl_dcu_drm_encoder_mode_fixup(struct drm_encoder *encoder,
> > +			       const struct drm_display_mode *mode,
> > +			       struct drm_display_mode *adjusted_mode) {
> > +	return true;
> > +}
> > +
> > +static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
> > +{
> > +	drm_encoder_cleanup(encoder);
> > +}
> > +
> > +static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
> > +	.dpms = fsl_dcu_drm_encoder_dpms,
> > +	.prepare = fsl_dcu_drm_encoder_mode_prepare,
> > +	.commit = fsl_dcu_drm_encoder_mode_commit,
> > +	.mode_set = fsl_dcu_drm_encoder_mode_set,
> > +	.disable = fsl_dcu_drm_encoder_disable,
> > +	.atomic_check = fsl_dcu_drm_encoder_atomic_check,
> > +	.mode_fixup = fsl_dcu_drm_encoder_mode_fixup, };
> > +
> > +static const struct drm_encoder_funcs encoder_funcs = {
> > +	.destroy = fsl_dcu_drm_encoder_destroy, };
> > +
> > +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev) {
> > +	struct drm_encoder *encoder = &fsl_dev->encoder;
> > +	int ret;
> > +
> > +	encoder->possible_crtcs = 1;
> > +
> > +	ret = drm_encoder_init(fsl_dev->ddev, encoder, &encoder_funcs,
> > +			       DRM_MODE_ENCODER_LVDS);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
> > +
> > +	return 0;
> > +}
> > +
> > +#define to_fsl_dcu_connector(connector) \
> > +	container_of(connector, struct fsl_dcu_drm_connector, connector)
> > +
> > +static int fsl_dcu_drm_connector_get_modes(struct drm_connector
> > +*connector) {
> > +	struct drm_device *dev = connector->dev;
> > +	struct device_node *display_np, *np = dev->dev->of_node;
> > +	struct drm_display_mode *mode = drm_mode_create(connector->dev);
> > +	int num_modes = 0;
> > +
> > +	if (np) {
> > +		display_np = of_parse_phandle(np, "display", 0);
> > +		if (!display_np) {
> > +			dev_err(dev->dev, "failed to find display phandle\n");
> > +			return num_modes;
> > +		}
> > +		of_get_drm_display_mode(display_np, mode, OF_USE_NATIVE_MODE);
> > +		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> > +		drm_mode_probed_add(connector, mode);
> > +		num_modes++;
> > +	}
> > +
> > +	return num_modes;
> > +}
> > +
> > +static int fsl_dcu_drm_connector_mode_valid(struct drm_connector
> *connector,
> > +					    struct drm_display_mode *mode) {
> > +	return MODE_OK;
> > +}
> > +
> > +static struct drm_encoder *
> > +fsl_dcu_drm_connector_best_encoder(struct drm_connector *connector) {
> > +	struct fsl_dcu_drm_connector *fsl_con =
> > +to_fsl_dcu_connector(connector);
> > +
> > +	return fsl_con->encoder;
> > +}
> > +
> > +static void fsl_dcu_drm_connector_destroy(struct drm_connector
> > +*connector) {
> > +	drm_connector_unregister(connector);
> > +	drm_connector_cleanup(connector);
> > +}
> > +
> > +static enum drm_connector_status
> > +fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool
> > +force) {
> > +	return connector_status_connected;
> > +}
> > +
> > +static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
> > +	.dpms = drm_atomic_helper_connector_dpms,
> > +	.reset = drm_atomic_helper_connector_reset,
> > +	.detect = fsl_dcu_drm_connector_detect,
> > +	.fill_modes = drm_helper_probe_single_connector_modes,
> > +	.destroy = fsl_dcu_drm_connector_destroy,
> > +	.atomic_duplicate_state =
> drm_atomic_helper_connector_duplicate_state,
> > +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> > +};
> > +
> > +static const struct drm_connector_helper_funcs connector_helper_funcs =
> {
> > +	.get_modes = fsl_dcu_drm_connector_get_modes,
> > +	.mode_valid = fsl_dcu_drm_connector_mode_valid,
> > +	.best_encoder = fsl_dcu_drm_connector_best_encoder,
> > +};
> > +
> > +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> > +				 struct drm_encoder *encoder)
> > +{
> > +	struct drm_connector *connector = &fsl_dev->connector.connector;
> > +	int ret;
> > +
> > +	fsl_dev->connector.encoder = encoder;
> > +
> > +	connector->display_info.width_mm = 0;
> > +	connector->display_info.height_mm = 0;
> > +
> > +	ret = drm_connector_init(fsl_dev->ddev, connector,
> > +				 &fsl_dcu_drm_connector_funcs,
> > +				 DRM_MODE_CONNECTOR_LVDS);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	connector->dpms = DRM_MODE_DPMS_OFF;
> > +	drm_connector_helper_add(connector, &connector_helper_funcs);
> > +	ret = drm_connector_register(connector);
> > +	if (ret < 0)
> > +		goto err_cleanup;
> > +
> > +	ret = drm_mode_connector_attach_encoder(connector, encoder);
> > +	if (ret < 0)
> > +		goto err_sysfs;
> > +
> > +	connector->encoder = encoder;
> > +
> > +	drm_object_property_set_value
> > +		(&connector->base, fsl_dev->ddev->mode_config.dpms_property,
> > +		DRM_MODE_DPMS_OFF);
> > +
> > +	return 0;
> > +
> > +err_sysfs:
> > +	drm_connector_unregister(connector);
> > +err_cleanup:
> > +	drm_connector_cleanup(connector);
> > +	return ret;
> > +}
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> > new file mode 100644
> > index 0000000..afe44ab
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> > @@ -0,0 +1,28 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_CONNECTOR_H__
> > +#define __FSL_DCU_DRM_CONNECTOR_H__
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_crtc.h>
> > +
> > +struct fsl_dcu_drm_device;
> > +struct fsl_dcu_drm_connector {
> > +	struct drm_connector connector;
> > +	struct drm_encoder *encoder;
> > +};
> > +
> > +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev);
> > +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> > +				 struct drm_encoder *encoder);
> > +
> > +#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> > new file mode 100644
> > index 0000000..a43e7ce
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> > @@ -0,0 +1,164 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <linux/regmap.h>
> > +#include <linux/clk.h>
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_atomic.h>
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_crtc.h>
> > +
> > +#include "fsl_dcu_drm_crtc.h"
> > +#include "fsl_dcu_drm_drv.h"
> > +#include "fsl_dcu_drm_plane.h"
> > +
> > +#define to_fsl_dcu_crtc(c)	container_of(c, struct fsl_dcu_drm_crtc,
> crtc)
> > +
> > +void fsl_dcu_drm_crtc_suspend(struct drm_crtc *crtc) { }
> > +
> > +static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) {
> > +	struct drm_device *dev = crtc->dev;
> > +	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
> > +	struct drm_display_mode *mode = &crtc->state->mode;
> > +	uint32_t hbp, hfp, hsw, vbp, vfp, vsw, div, index;
> > +
> > +	DBG(": set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
> > +	    mode->base.id, mode->name,
> > +	    mode->vrefresh, mode->clock,
> > +	    mode->hdisplay, mode->hsync_start,
> > +	    mode->hsync_end, mode->htotal,
> > +	    mode->vdisplay, mode->vsync_start,
> > +	    mode->vsync_end, mode->vtotal,
> > +	    mode->type, mode->flags);
> > +
> > +	index = drm_crtc_index(crtc);
> > +	div = (uint32_t)clk_get_rate(fsl_dev->clk) / mode->clock / 1000;
> > +
> > +	/* Configure timings: */
> > +	hbp = mode->htotal - mode->hsync_end;
> > +	hfp = mode->hsync_start - mode->hdisplay;
> > +	hsw = mode->hsync_end - mode->hsync_start;
> > +	vbp = mode->vtotal - mode->vsync_end;
> > +	vfp = mode->vsync_start - mode->vdisplay;
> > +	vsw = mode->vsync_end - mode->vsync_start;
> > +
> > +	regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
> > +		     DCU_HSYN_PARA_BP(hbp) |
> > +		     DCU_HSYN_PARA_PW(hsw) |
> > +		     DCU_HSYN_PARA_FP(hfp));
> > +	regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
> > +		     DCU_VSYN_PARA_BP(vbp) |
> > +		     DCU_VSYN_PARA_PW(vsw) |
> > +		     DCU_VSYN_PARA_FP(vfp));
> > +	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
> > +		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
> > +		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
> > +	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
> > +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
> > +DCU_UPDATE_MODE_READREG); }
> > +
> > +static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
> > +					const struct drm_display_mode *mode,
> > +					struct drm_display_mode *adjusted_mode) {
> > +	return true;
> > +}
> > +
> > +static void fsl_dcu_drm_crtc_prepare(struct drm_crtc *crtc) { }
> > +
> > +/* Now enable the clocks, plane, pipe, and connectors that we set up.
> > +*/ static void fsl_dcu_drm_crtc_mode_commit(struct drm_crtc *crtc) {
> > +}
> > +
> > +static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
> > +					 struct drm_crtc_state *state)
> > +{
> > +	return 0;
> > +}
> > +
> > +static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc) { }
> > +
> > +static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc) { }
> > +
> > +static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc) { }
> > +
> > +static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
> > +	.page_flip = drm_atomic_helper_page_flip,
> > +	.set_config = drm_crtc_helper_set_config,
> > +	.destroy = drm_crtc_cleanup,
> > +	.reset = drm_atomic_helper_crtc_reset,
> > +	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> > +	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> > +};
> > +
> > +static void fsl_dcu_drm_crtc_dpms(struct drm_crtc *crtc, int mode) {
> > +}
> > +
> > +static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs
> = {
> > +	.disable = fsl_dcu_drm_disable_crtc,
> > +	.mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
> > +	.mode_set = drm_helper_crtc_mode_set,
> > +	.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
> > +	.mode_set_base = drm_helper_crtc_mode_set_base,
> > +	.prepare = fsl_dcu_drm_crtc_prepare,
> > +	.commit = fsl_dcu_drm_crtc_mode_commit,
> > +	.atomic_check = fsl_dcu_drm_crtc_atomic_check,
> > +	.atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
> > +	.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
> > +	.dpms = fsl_dcu_drm_crtc_dpms,
> > +};
> > +
> > +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev) {
> > +	struct drm_plane *primary;
> > +	struct drm_crtc *crtc = &fsl_dev->crtc.crtc;
> > +	int ret;
> > +
> > +	fsl_dev->crtc.dpms = DRM_MODE_DPMS_OFF;
> > +
> > +	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->ddev);
> > +	ret = drm_crtc_init_with_planes(fsl_dev->ddev, crtc, primary, NULL,
> > +					&fsl_dcu_drm_crtc_funcs);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
> > +
> > +	regmap_write(fsl_dev->regmap, DCU_SYN_POL,
> > +		     DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
> > +	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
> > +		     DCU_BGND_G(0) | DCU_BGND_B(0));
> > +	regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
> > +		     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
> > +	regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
> > +		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
> > +		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
> > +		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
> > +	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
> > +			   DCU_MODE_DCU_MODE_MASK,
> > +			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
> > +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
> DCU_UPDATE_MODE_READREG);
> > +	return 0;
> > +}
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> > new file mode 100644
> > index 0000000..d44b564
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> > @@ -0,0 +1,26 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_CRTC_H__
> > +#define __FSL_DCU_DRM_CRTC_H__
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_crtc.h>
> > +
> > +struct fsl_dcu_drm_device;
> > +struct fsl_dcu_drm_crtc {
> > +	struct drm_crtc crtc;
> > +	int dpms;
> > +};
> > +
> > +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev);
> > +
> > +#endif /* __FSL_DCU_DRM_CRTC_H__ */
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> > new file mode 100644
> > index 0000000..10975ee
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> > @@ -0,0 +1,288 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/io.h>
> > +#include <linux/mm.h>
> > +#include <linux/module.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/pm.h>
> > +#include <linux/pm_runtime.h>
> > +#include <linux/regmap.h>
> > +
> > +#include <drm/drmP.h>
> > +#include <linux/fsl/dcu.h>
> > +
> > +#include "fsl_dcu_drm_drv.h"
> > +#include "fsl_dcu_drm_kms.h"
> > +
> > +static int fsl_dcu_unload(struct drm_device *dev) {
> > +	drm_mode_config_cleanup(dev);
> > +	drm_vblank_cleanup(dev);
> > +	drm_irq_uninstall(dev);
> > +
> > +	dev->dev_private = NULL;
> > +
> > +	return 0;
> > +}
> > +
> > +static struct regmap_config fsl_dcu_regmap_config = {
> > +	.reg_bits = 32,
> > +	.reg_stride = 4,
> > +	.val_bits = 32,
> > +};
> > +
> > +static int fsl_dcu_bypass_tcon(struct fsl_dcu_drm_device *fsl_dev,
> > +			       struct device_node *np)
> > +{
> > +	struct device_node *tcon_np;
> > +	struct platform_device *pdev;
> > +	struct clk *tcon_clk;
> > +	struct resource *res;
> > +	void __iomem *base;
> > +
> > +	tcon_np = of_parse_phandle(np, "tcon-controller", 0);
> > +	if (!tcon_np)
> > +		return -EINVAL;
> > +
> > +	pdev = of_find_device_by_node(tcon_np);
> > +	if (!pdev)
> > +		return -EINVAL;
> > +
> > +	tcon_clk = devm_clk_get(&pdev->dev, "tcon");
> > +	if (IS_ERR(tcon_clk))
> > +		return PTR_ERR(tcon_clk);
> > +	clk_prepare_enable(tcon_clk);
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	if (!res)
> > +		return -ENODEV;
> > +
> > +	base = devm_ioremap_resource(&pdev->dev, res);
> > +	if (IS_ERR(base))
> > +		return PTR_ERR(base);
> > +
> > +	fsl_dev->tcon_regmap = devm_regmap_init_mmio_clk(&pdev->dev,
> > +			"tcon", base, &fsl_dcu_regmap_config);
> > +	if (IS_ERR(fsl_dev->tcon_regmap)) {
> > +		dev_err(&pdev->dev, "regmap init failed\n");
> > +		return PTR_ERR(fsl_dev->tcon_regmap);
> > +	}
> > +
> > +	regmap_write(fsl_dev->tcon_regmap, TCON_CTRL1, TCON_BYPASS_ENABLE);
> > +	return 0;
> > +}
> > +
> > +static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
> > +{
> > +	struct platform_device *pdev = dev->platformdev;
> > +	struct fsl_dcu_drm_device *fsl_dev;
> > +	struct resource *res;
> > +	void __iomem *base;
> > +	int ret;
> > +
> > +	fsl_dev = devm_kzalloc(&pdev->dev, sizeof(*fsl_dev), GFP_KERNEL);
> > +	if (!fsl_dev)
> > +		return -ENOMEM;
> > +
> > +	fsl_dev->dev = &pdev->dev;
> > +	fsl_dev->ddev = dev;
> > +	dev->dev_private = fsl_dev;
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	base = devm_ioremap_resource(&pdev->dev, res);
> > +	if (IS_ERR(base)) {
> > +		ret = PTR_ERR(base);
> > +		return ret;
> > +	}
> > +
> > +	fsl_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
> > +			base, &fsl_dcu_regmap_config);
> > +	if (IS_ERR(fsl_dev->regmap)) {
> > +		dev_err(&pdev->dev, "regmap init failed\n");
> > +		return PTR_ERR(fsl_dev->regmap);
> > +	}
> > +
> > +	ret = fsl_dcu_drm_modeset_init(fsl_dev);
> > +	if (ret < 0) {
> > +		dev_err(&pdev->dev, "failed to initialize mode setting\n");
> > +		return ret;
> > +	}
> > +
> > +	ret = drm_vblank_init(dev, 1);
> > +	if (ret < 0) {
> > +		dev_err(&pdev->dev, "failed to initialize vblank\n");
> > +		goto done;
> > +	}
> > +
> > +	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
> > +	if (ret < 0) {
> > +		dev_err(&pdev->dev, "failed to install IRQ handler\n");
> > +		goto done;
> > +	}
> > +
> > +	/* Put TCON in bypass mode, so the input signals from DCU are passed
> > +	 * through TCON unchanged */
> > +	fsl_dcu_bypass_tcon(fsl_dev, pdev->dev.of_node);
> > +
> > +	fsl_dev->clk = devm_clk_get(&pdev->dev, "dcu");
> > +	if (IS_ERR(fsl_dev->clk)) {
> > +		ret = PTR_ERR(fsl_dev->clk);
> > +		dev_err(&pdev->dev, "could not get clock\n");
> > +		return ret;
> > +	}
> > +	clk_prepare_enable(fsl_dev->clk);
> > +
> > +	dev_set_drvdata(dev->dev, fsl_dev);
> > +
> > +	fsl_dcu_fbdev_init(dev);
> > +
> > +	return 0;
> > +done:
> > +	if (ret)
> > +		fsl_dcu_unload(dev);
> > +
> > +	return ret;
> > +}
> > +
> > +static void fsl_dcu_drm_preclose(struct drm_device *dev, struct
> > +drm_file *file) {
> > +	;
> > +}
> > +
> > +static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg) {
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int
> > +crtc) {
> > +	return 0;
> > +}
> > +
> > +static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int
> > +crtc) {
> > +	;
> > +}
> > +
> > +static const struct file_operations fsl_dcu_drm_fops = {
> > +	.owner		= THIS_MODULE,
> > +	.open		= drm_open,
> > +	.release	= drm_release,
> > +	.unlocked_ioctl	= drm_ioctl,
> > +#ifdef CONFIG_COMPAT
> > +	.compat_ioctl	= drm_compat_ioctl,
> > +#endif
> > +	.poll		= drm_poll,
> > +	.read		= drm_read,
> > +	.llseek		= no_llseek,
> > +	.mmap		= drm_gem_cma_mmap,
> > +};
> > +
> > +static struct drm_driver fsl_dcu_drm_driver = {
> > +	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
> > +				| DRIVER_PRIME,
> > +	.load			= fsl_dcu_load,
> > +	.unload			= fsl_dcu_unload,
> > +	.preclose		= fsl_dcu_drm_preclose,
> > +	.irq_handler		= fsl_dcu_drm_irq,
> > +	.get_vblank_counter	= drm_vblank_count,
> > +	.enable_vblank		= fsl_dcu_drm_enable_vblank,
> > +	.disable_vblank		= fsl_dcu_drm_disable_vblank,
> > +	.gem_free_object	= drm_gem_cma_free_object,
> > +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
> > +	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
> > +	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
> > +	.gem_prime_import	= drm_gem_prime_import,
> > +	.gem_prime_export	= drm_gem_prime_export,
> > +	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
> > +	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> > +	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
> > +	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
> > +	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
> > +	.dumb_create		= drm_gem_cma_dumb_create,
> > +	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
> > +	.dumb_destroy		= drm_gem_dumb_destroy,
> > +	.fops			= &fsl_dcu_drm_fops,
> > +	.name			= "fsl-dcu-drm",
> > +	.desc			= "Freescale DCU DRM",
> > +	.date			= "20150213",
> > +	.major			= 1,
> > +	.minor			= 0,
> > +};
> > +
> > +#ifdef CONFIG_PM_SLEEP
> > +static int fsl_dcu_drm_pm_suspend(struct device *dev) {
> > +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> > +
> > +	dcu_pixclk_disable();
> > +	drm_kms_helper_poll_disable(fsl_dev->ddev);
> > +	fsl_dcu_drm_crtc_suspend(&fsl_dev->crtc);
> > +
> > +	return 0;
> > +}
> > +
> > +static int fsl_dcu_drm_pm_resume(struct device *dev) {
> > +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> > +
> > +	drm_modeset_lock_all(fsl_dev->ddev);
> > +	fsl_dcu_drm_crtc_resume(&fsl_dev->crtc);
> > +	drm_modeset_unlock_all(fsl_dev->ddev);
> > +	drm_kms_helper_poll_enable(fsl_dev->ddev);
> > +	dcu_pixclk_enable();
> > +	return 0;
> > +}
> > +#endif
> > +
> > +static const struct dev_pm_ops fsl_dcu_drm_pm_ops = {
> > +	SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_drm_pm_suspend,
> > +fsl_dcu_drm_pm_resume) };
> > +
> > +static int fsl_dcu_drm_probe(struct platform_device *pdev) {
> > +	return drm_platform_init(&fsl_dcu_drm_driver, pdev); }
> > +
> > +static int fsl_dcu_drm_remove(struct platform_device *pdev) {
> > +	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
> > +
> > +	drm_put_dev(fsl_dev->ddev);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id fsl_dcu_of_match[] = {
> > +		{ .compatible = "fsl,dcu", },
> > +		{ },
> > +};
> > +MODULE_DEVICE_TABLE(of, fsl_dcu_of_match);
> > +
> > +static struct platform_driver fsl_dcu_drm_platform_driver = {
> > +	.probe		= fsl_dcu_drm_probe,
> > +	.remove		= fsl_dcu_drm_remove,
> > +	.driver		= {
> > +		.owner	= THIS_MODULE,
> > +		.name	= "fsl,dcu",
> > +		.pm	= &fsl_dcu_drm_pm_ops,
> > +		.of_match_table = fsl_dcu_of_match,
> > +	},
> > +};
> > +
> > +module_platform_driver(fsl_dcu_drm_platform_driver);
> > +
> > +MODULE_ALIAS("platform:fsl-dcu-drm");
> > +MODULE_DESCRIPTION("Freescale DCU DRM Driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> > new file mode 100644
> > index 0000000..cbdfefc
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> > @@ -0,0 +1,168 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_DRV_H__
> > +#define __FSL_DCU_DRM_DRV_H__
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/spinlock.h>
> > +#include <stddef.h>
> > +#include <drm/drm.h>
> > +#include <drm/drmP.h>
> > +#include <drm/drm_fb_helper.h>
> > +#include <drm/drm_crtc_helper.h>
> > +#include <drm/drm_gem_cma_helper.h>
> > +#include <drm/drm_fb_cma_helper.h>
> > +
> > +#include "fsl_dcu_drm_crtc.h"
> > +#include "fsl_dcu_drm_plane.h"
> > +#include "fsl_dcu_drm_connector.h"
> > +#define DRIVER_NAME			"fsl-dcu-fb"
> > +
> > +#define DCU_DCU_MODE			0x0010
> > +#define DCU_MODE_BLEND_ITER(x)		((x) << 20)
> > +#define DCU_MODE_RASTER_EN		BIT(14)
> > +#define DCU_MODE_DCU_MODE(x)		(x)
> > +#define DCU_MODE_DCU_MODE_MASK		0x03
> > +#define DCU_MODE_OFF			0
> > +#define DCU_MODE_NORMAL			1
> > +#define DCU_MODE_TEST			2
> > +#define DCU_MODE_COLORBAR		3
> > +
> > +#define DCU_BGND			0x0014
> > +#define DCU_BGND_R(x)			((x) << 16)
> > +#define DCU_BGND_G(x)			((x) << 8)
> > +#define DCU_BGND_B(x)			(x)
> > +
> > +#define DCU_DISP_SIZE			0x0018
> > +#define DCU_DISP_SIZE_DELTA_Y(x)	((x) << 16)
> > +/*Regisiter value 1/16 of horizontal resolution*/
> > +#define DCU_DISP_SIZE_DELTA_X(x)	((x) >> 4)
> > +
> > +#define DCU_HSYN_PARA			0x001c
> > +#define DCU_HSYN_PARA_BP(x)		((x) << 22)
> > +#define DCU_HSYN_PARA_PW(x)		((x) << 11)
> > +#define DCU_HSYN_PARA_FP(x)		(x)
> > +
> > +#define DCU_VSYN_PARA			0x0020
> > +#define DCU_VSYN_PARA_BP(x)		((x) << 22)
> > +#define DCU_VSYN_PARA_PW(x)		((x) << 11)
> > +#define DCU_VSYN_PARA_FP(x)		(x)
> > +
> > +#define DCU_SYN_POL			0x0024
> > +#define DCU_SYN_POL_INV_PXCK_FALL	(0 << 6)
> > +#define DCU_SYN_POL_NEG_REMAIN		(0 << 5)
> > +#define DCU_SYN_POL_INV_VS_LOW		BIT(1)
> > +#define DCU_SYN_POL_INV_HS_LOW		(1)
> > +
> > +#define DCU_THRESHOLD			0x0028
> > +#define DCU_THRESHOLD_LS_BF_VS(x)	((x) << 16)
> > +#define DCU_THRESHOLD_OUT_BUF_HIGH(x)	((x) << 8)
> > +#define DCU_THRESHOLD_OUT_BUF_LOW(x)	(x)
> > +#define BF_VS_VAL			0x03
> > +#define BUF_MAX_VAL			0x78
> > +#define BUF_MIN_VAL			0x0a
> > +
> > +#define DCU_INT_STATUS			0x002C
> > +#define DCU_INT_STATUS_UNDRUN		BIT(1)
> > +
> > +#define DCU_INT_MASK			0x0030
> > +#define DCU_INT_MASK_UNDRUN		BIT(1)
> > +#define DCU_INT_MASK_VBLANK		BIT(3)
> > +
> > +#define DCU_DIV_RATIO			0x0054
> > +
> > +#define DCU_UPDATE_MODE			0x00cc
> > +#define DCU_UPDATE_MODE_MODE		BIT(31)
> > +#define DCU_UPDATE_MODE_READREG		BIT(30)
> > +
> > +#define DCU_DCFB_MAX			0x300
> > +
> > +#define DCU_CTRLDESCLN_1(x)		(0x200 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_1_HEIGHT(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_1_WIDTH(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_2(x)		(0x204 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_2_POSY(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_2_POSX(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_3(x)		(0x208 + (x) * 0x40)
> > +
> > +#define DCU_CTRLDESCLN_4(x)		(0x20c + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_4_EN		BIT(31)
> > +#define DCU_CTRLDESCLN_4_TILE_EN	BIT(30)
> > +#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT	BIT(29)
> > +#define DCU_CTRLDESCLN_4_SAFETY_EN	BIT(28)
> > +#define DCU_CTRLDESCLN_4_TRANS(x)	((x) << 20)
> > +#define DCU_CTRLDESCLN_4_BPP(x)		((x) << 16)
> > +#define DCU_CTRLDESCLN_4_RLE_EN		BIT(15)
> > +#define DCU_CTRLDESCLN_4_LUOFFS(x)	((x) << 4)
> > +#define DCU_CTRLDESCLN_4_BB_ON		BIT(2)
> > +#define DCU_CTRLDESCLN_4_AB(x)		(x)
> > +
> > +#define DCU_CTRLDESCLN_5(x)		(0x210 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_5_CKMAX_R(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_5_CKMAX_G(x)	((x) << 8)
> > +#define DCU_CTRLDESCLN_5_CKMAX_B(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_6(x)		(0x214 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_6_CKMIN_R(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_6_CKMIN_G(x)	((x) << 8)
> > +#define DCU_CTRLDESCLN_6_CKMIN_B(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_7(x)		(0x218 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_7_TILE_VER(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_7_TILE_HOR(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_8(x)		(0x21c + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_8_FG_FCOLOR(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_9(x)		(0x220 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_9_BG_BCOLOR(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_10(x)		(0x224 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_10_POST_SKIP(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_10_PRE_SKIP(x)	(x)
> > +
> > +#define FSL_DCU_RGB565			4
> > +#define FSL_DCU_RGB888			5
> > +#define FSL_DCU_ARGB8888		6
> > +#define FSL_DCU_ARGB1555		11
> > +#define FSL_DCU_ARGB4444		12
> > +#define FSL_DCU_YUV422			14
> > +
> > +#define TCON_CTRL1			0x0000
> > +#define TCON_BYPASS_ENABLE		BIT(29)
> > +
> > +#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
> > +
> > +struct clk;
> > +struct device;
> > +struct drm_device;
> > +
> > +struct fsl_dcu_drm_device {
> > +	struct device *dev;
> > +	struct regmap *regmap;
> > +	struct regmap *tcon_regmap;
> > +	unsigned int irq;
> > +	struct clk *clk;
> > +	/*protects hardware register*/
> > +	spinlock_t irq_lock;
> > +	struct drm_device *ddev;
> > +	struct drm_fbdev_cma *fbdev;
> > +	struct fsl_dcu_drm_crtc crtc;
> > +	struct drm_encoder encoder;
> > +	struct fsl_dcu_drm_connector connector; };
> > +
> > +void fsl_dcu_fbdev_init(struct drm_device *dev);
> > +
> > +#endif /* __FSL_DCU_DRM_DRV_H__ */
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> > new file mode 100644
> > index 0000000..f8ef0e1
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> > @@ -0,0 +1,26 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * 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.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > +but WITHOUT
> > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> > +or
> > + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
> > +License for
> > + * more details.
> > + *
> > + */
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_fb_cma_helper.h>
> > +
> > +#include "fsl_dcu_drm_drv.h"
> > +
> > +/* initialize fbdev helper */
> > +void fsl_dcu_fbdev_init(struct drm_device *dev) {
> > +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
> > +
> > +	fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1); }
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> > new file mode 100644
> > index 0000000..4a840fb
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> > @@ -0,0 +1,42 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_atomic_helper.h>
> > +
> > +#include "fsl_dcu_drm_crtc.h"
> > +#include "fsl_dcu_drm_connector.h"
> > +#include "fsl_dcu_drm_drv.h"
> > +
> > +static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs
> = {
> > +	.fb_create = drm_fb_cma_create,
> > +	.atomic_check = drm_atomic_helper_check,
> > +	.atomic_commit = drm_atomic_helper_commit, };
> > +
> > +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev) {
> > +	drm_mode_config_init(fsl_dev->ddev);
> > +
> > +	fsl_dev->ddev->mode_config.min_width = 0;
> > +	fsl_dev->ddev->mode_config.min_height = 0;
> > +	fsl_dev->ddev->mode_config.max_width = 2031;
> > +	fsl_dev->ddev->mode_config.max_height = 2047;
> > +	fsl_dev->ddev->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;
> > +
> > +	drm_kms_helper_poll_init(fsl_dev->ddev);
> > +	fsl_dcu_drm_crtc_create(fsl_dev);
> > +	fsl_dcu_drm_encoder_create(fsl_dev);
> > +	fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
> > +	drm_mode_config_reset(fsl_dev->ddev);
> > +
> > +	return 0;
> > +}
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> > new file mode 100644
> > index 0000000..b9bd299
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> > @@ -0,0 +1,17 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_KMS_H__
> > +#define __FSL_DCU_DRM_KMS_H__
> > +
> > +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
> > +
> > +#endif /* __FSL_DCU_DRM_KMS_H__ */
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> > new file mode 100644
> > index 0000000..b7b4405
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> > @@ -0,0 +1,187 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_crtc.h>
> > +#include <drm/drm_crtc_helper.h>
> > +#include <drm/drm_fb_cma_helper.h>
> > +#include <drm/drm_gem_cma_helper.h>
> > +#include <linux/regmap.h>
> > +#include <drm/drm_plane_helper.h>
> > +#include <drm/drm_atomic_helper.h>
> > +
> > +#include "fsl_dcu_drm_drv.h"
> > +#include "fsl_dcu_drm_kms.h"
> > +#include "fsl_dcu_drm_plane.h"
> > +
> > +#define to_fsl_dcu_plane(plane) \
> > +	container_of(plane, struct fsl_dcu_drm_plane, plane)
> > +
> > +static int
> > +fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
> > +			     struct drm_framebuffer *fb,
> > +			     const struct drm_plane_state *new_state) {
> > +	return 0;
> > +}
> > +
> > +static void
> > +fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
> > +			     struct drm_framebuffer *fb,
> > +			     const struct drm_plane_state *new_state) { }
> > +
> > +static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
> > +					  struct drm_plane_state *state) {
> > +	return 0;
> > +}
> > +
> > +static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
> > +					     struct drm_plane_state *old_state) { }
> > +
> > +void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
> > +				     struct drm_plane_state *old_state) {
> > +	struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
> > +	struct drm_plane_state *state = plane->state;
> > +	struct drm_framebuffer *fb = plane->state->fb;
> > +	u32 index, alpha, bpp;
> > +	struct drm_gem_cma_object *gem;
> > +	struct fsl_dcu_drm_plane *fsl_plane = to_fsl_dcu_plane(plane);
> > +
> > +	index = fsl_plane->index;
> > +	gem = drm_fb_cma_get_gem_obj(fb, 0);
> > +
> > +	switch (fb->pixel_format) {
> > +	case DRM_FORMAT_RGB565:
> > +		bpp = FSL_DCU_RGB565;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_RGB888:
> > +		bpp = FSL_DCU_RGB888;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_ARGB8888:
> > +		bpp = FSL_DCU_ARGB8888;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_BGRA4444:
> > +		bpp = FSL_DCU_ARGB4444;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_ARGB1555:
> > +		bpp = FSL_DCU_ARGB1555;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_YUV422:
> > +		bpp = FSL_DCU_YUV422;
> > +		alpha = 0xff;
> > +		break;
> > +	default:
> > +		return;
> > +	}
> > +
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_1(index),
> > +		     DCU_CTRLDESCLN_1_HEIGHT(state->crtc_h) |
> > +		     DCU_CTRLDESCLN_1_WIDTH(state->crtc_w));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_2(index),
> > +		     DCU_CTRLDESCLN_2_POSY(state->crtc_y) |
> > +		     DCU_CTRLDESCLN_2_POSX(state->crtc_x));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_3(index), gem->paddr);
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_4(index),
> > +		     DCU_CTRLDESCLN_4_EN |
> > +		     DCU_CTRLDESCLN_4_TRANS(alpha) |
> > +		     DCU_CTRLDESCLN_4_BPP(bpp) |
> > +		     DCU_CTRLDESCLN_4_AB(2));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_5(index),
> > +		     DCU_CTRLDESCLN_5_CKMAX_R(0xFF) |
> > +		     DCU_CTRLDESCLN_5_CKMAX_G(0xFF) |
> > +		     DCU_CTRLDESCLN_5_CKMAX_B(0xFF));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_6(index),
> > +		     DCU_CTRLDESCLN_6_CKMIN_R(0) |
> > +		     DCU_CTRLDESCLN_6_CKMIN_G(0) |
> > +		     DCU_CTRLDESCLN_6_CKMIN_B(0));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_8(index),
> > +		     DCU_CTRLDESCLN_8_FG_FCOLOR(0));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_9(index),
> > +		     DCU_CTRLDESCLN_9_BG_BCOLOR(0));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_10(index),
> > +		     DCU_CTRLDESCLN_10_POST_SKIP(0) |
> > +		     DCU_CTRLDESCLN_10_PRE_SKIP(0));
> > +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
> > +DCU_UPDATE_MODE_READREG); }
> > +
> > +int fsl_dcu_drm_plane_disable(struct drm_plane *plane) {
> > +	return 0;
> > +}
> > +
> > +void fsl_dcu_drm_plane_destroy(struct drm_plane *plane) {
> > +	fsl_dcu_drm_plane_disable(plane);
> > +	drm_plane_cleanup(plane);
> > +}
> > +
> > +static const uint32_t fsl_dcu_drm_plane_formats[] = {
> > +	DRM_FORMAT_RGB565,
> > +	DRM_FORMAT_RGB888,
> > +	DRM_FORMAT_ARGB8888,
> > +	DRM_FORMAT_ARGB4444,
> > +	DRM_FORMAT_ARGB1555,
> > +	DRM_FORMAT_YUV422,
> > +};
> > +
> > +static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
> > +	.update_plane = drm_plane_helper_update,
> > +	.disable_plane = drm_plane_helper_disable,
> > +	.destroy = fsl_dcu_drm_plane_destroy,
> > +	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> > +	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> > +	.reset = drm_atomic_helper_plane_reset, };
> > +
> > +static const struct drm_plane_helper_funcs
> fsl_dcu_drm_plane_helper_funcs = {
> > +	.prepare_fb = fsl_dcu_drm_plane_prepare_fb,
> > +	.cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
> > +	.atomic_check = fsl_dcu_drm_plane_atomic_check,
> > +	.atomic_update = fsl_dcu_drm_plane_atomic_update,
> > +	.atomic_disable = fsl_dcu_drm_plane_atomic_disable, };
> > +
> > +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device
> > +*dev) {
> > +	struct drm_plane *primary;
> > +	int ret;
> > +
> > +	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> > +	if (!primary) {
> > +		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
> > +		return NULL;
> > +	}
> > +
> > +	/* possible_crtc's will be filled in later by crtc_init */
> > +	ret = drm_universal_plane_init(dev, primary, 0,
> > +				       &fsl_dcu_drm_plane_funcs,
> > +				       fsl_dcu_drm_plane_formats,
> > +				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
> > +				       DRM_PLANE_TYPE_PRIMARY);
> > +	if (ret) {
> > +		kfree(primary);
> > +		primary = NULL;
> > +	}
> > +	drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
> > +
> > +	return primary;
> > +}
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> > new file mode 100644
> > index 0000000..ccbfa61
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> > @@ -0,0 +1,23 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_PLANE_H__
> > +#define __FSL_DCU_DRM_PLANE_H__
> > +
> > +struct fsl_dcu_drm_device;
> > +struct fsl_dcu_drm_plane {
> > +	struct drm_plane plane;
> > +	unsigned int index;
> > +};
> > +
> > +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device
> > +*dev);
> > +
> > +#endif /* __FSL_DCU_DRM_PLANE_H__ */
> > diff --git a/include/linux/fsl/dcu.h b/include/linux/fsl/dcu.h new
> > file mode 100644 index 0000000..1873057
> > --- /dev/null
> > +++ b/include/linux/fsl/dcu.h
> > @@ -0,0 +1,22 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_H__
> > +#define __FSL_DCU_H__
> > +
> > +#define SCFG_PIXCLKCR			0x28
> > +#define PXCK_ENABLE			BIT(31)
> > +#define PXCK_DISABLE			0
> > +
> > +void dcu_pixclk_enable(void);
> > +void dcu_pixclk_disable(void);
> > +
> > +#endif /* __FSL_DCU_H__ */
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

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

* [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
@ 2015-03-19  1:41     ` Jianwei.Wang at freescale.com
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei.Wang at freescale.com @ 2015-03-19  1:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Stefan,

Thank you for your comment. I'll correct this next time.


> -----Original Message-----
> From: Stefan Agner [mailto:stefan at agner.ch]
> Sent: Thursday, March 19, 2015 6:58 AM
> To: Wang Jianwei-B52261
> Cc: Wood Scott-B07421; airlied at linux.ie; jbarnes at virtuousgeek.org; dri-
> devel at lists.freedesktop.org; Xiubo Li; Wang Huan-B18965; linux-
> kernel at vger.kernel.org; Jin Zhengxiong-R64188; linux-arm-
> kernel at lists.infradead.org
> Subject: Re: [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
> 
> Hi Jianwei,
> 
> Normally, for the second and higher iteration of a patchset, developers
> add the version to the subject (e.g. PATCH v2). You can use the --reroll-
> count option when creating the patches with git format-patch.
> 
> On 2015-03-13 10:44, Jianwei Wang wrote:
> > This patch add support for Two Dimensional Animation and Compositing
> > Engine (2D-ACE) on Freescale SoCs.
> >
> > 2D-ACE is a Freescale display controller. It provide an hardware
> > cursor.
> >
> > This is a simplified version, only a primary plane, a fb created for
> > fbdev, a crtc, a connector for TFT LCD panel, an encoder, and the
> > encoder is not in use.
> >
> > Signed-off-by: Alison Wang <b18965@freescale.com>
> > Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> > Signed-off-by: Jianwei Wang <b52261@freescale.com>
> > ---
> >
> > Changed in v2:
> > - Add atomic support
> > - Modify bindings file
> > - Rename node for compatibility
> > - Move platform related code out for compatibility
> >
> > Added in v1:
> > -?Add support for DCU display controller on the Freescale LS102x SoCs.
> > - Create a primary plane, a fb created for fbdev, a crtc, a connector
> > for TFT LCD panel, an encoder.
> >
> >  arch/arm/mach-imx/mach-ls1021a.c            |  36 ++++
> >  drivers/gpu/drm/Kconfig                     |   2 +
> >  drivers/gpu/drm/Makefile                    |   1 +
> >  drivers/gpu/drm/fsl/Kconfig                 |  17 ++
> >  drivers/gpu/drm/fsl/Makefile                |   8 +
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c | 203
> > ++++++++++++++++++++  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h |  28
> +++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c      | 164 ++++++++++++++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h      |  26 +++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c       | 288
> ++++++++++++++++++++++++++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h       | 168 ++++++++++++++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c     |  26 +++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c       |  42 ++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h       |  17 ++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c     | 187 ++++++++++++++++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h     |  23 +++
> >  include/linux/fsl/dcu.h                     |  22 +++
> >  17 files changed, 1258 insertions(+)
> >  create mode 100644 drivers/gpu/drm/fsl/Kconfig  create mode 100644
> > drivers/gpu/drm/fsl/Makefile  create mode 100644
> > drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> >  create mode 100644 include/linux/fsl/dcu.h
> >
> > diff --git a/arch/arm/mach-imx/mach-ls1021a.c
> > b/arch/arm/mach-imx/mach-ls1021a.c
> > index b89c858..4fb346d 100644
> > --- a/arch/arm/mach-imx/mach-ls1021a.c
> > +++ b/arch/arm/mach-imx/mach-ls1021a.c
> > @@ -8,9 +8,44 @@
> >   */
> >
> >  #include <asm/mach/arch.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/regmap.h>
> > +#include <linux/fsl/dcu.h>
> >
> >  #include "common.h"
> >
> > +void dcu_pixclk_disable(void)
> > +{
> > +	struct regmap *scfg_regmap;
> > +
> > +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> > +	if (IS_ERR(scfg_regmap)) {
> > +		pr_err("No syscfg phandle specified\n");
> > +		return;
> > +	}
> > +
> > +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_DISABLE); }
> > +
> > +void dcu_pixclk_enable(void)
> > +{
> > +	struct regmap *scfg_regmap;
> > +
> > +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> > +	if (IS_ERR(scfg_regmap)) {
> > +		pr_err("No syscfg phandle specified\n");
> > +		return;
> > +	}
> > +
> > +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_ENABLE); }
> > +
> > +static void __init ls1021a_init_machine(void) {
> > +	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> > +	dcu_pixclk_enable();
> > +}
> 
> This change should be in a separate patch. However, I'm not convinced that
> the current code is the right solution. You should try to avoid calling
> from the driver directly into arch code.
> 
> I don't have access to the reference manual, hence I can't lookup that
> module. But this register looks just like a clock gate...
> 
> On Vybrid, the Pixelclock is enabled through CCM_CSCDR3 and friends, and
> the CCM module makes use of the common clock framework. In the end, the
> clock is assigned to the nodes (e.g. DCU node in this case) and requested
> during runtime. The framework makes sure the clock and the relevant gates
> get enabled. See:
> http://lxr.free-electrons.com/source/arch/arm/mach-imx/clk-
> vf610.c?v=3.12#L241
> 
> --
> Stefan
> 
> >  static const char * const ls1021a_dt_compat[] __initconst = {
> >  	"fsl,ls1021a",
> >  	NULL,
> > @@ -18,5 +53,6 @@ static const char * const ls1021a_dt_compat[]
> > __initconst = {
> >
> >  DT_MACHINE_START(LS1021A, "Freescale LS1021A")
> >  	.smp		= smp_ops(ls1021a_smp_ops),
> > +	.init_machine	= ls1021a_init_machine,
> >  	.dt_compat	= ls1021a_dt_compat,
> >  MACHINE_END
> > diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index
> > 151a050..a6957aa 100644
> > --- a/drivers/gpu/drm/Kconfig
> > +++ b/drivers/gpu/drm/Kconfig
> > @@ -199,6 +199,8 @@ source "drivers/gpu/drm/bochs/Kconfig"
> >
> >  source "drivers/gpu/drm/msm/Kconfig"
> >
> > +source "drivers/gpu/drm/fsl/Kconfig"
> > +
> >  source "drivers/gpu/drm/tegra/Kconfig"
> >
> >  source "drivers/gpu/drm/panel/Kconfig"
> > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index
> > 2c239b9..ab5b9ef 100644
> > --- a/drivers/gpu/drm/Makefile
> > +++ b/drivers/gpu/drm/Makefile
> > @@ -56,6 +56,7 @@ obj-$(CONFIG_DRM_UDL) += udl/
> >  obj-$(CONFIG_DRM_AST) += ast/
> >  obj-$(CONFIG_DRM_ARMADA) += armada/
> >  obj-$(CONFIG_DRM_ATMEL_HLCDC)	+= atmel-hlcdc/
> > +obj-$(CONFIG_DRM_FSL_DCU) += fsl/
> >  obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
> >  obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
> >  obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
> > diff --git a/drivers/gpu/drm/fsl/Kconfig b/drivers/gpu/drm/fsl/Kconfig
> > new file mode 100644 index 0000000..e4f8df0
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/Kconfig
> > @@ -0,0 +1,17 @@
> > +config DRM_FSL_DCU
> > +	tristate "DRM Support for Freescale DCU"
> > +	depends on DRM && OF && ARM
> > +	select DRM_KMS_HELPER
> > +	select DRM_KMS_CMA_HELPER
> > +	select VIDEOMODE_HELPERS
> > +	select BACKLIGHT_CLASS_DEVICE
> > +	select BACKLIGHT_LCD_SUPPORT
> > +	select REGMAP_MMIO
> > +	select DRM_KMS_FB_HELPER
> > +	select FB_SYS_FILLRECT
> > +	select FB_SYS_COPYAREA
> > +	select FB_SYS_IMAGEBLIT
> > +	select FB_SYS_FOPS
> > +	help
> > +	  Choose this option if you have an Freescale DCU chipset.
> > +	  If M is selected the module will be called fsl-dcu-drm.
> > diff --git a/drivers/gpu/drm/fsl/Makefile
> > b/drivers/gpu/drm/fsl/Makefile new file mode 100644 index
> > 0000000..5f74aee
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/Makefile
> > @@ -0,0 +1,8 @@
> > +fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
> > +	       fsl_dcu_drm_kms.o \
> > +	       fsl_dcu_drm_connector.o \
> > +	       fsl_dcu_drm_plane.o \
> > +	       fsl_dcu_drm_crtc.o \
> > +	       fsl_dcu_drm_fbdev.o \
> > +
> > +obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> > new file mode 100644
> > index 0000000..178d647
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> > @@ -0,0 +1,203 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <linux/backlight.h>
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_atomic_helper.h>
> > +#include <video/of_display_timing.h>
> > +
> > +#include "fsl_dcu_drm_drv.h"
> > +#include "fsl_dcu_drm_connector.h"
> > +
> > +static void fsl_dcu_drm_encoder_dpms(struct drm_encoder *encoder, int
> > +mode) { }
> > +
> > +/* Disable the encoders as the first thing we do. */ static void
> > +fsl_dcu_drm_encoder_mode_prepare(struct drm_encoder *encoder) { }
> > +
> > +static void fsl_dcu_drm_encoder_mode_set(struct drm_encoder *encoder,
> > +					 struct drm_display_mode *mode,
> > +					 struct drm_display_mode *adjusted_mode) { }
> > +
> > +static void fsl_dcu_drm_encoder_mode_commit(struct drm_encoder
> > +*encoder) { }
> > +
> > +static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
> > +{ }
> > +
> > +static int
> > +fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
> > +				 struct drm_crtc_state *crtc_state,
> > +				 struct drm_connector_state *conn_state) {
> > +	return 0;
> > +}
> > +
> > +static bool
> > +fsl_dcu_drm_encoder_mode_fixup(struct drm_encoder *encoder,
> > +			       const struct drm_display_mode *mode,
> > +			       struct drm_display_mode *adjusted_mode) {
> > +	return true;
> > +}
> > +
> > +static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
> > +{
> > +	drm_encoder_cleanup(encoder);
> > +}
> > +
> > +static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
> > +	.dpms = fsl_dcu_drm_encoder_dpms,
> > +	.prepare = fsl_dcu_drm_encoder_mode_prepare,
> > +	.commit = fsl_dcu_drm_encoder_mode_commit,
> > +	.mode_set = fsl_dcu_drm_encoder_mode_set,
> > +	.disable = fsl_dcu_drm_encoder_disable,
> > +	.atomic_check = fsl_dcu_drm_encoder_atomic_check,
> > +	.mode_fixup = fsl_dcu_drm_encoder_mode_fixup, };
> > +
> > +static const struct drm_encoder_funcs encoder_funcs = {
> > +	.destroy = fsl_dcu_drm_encoder_destroy, };
> > +
> > +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev) {
> > +	struct drm_encoder *encoder = &fsl_dev->encoder;
> > +	int ret;
> > +
> > +	encoder->possible_crtcs = 1;
> > +
> > +	ret = drm_encoder_init(fsl_dev->ddev, encoder, &encoder_funcs,
> > +			       DRM_MODE_ENCODER_LVDS);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
> > +
> > +	return 0;
> > +}
> > +
> > +#define to_fsl_dcu_connector(connector) \
> > +	container_of(connector, struct fsl_dcu_drm_connector, connector)
> > +
> > +static int fsl_dcu_drm_connector_get_modes(struct drm_connector
> > +*connector) {
> > +	struct drm_device *dev = connector->dev;
> > +	struct device_node *display_np, *np = dev->dev->of_node;
> > +	struct drm_display_mode *mode = drm_mode_create(connector->dev);
> > +	int num_modes = 0;
> > +
> > +	if (np) {
> > +		display_np = of_parse_phandle(np, "display", 0);
> > +		if (!display_np) {
> > +			dev_err(dev->dev, "failed to find display phandle\n");
> > +			return num_modes;
> > +		}
> > +		of_get_drm_display_mode(display_np, mode, OF_USE_NATIVE_MODE);
> > +		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> > +		drm_mode_probed_add(connector, mode);
> > +		num_modes++;
> > +	}
> > +
> > +	return num_modes;
> > +}
> > +
> > +static int fsl_dcu_drm_connector_mode_valid(struct drm_connector
> *connector,
> > +					    struct drm_display_mode *mode) {
> > +	return MODE_OK;
> > +}
> > +
> > +static struct drm_encoder *
> > +fsl_dcu_drm_connector_best_encoder(struct drm_connector *connector) {
> > +	struct fsl_dcu_drm_connector *fsl_con =
> > +to_fsl_dcu_connector(connector);
> > +
> > +	return fsl_con->encoder;
> > +}
> > +
> > +static void fsl_dcu_drm_connector_destroy(struct drm_connector
> > +*connector) {
> > +	drm_connector_unregister(connector);
> > +	drm_connector_cleanup(connector);
> > +}
> > +
> > +static enum drm_connector_status
> > +fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool
> > +force) {
> > +	return connector_status_connected;
> > +}
> > +
> > +static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
> > +	.dpms = drm_atomic_helper_connector_dpms,
> > +	.reset = drm_atomic_helper_connector_reset,
> > +	.detect = fsl_dcu_drm_connector_detect,
> > +	.fill_modes = drm_helper_probe_single_connector_modes,
> > +	.destroy = fsl_dcu_drm_connector_destroy,
> > +	.atomic_duplicate_state =
> drm_atomic_helper_connector_duplicate_state,
> > +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> > +};
> > +
> > +static const struct drm_connector_helper_funcs connector_helper_funcs =
> {
> > +	.get_modes = fsl_dcu_drm_connector_get_modes,
> > +	.mode_valid = fsl_dcu_drm_connector_mode_valid,
> > +	.best_encoder = fsl_dcu_drm_connector_best_encoder,
> > +};
> > +
> > +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> > +				 struct drm_encoder *encoder)
> > +{
> > +	struct drm_connector *connector = &fsl_dev->connector.connector;
> > +	int ret;
> > +
> > +	fsl_dev->connector.encoder = encoder;
> > +
> > +	connector->display_info.width_mm = 0;
> > +	connector->display_info.height_mm = 0;
> > +
> > +	ret = drm_connector_init(fsl_dev->ddev, connector,
> > +				 &fsl_dcu_drm_connector_funcs,
> > +				 DRM_MODE_CONNECTOR_LVDS);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	connector->dpms = DRM_MODE_DPMS_OFF;
> > +	drm_connector_helper_add(connector, &connector_helper_funcs);
> > +	ret = drm_connector_register(connector);
> > +	if (ret < 0)
> > +		goto err_cleanup;
> > +
> > +	ret = drm_mode_connector_attach_encoder(connector, encoder);
> > +	if (ret < 0)
> > +		goto err_sysfs;
> > +
> > +	connector->encoder = encoder;
> > +
> > +	drm_object_property_set_value
> > +		(&connector->base, fsl_dev->ddev->mode_config.dpms_property,
> > +		DRM_MODE_DPMS_OFF);
> > +
> > +	return 0;
> > +
> > +err_sysfs:
> > +	drm_connector_unregister(connector);
> > +err_cleanup:
> > +	drm_connector_cleanup(connector);
> > +	return ret;
> > +}
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> > new file mode 100644
> > index 0000000..afe44ab
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> > @@ -0,0 +1,28 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_CONNECTOR_H__
> > +#define __FSL_DCU_DRM_CONNECTOR_H__
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_crtc.h>
> > +
> > +struct fsl_dcu_drm_device;
> > +struct fsl_dcu_drm_connector {
> > +	struct drm_connector connector;
> > +	struct drm_encoder *encoder;
> > +};
> > +
> > +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev);
> > +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> > +				 struct drm_encoder *encoder);
> > +
> > +#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> > new file mode 100644
> > index 0000000..a43e7ce
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> > @@ -0,0 +1,164 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <linux/regmap.h>
> > +#include <linux/clk.h>
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_atomic.h>
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_crtc.h>
> > +
> > +#include "fsl_dcu_drm_crtc.h"
> > +#include "fsl_dcu_drm_drv.h"
> > +#include "fsl_dcu_drm_plane.h"
> > +
> > +#define to_fsl_dcu_crtc(c)	container_of(c, struct fsl_dcu_drm_crtc,
> crtc)
> > +
> > +void fsl_dcu_drm_crtc_suspend(struct drm_crtc *crtc) { }
> > +
> > +static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) {
> > +	struct drm_device *dev = crtc->dev;
> > +	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
> > +	struct drm_display_mode *mode = &crtc->state->mode;
> > +	uint32_t hbp, hfp, hsw, vbp, vfp, vsw, div, index;
> > +
> > +	DBG(": set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
> > +	    mode->base.id, mode->name,
> > +	    mode->vrefresh, mode->clock,
> > +	    mode->hdisplay, mode->hsync_start,
> > +	    mode->hsync_end, mode->htotal,
> > +	    mode->vdisplay, mode->vsync_start,
> > +	    mode->vsync_end, mode->vtotal,
> > +	    mode->type, mode->flags);
> > +
> > +	index = drm_crtc_index(crtc);
> > +	div = (uint32_t)clk_get_rate(fsl_dev->clk) / mode->clock / 1000;
> > +
> > +	/* Configure timings: */
> > +	hbp = mode->htotal - mode->hsync_end;
> > +	hfp = mode->hsync_start - mode->hdisplay;
> > +	hsw = mode->hsync_end - mode->hsync_start;
> > +	vbp = mode->vtotal - mode->vsync_end;
> > +	vfp = mode->vsync_start - mode->vdisplay;
> > +	vsw = mode->vsync_end - mode->vsync_start;
> > +
> > +	regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
> > +		     DCU_HSYN_PARA_BP(hbp) |
> > +		     DCU_HSYN_PARA_PW(hsw) |
> > +		     DCU_HSYN_PARA_FP(hfp));
> > +	regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
> > +		     DCU_VSYN_PARA_BP(vbp) |
> > +		     DCU_VSYN_PARA_PW(vsw) |
> > +		     DCU_VSYN_PARA_FP(vfp));
> > +	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
> > +		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
> > +		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
> > +	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
> > +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
> > +DCU_UPDATE_MODE_READREG); }
> > +
> > +static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
> > +					const struct drm_display_mode *mode,
> > +					struct drm_display_mode *adjusted_mode) {
> > +	return true;
> > +}
> > +
> > +static void fsl_dcu_drm_crtc_prepare(struct drm_crtc *crtc) { }
> > +
> > +/* Now enable the clocks, plane, pipe, and connectors that we set up.
> > +*/ static void fsl_dcu_drm_crtc_mode_commit(struct drm_crtc *crtc) {
> > +}
> > +
> > +static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
> > +					 struct drm_crtc_state *state)
> > +{
> > +	return 0;
> > +}
> > +
> > +static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc) { }
> > +
> > +static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc) { }
> > +
> > +static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc) { }
> > +
> > +static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
> > +	.page_flip = drm_atomic_helper_page_flip,
> > +	.set_config = drm_crtc_helper_set_config,
> > +	.destroy = drm_crtc_cleanup,
> > +	.reset = drm_atomic_helper_crtc_reset,
> > +	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> > +	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> > +};
> > +
> > +static void fsl_dcu_drm_crtc_dpms(struct drm_crtc *crtc, int mode) {
> > +}
> > +
> > +static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs
> = {
> > +	.disable = fsl_dcu_drm_disable_crtc,
> > +	.mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
> > +	.mode_set = drm_helper_crtc_mode_set,
> > +	.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
> > +	.mode_set_base = drm_helper_crtc_mode_set_base,
> > +	.prepare = fsl_dcu_drm_crtc_prepare,
> > +	.commit = fsl_dcu_drm_crtc_mode_commit,
> > +	.atomic_check = fsl_dcu_drm_crtc_atomic_check,
> > +	.atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
> > +	.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
> > +	.dpms = fsl_dcu_drm_crtc_dpms,
> > +};
> > +
> > +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev) {
> > +	struct drm_plane *primary;
> > +	struct drm_crtc *crtc = &fsl_dev->crtc.crtc;
> > +	int ret;
> > +
> > +	fsl_dev->crtc.dpms = DRM_MODE_DPMS_OFF;
> > +
> > +	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->ddev);
> > +	ret = drm_crtc_init_with_planes(fsl_dev->ddev, crtc, primary, NULL,
> > +					&fsl_dcu_drm_crtc_funcs);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
> > +
> > +	regmap_write(fsl_dev->regmap, DCU_SYN_POL,
> > +		     DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
> > +	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
> > +		     DCU_BGND_G(0) | DCU_BGND_B(0));
> > +	regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
> > +		     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
> > +	regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
> > +		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
> > +		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
> > +		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
> > +	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
> > +			   DCU_MODE_DCU_MODE_MASK,
> > +			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
> > +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
> DCU_UPDATE_MODE_READREG);
> > +	return 0;
> > +}
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> > new file mode 100644
> > index 0000000..d44b564
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> > @@ -0,0 +1,26 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_CRTC_H__
> > +#define __FSL_DCU_DRM_CRTC_H__
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_crtc.h>
> > +
> > +struct fsl_dcu_drm_device;
> > +struct fsl_dcu_drm_crtc {
> > +	struct drm_crtc crtc;
> > +	int dpms;
> > +};
> > +
> > +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev);
> > +
> > +#endif /* __FSL_DCU_DRM_CRTC_H__ */
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> > new file mode 100644
> > index 0000000..10975ee
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> > @@ -0,0 +1,288 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/io.h>
> > +#include <linux/mm.h>
> > +#include <linux/module.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/pm.h>
> > +#include <linux/pm_runtime.h>
> > +#include <linux/regmap.h>
> > +
> > +#include <drm/drmP.h>
> > +#include <linux/fsl/dcu.h>
> > +
> > +#include "fsl_dcu_drm_drv.h"
> > +#include "fsl_dcu_drm_kms.h"
> > +
> > +static int fsl_dcu_unload(struct drm_device *dev) {
> > +	drm_mode_config_cleanup(dev);
> > +	drm_vblank_cleanup(dev);
> > +	drm_irq_uninstall(dev);
> > +
> > +	dev->dev_private = NULL;
> > +
> > +	return 0;
> > +}
> > +
> > +static struct regmap_config fsl_dcu_regmap_config = {
> > +	.reg_bits = 32,
> > +	.reg_stride = 4,
> > +	.val_bits = 32,
> > +};
> > +
> > +static int fsl_dcu_bypass_tcon(struct fsl_dcu_drm_device *fsl_dev,
> > +			       struct device_node *np)
> > +{
> > +	struct device_node *tcon_np;
> > +	struct platform_device *pdev;
> > +	struct clk *tcon_clk;
> > +	struct resource *res;
> > +	void __iomem *base;
> > +
> > +	tcon_np = of_parse_phandle(np, "tcon-controller", 0);
> > +	if (!tcon_np)
> > +		return -EINVAL;
> > +
> > +	pdev = of_find_device_by_node(tcon_np);
> > +	if (!pdev)
> > +		return -EINVAL;
> > +
> > +	tcon_clk = devm_clk_get(&pdev->dev, "tcon");
> > +	if (IS_ERR(tcon_clk))
> > +		return PTR_ERR(tcon_clk);
> > +	clk_prepare_enable(tcon_clk);
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	if (!res)
> > +		return -ENODEV;
> > +
> > +	base = devm_ioremap_resource(&pdev->dev, res);
> > +	if (IS_ERR(base))
> > +		return PTR_ERR(base);
> > +
> > +	fsl_dev->tcon_regmap = devm_regmap_init_mmio_clk(&pdev->dev,
> > +			"tcon", base, &fsl_dcu_regmap_config);
> > +	if (IS_ERR(fsl_dev->tcon_regmap)) {
> > +		dev_err(&pdev->dev, "regmap init failed\n");
> > +		return PTR_ERR(fsl_dev->tcon_regmap);
> > +	}
> > +
> > +	regmap_write(fsl_dev->tcon_regmap, TCON_CTRL1, TCON_BYPASS_ENABLE);
> > +	return 0;
> > +}
> > +
> > +static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
> > +{
> > +	struct platform_device *pdev = dev->platformdev;
> > +	struct fsl_dcu_drm_device *fsl_dev;
> > +	struct resource *res;
> > +	void __iomem *base;
> > +	int ret;
> > +
> > +	fsl_dev = devm_kzalloc(&pdev->dev, sizeof(*fsl_dev), GFP_KERNEL);
> > +	if (!fsl_dev)
> > +		return -ENOMEM;
> > +
> > +	fsl_dev->dev = &pdev->dev;
> > +	fsl_dev->ddev = dev;
> > +	dev->dev_private = fsl_dev;
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	base = devm_ioremap_resource(&pdev->dev, res);
> > +	if (IS_ERR(base)) {
> > +		ret = PTR_ERR(base);
> > +		return ret;
> > +	}
> > +
> > +	fsl_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
> > +			base, &fsl_dcu_regmap_config);
> > +	if (IS_ERR(fsl_dev->regmap)) {
> > +		dev_err(&pdev->dev, "regmap init failed\n");
> > +		return PTR_ERR(fsl_dev->regmap);
> > +	}
> > +
> > +	ret = fsl_dcu_drm_modeset_init(fsl_dev);
> > +	if (ret < 0) {
> > +		dev_err(&pdev->dev, "failed to initialize mode setting\n");
> > +		return ret;
> > +	}
> > +
> > +	ret = drm_vblank_init(dev, 1);
> > +	if (ret < 0) {
> > +		dev_err(&pdev->dev, "failed to initialize vblank\n");
> > +		goto done;
> > +	}
> > +
> > +	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
> > +	if (ret < 0) {
> > +		dev_err(&pdev->dev, "failed to install IRQ handler\n");
> > +		goto done;
> > +	}
> > +
> > +	/* Put TCON in bypass mode, so the input signals from DCU are passed
> > +	 * through TCON unchanged */
> > +	fsl_dcu_bypass_tcon(fsl_dev, pdev->dev.of_node);
> > +
> > +	fsl_dev->clk = devm_clk_get(&pdev->dev, "dcu");
> > +	if (IS_ERR(fsl_dev->clk)) {
> > +		ret = PTR_ERR(fsl_dev->clk);
> > +		dev_err(&pdev->dev, "could not get clock\n");
> > +		return ret;
> > +	}
> > +	clk_prepare_enable(fsl_dev->clk);
> > +
> > +	dev_set_drvdata(dev->dev, fsl_dev);
> > +
> > +	fsl_dcu_fbdev_init(dev);
> > +
> > +	return 0;
> > +done:
> > +	if (ret)
> > +		fsl_dcu_unload(dev);
> > +
> > +	return ret;
> > +}
> > +
> > +static void fsl_dcu_drm_preclose(struct drm_device *dev, struct
> > +drm_file *file) {
> > +	;
> > +}
> > +
> > +static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg) {
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int
> > +crtc) {
> > +	return 0;
> > +}
> > +
> > +static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int
> > +crtc) {
> > +	;
> > +}
> > +
> > +static const struct file_operations fsl_dcu_drm_fops = {
> > +	.owner		= THIS_MODULE,
> > +	.open		= drm_open,
> > +	.release	= drm_release,
> > +	.unlocked_ioctl	= drm_ioctl,
> > +#ifdef CONFIG_COMPAT
> > +	.compat_ioctl	= drm_compat_ioctl,
> > +#endif
> > +	.poll		= drm_poll,
> > +	.read		= drm_read,
> > +	.llseek		= no_llseek,
> > +	.mmap		= drm_gem_cma_mmap,
> > +};
> > +
> > +static struct drm_driver fsl_dcu_drm_driver = {
> > +	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
> > +				| DRIVER_PRIME,
> > +	.load			= fsl_dcu_load,
> > +	.unload			= fsl_dcu_unload,
> > +	.preclose		= fsl_dcu_drm_preclose,
> > +	.irq_handler		= fsl_dcu_drm_irq,
> > +	.get_vblank_counter	= drm_vblank_count,
> > +	.enable_vblank		= fsl_dcu_drm_enable_vblank,
> > +	.disable_vblank		= fsl_dcu_drm_disable_vblank,
> > +	.gem_free_object	= drm_gem_cma_free_object,
> > +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
> > +	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
> > +	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
> > +	.gem_prime_import	= drm_gem_prime_import,
> > +	.gem_prime_export	= drm_gem_prime_export,
> > +	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
> > +	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> > +	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
> > +	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
> > +	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
> > +	.dumb_create		= drm_gem_cma_dumb_create,
> > +	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
> > +	.dumb_destroy		= drm_gem_dumb_destroy,
> > +	.fops			= &fsl_dcu_drm_fops,
> > +	.name			= "fsl-dcu-drm",
> > +	.desc			= "Freescale DCU DRM",
> > +	.date			= "20150213",
> > +	.major			= 1,
> > +	.minor			= 0,
> > +};
> > +
> > +#ifdef CONFIG_PM_SLEEP
> > +static int fsl_dcu_drm_pm_suspend(struct device *dev) {
> > +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> > +
> > +	dcu_pixclk_disable();
> > +	drm_kms_helper_poll_disable(fsl_dev->ddev);
> > +	fsl_dcu_drm_crtc_suspend(&fsl_dev->crtc);
> > +
> > +	return 0;
> > +}
> > +
> > +static int fsl_dcu_drm_pm_resume(struct device *dev) {
> > +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> > +
> > +	drm_modeset_lock_all(fsl_dev->ddev);
> > +	fsl_dcu_drm_crtc_resume(&fsl_dev->crtc);
> > +	drm_modeset_unlock_all(fsl_dev->ddev);
> > +	drm_kms_helper_poll_enable(fsl_dev->ddev);
> > +	dcu_pixclk_enable();
> > +	return 0;
> > +}
> > +#endif
> > +
> > +static const struct dev_pm_ops fsl_dcu_drm_pm_ops = {
> > +	SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_drm_pm_suspend,
> > +fsl_dcu_drm_pm_resume) };
> > +
> > +static int fsl_dcu_drm_probe(struct platform_device *pdev) {
> > +	return drm_platform_init(&fsl_dcu_drm_driver, pdev); }
> > +
> > +static int fsl_dcu_drm_remove(struct platform_device *pdev) {
> > +	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
> > +
> > +	drm_put_dev(fsl_dev->ddev);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id fsl_dcu_of_match[] = {
> > +		{ .compatible = "fsl,dcu", },
> > +		{ },
> > +};
> > +MODULE_DEVICE_TABLE(of, fsl_dcu_of_match);
> > +
> > +static struct platform_driver fsl_dcu_drm_platform_driver = {
> > +	.probe		= fsl_dcu_drm_probe,
> > +	.remove		= fsl_dcu_drm_remove,
> > +	.driver		= {
> > +		.owner	= THIS_MODULE,
> > +		.name	= "fsl,dcu",
> > +		.pm	= &fsl_dcu_drm_pm_ops,
> > +		.of_match_table = fsl_dcu_of_match,
> > +	},
> > +};
> > +
> > +module_platform_driver(fsl_dcu_drm_platform_driver);
> > +
> > +MODULE_ALIAS("platform:fsl-dcu-drm");
> > +MODULE_DESCRIPTION("Freescale DCU DRM Driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> > new file mode 100644
> > index 0000000..cbdfefc
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> > @@ -0,0 +1,168 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_DRV_H__
> > +#define __FSL_DCU_DRM_DRV_H__
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/spinlock.h>
> > +#include <stddef.h>
> > +#include <drm/drm.h>
> > +#include <drm/drmP.h>
> > +#include <drm/drm_fb_helper.h>
> > +#include <drm/drm_crtc_helper.h>
> > +#include <drm/drm_gem_cma_helper.h>
> > +#include <drm/drm_fb_cma_helper.h>
> > +
> > +#include "fsl_dcu_drm_crtc.h"
> > +#include "fsl_dcu_drm_plane.h"
> > +#include "fsl_dcu_drm_connector.h"
> > +#define DRIVER_NAME			"fsl-dcu-fb"
> > +
> > +#define DCU_DCU_MODE			0x0010
> > +#define DCU_MODE_BLEND_ITER(x)		((x) << 20)
> > +#define DCU_MODE_RASTER_EN		BIT(14)
> > +#define DCU_MODE_DCU_MODE(x)		(x)
> > +#define DCU_MODE_DCU_MODE_MASK		0x03
> > +#define DCU_MODE_OFF			0
> > +#define DCU_MODE_NORMAL			1
> > +#define DCU_MODE_TEST			2
> > +#define DCU_MODE_COLORBAR		3
> > +
> > +#define DCU_BGND			0x0014
> > +#define DCU_BGND_R(x)			((x) << 16)
> > +#define DCU_BGND_G(x)			((x) << 8)
> > +#define DCU_BGND_B(x)			(x)
> > +
> > +#define DCU_DISP_SIZE			0x0018
> > +#define DCU_DISP_SIZE_DELTA_Y(x)	((x) << 16)
> > +/*Regisiter value 1/16 of horizontal resolution*/
> > +#define DCU_DISP_SIZE_DELTA_X(x)	((x) >> 4)
> > +
> > +#define DCU_HSYN_PARA			0x001c
> > +#define DCU_HSYN_PARA_BP(x)		((x) << 22)
> > +#define DCU_HSYN_PARA_PW(x)		((x) << 11)
> > +#define DCU_HSYN_PARA_FP(x)		(x)
> > +
> > +#define DCU_VSYN_PARA			0x0020
> > +#define DCU_VSYN_PARA_BP(x)		((x) << 22)
> > +#define DCU_VSYN_PARA_PW(x)		((x) << 11)
> > +#define DCU_VSYN_PARA_FP(x)		(x)
> > +
> > +#define DCU_SYN_POL			0x0024
> > +#define DCU_SYN_POL_INV_PXCK_FALL	(0 << 6)
> > +#define DCU_SYN_POL_NEG_REMAIN		(0 << 5)
> > +#define DCU_SYN_POL_INV_VS_LOW		BIT(1)
> > +#define DCU_SYN_POL_INV_HS_LOW		(1)
> > +
> > +#define DCU_THRESHOLD			0x0028
> > +#define DCU_THRESHOLD_LS_BF_VS(x)	((x) << 16)
> > +#define DCU_THRESHOLD_OUT_BUF_HIGH(x)	((x) << 8)
> > +#define DCU_THRESHOLD_OUT_BUF_LOW(x)	(x)
> > +#define BF_VS_VAL			0x03
> > +#define BUF_MAX_VAL			0x78
> > +#define BUF_MIN_VAL			0x0a
> > +
> > +#define DCU_INT_STATUS			0x002C
> > +#define DCU_INT_STATUS_UNDRUN		BIT(1)
> > +
> > +#define DCU_INT_MASK			0x0030
> > +#define DCU_INT_MASK_UNDRUN		BIT(1)
> > +#define DCU_INT_MASK_VBLANK		BIT(3)
> > +
> > +#define DCU_DIV_RATIO			0x0054
> > +
> > +#define DCU_UPDATE_MODE			0x00cc
> > +#define DCU_UPDATE_MODE_MODE		BIT(31)
> > +#define DCU_UPDATE_MODE_READREG		BIT(30)
> > +
> > +#define DCU_DCFB_MAX			0x300
> > +
> > +#define DCU_CTRLDESCLN_1(x)		(0x200 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_1_HEIGHT(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_1_WIDTH(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_2(x)		(0x204 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_2_POSY(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_2_POSX(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_3(x)		(0x208 + (x) * 0x40)
> > +
> > +#define DCU_CTRLDESCLN_4(x)		(0x20c + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_4_EN		BIT(31)
> > +#define DCU_CTRLDESCLN_4_TILE_EN	BIT(30)
> > +#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT	BIT(29)
> > +#define DCU_CTRLDESCLN_4_SAFETY_EN	BIT(28)
> > +#define DCU_CTRLDESCLN_4_TRANS(x)	((x) << 20)
> > +#define DCU_CTRLDESCLN_4_BPP(x)		((x) << 16)
> > +#define DCU_CTRLDESCLN_4_RLE_EN		BIT(15)
> > +#define DCU_CTRLDESCLN_4_LUOFFS(x)	((x) << 4)
> > +#define DCU_CTRLDESCLN_4_BB_ON		BIT(2)
> > +#define DCU_CTRLDESCLN_4_AB(x)		(x)
> > +
> > +#define DCU_CTRLDESCLN_5(x)		(0x210 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_5_CKMAX_R(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_5_CKMAX_G(x)	((x) << 8)
> > +#define DCU_CTRLDESCLN_5_CKMAX_B(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_6(x)		(0x214 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_6_CKMIN_R(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_6_CKMIN_G(x)	((x) << 8)
> > +#define DCU_CTRLDESCLN_6_CKMIN_B(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_7(x)		(0x218 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_7_TILE_VER(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_7_TILE_HOR(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_8(x)		(0x21c + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_8_FG_FCOLOR(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_9(x)		(0x220 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_9_BG_BCOLOR(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_10(x)		(0x224 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_10_POST_SKIP(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_10_PRE_SKIP(x)	(x)
> > +
> > +#define FSL_DCU_RGB565			4
> > +#define FSL_DCU_RGB888			5
> > +#define FSL_DCU_ARGB8888		6
> > +#define FSL_DCU_ARGB1555		11
> > +#define FSL_DCU_ARGB4444		12
> > +#define FSL_DCU_YUV422			14
> > +
> > +#define TCON_CTRL1			0x0000
> > +#define TCON_BYPASS_ENABLE		BIT(29)
> > +
> > +#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
> > +
> > +struct clk;
> > +struct device;
> > +struct drm_device;
> > +
> > +struct fsl_dcu_drm_device {
> > +	struct device *dev;
> > +	struct regmap *regmap;
> > +	struct regmap *tcon_regmap;
> > +	unsigned int irq;
> > +	struct clk *clk;
> > +	/*protects hardware register*/
> > +	spinlock_t irq_lock;
> > +	struct drm_device *ddev;
> > +	struct drm_fbdev_cma *fbdev;
> > +	struct fsl_dcu_drm_crtc crtc;
> > +	struct drm_encoder encoder;
> > +	struct fsl_dcu_drm_connector connector; };
> > +
> > +void fsl_dcu_fbdev_init(struct drm_device *dev);
> > +
> > +#endif /* __FSL_DCU_DRM_DRV_H__ */
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> > new file mode 100644
> > index 0000000..f8ef0e1
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> > @@ -0,0 +1,26 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * 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.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > +but WITHOUT
> > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> > +or
> > + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
> > +License for
> > + * more details.
> > + *
> > + */
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_fb_cma_helper.h>
> > +
> > +#include "fsl_dcu_drm_drv.h"
> > +
> > +/* initialize fbdev helper */
> > +void fsl_dcu_fbdev_init(struct drm_device *dev) {
> > +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
> > +
> > +	fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1); }
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> > new file mode 100644
> > index 0000000..4a840fb
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> > @@ -0,0 +1,42 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_atomic_helper.h>
> > +
> > +#include "fsl_dcu_drm_crtc.h"
> > +#include "fsl_dcu_drm_connector.h"
> > +#include "fsl_dcu_drm_drv.h"
> > +
> > +static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs
> = {
> > +	.fb_create = drm_fb_cma_create,
> > +	.atomic_check = drm_atomic_helper_check,
> > +	.atomic_commit = drm_atomic_helper_commit, };
> > +
> > +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev) {
> > +	drm_mode_config_init(fsl_dev->ddev);
> > +
> > +	fsl_dev->ddev->mode_config.min_width = 0;
> > +	fsl_dev->ddev->mode_config.min_height = 0;
> > +	fsl_dev->ddev->mode_config.max_width = 2031;
> > +	fsl_dev->ddev->mode_config.max_height = 2047;
> > +	fsl_dev->ddev->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;
> > +
> > +	drm_kms_helper_poll_init(fsl_dev->ddev);
> > +	fsl_dcu_drm_crtc_create(fsl_dev);
> > +	fsl_dcu_drm_encoder_create(fsl_dev);
> > +	fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
> > +	drm_mode_config_reset(fsl_dev->ddev);
> > +
> > +	return 0;
> > +}
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> > new file mode 100644
> > index 0000000..b9bd299
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> > @@ -0,0 +1,17 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_KMS_H__
> > +#define __FSL_DCU_DRM_KMS_H__
> > +
> > +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
> > +
> > +#endif /* __FSL_DCU_DRM_KMS_H__ */
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> > new file mode 100644
> > index 0000000..b7b4405
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> > @@ -0,0 +1,187 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_crtc.h>
> > +#include <drm/drm_crtc_helper.h>
> > +#include <drm/drm_fb_cma_helper.h>
> > +#include <drm/drm_gem_cma_helper.h>
> > +#include <linux/regmap.h>
> > +#include <drm/drm_plane_helper.h>
> > +#include <drm/drm_atomic_helper.h>
> > +
> > +#include "fsl_dcu_drm_drv.h"
> > +#include "fsl_dcu_drm_kms.h"
> > +#include "fsl_dcu_drm_plane.h"
> > +
> > +#define to_fsl_dcu_plane(plane) \
> > +	container_of(plane, struct fsl_dcu_drm_plane, plane)
> > +
> > +static int
> > +fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
> > +			     struct drm_framebuffer *fb,
> > +			     const struct drm_plane_state *new_state) {
> > +	return 0;
> > +}
> > +
> > +static void
> > +fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
> > +			     struct drm_framebuffer *fb,
> > +			     const struct drm_plane_state *new_state) { }
> > +
> > +static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
> > +					  struct drm_plane_state *state) {
> > +	return 0;
> > +}
> > +
> > +static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
> > +					     struct drm_plane_state *old_state) { }
> > +
> > +void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
> > +				     struct drm_plane_state *old_state) {
> > +	struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
> > +	struct drm_plane_state *state = plane->state;
> > +	struct drm_framebuffer *fb = plane->state->fb;
> > +	u32 index, alpha, bpp;
> > +	struct drm_gem_cma_object *gem;
> > +	struct fsl_dcu_drm_plane *fsl_plane = to_fsl_dcu_plane(plane);
> > +
> > +	index = fsl_plane->index;
> > +	gem = drm_fb_cma_get_gem_obj(fb, 0);
> > +
> > +	switch (fb->pixel_format) {
> > +	case DRM_FORMAT_RGB565:
> > +		bpp = FSL_DCU_RGB565;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_RGB888:
> > +		bpp = FSL_DCU_RGB888;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_ARGB8888:
> > +		bpp = FSL_DCU_ARGB8888;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_BGRA4444:
> > +		bpp = FSL_DCU_ARGB4444;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_ARGB1555:
> > +		bpp = FSL_DCU_ARGB1555;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_YUV422:
> > +		bpp = FSL_DCU_YUV422;
> > +		alpha = 0xff;
> > +		break;
> > +	default:
> > +		return;
> > +	}
> > +
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_1(index),
> > +		     DCU_CTRLDESCLN_1_HEIGHT(state->crtc_h) |
> > +		     DCU_CTRLDESCLN_1_WIDTH(state->crtc_w));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_2(index),
> > +		     DCU_CTRLDESCLN_2_POSY(state->crtc_y) |
> > +		     DCU_CTRLDESCLN_2_POSX(state->crtc_x));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_3(index), gem->paddr);
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_4(index),
> > +		     DCU_CTRLDESCLN_4_EN |
> > +		     DCU_CTRLDESCLN_4_TRANS(alpha) |
> > +		     DCU_CTRLDESCLN_4_BPP(bpp) |
> > +		     DCU_CTRLDESCLN_4_AB(2));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_5(index),
> > +		     DCU_CTRLDESCLN_5_CKMAX_R(0xFF) |
> > +		     DCU_CTRLDESCLN_5_CKMAX_G(0xFF) |
> > +		     DCU_CTRLDESCLN_5_CKMAX_B(0xFF));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_6(index),
> > +		     DCU_CTRLDESCLN_6_CKMIN_R(0) |
> > +		     DCU_CTRLDESCLN_6_CKMIN_G(0) |
> > +		     DCU_CTRLDESCLN_6_CKMIN_B(0));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_8(index),
> > +		     DCU_CTRLDESCLN_8_FG_FCOLOR(0));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_9(index),
> > +		     DCU_CTRLDESCLN_9_BG_BCOLOR(0));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_10(index),
> > +		     DCU_CTRLDESCLN_10_POST_SKIP(0) |
> > +		     DCU_CTRLDESCLN_10_PRE_SKIP(0));
> > +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
> > +DCU_UPDATE_MODE_READREG); }
> > +
> > +int fsl_dcu_drm_plane_disable(struct drm_plane *plane) {
> > +	return 0;
> > +}
> > +
> > +void fsl_dcu_drm_plane_destroy(struct drm_plane *plane) {
> > +	fsl_dcu_drm_plane_disable(plane);
> > +	drm_plane_cleanup(plane);
> > +}
> > +
> > +static const uint32_t fsl_dcu_drm_plane_formats[] = {
> > +	DRM_FORMAT_RGB565,
> > +	DRM_FORMAT_RGB888,
> > +	DRM_FORMAT_ARGB8888,
> > +	DRM_FORMAT_ARGB4444,
> > +	DRM_FORMAT_ARGB1555,
> > +	DRM_FORMAT_YUV422,
> > +};
> > +
> > +static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
> > +	.update_plane = drm_plane_helper_update,
> > +	.disable_plane = drm_plane_helper_disable,
> > +	.destroy = fsl_dcu_drm_plane_destroy,
> > +	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> > +	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> > +	.reset = drm_atomic_helper_plane_reset, };
> > +
> > +static const struct drm_plane_helper_funcs
> fsl_dcu_drm_plane_helper_funcs = {
> > +	.prepare_fb = fsl_dcu_drm_plane_prepare_fb,
> > +	.cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
> > +	.atomic_check = fsl_dcu_drm_plane_atomic_check,
> > +	.atomic_update = fsl_dcu_drm_plane_atomic_update,
> > +	.atomic_disable = fsl_dcu_drm_plane_atomic_disable, };
> > +
> > +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device
> > +*dev) {
> > +	struct drm_plane *primary;
> > +	int ret;
> > +
> > +	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> > +	if (!primary) {
> > +		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
> > +		return NULL;
> > +	}
> > +
> > +	/* possible_crtc's will be filled in later by crtc_init */
> > +	ret = drm_universal_plane_init(dev, primary, 0,
> > +				       &fsl_dcu_drm_plane_funcs,
> > +				       fsl_dcu_drm_plane_formats,
> > +				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
> > +				       DRM_PLANE_TYPE_PRIMARY);
> > +	if (ret) {
> > +		kfree(primary);
> > +		primary = NULL;
> > +	}
> > +	drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
> > +
> > +	return primary;
> > +}
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> > new file mode 100644
> > index 0000000..ccbfa61
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> > @@ -0,0 +1,23 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_PLANE_H__
> > +#define __FSL_DCU_DRM_PLANE_H__
> > +
> > +struct fsl_dcu_drm_device;
> > +struct fsl_dcu_drm_plane {
> > +	struct drm_plane plane;
> > +	unsigned int index;
> > +};
> > +
> > +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device
> > +*dev);
> > +
> > +#endif /* __FSL_DCU_DRM_PLANE_H__ */
> > diff --git a/include/linux/fsl/dcu.h b/include/linux/fsl/dcu.h new
> > file mode 100644 index 0000000..1873057
> > --- /dev/null
> > +++ b/include/linux/fsl/dcu.h
> > @@ -0,0 +1,22 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_H__
> > +#define __FSL_DCU_H__
> > +
> > +#define SCFG_PIXCLKCR			0x28
> > +#define PXCK_ENABLE			BIT(31)
> > +#define PXCK_DISABLE			0
> > +
> > +void dcu_pixclk_enable(void);
> > +void dcu_pixclk_disable(void);
> > +
> > +#endif /* __FSL_DCU_H__ */
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
@ 2015-03-19  1:41     ` Jianwei.Wang at freescale.com
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei.Wang @ 2015-03-19  1:41 UTC (permalink / raw)
  To: Stefan Agner
  Cc: Scott Wood, airlied, jbarnes, dri-devel, Xiubo Li, Huan Wang,
	linux-kernel, Jason.Jin, linux-arm-kernel

Hi Stefan,

Thank you for your comment. I'll correct this next time.


> -----Original Message-----
> From: Stefan Agner [mailto:stefan@agner.ch]
> Sent: Thursday, March 19, 2015 6:58 AM
> To: Wang Jianwei-B52261
> Cc: Wood Scott-B07421; airlied@linux.ie; jbarnes@virtuousgeek.org; dri-
> devel@lists.freedesktop.org; Xiubo Li; Wang Huan-B18965; linux-
> kernel@vger.kernel.org; Jin Zhengxiong-R64188; linux-arm-
> kernel@lists.infradead.org
> Subject: Re: [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
> 
> Hi Jianwei,
> 
> Normally, for the second and higher iteration of a patchset, developers
> add the version to the subject (e.g. PATCH v2). You can use the --reroll-
> count option when creating the patches with git format-patch.
> 
> On 2015-03-13 10:44, Jianwei Wang wrote:
> > This patch add support for Two Dimensional Animation and Compositing
> > Engine (2D-ACE) on Freescale SoCs.
> >
> > 2D-ACE is a Freescale display controller. It provide an hardware
> > cursor.
> >
> > This is a simplified version, only a primary plane, a fb created for
> > fbdev, a crtc, a connector for TFT LCD panel, an encoder, and the
> > encoder is not in use.
> >
> > Signed-off-by: Alison Wang <b18965@freescale.com>
> > Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> > Signed-off-by: Jianwei Wang <b52261@freescale.com>
> > ---
> >
> > Changed in v2:
> > - Add atomic support
> > - Modify bindings file
> > - Rename node for compatibility
> > - Move platform related code out for compatibility
> >
> > Added in v1:
> > - Add support for DCU display controller on the Freescale LS102x SoCs.
> > - Create a primary plane, a fb created for fbdev, a crtc, a connector
> > for TFT LCD panel, an encoder.
> >
> >  arch/arm/mach-imx/mach-ls1021a.c            |  36 ++++
> >  drivers/gpu/drm/Kconfig                     |   2 +
> >  drivers/gpu/drm/Makefile                    |   1 +
> >  drivers/gpu/drm/fsl/Kconfig                 |  17 ++
> >  drivers/gpu/drm/fsl/Makefile                |   8 +
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c | 203
> > ++++++++++++++++++++  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h |  28
> +++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c      | 164 ++++++++++++++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h      |  26 +++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c       | 288
> ++++++++++++++++++++++++++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h       | 168 ++++++++++++++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c     |  26 +++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c       |  42 ++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h       |  17 ++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c     | 187 ++++++++++++++++++
> >  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h     |  23 +++
> >  include/linux/fsl/dcu.h                     |  22 +++
> >  17 files changed, 1258 insertions(+)
> >  create mode 100644 drivers/gpu/drm/fsl/Kconfig  create mode 100644
> > drivers/gpu/drm/fsl/Makefile  create mode 100644
> > drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> >  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> >  create mode 100644 include/linux/fsl/dcu.h
> >
> > diff --git a/arch/arm/mach-imx/mach-ls1021a.c
> > b/arch/arm/mach-imx/mach-ls1021a.c
> > index b89c858..4fb346d 100644
> > --- a/arch/arm/mach-imx/mach-ls1021a.c
> > +++ b/arch/arm/mach-imx/mach-ls1021a.c
> > @@ -8,9 +8,44 @@
> >   */
> >
> >  #include <asm/mach/arch.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/regmap.h>
> > +#include <linux/fsl/dcu.h>
> >
> >  #include "common.h"
> >
> > +void dcu_pixclk_disable(void)
> > +{
> > +	struct regmap *scfg_regmap;
> > +
> > +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> > +	if (IS_ERR(scfg_regmap)) {
> > +		pr_err("No syscfg phandle specified\n");
> > +		return;
> > +	}
> > +
> > +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_DISABLE); }
> > +
> > +void dcu_pixclk_enable(void)
> > +{
> > +	struct regmap *scfg_regmap;
> > +
> > +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> > +	if (IS_ERR(scfg_regmap)) {
> > +		pr_err("No syscfg phandle specified\n");
> > +		return;
> > +	}
> > +
> > +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_ENABLE); }
> > +
> > +static void __init ls1021a_init_machine(void) {
> > +	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> > +	dcu_pixclk_enable();
> > +}
> 
> This change should be in a separate patch. However, I'm not convinced that
> the current code is the right solution. You should try to avoid calling
> from the driver directly into arch code.
> 
> I don't have access to the reference manual, hence I can't lookup that
> module. But this register looks just like a clock gate...
> 
> On Vybrid, the Pixelclock is enabled through CCM_CSCDR3 and friends, and
> the CCM module makes use of the common clock framework. In the end, the
> clock is assigned to the nodes (e.g. DCU node in this case) and requested
> during runtime. The framework makes sure the clock and the relevant gates
> get enabled. See:
> http://lxr.free-electrons.com/source/arch/arm/mach-imx/clk-
> vf610.c?v=3.12#L241
> 
> --
> Stefan
> 
> >  static const char * const ls1021a_dt_compat[] __initconst = {
> >  	"fsl,ls1021a",
> >  	NULL,
> > @@ -18,5 +53,6 @@ static const char * const ls1021a_dt_compat[]
> > __initconst = {
> >
> >  DT_MACHINE_START(LS1021A, "Freescale LS1021A")
> >  	.smp		= smp_ops(ls1021a_smp_ops),
> > +	.init_machine	= ls1021a_init_machine,
> >  	.dt_compat	= ls1021a_dt_compat,
> >  MACHINE_END
> > diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index
> > 151a050..a6957aa 100644
> > --- a/drivers/gpu/drm/Kconfig
> > +++ b/drivers/gpu/drm/Kconfig
> > @@ -199,6 +199,8 @@ source "drivers/gpu/drm/bochs/Kconfig"
> >
> >  source "drivers/gpu/drm/msm/Kconfig"
> >
> > +source "drivers/gpu/drm/fsl/Kconfig"
> > +
> >  source "drivers/gpu/drm/tegra/Kconfig"
> >
> >  source "drivers/gpu/drm/panel/Kconfig"
> > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index
> > 2c239b9..ab5b9ef 100644
> > --- a/drivers/gpu/drm/Makefile
> > +++ b/drivers/gpu/drm/Makefile
> > @@ -56,6 +56,7 @@ obj-$(CONFIG_DRM_UDL) += udl/
> >  obj-$(CONFIG_DRM_AST) += ast/
> >  obj-$(CONFIG_DRM_ARMADA) += armada/
> >  obj-$(CONFIG_DRM_ATMEL_HLCDC)	+= atmel-hlcdc/
> > +obj-$(CONFIG_DRM_FSL_DCU) += fsl/
> >  obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
> >  obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
> >  obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
> > diff --git a/drivers/gpu/drm/fsl/Kconfig b/drivers/gpu/drm/fsl/Kconfig
> > new file mode 100644 index 0000000..e4f8df0
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/Kconfig
> > @@ -0,0 +1,17 @@
> > +config DRM_FSL_DCU
> > +	tristate "DRM Support for Freescale DCU"
> > +	depends on DRM && OF && ARM
> > +	select DRM_KMS_HELPER
> > +	select DRM_KMS_CMA_HELPER
> > +	select VIDEOMODE_HELPERS
> > +	select BACKLIGHT_CLASS_DEVICE
> > +	select BACKLIGHT_LCD_SUPPORT
> > +	select REGMAP_MMIO
> > +	select DRM_KMS_FB_HELPER
> > +	select FB_SYS_FILLRECT
> > +	select FB_SYS_COPYAREA
> > +	select FB_SYS_IMAGEBLIT
> > +	select FB_SYS_FOPS
> > +	help
> > +	  Choose this option if you have an Freescale DCU chipset.
> > +	  If M is selected the module will be called fsl-dcu-drm.
> > diff --git a/drivers/gpu/drm/fsl/Makefile
> > b/drivers/gpu/drm/fsl/Makefile new file mode 100644 index
> > 0000000..5f74aee
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/Makefile
> > @@ -0,0 +1,8 @@
> > +fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
> > +	       fsl_dcu_drm_kms.o \
> > +	       fsl_dcu_drm_connector.o \
> > +	       fsl_dcu_drm_plane.o \
> > +	       fsl_dcu_drm_crtc.o \
> > +	       fsl_dcu_drm_fbdev.o \
> > +
> > +obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> > new file mode 100644
> > index 0000000..178d647
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> > @@ -0,0 +1,203 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <linux/backlight.h>
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_atomic_helper.h>
> > +#include <video/of_display_timing.h>
> > +
> > +#include "fsl_dcu_drm_drv.h"
> > +#include "fsl_dcu_drm_connector.h"
> > +
> > +static void fsl_dcu_drm_encoder_dpms(struct drm_encoder *encoder, int
> > +mode) { }
> > +
> > +/* Disable the encoders as the first thing we do. */ static void
> > +fsl_dcu_drm_encoder_mode_prepare(struct drm_encoder *encoder) { }
> > +
> > +static void fsl_dcu_drm_encoder_mode_set(struct drm_encoder *encoder,
> > +					 struct drm_display_mode *mode,
> > +					 struct drm_display_mode *adjusted_mode) { }
> > +
> > +static void fsl_dcu_drm_encoder_mode_commit(struct drm_encoder
> > +*encoder) { }
> > +
> > +static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
> > +{ }
> > +
> > +static int
> > +fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
> > +				 struct drm_crtc_state *crtc_state,
> > +				 struct drm_connector_state *conn_state) {
> > +	return 0;
> > +}
> > +
> > +static bool
> > +fsl_dcu_drm_encoder_mode_fixup(struct drm_encoder *encoder,
> > +			       const struct drm_display_mode *mode,
> > +			       struct drm_display_mode *adjusted_mode) {
> > +	return true;
> > +}
> > +
> > +static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
> > +{
> > +	drm_encoder_cleanup(encoder);
> > +}
> > +
> > +static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
> > +	.dpms = fsl_dcu_drm_encoder_dpms,
> > +	.prepare = fsl_dcu_drm_encoder_mode_prepare,
> > +	.commit = fsl_dcu_drm_encoder_mode_commit,
> > +	.mode_set = fsl_dcu_drm_encoder_mode_set,
> > +	.disable = fsl_dcu_drm_encoder_disable,
> > +	.atomic_check = fsl_dcu_drm_encoder_atomic_check,
> > +	.mode_fixup = fsl_dcu_drm_encoder_mode_fixup, };
> > +
> > +static const struct drm_encoder_funcs encoder_funcs = {
> > +	.destroy = fsl_dcu_drm_encoder_destroy, };
> > +
> > +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev) {
> > +	struct drm_encoder *encoder = &fsl_dev->encoder;
> > +	int ret;
> > +
> > +	encoder->possible_crtcs = 1;
> > +
> > +	ret = drm_encoder_init(fsl_dev->ddev, encoder, &encoder_funcs,
> > +			       DRM_MODE_ENCODER_LVDS);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
> > +
> > +	return 0;
> > +}
> > +
> > +#define to_fsl_dcu_connector(connector) \
> > +	container_of(connector, struct fsl_dcu_drm_connector, connector)
> > +
> > +static int fsl_dcu_drm_connector_get_modes(struct drm_connector
> > +*connector) {
> > +	struct drm_device *dev = connector->dev;
> > +	struct device_node *display_np, *np = dev->dev->of_node;
> > +	struct drm_display_mode *mode = drm_mode_create(connector->dev);
> > +	int num_modes = 0;
> > +
> > +	if (np) {
> > +		display_np = of_parse_phandle(np, "display", 0);
> > +		if (!display_np) {
> > +			dev_err(dev->dev, "failed to find display phandle\n");
> > +			return num_modes;
> > +		}
> > +		of_get_drm_display_mode(display_np, mode, OF_USE_NATIVE_MODE);
> > +		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> > +		drm_mode_probed_add(connector, mode);
> > +		num_modes++;
> > +	}
> > +
> > +	return num_modes;
> > +}
> > +
> > +static int fsl_dcu_drm_connector_mode_valid(struct drm_connector
> *connector,
> > +					    struct drm_display_mode *mode) {
> > +	return MODE_OK;
> > +}
> > +
> > +static struct drm_encoder *
> > +fsl_dcu_drm_connector_best_encoder(struct drm_connector *connector) {
> > +	struct fsl_dcu_drm_connector *fsl_con =
> > +to_fsl_dcu_connector(connector);
> > +
> > +	return fsl_con->encoder;
> > +}
> > +
> > +static void fsl_dcu_drm_connector_destroy(struct drm_connector
> > +*connector) {
> > +	drm_connector_unregister(connector);
> > +	drm_connector_cleanup(connector);
> > +}
> > +
> > +static enum drm_connector_status
> > +fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool
> > +force) {
> > +	return connector_status_connected;
> > +}
> > +
> > +static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
> > +	.dpms = drm_atomic_helper_connector_dpms,
> > +	.reset = drm_atomic_helper_connector_reset,
> > +	.detect = fsl_dcu_drm_connector_detect,
> > +	.fill_modes = drm_helper_probe_single_connector_modes,
> > +	.destroy = fsl_dcu_drm_connector_destroy,
> > +	.atomic_duplicate_state =
> drm_atomic_helper_connector_duplicate_state,
> > +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> > +};
> > +
> > +static const struct drm_connector_helper_funcs connector_helper_funcs =
> {
> > +	.get_modes = fsl_dcu_drm_connector_get_modes,
> > +	.mode_valid = fsl_dcu_drm_connector_mode_valid,
> > +	.best_encoder = fsl_dcu_drm_connector_best_encoder,
> > +};
> > +
> > +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> > +				 struct drm_encoder *encoder)
> > +{
> > +	struct drm_connector *connector = &fsl_dev->connector.connector;
> > +	int ret;
> > +
> > +	fsl_dev->connector.encoder = encoder;
> > +
> > +	connector->display_info.width_mm = 0;
> > +	connector->display_info.height_mm = 0;
> > +
> > +	ret = drm_connector_init(fsl_dev->ddev, connector,
> > +				 &fsl_dcu_drm_connector_funcs,
> > +				 DRM_MODE_CONNECTOR_LVDS);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	connector->dpms = DRM_MODE_DPMS_OFF;
> > +	drm_connector_helper_add(connector, &connector_helper_funcs);
> > +	ret = drm_connector_register(connector);
> > +	if (ret < 0)
> > +		goto err_cleanup;
> > +
> > +	ret = drm_mode_connector_attach_encoder(connector, encoder);
> > +	if (ret < 0)
> > +		goto err_sysfs;
> > +
> > +	connector->encoder = encoder;
> > +
> > +	drm_object_property_set_value
> > +		(&connector->base, fsl_dev->ddev->mode_config.dpms_property,
> > +		DRM_MODE_DPMS_OFF);
> > +
> > +	return 0;
> > +
> > +err_sysfs:
> > +	drm_connector_unregister(connector);
> > +err_cleanup:
> > +	drm_connector_cleanup(connector);
> > +	return ret;
> > +}
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> > new file mode 100644
> > index 0000000..afe44ab
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> > @@ -0,0 +1,28 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_CONNECTOR_H__
> > +#define __FSL_DCU_DRM_CONNECTOR_H__
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_crtc.h>
> > +
> > +struct fsl_dcu_drm_device;
> > +struct fsl_dcu_drm_connector {
> > +	struct drm_connector connector;
> > +	struct drm_encoder *encoder;
> > +};
> > +
> > +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev);
> > +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> > +				 struct drm_encoder *encoder);
> > +
> > +#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> > new file mode 100644
> > index 0000000..a43e7ce
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> > @@ -0,0 +1,164 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <linux/regmap.h>
> > +#include <linux/clk.h>
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_atomic.h>
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_crtc.h>
> > +
> > +#include "fsl_dcu_drm_crtc.h"
> > +#include "fsl_dcu_drm_drv.h"
> > +#include "fsl_dcu_drm_plane.h"
> > +
> > +#define to_fsl_dcu_crtc(c)	container_of(c, struct fsl_dcu_drm_crtc,
> crtc)
> > +
> > +void fsl_dcu_drm_crtc_suspend(struct drm_crtc *crtc) { }
> > +
> > +static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) {
> > +	struct drm_device *dev = crtc->dev;
> > +	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
> > +	struct drm_display_mode *mode = &crtc->state->mode;
> > +	uint32_t hbp, hfp, hsw, vbp, vfp, vsw, div, index;
> > +
> > +	DBG(": set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
> > +	    mode->base.id, mode->name,
> > +	    mode->vrefresh, mode->clock,
> > +	    mode->hdisplay, mode->hsync_start,
> > +	    mode->hsync_end, mode->htotal,
> > +	    mode->vdisplay, mode->vsync_start,
> > +	    mode->vsync_end, mode->vtotal,
> > +	    mode->type, mode->flags);
> > +
> > +	index = drm_crtc_index(crtc);
> > +	div = (uint32_t)clk_get_rate(fsl_dev->clk) / mode->clock / 1000;
> > +
> > +	/* Configure timings: */
> > +	hbp = mode->htotal - mode->hsync_end;
> > +	hfp = mode->hsync_start - mode->hdisplay;
> > +	hsw = mode->hsync_end - mode->hsync_start;
> > +	vbp = mode->vtotal - mode->vsync_end;
> > +	vfp = mode->vsync_start - mode->vdisplay;
> > +	vsw = mode->vsync_end - mode->vsync_start;
> > +
> > +	regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
> > +		     DCU_HSYN_PARA_BP(hbp) |
> > +		     DCU_HSYN_PARA_PW(hsw) |
> > +		     DCU_HSYN_PARA_FP(hfp));
> > +	regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
> > +		     DCU_VSYN_PARA_BP(vbp) |
> > +		     DCU_VSYN_PARA_PW(vsw) |
> > +		     DCU_VSYN_PARA_FP(vfp));
> > +	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
> > +		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
> > +		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
> > +	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
> > +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
> > +DCU_UPDATE_MODE_READREG); }
> > +
> > +static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
> > +					const struct drm_display_mode *mode,
> > +					struct drm_display_mode *adjusted_mode) {
> > +	return true;
> > +}
> > +
> > +static void fsl_dcu_drm_crtc_prepare(struct drm_crtc *crtc) { }
> > +
> > +/* Now enable the clocks, plane, pipe, and connectors that we set up.
> > +*/ static void fsl_dcu_drm_crtc_mode_commit(struct drm_crtc *crtc) {
> > +}
> > +
> > +static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
> > +					 struct drm_crtc_state *state)
> > +{
> > +	return 0;
> > +}
> > +
> > +static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc) { }
> > +
> > +static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc) { }
> > +
> > +static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc) { }
> > +
> > +static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
> > +	.page_flip = drm_atomic_helper_page_flip,
> > +	.set_config = drm_crtc_helper_set_config,
> > +	.destroy = drm_crtc_cleanup,
> > +	.reset = drm_atomic_helper_crtc_reset,
> > +	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> > +	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> > +};
> > +
> > +static void fsl_dcu_drm_crtc_dpms(struct drm_crtc *crtc, int mode) {
> > +}
> > +
> > +static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs
> = {
> > +	.disable = fsl_dcu_drm_disable_crtc,
> > +	.mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
> > +	.mode_set = drm_helper_crtc_mode_set,
> > +	.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
> > +	.mode_set_base = drm_helper_crtc_mode_set_base,
> > +	.prepare = fsl_dcu_drm_crtc_prepare,
> > +	.commit = fsl_dcu_drm_crtc_mode_commit,
> > +	.atomic_check = fsl_dcu_drm_crtc_atomic_check,
> > +	.atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
> > +	.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
> > +	.dpms = fsl_dcu_drm_crtc_dpms,
> > +};
> > +
> > +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev) {
> > +	struct drm_plane *primary;
> > +	struct drm_crtc *crtc = &fsl_dev->crtc.crtc;
> > +	int ret;
> > +
> > +	fsl_dev->crtc.dpms = DRM_MODE_DPMS_OFF;
> > +
> > +	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->ddev);
> > +	ret = drm_crtc_init_with_planes(fsl_dev->ddev, crtc, primary, NULL,
> > +					&fsl_dcu_drm_crtc_funcs);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
> > +
> > +	regmap_write(fsl_dev->regmap, DCU_SYN_POL,
> > +		     DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
> > +	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
> > +		     DCU_BGND_G(0) | DCU_BGND_B(0));
> > +	regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
> > +		     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
> > +	regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
> > +		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
> > +		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
> > +		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
> > +	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
> > +			   DCU_MODE_DCU_MODE_MASK,
> > +			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
> > +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
> DCU_UPDATE_MODE_READREG);
> > +	return 0;
> > +}
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> > new file mode 100644
> > index 0000000..d44b564
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> > @@ -0,0 +1,26 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_CRTC_H__
> > +#define __FSL_DCU_DRM_CRTC_H__
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_crtc.h>
> > +
> > +struct fsl_dcu_drm_device;
> > +struct fsl_dcu_drm_crtc {
> > +	struct drm_crtc crtc;
> > +	int dpms;
> > +};
> > +
> > +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev);
> > +
> > +#endif /* __FSL_DCU_DRM_CRTC_H__ */
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> > new file mode 100644
> > index 0000000..10975ee
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> > @@ -0,0 +1,288 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/io.h>
> > +#include <linux/mm.h>
> > +#include <linux/module.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/pm.h>
> > +#include <linux/pm_runtime.h>
> > +#include <linux/regmap.h>
> > +
> > +#include <drm/drmP.h>
> > +#include <linux/fsl/dcu.h>
> > +
> > +#include "fsl_dcu_drm_drv.h"
> > +#include "fsl_dcu_drm_kms.h"
> > +
> > +static int fsl_dcu_unload(struct drm_device *dev) {
> > +	drm_mode_config_cleanup(dev);
> > +	drm_vblank_cleanup(dev);
> > +	drm_irq_uninstall(dev);
> > +
> > +	dev->dev_private = NULL;
> > +
> > +	return 0;
> > +}
> > +
> > +static struct regmap_config fsl_dcu_regmap_config = {
> > +	.reg_bits = 32,
> > +	.reg_stride = 4,
> > +	.val_bits = 32,
> > +};
> > +
> > +static int fsl_dcu_bypass_tcon(struct fsl_dcu_drm_device *fsl_dev,
> > +			       struct device_node *np)
> > +{
> > +	struct device_node *tcon_np;
> > +	struct platform_device *pdev;
> > +	struct clk *tcon_clk;
> > +	struct resource *res;
> > +	void __iomem *base;
> > +
> > +	tcon_np = of_parse_phandle(np, "tcon-controller", 0);
> > +	if (!tcon_np)
> > +		return -EINVAL;
> > +
> > +	pdev = of_find_device_by_node(tcon_np);
> > +	if (!pdev)
> > +		return -EINVAL;
> > +
> > +	tcon_clk = devm_clk_get(&pdev->dev, "tcon");
> > +	if (IS_ERR(tcon_clk))
> > +		return PTR_ERR(tcon_clk);
> > +	clk_prepare_enable(tcon_clk);
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	if (!res)
> > +		return -ENODEV;
> > +
> > +	base = devm_ioremap_resource(&pdev->dev, res);
> > +	if (IS_ERR(base))
> > +		return PTR_ERR(base);
> > +
> > +	fsl_dev->tcon_regmap = devm_regmap_init_mmio_clk(&pdev->dev,
> > +			"tcon", base, &fsl_dcu_regmap_config);
> > +	if (IS_ERR(fsl_dev->tcon_regmap)) {
> > +		dev_err(&pdev->dev, "regmap init failed\n");
> > +		return PTR_ERR(fsl_dev->tcon_regmap);
> > +	}
> > +
> > +	regmap_write(fsl_dev->tcon_regmap, TCON_CTRL1, TCON_BYPASS_ENABLE);
> > +	return 0;
> > +}
> > +
> > +static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
> > +{
> > +	struct platform_device *pdev = dev->platformdev;
> > +	struct fsl_dcu_drm_device *fsl_dev;
> > +	struct resource *res;
> > +	void __iomem *base;
> > +	int ret;
> > +
> > +	fsl_dev = devm_kzalloc(&pdev->dev, sizeof(*fsl_dev), GFP_KERNEL);
> > +	if (!fsl_dev)
> > +		return -ENOMEM;
> > +
> > +	fsl_dev->dev = &pdev->dev;
> > +	fsl_dev->ddev = dev;
> > +	dev->dev_private = fsl_dev;
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	base = devm_ioremap_resource(&pdev->dev, res);
> > +	if (IS_ERR(base)) {
> > +		ret = PTR_ERR(base);
> > +		return ret;
> > +	}
> > +
> > +	fsl_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
> > +			base, &fsl_dcu_regmap_config);
> > +	if (IS_ERR(fsl_dev->regmap)) {
> > +		dev_err(&pdev->dev, "regmap init failed\n");
> > +		return PTR_ERR(fsl_dev->regmap);
> > +	}
> > +
> > +	ret = fsl_dcu_drm_modeset_init(fsl_dev);
> > +	if (ret < 0) {
> > +		dev_err(&pdev->dev, "failed to initialize mode setting\n");
> > +		return ret;
> > +	}
> > +
> > +	ret = drm_vblank_init(dev, 1);
> > +	if (ret < 0) {
> > +		dev_err(&pdev->dev, "failed to initialize vblank\n");
> > +		goto done;
> > +	}
> > +
> > +	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
> > +	if (ret < 0) {
> > +		dev_err(&pdev->dev, "failed to install IRQ handler\n");
> > +		goto done;
> > +	}
> > +
> > +	/* Put TCON in bypass mode, so the input signals from DCU are passed
> > +	 * through TCON unchanged */
> > +	fsl_dcu_bypass_tcon(fsl_dev, pdev->dev.of_node);
> > +
> > +	fsl_dev->clk = devm_clk_get(&pdev->dev, "dcu");
> > +	if (IS_ERR(fsl_dev->clk)) {
> > +		ret = PTR_ERR(fsl_dev->clk);
> > +		dev_err(&pdev->dev, "could not get clock\n");
> > +		return ret;
> > +	}
> > +	clk_prepare_enable(fsl_dev->clk);
> > +
> > +	dev_set_drvdata(dev->dev, fsl_dev);
> > +
> > +	fsl_dcu_fbdev_init(dev);
> > +
> > +	return 0;
> > +done:
> > +	if (ret)
> > +		fsl_dcu_unload(dev);
> > +
> > +	return ret;
> > +}
> > +
> > +static void fsl_dcu_drm_preclose(struct drm_device *dev, struct
> > +drm_file *file) {
> > +	;
> > +}
> > +
> > +static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg) {
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int
> > +crtc) {
> > +	return 0;
> > +}
> > +
> > +static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int
> > +crtc) {
> > +	;
> > +}
> > +
> > +static const struct file_operations fsl_dcu_drm_fops = {
> > +	.owner		= THIS_MODULE,
> > +	.open		= drm_open,
> > +	.release	= drm_release,
> > +	.unlocked_ioctl	= drm_ioctl,
> > +#ifdef CONFIG_COMPAT
> > +	.compat_ioctl	= drm_compat_ioctl,
> > +#endif
> > +	.poll		= drm_poll,
> > +	.read		= drm_read,
> > +	.llseek		= no_llseek,
> > +	.mmap		= drm_gem_cma_mmap,
> > +};
> > +
> > +static struct drm_driver fsl_dcu_drm_driver = {
> > +	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
> > +				| DRIVER_PRIME,
> > +	.load			= fsl_dcu_load,
> > +	.unload			= fsl_dcu_unload,
> > +	.preclose		= fsl_dcu_drm_preclose,
> > +	.irq_handler		= fsl_dcu_drm_irq,
> > +	.get_vblank_counter	= drm_vblank_count,
> > +	.enable_vblank		= fsl_dcu_drm_enable_vblank,
> > +	.disable_vblank		= fsl_dcu_drm_disable_vblank,
> > +	.gem_free_object	= drm_gem_cma_free_object,
> > +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
> > +	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
> > +	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
> > +	.gem_prime_import	= drm_gem_prime_import,
> > +	.gem_prime_export	= drm_gem_prime_export,
> > +	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
> > +	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> > +	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
> > +	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
> > +	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
> > +	.dumb_create		= drm_gem_cma_dumb_create,
> > +	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
> > +	.dumb_destroy		= drm_gem_dumb_destroy,
> > +	.fops			= &fsl_dcu_drm_fops,
> > +	.name			= "fsl-dcu-drm",
> > +	.desc			= "Freescale DCU DRM",
> > +	.date			= "20150213",
> > +	.major			= 1,
> > +	.minor			= 0,
> > +};
> > +
> > +#ifdef CONFIG_PM_SLEEP
> > +static int fsl_dcu_drm_pm_suspend(struct device *dev) {
> > +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> > +
> > +	dcu_pixclk_disable();
> > +	drm_kms_helper_poll_disable(fsl_dev->ddev);
> > +	fsl_dcu_drm_crtc_suspend(&fsl_dev->crtc);
> > +
> > +	return 0;
> > +}
> > +
> > +static int fsl_dcu_drm_pm_resume(struct device *dev) {
> > +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> > +
> > +	drm_modeset_lock_all(fsl_dev->ddev);
> > +	fsl_dcu_drm_crtc_resume(&fsl_dev->crtc);
> > +	drm_modeset_unlock_all(fsl_dev->ddev);
> > +	drm_kms_helper_poll_enable(fsl_dev->ddev);
> > +	dcu_pixclk_enable();
> > +	return 0;
> > +}
> > +#endif
> > +
> > +static const struct dev_pm_ops fsl_dcu_drm_pm_ops = {
> > +	SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_drm_pm_suspend,
> > +fsl_dcu_drm_pm_resume) };
> > +
> > +static int fsl_dcu_drm_probe(struct platform_device *pdev) {
> > +	return drm_platform_init(&fsl_dcu_drm_driver, pdev); }
> > +
> > +static int fsl_dcu_drm_remove(struct platform_device *pdev) {
> > +	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
> > +
> > +	drm_put_dev(fsl_dev->ddev);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id fsl_dcu_of_match[] = {
> > +		{ .compatible = "fsl,dcu", },
> > +		{ },
> > +};
> > +MODULE_DEVICE_TABLE(of, fsl_dcu_of_match);
> > +
> > +static struct platform_driver fsl_dcu_drm_platform_driver = {
> > +	.probe		= fsl_dcu_drm_probe,
> > +	.remove		= fsl_dcu_drm_remove,
> > +	.driver		= {
> > +		.owner	= THIS_MODULE,
> > +		.name	= "fsl,dcu",
> > +		.pm	= &fsl_dcu_drm_pm_ops,
> > +		.of_match_table = fsl_dcu_of_match,
> > +	},
> > +};
> > +
> > +module_platform_driver(fsl_dcu_drm_platform_driver);
> > +
> > +MODULE_ALIAS("platform:fsl-dcu-drm");
> > +MODULE_DESCRIPTION("Freescale DCU DRM Driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> > new file mode 100644
> > index 0000000..cbdfefc
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> > @@ -0,0 +1,168 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_DRV_H__
> > +#define __FSL_DCU_DRM_DRV_H__
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/spinlock.h>
> > +#include <stddef.h>
> > +#include <drm/drm.h>
> > +#include <drm/drmP.h>
> > +#include <drm/drm_fb_helper.h>
> > +#include <drm/drm_crtc_helper.h>
> > +#include <drm/drm_gem_cma_helper.h>
> > +#include <drm/drm_fb_cma_helper.h>
> > +
> > +#include "fsl_dcu_drm_crtc.h"
> > +#include "fsl_dcu_drm_plane.h"
> > +#include "fsl_dcu_drm_connector.h"
> > +#define DRIVER_NAME			"fsl-dcu-fb"
> > +
> > +#define DCU_DCU_MODE			0x0010
> > +#define DCU_MODE_BLEND_ITER(x)		((x) << 20)
> > +#define DCU_MODE_RASTER_EN		BIT(14)
> > +#define DCU_MODE_DCU_MODE(x)		(x)
> > +#define DCU_MODE_DCU_MODE_MASK		0x03
> > +#define DCU_MODE_OFF			0
> > +#define DCU_MODE_NORMAL			1
> > +#define DCU_MODE_TEST			2
> > +#define DCU_MODE_COLORBAR		3
> > +
> > +#define DCU_BGND			0x0014
> > +#define DCU_BGND_R(x)			((x) << 16)
> > +#define DCU_BGND_G(x)			((x) << 8)
> > +#define DCU_BGND_B(x)			(x)
> > +
> > +#define DCU_DISP_SIZE			0x0018
> > +#define DCU_DISP_SIZE_DELTA_Y(x)	((x) << 16)
> > +/*Regisiter value 1/16 of horizontal resolution*/
> > +#define DCU_DISP_SIZE_DELTA_X(x)	((x) >> 4)
> > +
> > +#define DCU_HSYN_PARA			0x001c
> > +#define DCU_HSYN_PARA_BP(x)		((x) << 22)
> > +#define DCU_HSYN_PARA_PW(x)		((x) << 11)
> > +#define DCU_HSYN_PARA_FP(x)		(x)
> > +
> > +#define DCU_VSYN_PARA			0x0020
> > +#define DCU_VSYN_PARA_BP(x)		((x) << 22)
> > +#define DCU_VSYN_PARA_PW(x)		((x) << 11)
> > +#define DCU_VSYN_PARA_FP(x)		(x)
> > +
> > +#define DCU_SYN_POL			0x0024
> > +#define DCU_SYN_POL_INV_PXCK_FALL	(0 << 6)
> > +#define DCU_SYN_POL_NEG_REMAIN		(0 << 5)
> > +#define DCU_SYN_POL_INV_VS_LOW		BIT(1)
> > +#define DCU_SYN_POL_INV_HS_LOW		(1)
> > +
> > +#define DCU_THRESHOLD			0x0028
> > +#define DCU_THRESHOLD_LS_BF_VS(x)	((x) << 16)
> > +#define DCU_THRESHOLD_OUT_BUF_HIGH(x)	((x) << 8)
> > +#define DCU_THRESHOLD_OUT_BUF_LOW(x)	(x)
> > +#define BF_VS_VAL			0x03
> > +#define BUF_MAX_VAL			0x78
> > +#define BUF_MIN_VAL			0x0a
> > +
> > +#define DCU_INT_STATUS			0x002C
> > +#define DCU_INT_STATUS_UNDRUN		BIT(1)
> > +
> > +#define DCU_INT_MASK			0x0030
> > +#define DCU_INT_MASK_UNDRUN		BIT(1)
> > +#define DCU_INT_MASK_VBLANK		BIT(3)
> > +
> > +#define DCU_DIV_RATIO			0x0054
> > +
> > +#define DCU_UPDATE_MODE			0x00cc
> > +#define DCU_UPDATE_MODE_MODE		BIT(31)
> > +#define DCU_UPDATE_MODE_READREG		BIT(30)
> > +
> > +#define DCU_DCFB_MAX			0x300
> > +
> > +#define DCU_CTRLDESCLN_1(x)		(0x200 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_1_HEIGHT(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_1_WIDTH(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_2(x)		(0x204 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_2_POSY(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_2_POSX(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_3(x)		(0x208 + (x) * 0x40)
> > +
> > +#define DCU_CTRLDESCLN_4(x)		(0x20c + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_4_EN		BIT(31)
> > +#define DCU_CTRLDESCLN_4_TILE_EN	BIT(30)
> > +#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT	BIT(29)
> > +#define DCU_CTRLDESCLN_4_SAFETY_EN	BIT(28)
> > +#define DCU_CTRLDESCLN_4_TRANS(x)	((x) << 20)
> > +#define DCU_CTRLDESCLN_4_BPP(x)		((x) << 16)
> > +#define DCU_CTRLDESCLN_4_RLE_EN		BIT(15)
> > +#define DCU_CTRLDESCLN_4_LUOFFS(x)	((x) << 4)
> > +#define DCU_CTRLDESCLN_4_BB_ON		BIT(2)
> > +#define DCU_CTRLDESCLN_4_AB(x)		(x)
> > +
> > +#define DCU_CTRLDESCLN_5(x)		(0x210 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_5_CKMAX_R(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_5_CKMAX_G(x)	((x) << 8)
> > +#define DCU_CTRLDESCLN_5_CKMAX_B(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_6(x)		(0x214 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_6_CKMIN_R(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_6_CKMIN_G(x)	((x) << 8)
> > +#define DCU_CTRLDESCLN_6_CKMIN_B(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_7(x)		(0x218 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_7_TILE_VER(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_7_TILE_HOR(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_8(x)		(0x21c + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_8_FG_FCOLOR(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_9(x)		(0x220 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_9_BG_BCOLOR(x)	(x)
> > +
> > +#define DCU_CTRLDESCLN_10(x)		(0x224 + (x) * 0x40)
> > +#define DCU_CTRLDESCLN_10_POST_SKIP(x)	((x) << 16)
> > +#define DCU_CTRLDESCLN_10_PRE_SKIP(x)	(x)
> > +
> > +#define FSL_DCU_RGB565			4
> > +#define FSL_DCU_RGB888			5
> > +#define FSL_DCU_ARGB8888		6
> > +#define FSL_DCU_ARGB1555		11
> > +#define FSL_DCU_ARGB4444		12
> > +#define FSL_DCU_YUV422			14
> > +
> > +#define TCON_CTRL1			0x0000
> > +#define TCON_BYPASS_ENABLE		BIT(29)
> > +
> > +#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
> > +
> > +struct clk;
> > +struct device;
> > +struct drm_device;
> > +
> > +struct fsl_dcu_drm_device {
> > +	struct device *dev;
> > +	struct regmap *regmap;
> > +	struct regmap *tcon_regmap;
> > +	unsigned int irq;
> > +	struct clk *clk;
> > +	/*protects hardware register*/
> > +	spinlock_t irq_lock;
> > +	struct drm_device *ddev;
> > +	struct drm_fbdev_cma *fbdev;
> > +	struct fsl_dcu_drm_crtc crtc;
> > +	struct drm_encoder encoder;
> > +	struct fsl_dcu_drm_connector connector; };
> > +
> > +void fsl_dcu_fbdev_init(struct drm_device *dev);
> > +
> > +#endif /* __FSL_DCU_DRM_DRV_H__ */
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> > new file mode 100644
> > index 0000000..f8ef0e1
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> > @@ -0,0 +1,26 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * 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.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > +but WITHOUT
> > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> > +or
> > + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
> > +License for
> > + * more details.
> > + *
> > + */
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_fb_cma_helper.h>
> > +
> > +#include "fsl_dcu_drm_drv.h"
> > +
> > +/* initialize fbdev helper */
> > +void fsl_dcu_fbdev_init(struct drm_device *dev) {
> > +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
> > +
> > +	fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1); }
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> > new file mode 100644
> > index 0000000..4a840fb
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> > @@ -0,0 +1,42 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_atomic_helper.h>
> > +
> > +#include "fsl_dcu_drm_crtc.h"
> > +#include "fsl_dcu_drm_connector.h"
> > +#include "fsl_dcu_drm_drv.h"
> > +
> > +static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs
> = {
> > +	.fb_create = drm_fb_cma_create,
> > +	.atomic_check = drm_atomic_helper_check,
> > +	.atomic_commit = drm_atomic_helper_commit, };
> > +
> > +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev) {
> > +	drm_mode_config_init(fsl_dev->ddev);
> > +
> > +	fsl_dev->ddev->mode_config.min_width = 0;
> > +	fsl_dev->ddev->mode_config.min_height = 0;
> > +	fsl_dev->ddev->mode_config.max_width = 2031;
> > +	fsl_dev->ddev->mode_config.max_height = 2047;
> > +	fsl_dev->ddev->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;
> > +
> > +	drm_kms_helper_poll_init(fsl_dev->ddev);
> > +	fsl_dcu_drm_crtc_create(fsl_dev);
> > +	fsl_dcu_drm_encoder_create(fsl_dev);
> > +	fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
> > +	drm_mode_config_reset(fsl_dev->ddev);
> > +
> > +	return 0;
> > +}
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> > new file mode 100644
> > index 0000000..b9bd299
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> > @@ -0,0 +1,17 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_KMS_H__
> > +#define __FSL_DCU_DRM_KMS_H__
> > +
> > +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
> > +
> > +#endif /* __FSL_DCU_DRM_KMS_H__ */
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> > new file mode 100644
> > index 0000000..b7b4405
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> > @@ -0,0 +1,187 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_crtc.h>
> > +#include <drm/drm_crtc_helper.h>
> > +#include <drm/drm_fb_cma_helper.h>
> > +#include <drm/drm_gem_cma_helper.h>
> > +#include <linux/regmap.h>
> > +#include <drm/drm_plane_helper.h>
> > +#include <drm/drm_atomic_helper.h>
> > +
> > +#include "fsl_dcu_drm_drv.h"
> > +#include "fsl_dcu_drm_kms.h"
> > +#include "fsl_dcu_drm_plane.h"
> > +
> > +#define to_fsl_dcu_plane(plane) \
> > +	container_of(plane, struct fsl_dcu_drm_plane, plane)
> > +
> > +static int
> > +fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
> > +			     struct drm_framebuffer *fb,
> > +			     const struct drm_plane_state *new_state) {
> > +	return 0;
> > +}
> > +
> > +static void
> > +fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
> > +			     struct drm_framebuffer *fb,
> > +			     const struct drm_plane_state *new_state) { }
> > +
> > +static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
> > +					  struct drm_plane_state *state) {
> > +	return 0;
> > +}
> > +
> > +static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
> > +					     struct drm_plane_state *old_state) { }
> > +
> > +void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
> > +				     struct drm_plane_state *old_state) {
> > +	struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
> > +	struct drm_plane_state *state = plane->state;
> > +	struct drm_framebuffer *fb = plane->state->fb;
> > +	u32 index, alpha, bpp;
> > +	struct drm_gem_cma_object *gem;
> > +	struct fsl_dcu_drm_plane *fsl_plane = to_fsl_dcu_plane(plane);
> > +
> > +	index = fsl_plane->index;
> > +	gem = drm_fb_cma_get_gem_obj(fb, 0);
> > +
> > +	switch (fb->pixel_format) {
> > +	case DRM_FORMAT_RGB565:
> > +		bpp = FSL_DCU_RGB565;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_RGB888:
> > +		bpp = FSL_DCU_RGB888;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_ARGB8888:
> > +		bpp = FSL_DCU_ARGB8888;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_BGRA4444:
> > +		bpp = FSL_DCU_ARGB4444;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_ARGB1555:
> > +		bpp = FSL_DCU_ARGB1555;
> > +		alpha = 0xff;
> > +		break;
> > +	case DRM_FORMAT_YUV422:
> > +		bpp = FSL_DCU_YUV422;
> > +		alpha = 0xff;
> > +		break;
> > +	default:
> > +		return;
> > +	}
> > +
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_1(index),
> > +		     DCU_CTRLDESCLN_1_HEIGHT(state->crtc_h) |
> > +		     DCU_CTRLDESCLN_1_WIDTH(state->crtc_w));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_2(index),
> > +		     DCU_CTRLDESCLN_2_POSY(state->crtc_y) |
> > +		     DCU_CTRLDESCLN_2_POSX(state->crtc_x));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_3(index), gem->paddr);
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_4(index),
> > +		     DCU_CTRLDESCLN_4_EN |
> > +		     DCU_CTRLDESCLN_4_TRANS(alpha) |
> > +		     DCU_CTRLDESCLN_4_BPP(bpp) |
> > +		     DCU_CTRLDESCLN_4_AB(2));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_5(index),
> > +		     DCU_CTRLDESCLN_5_CKMAX_R(0xFF) |
> > +		     DCU_CTRLDESCLN_5_CKMAX_G(0xFF) |
> > +		     DCU_CTRLDESCLN_5_CKMAX_B(0xFF));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_6(index),
> > +		     DCU_CTRLDESCLN_6_CKMIN_R(0) |
> > +		     DCU_CTRLDESCLN_6_CKMIN_G(0) |
> > +		     DCU_CTRLDESCLN_6_CKMIN_B(0));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_8(index),
> > +		     DCU_CTRLDESCLN_8_FG_FCOLOR(0));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_9(index),
> > +		     DCU_CTRLDESCLN_9_BG_BCOLOR(0));
> > +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_10(index),
> > +		     DCU_CTRLDESCLN_10_POST_SKIP(0) |
> > +		     DCU_CTRLDESCLN_10_PRE_SKIP(0));
> > +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
> > +DCU_UPDATE_MODE_READREG); }
> > +
> > +int fsl_dcu_drm_plane_disable(struct drm_plane *plane) {
> > +	return 0;
> > +}
> > +
> > +void fsl_dcu_drm_plane_destroy(struct drm_plane *plane) {
> > +	fsl_dcu_drm_plane_disable(plane);
> > +	drm_plane_cleanup(plane);
> > +}
> > +
> > +static const uint32_t fsl_dcu_drm_plane_formats[] = {
> > +	DRM_FORMAT_RGB565,
> > +	DRM_FORMAT_RGB888,
> > +	DRM_FORMAT_ARGB8888,
> > +	DRM_FORMAT_ARGB4444,
> > +	DRM_FORMAT_ARGB1555,
> > +	DRM_FORMAT_YUV422,
> > +};
> > +
> > +static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
> > +	.update_plane = drm_plane_helper_update,
> > +	.disable_plane = drm_plane_helper_disable,
> > +	.destroy = fsl_dcu_drm_plane_destroy,
> > +	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> > +	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> > +	.reset = drm_atomic_helper_plane_reset, };
> > +
> > +static const struct drm_plane_helper_funcs
> fsl_dcu_drm_plane_helper_funcs = {
> > +	.prepare_fb = fsl_dcu_drm_plane_prepare_fb,
> > +	.cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
> > +	.atomic_check = fsl_dcu_drm_plane_atomic_check,
> > +	.atomic_update = fsl_dcu_drm_plane_atomic_update,
> > +	.atomic_disable = fsl_dcu_drm_plane_atomic_disable, };
> > +
> > +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device
> > +*dev) {
> > +	struct drm_plane *primary;
> > +	int ret;
> > +
> > +	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> > +	if (!primary) {
> > +		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
> > +		return NULL;
> > +	}
> > +
> > +	/* possible_crtc's will be filled in later by crtc_init */
> > +	ret = drm_universal_plane_init(dev, primary, 0,
> > +				       &fsl_dcu_drm_plane_funcs,
> > +				       fsl_dcu_drm_plane_formats,
> > +				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
> > +				       DRM_PLANE_TYPE_PRIMARY);
> > +	if (ret) {
> > +		kfree(primary);
> > +		primary = NULL;
> > +	}
> > +	drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
> > +
> > +	return primary;
> > +}
> > diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> > b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> > new file mode 100644
> > index 0000000..ccbfa61
> > --- /dev/null
> > +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> > @@ -0,0 +1,23 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_DRM_PLANE_H__
> > +#define __FSL_DCU_DRM_PLANE_H__
> > +
> > +struct fsl_dcu_drm_device;
> > +struct fsl_dcu_drm_plane {
> > +	struct drm_plane plane;
> > +	unsigned int index;
> > +};
> > +
> > +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device
> > +*dev);
> > +
> > +#endif /* __FSL_DCU_DRM_PLANE_H__ */
> > diff --git a/include/linux/fsl/dcu.h b/include/linux/fsl/dcu.h new
> > file mode 100644 index 0000000..1873057
> > --- /dev/null
> > +++ b/include/linux/fsl/dcu.h
> > @@ -0,0 +1,22 @@
> > +/*
> > + * Copyright 2015 Freescale Semiconductor, Inc.
> > + *
> > + * Freescale DCU drm device driver
> > + *
> > + * This program is free software; you can redistribute it and/or
> > +modify
> > + * it under the terms of the GNU General Public License as published
> > +by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __FSL_DCU_H__
> > +#define __FSL_DCU_H__
> > +
> > +#define SCFG_PIXCLKCR			0x28
> > +#define PXCK_ENABLE			BIT(31)
> > +#define PXCK_DISABLE			0
> > +
> > +void dcu_pixclk_enable(void);
> > +void dcu_pixclk_disable(void);
> > +
> > +#endif /* __FSL_DCU_H__ */
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


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

* Re: [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
  2015-03-13  9:44 ` Jianwei Wang
  (?)
@ 2015-03-19 14:30   ` Daniel Vetter
  -1 siblings, 0 replies; 26+ messages in thread
From: Daniel Vetter @ 2015-03-19 14:30 UTC (permalink / raw)
  To: Jianwei Wang
  Cc: scottwood, airlied, jbarnes, dri-devel, Xiubo Li, Alison Wang,
	linux-kernel, Jason.Jin, linux-arm-kernel

On Fri, Mar 13, 2015 at 05:44:17PM +0800, Jianwei Wang wrote:
> This patch add support for Two Dimensional Animation and Compositing
> Engine (2D-ACE) on Freescale SoCs.
> 
> 2D-ACE is a Freescale display controller. It provide an hardware
> cursor.
> 
> This is a simplified version, only a primary plane, a fb created for
> fbdev, a crtc, a connector for TFT LCD panel, an encoder, and the
> encoder is not in use.
> 
> Signed-off-by: Alison Wang <b18965@freescale.com>
> Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> Signed-off-by: Jianwei Wang <b52261@freescale.com>

I've spotted two more places where you need to upgrade to atomic functions
for legacy entry points. Otherwise it looks good from that pov. See
comments below.

Thanks, Daniel

> ---
> 
> Changed in v2: 
> - Add atomic support
> - Modify bindings file
> - Rename node for compatibility
> - Move platform related code out for compatibility
> 
> Added in v1: 
> - Add support for DCU display controller on the Freescale LS102x SoCs.
> - Create a primary plane, a fb created for fbdev, a crtc, a connector
> for TFT LCD panel, an encoder.
> 
>  arch/arm/mach-imx/mach-ls1021a.c            |  36 ++++
>  drivers/gpu/drm/Kconfig                     |   2 +
>  drivers/gpu/drm/Makefile                    |   1 +
>  drivers/gpu/drm/fsl/Kconfig                 |  17 ++
>  drivers/gpu/drm/fsl/Makefile                |   8 +
>  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c | 203 ++++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h |  28 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c      | 164 ++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h      |  26 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c       | 288 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h       | 168 ++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c     |  26 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c       |  42 ++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h       |  17 ++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c     | 187 ++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h     |  23 +++
>  include/linux/fsl/dcu.h                     |  22 +++
>  17 files changed, 1258 insertions(+)
>  create mode 100644 drivers/gpu/drm/fsl/Kconfig
>  create mode 100644 drivers/gpu/drm/fsl/Makefile
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
>  create mode 100644 include/linux/fsl/dcu.h
> 
> diff --git a/arch/arm/mach-imx/mach-ls1021a.c b/arch/arm/mach-imx/mach-ls1021a.c
> index b89c858..4fb346d 100644
> --- a/arch/arm/mach-imx/mach-ls1021a.c
> +++ b/arch/arm/mach-imx/mach-ls1021a.c
> @@ -8,9 +8,44 @@
>   */
>  
>  #include <asm/mach/arch.h>
> +#include <linux/of_platform.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <linux/fsl/dcu.h>
>  
>  #include "common.h"
>  
> +void dcu_pixclk_disable(void)
> +{
> +	struct regmap *scfg_regmap;
> +
> +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> +	if (IS_ERR(scfg_regmap)) {
> +		pr_err("No syscfg phandle specified\n");
> +		return;
> +	}
> +
> +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_DISABLE);
> +}
> +
> +void dcu_pixclk_enable(void)
> +{
> +	struct regmap *scfg_regmap;
> +
> +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> +	if (IS_ERR(scfg_regmap)) {
> +		pr_err("No syscfg phandle specified\n");
> +		return;
> +	}
> +
> +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_ENABLE);
> +}
> +
> +static void __init ls1021a_init_machine(void)
> +{
> +	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> +	dcu_pixclk_enable();
> +}
>  static const char * const ls1021a_dt_compat[] __initconst = {
>  	"fsl,ls1021a",
>  	NULL,
> @@ -18,5 +53,6 @@ static const char * const ls1021a_dt_compat[] __initconst = {
>  
>  DT_MACHINE_START(LS1021A, "Freescale LS1021A")
>  	.smp		= smp_ops(ls1021a_smp_ops),
> +	.init_machine	= ls1021a_init_machine,
>  	.dt_compat	= ls1021a_dt_compat,
>  MACHINE_END
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index 151a050..a6957aa 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -199,6 +199,8 @@ source "drivers/gpu/drm/bochs/Kconfig"
>  
>  source "drivers/gpu/drm/msm/Kconfig"
>  
> +source "drivers/gpu/drm/fsl/Kconfig"
> +
>  source "drivers/gpu/drm/tegra/Kconfig"
>  
>  source "drivers/gpu/drm/panel/Kconfig"
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 2c239b9..ab5b9ef 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -56,6 +56,7 @@ obj-$(CONFIG_DRM_UDL) += udl/
>  obj-$(CONFIG_DRM_AST) += ast/
>  obj-$(CONFIG_DRM_ARMADA) += armada/
>  obj-$(CONFIG_DRM_ATMEL_HLCDC)	+= atmel-hlcdc/
> +obj-$(CONFIG_DRM_FSL_DCU) += fsl/
>  obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
>  obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
>  obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
> diff --git a/drivers/gpu/drm/fsl/Kconfig b/drivers/gpu/drm/fsl/Kconfig
> new file mode 100644
> index 0000000..e4f8df0
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/Kconfig
> @@ -0,0 +1,17 @@
> +config DRM_FSL_DCU
> +	tristate "DRM Support for Freescale DCU"
> +	depends on DRM && OF && ARM
> +	select DRM_KMS_HELPER
> +	select DRM_KMS_CMA_HELPER
> +	select VIDEOMODE_HELPERS
> +	select BACKLIGHT_CLASS_DEVICE
> +	select BACKLIGHT_LCD_SUPPORT
> +	select REGMAP_MMIO
> +	select DRM_KMS_FB_HELPER
> +	select FB_SYS_FILLRECT
> +	select FB_SYS_COPYAREA
> +	select FB_SYS_IMAGEBLIT
> +	select FB_SYS_FOPS
> +	help
> +	  Choose this option if you have an Freescale DCU chipset.
> +	  If M is selected the module will be called fsl-dcu-drm.
> diff --git a/drivers/gpu/drm/fsl/Makefile b/drivers/gpu/drm/fsl/Makefile
> new file mode 100644
> index 0000000..5f74aee
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/Makefile
> @@ -0,0 +1,8 @@
> +fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
> +	       fsl_dcu_drm_kms.o \
> +	       fsl_dcu_drm_connector.o \
> +	       fsl_dcu_drm_plane.o \
> +	       fsl_dcu_drm_crtc.o \
> +	       fsl_dcu_drm_fbdev.o \
> +
> +obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> new file mode 100644
> index 0000000..178d647
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> @@ -0,0 +1,203 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/backlight.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <video/of_display_timing.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_connector.h"
> +
> +static void fsl_dcu_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
> +{
> +}
> +
> +/* Disable the encoders as the first thing we do. */
> +static void fsl_dcu_drm_encoder_mode_prepare(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_mode_set(struct drm_encoder *encoder,
> +					 struct drm_display_mode *mode,
> +					 struct drm_display_mode *adjusted_mode)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_mode_commit(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
> +{
> +}
> +
> +static int
> +fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
> +				 struct drm_crtc_state *crtc_state,
> +				 struct drm_connector_state *conn_state)
> +{
> +	return 0;
> +}
> +
> +static bool
> +fsl_dcu_drm_encoder_mode_fixup(struct drm_encoder *encoder,
> +			       const struct drm_display_mode *mode,
> +			       struct drm_display_mode *adjusted_mode)
> +{
> +	return true;
> +}
> +
> +static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
> +{
> +	drm_encoder_cleanup(encoder);
> +}
> +
> +static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
> +	.dpms = fsl_dcu_drm_encoder_dpms,
> +	.prepare = fsl_dcu_drm_encoder_mode_prepare,
> +	.commit = fsl_dcu_drm_encoder_mode_commit,
> +	.mode_set = fsl_dcu_drm_encoder_mode_set,
> +	.disable = fsl_dcu_drm_encoder_disable,
> +	.atomic_check = fsl_dcu_drm_encoder_atomic_check,
> +	.mode_fixup = fsl_dcu_drm_encoder_mode_fixup,
> +};
> +
> +static const struct drm_encoder_funcs encoder_funcs = {
> +	.destroy = fsl_dcu_drm_encoder_destroy,
> +};
> +
> +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	struct drm_encoder *encoder = &fsl_dev->encoder;
> +	int ret;
> +
> +	encoder->possible_crtcs = 1;
> +
> +	ret = drm_encoder_init(fsl_dev->ddev, encoder, &encoder_funcs,
> +			       DRM_MODE_ENCODER_LVDS);
> +	if (ret < 0)
> +		return ret;
> +
> +	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
> +
> +	return 0;
> +}
> +
> +#define to_fsl_dcu_connector(connector) \
> +	container_of(connector, struct fsl_dcu_drm_connector, connector)
> +
> +static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector)
> +{
> +	struct drm_device *dev = connector->dev;
> +	struct device_node *display_np, *np = dev->dev->of_node;
> +	struct drm_display_mode *mode = drm_mode_create(connector->dev);
> +	int num_modes = 0;
> +
> +	if (np) {
> +		display_np = of_parse_phandle(np, "display", 0);
> +		if (!display_np) {
> +			dev_err(dev->dev, "failed to find display phandle\n");
> +			return num_modes;
> +		}
> +		of_get_drm_display_mode(display_np, mode, OF_USE_NATIVE_MODE);
> +		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> +		drm_mode_probed_add(connector, mode);
> +		num_modes++;
> +	}
> +
> +	return num_modes;
> +}
> +
> +static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
> +					    struct drm_display_mode *mode)
> +{
> +	return MODE_OK;
> +}
> +
> +static struct drm_encoder *
> +fsl_dcu_drm_connector_best_encoder(struct drm_connector *connector)
> +{
> +	struct fsl_dcu_drm_connector *fsl_con = to_fsl_dcu_connector(connector);
> +
> +	return fsl_con->encoder;
> +}
> +
> +static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_connector_unregister(connector);
> +	drm_connector_cleanup(connector);
> +}
> +
> +static enum drm_connector_status
> +fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	return connector_status_connected;
> +}
> +
> +static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
> +	.dpms = drm_atomic_helper_connector_dpms,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.detect = fsl_dcu_drm_connector_detect,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.destroy = fsl_dcu_drm_connector_destroy,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static const struct drm_connector_helper_funcs connector_helper_funcs = {
> +	.get_modes = fsl_dcu_drm_connector_get_modes,
> +	.mode_valid = fsl_dcu_drm_connector_mode_valid,
> +	.best_encoder = fsl_dcu_drm_connector_best_encoder,
> +};
> +
> +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> +				 struct drm_encoder *encoder)
> +{
> +	struct drm_connector *connector = &fsl_dev->connector.connector;
> +	int ret;
> +
> +	fsl_dev->connector.encoder = encoder;
> +
> +	connector->display_info.width_mm = 0;
> +	connector->display_info.height_mm = 0;
> +
> +	ret = drm_connector_init(fsl_dev->ddev, connector,
> +				 &fsl_dcu_drm_connector_funcs,
> +				 DRM_MODE_CONNECTOR_LVDS);
> +	if (ret < 0)
> +		return ret;
> +
> +	connector->dpms = DRM_MODE_DPMS_OFF;
> +	drm_connector_helper_add(connector, &connector_helper_funcs);
> +	ret = drm_connector_register(connector);
> +	if (ret < 0)
> +		goto err_cleanup;
> +
> +	ret = drm_mode_connector_attach_encoder(connector, encoder);
> +	if (ret < 0)
> +		goto err_sysfs;
> +
> +	connector->encoder = encoder;
> +
> +	drm_object_property_set_value
> +		(&connector->base, fsl_dev->ddev->mode_config.dpms_property,
> +		DRM_MODE_DPMS_OFF);
> +
> +	return 0;
> +
> +err_sysfs:
> +	drm_connector_unregister(connector);
> +err_cleanup:
> +	drm_connector_cleanup(connector);
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> new file mode 100644
> index 0000000..afe44ab
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> @@ -0,0 +1,28 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_CONNECTOR_H__
> +#define __FSL_DCU_DRM_CONNECTOR_H__
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_connector {
> +	struct drm_connector connector;
> +	struct drm_encoder *encoder;
> +};
> +
> +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev);
> +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> +				 struct drm_encoder *encoder);
> +
> +#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> new file mode 100644
> index 0000000..a43e7ce
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> @@ -0,0 +1,164 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/regmap.h>
> +#include <linux/clk.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_plane.h"
> +
> +#define to_fsl_dcu_crtc(c)	container_of(c, struct fsl_dcu_drm_crtc, crtc)
> +
> +void fsl_dcu_drm_crtc_suspend(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
> +	struct drm_display_mode *mode = &crtc->state->mode;
> +	uint32_t hbp, hfp, hsw, vbp, vfp, vsw, div, index;
> +
> +	DBG(": set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
> +	    mode->base.id, mode->name,
> +	    mode->vrefresh, mode->clock,
> +	    mode->hdisplay, mode->hsync_start,
> +	    mode->hsync_end, mode->htotal,
> +	    mode->vdisplay, mode->vsync_start,
> +	    mode->vsync_end, mode->vtotal,
> +	    mode->type, mode->flags);
> +
> +	index = drm_crtc_index(crtc);
> +	div = (uint32_t)clk_get_rate(fsl_dev->clk) / mode->clock / 1000;
> +
> +	/* Configure timings: */
> +	hbp = mode->htotal - mode->hsync_end;
> +	hfp = mode->hsync_start - mode->hdisplay;
> +	hsw = mode->hsync_end - mode->hsync_start;
> +	vbp = mode->vtotal - mode->vsync_end;
> +	vfp = mode->vsync_start - mode->vdisplay;
> +	vsw = mode->vsync_end - mode->vsync_start;
> +
> +	regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
> +		     DCU_HSYN_PARA_BP(hbp) |
> +		     DCU_HSYN_PARA_PW(hsw) |
> +		     DCU_HSYN_PARA_FP(hfp));
> +	regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
> +		     DCU_VSYN_PARA_BP(vbp) |
> +		     DCU_VSYN_PARA_PW(vsw) |
> +		     DCU_VSYN_PARA_FP(vfp));
> +	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
> +		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
> +		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
> +	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +}
> +
> +static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
> +					const struct drm_display_mode *mode,
> +					struct drm_display_mode *adjusted_mode)
> +{
> +	return true;
> +}
> +
> +static void fsl_dcu_drm_crtc_prepare(struct drm_crtc *crtc)
> +{
> +}
> +
> +/* Now enable the clocks, plane, pipe, and connectors that we set up. */
> +static void fsl_dcu_drm_crtc_mode_commit(struct drm_crtc *crtc)
> +{
> +}
> +
> +static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
> +					 struct drm_crtc_state *state)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
> +{
> +}
> +
> +static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
> +	.page_flip = drm_atomic_helper_page_flip,
> +	.set_config = drm_crtc_helper_set_config,

This is the legacy function, please use the atomic one instead from
drm_atomic_helper.c for ->set_config.

> +	.destroy = drm_crtc_cleanup,
> +	.reset = drm_atomic_helper_crtc_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> +};
> +
> +static void fsl_dcu_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
> +{
> +}
> +
> +static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
> +	.disable = fsl_dcu_drm_disable_crtc,
> +	.mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
> +	.mode_set = drm_helper_crtc_mode_set,
> +	.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
> +	.mode_set_base = drm_helper_crtc_mode_set_base,
> +	.prepare = fsl_dcu_drm_crtc_prepare,
> +	.commit = fsl_dcu_drm_crtc_mode_commit,
> +	.atomic_check = fsl_dcu_drm_crtc_atomic_check,
> +	.atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
> +	.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
> +	.dpms = fsl_dcu_drm_crtc_dpms,
> +};
> +
> +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	struct drm_plane *primary;
> +	struct drm_crtc *crtc = &fsl_dev->crtc.crtc;
> +	int ret;
> +
> +	fsl_dev->crtc.dpms = DRM_MODE_DPMS_OFF;
> +
> +	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->ddev);
> +	ret = drm_crtc_init_with_planes(fsl_dev->ddev, crtc, primary, NULL,
> +					&fsl_dcu_drm_crtc_funcs);
> +	if (ret < 0)
> +		return ret;
> +
> +	drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
> +
> +	regmap_write(fsl_dev->regmap, DCU_SYN_POL,
> +		     DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
> +	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
> +		     DCU_BGND_G(0) | DCU_BGND_B(0));
> +	regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
> +		     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
> +	regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
> +		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
> +		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
> +		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
> +	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
> +			   DCU_MODE_DCU_MODE_MASK,
> +			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> new file mode 100644
> index 0000000..d44b564
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_CRTC_H__
> +#define __FSL_DCU_DRM_CRTC_H__
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_crtc {
> +	struct drm_crtc crtc;
> +	int dpms;
> +};
> +
> +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev);
> +
> +#endif /* __FSL_DCU_DRM_CRTC_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> new file mode 100644
> index 0000000..10975ee
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> @@ -0,0 +1,288 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/mm.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> +
> +#include <drm/drmP.h>
> +#include <linux/fsl/dcu.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_kms.h"
> +
> +static int fsl_dcu_unload(struct drm_device *dev)
> +{
> +	drm_mode_config_cleanup(dev);
> +	drm_vblank_cleanup(dev);
> +	drm_irq_uninstall(dev);
> +
> +	dev->dev_private = NULL;
> +
> +	return 0;
> +}
> +
> +static struct regmap_config fsl_dcu_regmap_config = {
> +	.reg_bits = 32,
> +	.reg_stride = 4,
> +	.val_bits = 32,
> +};
> +
> +static int fsl_dcu_bypass_tcon(struct fsl_dcu_drm_device *fsl_dev,
> +			       struct device_node *np)
> +{
> +	struct device_node *tcon_np;
> +	struct platform_device *pdev;
> +	struct clk *tcon_clk;
> +	struct resource *res;
> +	void __iomem *base;
> +
> +	tcon_np = of_parse_phandle(np, "tcon-controller", 0);
> +	if (!tcon_np)
> +		return -EINVAL;
> +
> +	pdev = of_find_device_by_node(tcon_np);
> +	if (!pdev)
> +		return -EINVAL;
> +
> +	tcon_clk = devm_clk_get(&pdev->dev, "tcon");
> +	if (IS_ERR(tcon_clk))
> +		return PTR_ERR(tcon_clk);
> +	clk_prepare_enable(tcon_clk);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -ENODEV;
> +
> +	base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	fsl_dev->tcon_regmap = devm_regmap_init_mmio_clk(&pdev->dev,
> +			"tcon", base, &fsl_dcu_regmap_config);
> +	if (IS_ERR(fsl_dev->tcon_regmap)) {
> +		dev_err(&pdev->dev, "regmap init failed\n");
> +		return PTR_ERR(fsl_dev->tcon_regmap);
> +	}
> +
> +	regmap_write(fsl_dev->tcon_regmap, TCON_CTRL1, TCON_BYPASS_ENABLE);
> +	return 0;
> +}
> +
> +static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
> +{
> +	struct platform_device *pdev = dev->platformdev;
> +	struct fsl_dcu_drm_device *fsl_dev;
> +	struct resource *res;
> +	void __iomem *base;
> +	int ret;
> +
> +	fsl_dev = devm_kzalloc(&pdev->dev, sizeof(*fsl_dev), GFP_KERNEL);
> +	if (!fsl_dev)
> +		return -ENOMEM;
> +
> +	fsl_dev->dev = &pdev->dev;
> +	fsl_dev->ddev = dev;
> +	dev->dev_private = fsl_dev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(base)) {
> +		ret = PTR_ERR(base);
> +		return ret;
> +	}
> +
> +	fsl_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
> +			base, &fsl_dcu_regmap_config);
> +	if (IS_ERR(fsl_dev->regmap)) {
> +		dev_err(&pdev->dev, "regmap init failed\n");
> +		return PTR_ERR(fsl_dev->regmap);
> +	}
> +
> +	ret = fsl_dcu_drm_modeset_init(fsl_dev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to initialize mode setting\n");
> +		return ret;
> +	}
> +
> +	ret = drm_vblank_init(dev, 1);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to initialize vblank\n");
> +		goto done;
> +	}
> +
> +	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to install IRQ handler\n");
> +		goto done;
> +	}
> +
> +	/* Put TCON in bypass mode, so the input signals from DCU are passed
> +	 * through TCON unchanged */
> +	fsl_dcu_bypass_tcon(fsl_dev, pdev->dev.of_node);
> +
> +	fsl_dev->clk = devm_clk_get(&pdev->dev, "dcu");
> +	if (IS_ERR(fsl_dev->clk)) {
> +		ret = PTR_ERR(fsl_dev->clk);
> +		dev_err(&pdev->dev, "could not get clock\n");
> +		return ret;
> +	}
> +	clk_prepare_enable(fsl_dev->clk);
> +
> +	dev_set_drvdata(dev->dev, fsl_dev);
> +
> +	fsl_dcu_fbdev_init(dev);
> +
> +	return 0;
> +done:
> +	if (ret)
> +		fsl_dcu_unload(dev);
> +
> +	return ret;
> +}
> +
> +static void fsl_dcu_drm_preclose(struct drm_device *dev, struct drm_file *file)
> +{
> +	;
> +}
> +
> +static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
> +{
> +	return IRQ_HANDLED;
> +}
> +
> +static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int crtc)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int crtc)
> +{
> +	;
> +}
> +
> +static const struct file_operations fsl_dcu_drm_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= drm_open,
> +	.release	= drm_release,
> +	.unlocked_ioctl	= drm_ioctl,
> +#ifdef CONFIG_COMPAT
> +	.compat_ioctl	= drm_compat_ioctl,
> +#endif
> +	.poll		= drm_poll,
> +	.read		= drm_read,
> +	.llseek		= no_llseek,
> +	.mmap		= drm_gem_cma_mmap,
> +};
> +
> +static struct drm_driver fsl_dcu_drm_driver = {
> +	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
> +				| DRIVER_PRIME,
> +	.load			= fsl_dcu_load,
> +	.unload			= fsl_dcu_unload,
> +	.preclose		= fsl_dcu_drm_preclose,
> +	.irq_handler		= fsl_dcu_drm_irq,
> +	.get_vblank_counter	= drm_vblank_count,
> +	.enable_vblank		= fsl_dcu_drm_enable_vblank,
> +	.disable_vblank		= fsl_dcu_drm_disable_vblank,
> +	.gem_free_object	= drm_gem_cma_free_object,
> +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
> +	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
> +	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
> +	.gem_prime_import	= drm_gem_prime_import,
> +	.gem_prime_export	= drm_gem_prime_export,
> +	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
> +	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> +	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
> +	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
> +	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
> +	.dumb_create		= drm_gem_cma_dumb_create,
> +	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
> +	.dumb_destroy		= drm_gem_dumb_destroy,
> +	.fops			= &fsl_dcu_drm_fops,
> +	.name			= "fsl-dcu-drm",
> +	.desc			= "Freescale DCU DRM",
> +	.date			= "20150213",
> +	.major			= 1,
> +	.minor			= 0,
> +};
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int fsl_dcu_drm_pm_suspend(struct device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> +
> +	dcu_pixclk_disable();
> +	drm_kms_helper_poll_disable(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_suspend(&fsl_dev->crtc);
> +
> +	return 0;
> +}
> +
> +static int fsl_dcu_drm_pm_resume(struct device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> +
> +	drm_modeset_lock_all(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_resume(&fsl_dev->crtc);
> +	drm_modeset_unlock_all(fsl_dev->ddev);
> +	drm_kms_helper_poll_enable(fsl_dev->ddev);
> +	dcu_pixclk_enable();
> +	return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops fsl_dcu_drm_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_drm_pm_suspend, fsl_dcu_drm_pm_resume)
> +};
> +
> +static int fsl_dcu_drm_probe(struct platform_device *pdev)
> +{
> +	return drm_platform_init(&fsl_dcu_drm_driver, pdev);
> +}
> +
> +static int fsl_dcu_drm_remove(struct platform_device *pdev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
> +
> +	drm_put_dev(fsl_dev->ddev);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id fsl_dcu_of_match[] = {
> +		{ .compatible = "fsl,dcu", },
> +		{ },
> +};
> +MODULE_DEVICE_TABLE(of, fsl_dcu_of_match);
> +
> +static struct platform_driver fsl_dcu_drm_platform_driver = {
> +	.probe		= fsl_dcu_drm_probe,
> +	.remove		= fsl_dcu_drm_remove,
> +	.driver		= {
> +		.owner	= THIS_MODULE,
> +		.name	= "fsl,dcu",
> +		.pm	= &fsl_dcu_drm_pm_ops,
> +		.of_match_table = fsl_dcu_of_match,
> +	},
> +};
> +
> +module_platform_driver(fsl_dcu_drm_platform_driver);
> +
> +MODULE_ALIAS("platform:fsl-dcu-drm");
> +MODULE_DESCRIPTION("Freescale DCU DRM Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> new file mode 100644
> index 0000000..cbdfefc
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> @@ -0,0 +1,168 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_DRV_H__
> +#define __FSL_DCU_DRM_DRV_H__
> +
> +#include <linux/kernel.h>
> +#include <linux/spinlock.h>
> +#include <stddef.h>
> +#include <drm/drm.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_plane.h"
> +#include "fsl_dcu_drm_connector.h"
> +#define DRIVER_NAME			"fsl-dcu-fb"
> +
> +#define DCU_DCU_MODE			0x0010
> +#define DCU_MODE_BLEND_ITER(x)		((x) << 20)
> +#define DCU_MODE_RASTER_EN		BIT(14)
> +#define DCU_MODE_DCU_MODE(x)		(x)
> +#define DCU_MODE_DCU_MODE_MASK		0x03
> +#define DCU_MODE_OFF			0
> +#define DCU_MODE_NORMAL			1
> +#define DCU_MODE_TEST			2
> +#define DCU_MODE_COLORBAR		3
> +
> +#define DCU_BGND			0x0014
> +#define DCU_BGND_R(x)			((x) << 16)
> +#define DCU_BGND_G(x)			((x) << 8)
> +#define DCU_BGND_B(x)			(x)
> +
> +#define DCU_DISP_SIZE			0x0018
> +#define DCU_DISP_SIZE_DELTA_Y(x)	((x) << 16)
> +/*Regisiter value 1/16 of horizontal resolution*/
> +#define DCU_DISP_SIZE_DELTA_X(x)	((x) >> 4)
> +
> +#define DCU_HSYN_PARA			0x001c
> +#define DCU_HSYN_PARA_BP(x)		((x) << 22)
> +#define DCU_HSYN_PARA_PW(x)		((x) << 11)
> +#define DCU_HSYN_PARA_FP(x)		(x)
> +
> +#define DCU_VSYN_PARA			0x0020
> +#define DCU_VSYN_PARA_BP(x)		((x) << 22)
> +#define DCU_VSYN_PARA_PW(x)		((x) << 11)
> +#define DCU_VSYN_PARA_FP(x)		(x)
> +
> +#define DCU_SYN_POL			0x0024
> +#define DCU_SYN_POL_INV_PXCK_FALL	(0 << 6)
> +#define DCU_SYN_POL_NEG_REMAIN		(0 << 5)
> +#define DCU_SYN_POL_INV_VS_LOW		BIT(1)
> +#define DCU_SYN_POL_INV_HS_LOW		(1)
> +
> +#define DCU_THRESHOLD			0x0028
> +#define DCU_THRESHOLD_LS_BF_VS(x)	((x) << 16)
> +#define DCU_THRESHOLD_OUT_BUF_HIGH(x)	((x) << 8)
> +#define DCU_THRESHOLD_OUT_BUF_LOW(x)	(x)
> +#define BF_VS_VAL			0x03
> +#define BUF_MAX_VAL			0x78
> +#define BUF_MIN_VAL			0x0a
> +
> +#define DCU_INT_STATUS			0x002C
> +#define DCU_INT_STATUS_UNDRUN		BIT(1)
> +
> +#define DCU_INT_MASK			0x0030
> +#define DCU_INT_MASK_UNDRUN		BIT(1)
> +#define DCU_INT_MASK_VBLANK		BIT(3)
> +
> +#define DCU_DIV_RATIO			0x0054
> +
> +#define DCU_UPDATE_MODE			0x00cc
> +#define DCU_UPDATE_MODE_MODE		BIT(31)
> +#define DCU_UPDATE_MODE_READREG		BIT(30)
> +
> +#define DCU_DCFB_MAX			0x300
> +
> +#define DCU_CTRLDESCLN_1(x)		(0x200 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_1_HEIGHT(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_1_WIDTH(x)	(x)
> +
> +#define DCU_CTRLDESCLN_2(x)		(0x204 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_2_POSY(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_2_POSX(x)	(x)
> +
> +#define DCU_CTRLDESCLN_3(x)		(0x208 + (x) * 0x40)
> +
> +#define DCU_CTRLDESCLN_4(x)		(0x20c + (x) * 0x40)
> +#define DCU_CTRLDESCLN_4_EN		BIT(31)
> +#define DCU_CTRLDESCLN_4_TILE_EN	BIT(30)
> +#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT	BIT(29)
> +#define DCU_CTRLDESCLN_4_SAFETY_EN	BIT(28)
> +#define DCU_CTRLDESCLN_4_TRANS(x)	((x) << 20)
> +#define DCU_CTRLDESCLN_4_BPP(x)		((x) << 16)
> +#define DCU_CTRLDESCLN_4_RLE_EN		BIT(15)
> +#define DCU_CTRLDESCLN_4_LUOFFS(x)	((x) << 4)
> +#define DCU_CTRLDESCLN_4_BB_ON		BIT(2)
> +#define DCU_CTRLDESCLN_4_AB(x)		(x)
> +
> +#define DCU_CTRLDESCLN_5(x)		(0x210 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_5_CKMAX_R(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_5_CKMAX_G(x)	((x) << 8)
> +#define DCU_CTRLDESCLN_5_CKMAX_B(x)	(x)
> +
> +#define DCU_CTRLDESCLN_6(x)		(0x214 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_6_CKMIN_R(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_6_CKMIN_G(x)	((x) << 8)
> +#define DCU_CTRLDESCLN_6_CKMIN_B(x)	(x)
> +
> +#define DCU_CTRLDESCLN_7(x)		(0x218 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_7_TILE_VER(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_7_TILE_HOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_8(x)		(0x21c + (x) * 0x40)
> +#define DCU_CTRLDESCLN_8_FG_FCOLOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_9(x)		(0x220 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_9_BG_BCOLOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_10(x)		(0x224 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_10_POST_SKIP(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_10_PRE_SKIP(x)	(x)
> +
> +#define FSL_DCU_RGB565			4
> +#define FSL_DCU_RGB888			5
> +#define FSL_DCU_ARGB8888		6
> +#define FSL_DCU_ARGB1555		11
> +#define FSL_DCU_ARGB4444		12
> +#define FSL_DCU_YUV422			14
> +
> +#define TCON_CTRL1			0x0000
> +#define TCON_BYPASS_ENABLE		BIT(29)
> +
> +#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
> +
> +struct clk;
> +struct device;
> +struct drm_device;
> +
> +struct fsl_dcu_drm_device {
> +	struct device *dev;
> +	struct regmap *regmap;
> +	struct regmap *tcon_regmap;
> +	unsigned int irq;
> +	struct clk *clk;
> +	/*protects hardware register*/
> +	spinlock_t irq_lock;
> +	struct drm_device *ddev;
> +	struct drm_fbdev_cma *fbdev;
> +	struct fsl_dcu_drm_crtc crtc;
> +	struct drm_encoder encoder;
> +	struct fsl_dcu_drm_connector connector;
> +};
> +
> +void fsl_dcu_fbdev_init(struct drm_device *dev);
> +
> +#endif /* __FSL_DCU_DRM_DRV_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> new file mode 100644
> index 0000000..f8ef0e1
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_cma_helper.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +
> +/* initialize fbdev helper */
> +void fsl_dcu_fbdev_init(struct drm_device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
> +
> +	fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1);
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> new file mode 100644
> index 0000000..4a840fb
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> @@ -0,0 +1,42 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_connector.h"
> +#include "fsl_dcu_drm_drv.h"
> +
> +static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs = {
> +	.fb_create = drm_fb_cma_create,
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	drm_mode_config_init(fsl_dev->ddev);
> +
> +	fsl_dev->ddev->mode_config.min_width = 0;
> +	fsl_dev->ddev->mode_config.min_height = 0;
> +	fsl_dev->ddev->mode_config.max_width = 2031;
> +	fsl_dev->ddev->mode_config.max_height = 2047;
> +	fsl_dev->ddev->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;
> +
> +	drm_kms_helper_poll_init(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_create(fsl_dev);
> +	fsl_dcu_drm_encoder_create(fsl_dev);
> +	fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
> +	drm_mode_config_reset(fsl_dev->ddev);
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> new file mode 100644
> index 0000000..b9bd299
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> @@ -0,0 +1,17 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_KMS_H__
> +#define __FSL_DCU_DRM_KMS_H__
> +
> +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
> +
> +#endif /* __FSL_DCU_DRM_KMS_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> new file mode 100644
> index 0000000..b7b4405
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> @@ -0,0 +1,187 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <linux/regmap.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_kms.h"
> +#include "fsl_dcu_drm_plane.h"
> +
> +#define to_fsl_dcu_plane(plane) \
> +	container_of(plane, struct fsl_dcu_drm_plane, plane)
> +
> +static int
> +fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
> +			     struct drm_framebuffer *fb,
> +			     const struct drm_plane_state *new_state)
> +{
> +	return 0;
> +}
> +
> +static void
> +fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
> +			     struct drm_framebuffer *fb,
> +			     const struct drm_plane_state *new_state)
> +{
> +}
> +
> +static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
> +					  struct drm_plane_state *state)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
> +					     struct drm_plane_state *old_state)
> +{
> +}
> +
> +void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
> +				     struct drm_plane_state *old_state)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = plane->state->fb;
> +	u32 index, alpha, bpp;
> +	struct drm_gem_cma_object *gem;
> +	struct fsl_dcu_drm_plane *fsl_plane = to_fsl_dcu_plane(plane);
> +
> +	index = fsl_plane->index;
> +	gem = drm_fb_cma_get_gem_obj(fb, 0);
> +
> +	switch (fb->pixel_format) {
> +	case DRM_FORMAT_RGB565:
> +		bpp = FSL_DCU_RGB565;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_RGB888:
> +		bpp = FSL_DCU_RGB888;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_ARGB8888:
> +		bpp = FSL_DCU_ARGB8888;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_BGRA4444:
> +		bpp = FSL_DCU_ARGB4444;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_ARGB1555:
> +		bpp = FSL_DCU_ARGB1555;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_YUV422:
> +		bpp = FSL_DCU_YUV422;
> +		alpha = 0xff;
> +		break;
> +	default:
> +		return;
> +	}
> +
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_1(index),
> +		     DCU_CTRLDESCLN_1_HEIGHT(state->crtc_h) |
> +		     DCU_CTRLDESCLN_1_WIDTH(state->crtc_w));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_2(index),
> +		     DCU_CTRLDESCLN_2_POSY(state->crtc_y) |
> +		     DCU_CTRLDESCLN_2_POSX(state->crtc_x));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_3(index), gem->paddr);
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_4(index),
> +		     DCU_CTRLDESCLN_4_EN |
> +		     DCU_CTRLDESCLN_4_TRANS(alpha) |
> +		     DCU_CTRLDESCLN_4_BPP(bpp) |
> +		     DCU_CTRLDESCLN_4_AB(2));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_5(index),
> +		     DCU_CTRLDESCLN_5_CKMAX_R(0xFF) |
> +		     DCU_CTRLDESCLN_5_CKMAX_G(0xFF) |
> +		     DCU_CTRLDESCLN_5_CKMAX_B(0xFF));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_6(index),
> +		     DCU_CTRLDESCLN_6_CKMIN_R(0) |
> +		     DCU_CTRLDESCLN_6_CKMIN_G(0) |
> +		     DCU_CTRLDESCLN_6_CKMIN_B(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_8(index),
> +		     DCU_CTRLDESCLN_8_FG_FCOLOR(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_9(index),
> +		     DCU_CTRLDESCLN_9_BG_BCOLOR(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_10(index),
> +		     DCU_CTRLDESCLN_10_POST_SKIP(0) |
> +		     DCU_CTRLDESCLN_10_PRE_SKIP(0));
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +}
> +
> +int fsl_dcu_drm_plane_disable(struct drm_plane *plane)
> +{
> +	return 0;
> +}
> +
> +void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
> +{
> +	fsl_dcu_drm_plane_disable(plane);
> +	drm_plane_cleanup(plane);
> +}
> +
> +static const uint32_t fsl_dcu_drm_plane_formats[] = {
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_RGB888,
> +	DRM_FORMAT_ARGB8888,
> +	DRM_FORMAT_ARGB4444,
> +	DRM_FORMAT_ARGB1555,
> +	DRM_FORMAT_YUV422,
> +};
> +
> +static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
> +	.update_plane = drm_plane_helper_update,
> +	.disable_plane = drm_plane_helper_disable,

These are the transitional helpers used for converting drivers, please
switch to the atomic helpers in drm_atomic_helper.c.

> +	.destroy = fsl_dcu_drm_plane_destroy,
> +	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> +	.reset = drm_atomic_helper_plane_reset,
> +};
> +
> +static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
> +	.prepare_fb = fsl_dcu_drm_plane_prepare_fb,
> +	.cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
> +	.atomic_check = fsl_dcu_drm_plane_atomic_check,
> +	.atomic_update = fsl_dcu_drm_plane_atomic_update,
> +	.atomic_disable = fsl_dcu_drm_plane_atomic_disable,
> +};
> +
> +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
> +{
> +	struct drm_plane *primary;
> +	int ret;
> +
> +	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> +	if (!primary) {
> +		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
> +		return NULL;
> +	}
> +
> +	/* possible_crtc's will be filled in later by crtc_init */
> +	ret = drm_universal_plane_init(dev, primary, 0,
> +				       &fsl_dcu_drm_plane_funcs,
> +				       fsl_dcu_drm_plane_formats,
> +				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
> +				       DRM_PLANE_TYPE_PRIMARY);
> +	if (ret) {
> +		kfree(primary);
> +		primary = NULL;
> +	}
> +	drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
> +
> +	return primary;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> new file mode 100644
> index 0000000..ccbfa61
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> @@ -0,0 +1,23 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_PLANE_H__
> +#define __FSL_DCU_DRM_PLANE_H__
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_plane {
> +	struct drm_plane plane;
> +	unsigned int index;
> +};
> +
> +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev);
> +
> +#endif /* __FSL_DCU_DRM_PLANE_H__ */
> diff --git a/include/linux/fsl/dcu.h b/include/linux/fsl/dcu.h
> new file mode 100644
> index 0000000..1873057
> --- /dev/null
> +++ b/include/linux/fsl/dcu.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_H__
> +#define __FSL_DCU_H__
> +
> +#define SCFG_PIXCLKCR			0x28
> +#define PXCK_ENABLE			BIT(31)
> +#define PXCK_DISABLE			0
> +
> +void dcu_pixclk_enable(void);
> +void dcu_pixclk_disable(void);
> +
> +#endif /* __FSL_DCU_H__ */
> -- 
> 2.1.0.27.g96db324
> 

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


-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
@ 2015-03-19 14:30   ` Daniel Vetter
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Vetter @ 2015-03-19 14:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Mar 13, 2015 at 05:44:17PM +0800, Jianwei Wang wrote:
> This patch add support for Two Dimensional Animation and Compositing
> Engine (2D-ACE) on Freescale SoCs.
> 
> 2D-ACE is a Freescale display controller. It provide an hardware
> cursor.
> 
> This is a simplified version, only a primary plane, a fb created for
> fbdev, a crtc, a connector for TFT LCD panel, an encoder, and the
> encoder is not in use.
> 
> Signed-off-by: Alison Wang <b18965@freescale.com>
> Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> Signed-off-by: Jianwei Wang <b52261@freescale.com>

I've spotted two more places where you need to upgrade to atomic functions
for legacy entry points. Otherwise it looks good from that pov. See
comments below.

Thanks, Daniel

> ---
> 
> Changed in v2:?
> - Add atomic support
> - Modify bindings file
> - Rename node for compatibility
> - Move platform related code out for compatibility
> 
> Added in v1:?
> -?Add support for DCU display controller on the Freescale LS102x SoCs.
> - Create a primary plane, a fb created for fbdev, a crtc, a connector
> for TFT LCD panel, an encoder.
> 
>  arch/arm/mach-imx/mach-ls1021a.c            |  36 ++++
>  drivers/gpu/drm/Kconfig                     |   2 +
>  drivers/gpu/drm/Makefile                    |   1 +
>  drivers/gpu/drm/fsl/Kconfig                 |  17 ++
>  drivers/gpu/drm/fsl/Makefile                |   8 +
>  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c | 203 ++++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h |  28 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c      | 164 ++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h      |  26 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c       | 288 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h       | 168 ++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c     |  26 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c       |  42 ++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h       |  17 ++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c     | 187 ++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h     |  23 +++
>  include/linux/fsl/dcu.h                     |  22 +++
>  17 files changed, 1258 insertions(+)
>  create mode 100644 drivers/gpu/drm/fsl/Kconfig
>  create mode 100644 drivers/gpu/drm/fsl/Makefile
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
>  create mode 100644 include/linux/fsl/dcu.h
> 
> diff --git a/arch/arm/mach-imx/mach-ls1021a.c b/arch/arm/mach-imx/mach-ls1021a.c
> index b89c858..4fb346d 100644
> --- a/arch/arm/mach-imx/mach-ls1021a.c
> +++ b/arch/arm/mach-imx/mach-ls1021a.c
> @@ -8,9 +8,44 @@
>   */
>  
>  #include <asm/mach/arch.h>
> +#include <linux/of_platform.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <linux/fsl/dcu.h>
>  
>  #include "common.h"
>  
> +void dcu_pixclk_disable(void)
> +{
> +	struct regmap *scfg_regmap;
> +
> +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> +	if (IS_ERR(scfg_regmap)) {
> +		pr_err("No syscfg phandle specified\n");
> +		return;
> +	}
> +
> +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_DISABLE);
> +}
> +
> +void dcu_pixclk_enable(void)
> +{
> +	struct regmap *scfg_regmap;
> +
> +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> +	if (IS_ERR(scfg_regmap)) {
> +		pr_err("No syscfg phandle specified\n");
> +		return;
> +	}
> +
> +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_ENABLE);
> +}
> +
> +static void __init ls1021a_init_machine(void)
> +{
> +	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> +	dcu_pixclk_enable();
> +}
>  static const char * const ls1021a_dt_compat[] __initconst = {
>  	"fsl,ls1021a",
>  	NULL,
> @@ -18,5 +53,6 @@ static const char * const ls1021a_dt_compat[] __initconst = {
>  
>  DT_MACHINE_START(LS1021A, "Freescale LS1021A")
>  	.smp		= smp_ops(ls1021a_smp_ops),
> +	.init_machine	= ls1021a_init_machine,
>  	.dt_compat	= ls1021a_dt_compat,
>  MACHINE_END
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index 151a050..a6957aa 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -199,6 +199,8 @@ source "drivers/gpu/drm/bochs/Kconfig"
>  
>  source "drivers/gpu/drm/msm/Kconfig"
>  
> +source "drivers/gpu/drm/fsl/Kconfig"
> +
>  source "drivers/gpu/drm/tegra/Kconfig"
>  
>  source "drivers/gpu/drm/panel/Kconfig"
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 2c239b9..ab5b9ef 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -56,6 +56,7 @@ obj-$(CONFIG_DRM_UDL) += udl/
>  obj-$(CONFIG_DRM_AST) += ast/
>  obj-$(CONFIG_DRM_ARMADA) += armada/
>  obj-$(CONFIG_DRM_ATMEL_HLCDC)	+= atmel-hlcdc/
> +obj-$(CONFIG_DRM_FSL_DCU) += fsl/
>  obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
>  obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
>  obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
> diff --git a/drivers/gpu/drm/fsl/Kconfig b/drivers/gpu/drm/fsl/Kconfig
> new file mode 100644
> index 0000000..e4f8df0
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/Kconfig
> @@ -0,0 +1,17 @@
> +config DRM_FSL_DCU
> +	tristate "DRM Support for Freescale DCU"
> +	depends on DRM && OF && ARM
> +	select DRM_KMS_HELPER
> +	select DRM_KMS_CMA_HELPER
> +	select VIDEOMODE_HELPERS
> +	select BACKLIGHT_CLASS_DEVICE
> +	select BACKLIGHT_LCD_SUPPORT
> +	select REGMAP_MMIO
> +	select DRM_KMS_FB_HELPER
> +	select FB_SYS_FILLRECT
> +	select FB_SYS_COPYAREA
> +	select FB_SYS_IMAGEBLIT
> +	select FB_SYS_FOPS
> +	help
> +	  Choose this option if you have an Freescale DCU chipset.
> +	  If M is selected the module will be called fsl-dcu-drm.
> diff --git a/drivers/gpu/drm/fsl/Makefile b/drivers/gpu/drm/fsl/Makefile
> new file mode 100644
> index 0000000..5f74aee
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/Makefile
> @@ -0,0 +1,8 @@
> +fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
> +	       fsl_dcu_drm_kms.o \
> +	       fsl_dcu_drm_connector.o \
> +	       fsl_dcu_drm_plane.o \
> +	       fsl_dcu_drm_crtc.o \
> +	       fsl_dcu_drm_fbdev.o \
> +
> +obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> new file mode 100644
> index 0000000..178d647
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> @@ -0,0 +1,203 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/backlight.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <video/of_display_timing.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_connector.h"
> +
> +static void fsl_dcu_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
> +{
> +}
> +
> +/* Disable the encoders as the first thing we do. */
> +static void fsl_dcu_drm_encoder_mode_prepare(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_mode_set(struct drm_encoder *encoder,
> +					 struct drm_display_mode *mode,
> +					 struct drm_display_mode *adjusted_mode)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_mode_commit(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
> +{
> +}
> +
> +static int
> +fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
> +				 struct drm_crtc_state *crtc_state,
> +				 struct drm_connector_state *conn_state)
> +{
> +	return 0;
> +}
> +
> +static bool
> +fsl_dcu_drm_encoder_mode_fixup(struct drm_encoder *encoder,
> +			       const struct drm_display_mode *mode,
> +			       struct drm_display_mode *adjusted_mode)
> +{
> +	return true;
> +}
> +
> +static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
> +{
> +	drm_encoder_cleanup(encoder);
> +}
> +
> +static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
> +	.dpms = fsl_dcu_drm_encoder_dpms,
> +	.prepare = fsl_dcu_drm_encoder_mode_prepare,
> +	.commit = fsl_dcu_drm_encoder_mode_commit,
> +	.mode_set = fsl_dcu_drm_encoder_mode_set,
> +	.disable = fsl_dcu_drm_encoder_disable,
> +	.atomic_check = fsl_dcu_drm_encoder_atomic_check,
> +	.mode_fixup = fsl_dcu_drm_encoder_mode_fixup,
> +};
> +
> +static const struct drm_encoder_funcs encoder_funcs = {
> +	.destroy = fsl_dcu_drm_encoder_destroy,
> +};
> +
> +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	struct drm_encoder *encoder = &fsl_dev->encoder;
> +	int ret;
> +
> +	encoder->possible_crtcs = 1;
> +
> +	ret = drm_encoder_init(fsl_dev->ddev, encoder, &encoder_funcs,
> +			       DRM_MODE_ENCODER_LVDS);
> +	if (ret < 0)
> +		return ret;
> +
> +	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
> +
> +	return 0;
> +}
> +
> +#define to_fsl_dcu_connector(connector) \
> +	container_of(connector, struct fsl_dcu_drm_connector, connector)
> +
> +static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector)
> +{
> +	struct drm_device *dev = connector->dev;
> +	struct device_node *display_np, *np = dev->dev->of_node;
> +	struct drm_display_mode *mode = drm_mode_create(connector->dev);
> +	int num_modes = 0;
> +
> +	if (np) {
> +		display_np = of_parse_phandle(np, "display", 0);
> +		if (!display_np) {
> +			dev_err(dev->dev, "failed to find display phandle\n");
> +			return num_modes;
> +		}
> +		of_get_drm_display_mode(display_np, mode, OF_USE_NATIVE_MODE);
> +		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> +		drm_mode_probed_add(connector, mode);
> +		num_modes++;
> +	}
> +
> +	return num_modes;
> +}
> +
> +static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
> +					    struct drm_display_mode *mode)
> +{
> +	return MODE_OK;
> +}
> +
> +static struct drm_encoder *
> +fsl_dcu_drm_connector_best_encoder(struct drm_connector *connector)
> +{
> +	struct fsl_dcu_drm_connector *fsl_con = to_fsl_dcu_connector(connector);
> +
> +	return fsl_con->encoder;
> +}
> +
> +static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_connector_unregister(connector);
> +	drm_connector_cleanup(connector);
> +}
> +
> +static enum drm_connector_status
> +fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	return connector_status_connected;
> +}
> +
> +static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
> +	.dpms = drm_atomic_helper_connector_dpms,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.detect = fsl_dcu_drm_connector_detect,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.destroy = fsl_dcu_drm_connector_destroy,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static const struct drm_connector_helper_funcs connector_helper_funcs = {
> +	.get_modes = fsl_dcu_drm_connector_get_modes,
> +	.mode_valid = fsl_dcu_drm_connector_mode_valid,
> +	.best_encoder = fsl_dcu_drm_connector_best_encoder,
> +};
> +
> +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> +				 struct drm_encoder *encoder)
> +{
> +	struct drm_connector *connector = &fsl_dev->connector.connector;
> +	int ret;
> +
> +	fsl_dev->connector.encoder = encoder;
> +
> +	connector->display_info.width_mm = 0;
> +	connector->display_info.height_mm = 0;
> +
> +	ret = drm_connector_init(fsl_dev->ddev, connector,
> +				 &fsl_dcu_drm_connector_funcs,
> +				 DRM_MODE_CONNECTOR_LVDS);
> +	if (ret < 0)
> +		return ret;
> +
> +	connector->dpms = DRM_MODE_DPMS_OFF;
> +	drm_connector_helper_add(connector, &connector_helper_funcs);
> +	ret = drm_connector_register(connector);
> +	if (ret < 0)
> +		goto err_cleanup;
> +
> +	ret = drm_mode_connector_attach_encoder(connector, encoder);
> +	if (ret < 0)
> +		goto err_sysfs;
> +
> +	connector->encoder = encoder;
> +
> +	drm_object_property_set_value
> +		(&connector->base, fsl_dev->ddev->mode_config.dpms_property,
> +		DRM_MODE_DPMS_OFF);
> +
> +	return 0;
> +
> +err_sysfs:
> +	drm_connector_unregister(connector);
> +err_cleanup:
> +	drm_connector_cleanup(connector);
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> new file mode 100644
> index 0000000..afe44ab
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> @@ -0,0 +1,28 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_CONNECTOR_H__
> +#define __FSL_DCU_DRM_CONNECTOR_H__
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_connector {
> +	struct drm_connector connector;
> +	struct drm_encoder *encoder;
> +};
> +
> +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev);
> +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> +				 struct drm_encoder *encoder);
> +
> +#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> new file mode 100644
> index 0000000..a43e7ce
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> @@ -0,0 +1,164 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/regmap.h>
> +#include <linux/clk.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_plane.h"
> +
> +#define to_fsl_dcu_crtc(c)	container_of(c, struct fsl_dcu_drm_crtc, crtc)
> +
> +void fsl_dcu_drm_crtc_suspend(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
> +	struct drm_display_mode *mode = &crtc->state->mode;
> +	uint32_t hbp, hfp, hsw, vbp, vfp, vsw, div, index;
> +
> +	DBG(": set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
> +	    mode->base.id, mode->name,
> +	    mode->vrefresh, mode->clock,
> +	    mode->hdisplay, mode->hsync_start,
> +	    mode->hsync_end, mode->htotal,
> +	    mode->vdisplay, mode->vsync_start,
> +	    mode->vsync_end, mode->vtotal,
> +	    mode->type, mode->flags);
> +
> +	index = drm_crtc_index(crtc);
> +	div = (uint32_t)clk_get_rate(fsl_dev->clk) / mode->clock / 1000;
> +
> +	/* Configure timings: */
> +	hbp = mode->htotal - mode->hsync_end;
> +	hfp = mode->hsync_start - mode->hdisplay;
> +	hsw = mode->hsync_end - mode->hsync_start;
> +	vbp = mode->vtotal - mode->vsync_end;
> +	vfp = mode->vsync_start - mode->vdisplay;
> +	vsw = mode->vsync_end - mode->vsync_start;
> +
> +	regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
> +		     DCU_HSYN_PARA_BP(hbp) |
> +		     DCU_HSYN_PARA_PW(hsw) |
> +		     DCU_HSYN_PARA_FP(hfp));
> +	regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
> +		     DCU_VSYN_PARA_BP(vbp) |
> +		     DCU_VSYN_PARA_PW(vsw) |
> +		     DCU_VSYN_PARA_FP(vfp));
> +	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
> +		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
> +		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
> +	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +}
> +
> +static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
> +					const struct drm_display_mode *mode,
> +					struct drm_display_mode *adjusted_mode)
> +{
> +	return true;
> +}
> +
> +static void fsl_dcu_drm_crtc_prepare(struct drm_crtc *crtc)
> +{
> +}
> +
> +/* Now enable the clocks, plane, pipe, and connectors that we set up. */
> +static void fsl_dcu_drm_crtc_mode_commit(struct drm_crtc *crtc)
> +{
> +}
> +
> +static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
> +					 struct drm_crtc_state *state)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
> +{
> +}
> +
> +static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
> +	.page_flip = drm_atomic_helper_page_flip,
> +	.set_config = drm_crtc_helper_set_config,

This is the legacy function, please use the atomic one instead from
drm_atomic_helper.c for ->set_config.

> +	.destroy = drm_crtc_cleanup,
> +	.reset = drm_atomic_helper_crtc_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> +};
> +
> +static void fsl_dcu_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
> +{
> +}
> +
> +static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
> +	.disable = fsl_dcu_drm_disable_crtc,
> +	.mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
> +	.mode_set = drm_helper_crtc_mode_set,
> +	.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
> +	.mode_set_base = drm_helper_crtc_mode_set_base,
> +	.prepare = fsl_dcu_drm_crtc_prepare,
> +	.commit = fsl_dcu_drm_crtc_mode_commit,
> +	.atomic_check = fsl_dcu_drm_crtc_atomic_check,
> +	.atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
> +	.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
> +	.dpms = fsl_dcu_drm_crtc_dpms,
> +};
> +
> +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	struct drm_plane *primary;
> +	struct drm_crtc *crtc = &fsl_dev->crtc.crtc;
> +	int ret;
> +
> +	fsl_dev->crtc.dpms = DRM_MODE_DPMS_OFF;
> +
> +	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->ddev);
> +	ret = drm_crtc_init_with_planes(fsl_dev->ddev, crtc, primary, NULL,
> +					&fsl_dcu_drm_crtc_funcs);
> +	if (ret < 0)
> +		return ret;
> +
> +	drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
> +
> +	regmap_write(fsl_dev->regmap, DCU_SYN_POL,
> +		     DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
> +	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
> +		     DCU_BGND_G(0) | DCU_BGND_B(0));
> +	regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
> +		     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
> +	regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
> +		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
> +		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
> +		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
> +	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
> +			   DCU_MODE_DCU_MODE_MASK,
> +			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> new file mode 100644
> index 0000000..d44b564
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_CRTC_H__
> +#define __FSL_DCU_DRM_CRTC_H__
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_crtc {
> +	struct drm_crtc crtc;
> +	int dpms;
> +};
> +
> +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev);
> +
> +#endif /* __FSL_DCU_DRM_CRTC_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> new file mode 100644
> index 0000000..10975ee
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> @@ -0,0 +1,288 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/mm.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> +
> +#include <drm/drmP.h>
> +#include <linux/fsl/dcu.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_kms.h"
> +
> +static int fsl_dcu_unload(struct drm_device *dev)
> +{
> +	drm_mode_config_cleanup(dev);
> +	drm_vblank_cleanup(dev);
> +	drm_irq_uninstall(dev);
> +
> +	dev->dev_private = NULL;
> +
> +	return 0;
> +}
> +
> +static struct regmap_config fsl_dcu_regmap_config = {
> +	.reg_bits = 32,
> +	.reg_stride = 4,
> +	.val_bits = 32,
> +};
> +
> +static int fsl_dcu_bypass_tcon(struct fsl_dcu_drm_device *fsl_dev,
> +			       struct device_node *np)
> +{
> +	struct device_node *tcon_np;
> +	struct platform_device *pdev;
> +	struct clk *tcon_clk;
> +	struct resource *res;
> +	void __iomem *base;
> +
> +	tcon_np = of_parse_phandle(np, "tcon-controller", 0);
> +	if (!tcon_np)
> +		return -EINVAL;
> +
> +	pdev = of_find_device_by_node(tcon_np);
> +	if (!pdev)
> +		return -EINVAL;
> +
> +	tcon_clk = devm_clk_get(&pdev->dev, "tcon");
> +	if (IS_ERR(tcon_clk))
> +		return PTR_ERR(tcon_clk);
> +	clk_prepare_enable(tcon_clk);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -ENODEV;
> +
> +	base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	fsl_dev->tcon_regmap = devm_regmap_init_mmio_clk(&pdev->dev,
> +			"tcon", base, &fsl_dcu_regmap_config);
> +	if (IS_ERR(fsl_dev->tcon_regmap)) {
> +		dev_err(&pdev->dev, "regmap init failed\n");
> +		return PTR_ERR(fsl_dev->tcon_regmap);
> +	}
> +
> +	regmap_write(fsl_dev->tcon_regmap, TCON_CTRL1, TCON_BYPASS_ENABLE);
> +	return 0;
> +}
> +
> +static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
> +{
> +	struct platform_device *pdev = dev->platformdev;
> +	struct fsl_dcu_drm_device *fsl_dev;
> +	struct resource *res;
> +	void __iomem *base;
> +	int ret;
> +
> +	fsl_dev = devm_kzalloc(&pdev->dev, sizeof(*fsl_dev), GFP_KERNEL);
> +	if (!fsl_dev)
> +		return -ENOMEM;
> +
> +	fsl_dev->dev = &pdev->dev;
> +	fsl_dev->ddev = dev;
> +	dev->dev_private = fsl_dev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(base)) {
> +		ret = PTR_ERR(base);
> +		return ret;
> +	}
> +
> +	fsl_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
> +			base, &fsl_dcu_regmap_config);
> +	if (IS_ERR(fsl_dev->regmap)) {
> +		dev_err(&pdev->dev, "regmap init failed\n");
> +		return PTR_ERR(fsl_dev->regmap);
> +	}
> +
> +	ret = fsl_dcu_drm_modeset_init(fsl_dev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to initialize mode setting\n");
> +		return ret;
> +	}
> +
> +	ret = drm_vblank_init(dev, 1);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to initialize vblank\n");
> +		goto done;
> +	}
> +
> +	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to install IRQ handler\n");
> +		goto done;
> +	}
> +
> +	/* Put TCON in bypass mode, so the input signals from DCU are passed
> +	 * through TCON unchanged */
> +	fsl_dcu_bypass_tcon(fsl_dev, pdev->dev.of_node);
> +
> +	fsl_dev->clk = devm_clk_get(&pdev->dev, "dcu");
> +	if (IS_ERR(fsl_dev->clk)) {
> +		ret = PTR_ERR(fsl_dev->clk);
> +		dev_err(&pdev->dev, "could not get clock\n");
> +		return ret;
> +	}
> +	clk_prepare_enable(fsl_dev->clk);
> +
> +	dev_set_drvdata(dev->dev, fsl_dev);
> +
> +	fsl_dcu_fbdev_init(dev);
> +
> +	return 0;
> +done:
> +	if (ret)
> +		fsl_dcu_unload(dev);
> +
> +	return ret;
> +}
> +
> +static void fsl_dcu_drm_preclose(struct drm_device *dev, struct drm_file *file)
> +{
> +	;
> +}
> +
> +static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
> +{
> +	return IRQ_HANDLED;
> +}
> +
> +static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int crtc)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int crtc)
> +{
> +	;
> +}
> +
> +static const struct file_operations fsl_dcu_drm_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= drm_open,
> +	.release	= drm_release,
> +	.unlocked_ioctl	= drm_ioctl,
> +#ifdef CONFIG_COMPAT
> +	.compat_ioctl	= drm_compat_ioctl,
> +#endif
> +	.poll		= drm_poll,
> +	.read		= drm_read,
> +	.llseek		= no_llseek,
> +	.mmap		= drm_gem_cma_mmap,
> +};
> +
> +static struct drm_driver fsl_dcu_drm_driver = {
> +	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
> +				| DRIVER_PRIME,
> +	.load			= fsl_dcu_load,
> +	.unload			= fsl_dcu_unload,
> +	.preclose		= fsl_dcu_drm_preclose,
> +	.irq_handler		= fsl_dcu_drm_irq,
> +	.get_vblank_counter	= drm_vblank_count,
> +	.enable_vblank		= fsl_dcu_drm_enable_vblank,
> +	.disable_vblank		= fsl_dcu_drm_disable_vblank,
> +	.gem_free_object	= drm_gem_cma_free_object,
> +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
> +	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
> +	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
> +	.gem_prime_import	= drm_gem_prime_import,
> +	.gem_prime_export	= drm_gem_prime_export,
> +	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
> +	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> +	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
> +	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
> +	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
> +	.dumb_create		= drm_gem_cma_dumb_create,
> +	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
> +	.dumb_destroy		= drm_gem_dumb_destroy,
> +	.fops			= &fsl_dcu_drm_fops,
> +	.name			= "fsl-dcu-drm",
> +	.desc			= "Freescale DCU DRM",
> +	.date			= "20150213",
> +	.major			= 1,
> +	.minor			= 0,
> +};
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int fsl_dcu_drm_pm_suspend(struct device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> +
> +	dcu_pixclk_disable();
> +	drm_kms_helper_poll_disable(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_suspend(&fsl_dev->crtc);
> +
> +	return 0;
> +}
> +
> +static int fsl_dcu_drm_pm_resume(struct device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> +
> +	drm_modeset_lock_all(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_resume(&fsl_dev->crtc);
> +	drm_modeset_unlock_all(fsl_dev->ddev);
> +	drm_kms_helper_poll_enable(fsl_dev->ddev);
> +	dcu_pixclk_enable();
> +	return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops fsl_dcu_drm_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_drm_pm_suspend, fsl_dcu_drm_pm_resume)
> +};
> +
> +static int fsl_dcu_drm_probe(struct platform_device *pdev)
> +{
> +	return drm_platform_init(&fsl_dcu_drm_driver, pdev);
> +}
> +
> +static int fsl_dcu_drm_remove(struct platform_device *pdev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
> +
> +	drm_put_dev(fsl_dev->ddev);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id fsl_dcu_of_match[] = {
> +		{ .compatible = "fsl,dcu", },
> +		{ },
> +};
> +MODULE_DEVICE_TABLE(of, fsl_dcu_of_match);
> +
> +static struct platform_driver fsl_dcu_drm_platform_driver = {
> +	.probe		= fsl_dcu_drm_probe,
> +	.remove		= fsl_dcu_drm_remove,
> +	.driver		= {
> +		.owner	= THIS_MODULE,
> +		.name	= "fsl,dcu",
> +		.pm	= &fsl_dcu_drm_pm_ops,
> +		.of_match_table = fsl_dcu_of_match,
> +	},
> +};
> +
> +module_platform_driver(fsl_dcu_drm_platform_driver);
> +
> +MODULE_ALIAS("platform:fsl-dcu-drm");
> +MODULE_DESCRIPTION("Freescale DCU DRM Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> new file mode 100644
> index 0000000..cbdfefc
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> @@ -0,0 +1,168 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_DRV_H__
> +#define __FSL_DCU_DRM_DRV_H__
> +
> +#include <linux/kernel.h>
> +#include <linux/spinlock.h>
> +#include <stddef.h>
> +#include <drm/drm.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_plane.h"
> +#include "fsl_dcu_drm_connector.h"
> +#define DRIVER_NAME			"fsl-dcu-fb"
> +
> +#define DCU_DCU_MODE			0x0010
> +#define DCU_MODE_BLEND_ITER(x)		((x) << 20)
> +#define DCU_MODE_RASTER_EN		BIT(14)
> +#define DCU_MODE_DCU_MODE(x)		(x)
> +#define DCU_MODE_DCU_MODE_MASK		0x03
> +#define DCU_MODE_OFF			0
> +#define DCU_MODE_NORMAL			1
> +#define DCU_MODE_TEST			2
> +#define DCU_MODE_COLORBAR		3
> +
> +#define DCU_BGND			0x0014
> +#define DCU_BGND_R(x)			((x) << 16)
> +#define DCU_BGND_G(x)			((x) << 8)
> +#define DCU_BGND_B(x)			(x)
> +
> +#define DCU_DISP_SIZE			0x0018
> +#define DCU_DISP_SIZE_DELTA_Y(x)	((x) << 16)
> +/*Regisiter value 1/16 of horizontal resolution*/
> +#define DCU_DISP_SIZE_DELTA_X(x)	((x) >> 4)
> +
> +#define DCU_HSYN_PARA			0x001c
> +#define DCU_HSYN_PARA_BP(x)		((x) << 22)
> +#define DCU_HSYN_PARA_PW(x)		((x) << 11)
> +#define DCU_HSYN_PARA_FP(x)		(x)
> +
> +#define DCU_VSYN_PARA			0x0020
> +#define DCU_VSYN_PARA_BP(x)		((x) << 22)
> +#define DCU_VSYN_PARA_PW(x)		((x) << 11)
> +#define DCU_VSYN_PARA_FP(x)		(x)
> +
> +#define DCU_SYN_POL			0x0024
> +#define DCU_SYN_POL_INV_PXCK_FALL	(0 << 6)
> +#define DCU_SYN_POL_NEG_REMAIN		(0 << 5)
> +#define DCU_SYN_POL_INV_VS_LOW		BIT(1)
> +#define DCU_SYN_POL_INV_HS_LOW		(1)
> +
> +#define DCU_THRESHOLD			0x0028
> +#define DCU_THRESHOLD_LS_BF_VS(x)	((x) << 16)
> +#define DCU_THRESHOLD_OUT_BUF_HIGH(x)	((x) << 8)
> +#define DCU_THRESHOLD_OUT_BUF_LOW(x)	(x)
> +#define BF_VS_VAL			0x03
> +#define BUF_MAX_VAL			0x78
> +#define BUF_MIN_VAL			0x0a
> +
> +#define DCU_INT_STATUS			0x002C
> +#define DCU_INT_STATUS_UNDRUN		BIT(1)
> +
> +#define DCU_INT_MASK			0x0030
> +#define DCU_INT_MASK_UNDRUN		BIT(1)
> +#define DCU_INT_MASK_VBLANK		BIT(3)
> +
> +#define DCU_DIV_RATIO			0x0054
> +
> +#define DCU_UPDATE_MODE			0x00cc
> +#define DCU_UPDATE_MODE_MODE		BIT(31)
> +#define DCU_UPDATE_MODE_READREG		BIT(30)
> +
> +#define DCU_DCFB_MAX			0x300
> +
> +#define DCU_CTRLDESCLN_1(x)		(0x200 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_1_HEIGHT(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_1_WIDTH(x)	(x)
> +
> +#define DCU_CTRLDESCLN_2(x)		(0x204 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_2_POSY(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_2_POSX(x)	(x)
> +
> +#define DCU_CTRLDESCLN_3(x)		(0x208 + (x) * 0x40)
> +
> +#define DCU_CTRLDESCLN_4(x)		(0x20c + (x) * 0x40)
> +#define DCU_CTRLDESCLN_4_EN		BIT(31)
> +#define DCU_CTRLDESCLN_4_TILE_EN	BIT(30)
> +#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT	BIT(29)
> +#define DCU_CTRLDESCLN_4_SAFETY_EN	BIT(28)
> +#define DCU_CTRLDESCLN_4_TRANS(x)	((x) << 20)
> +#define DCU_CTRLDESCLN_4_BPP(x)		((x) << 16)
> +#define DCU_CTRLDESCLN_4_RLE_EN		BIT(15)
> +#define DCU_CTRLDESCLN_4_LUOFFS(x)	((x) << 4)
> +#define DCU_CTRLDESCLN_4_BB_ON		BIT(2)
> +#define DCU_CTRLDESCLN_4_AB(x)		(x)
> +
> +#define DCU_CTRLDESCLN_5(x)		(0x210 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_5_CKMAX_R(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_5_CKMAX_G(x)	((x) << 8)
> +#define DCU_CTRLDESCLN_5_CKMAX_B(x)	(x)
> +
> +#define DCU_CTRLDESCLN_6(x)		(0x214 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_6_CKMIN_R(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_6_CKMIN_G(x)	((x) << 8)
> +#define DCU_CTRLDESCLN_6_CKMIN_B(x)	(x)
> +
> +#define DCU_CTRLDESCLN_7(x)		(0x218 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_7_TILE_VER(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_7_TILE_HOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_8(x)		(0x21c + (x) * 0x40)
> +#define DCU_CTRLDESCLN_8_FG_FCOLOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_9(x)		(0x220 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_9_BG_BCOLOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_10(x)		(0x224 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_10_POST_SKIP(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_10_PRE_SKIP(x)	(x)
> +
> +#define FSL_DCU_RGB565			4
> +#define FSL_DCU_RGB888			5
> +#define FSL_DCU_ARGB8888		6
> +#define FSL_DCU_ARGB1555		11
> +#define FSL_DCU_ARGB4444		12
> +#define FSL_DCU_YUV422			14
> +
> +#define TCON_CTRL1			0x0000
> +#define TCON_BYPASS_ENABLE		BIT(29)
> +
> +#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
> +
> +struct clk;
> +struct device;
> +struct drm_device;
> +
> +struct fsl_dcu_drm_device {
> +	struct device *dev;
> +	struct regmap *regmap;
> +	struct regmap *tcon_regmap;
> +	unsigned int irq;
> +	struct clk *clk;
> +	/*protects hardware register*/
> +	spinlock_t irq_lock;
> +	struct drm_device *ddev;
> +	struct drm_fbdev_cma *fbdev;
> +	struct fsl_dcu_drm_crtc crtc;
> +	struct drm_encoder encoder;
> +	struct fsl_dcu_drm_connector connector;
> +};
> +
> +void fsl_dcu_fbdev_init(struct drm_device *dev);
> +
> +#endif /* __FSL_DCU_DRM_DRV_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> new file mode 100644
> index 0000000..f8ef0e1
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_cma_helper.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +
> +/* initialize fbdev helper */
> +void fsl_dcu_fbdev_init(struct drm_device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
> +
> +	fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1);
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> new file mode 100644
> index 0000000..4a840fb
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> @@ -0,0 +1,42 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_connector.h"
> +#include "fsl_dcu_drm_drv.h"
> +
> +static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs = {
> +	.fb_create = drm_fb_cma_create,
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	drm_mode_config_init(fsl_dev->ddev);
> +
> +	fsl_dev->ddev->mode_config.min_width = 0;
> +	fsl_dev->ddev->mode_config.min_height = 0;
> +	fsl_dev->ddev->mode_config.max_width = 2031;
> +	fsl_dev->ddev->mode_config.max_height = 2047;
> +	fsl_dev->ddev->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;
> +
> +	drm_kms_helper_poll_init(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_create(fsl_dev);
> +	fsl_dcu_drm_encoder_create(fsl_dev);
> +	fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
> +	drm_mode_config_reset(fsl_dev->ddev);
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> new file mode 100644
> index 0000000..b9bd299
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> @@ -0,0 +1,17 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_KMS_H__
> +#define __FSL_DCU_DRM_KMS_H__
> +
> +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
> +
> +#endif /* __FSL_DCU_DRM_KMS_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> new file mode 100644
> index 0000000..b7b4405
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> @@ -0,0 +1,187 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <linux/regmap.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_kms.h"
> +#include "fsl_dcu_drm_plane.h"
> +
> +#define to_fsl_dcu_plane(plane) \
> +	container_of(plane, struct fsl_dcu_drm_plane, plane)
> +
> +static int
> +fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
> +			     struct drm_framebuffer *fb,
> +			     const struct drm_plane_state *new_state)
> +{
> +	return 0;
> +}
> +
> +static void
> +fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
> +			     struct drm_framebuffer *fb,
> +			     const struct drm_plane_state *new_state)
> +{
> +}
> +
> +static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
> +					  struct drm_plane_state *state)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
> +					     struct drm_plane_state *old_state)
> +{
> +}
> +
> +void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
> +				     struct drm_plane_state *old_state)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = plane->state->fb;
> +	u32 index, alpha, bpp;
> +	struct drm_gem_cma_object *gem;
> +	struct fsl_dcu_drm_plane *fsl_plane = to_fsl_dcu_plane(plane);
> +
> +	index = fsl_plane->index;
> +	gem = drm_fb_cma_get_gem_obj(fb, 0);
> +
> +	switch (fb->pixel_format) {
> +	case DRM_FORMAT_RGB565:
> +		bpp = FSL_DCU_RGB565;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_RGB888:
> +		bpp = FSL_DCU_RGB888;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_ARGB8888:
> +		bpp = FSL_DCU_ARGB8888;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_BGRA4444:
> +		bpp = FSL_DCU_ARGB4444;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_ARGB1555:
> +		bpp = FSL_DCU_ARGB1555;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_YUV422:
> +		bpp = FSL_DCU_YUV422;
> +		alpha = 0xff;
> +		break;
> +	default:
> +		return;
> +	}
> +
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_1(index),
> +		     DCU_CTRLDESCLN_1_HEIGHT(state->crtc_h) |
> +		     DCU_CTRLDESCLN_1_WIDTH(state->crtc_w));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_2(index),
> +		     DCU_CTRLDESCLN_2_POSY(state->crtc_y) |
> +		     DCU_CTRLDESCLN_2_POSX(state->crtc_x));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_3(index), gem->paddr);
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_4(index),
> +		     DCU_CTRLDESCLN_4_EN |
> +		     DCU_CTRLDESCLN_4_TRANS(alpha) |
> +		     DCU_CTRLDESCLN_4_BPP(bpp) |
> +		     DCU_CTRLDESCLN_4_AB(2));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_5(index),
> +		     DCU_CTRLDESCLN_5_CKMAX_R(0xFF) |
> +		     DCU_CTRLDESCLN_5_CKMAX_G(0xFF) |
> +		     DCU_CTRLDESCLN_5_CKMAX_B(0xFF));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_6(index),
> +		     DCU_CTRLDESCLN_6_CKMIN_R(0) |
> +		     DCU_CTRLDESCLN_6_CKMIN_G(0) |
> +		     DCU_CTRLDESCLN_6_CKMIN_B(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_8(index),
> +		     DCU_CTRLDESCLN_8_FG_FCOLOR(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_9(index),
> +		     DCU_CTRLDESCLN_9_BG_BCOLOR(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_10(index),
> +		     DCU_CTRLDESCLN_10_POST_SKIP(0) |
> +		     DCU_CTRLDESCLN_10_PRE_SKIP(0));
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +}
> +
> +int fsl_dcu_drm_plane_disable(struct drm_plane *plane)
> +{
> +	return 0;
> +}
> +
> +void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
> +{
> +	fsl_dcu_drm_plane_disable(plane);
> +	drm_plane_cleanup(plane);
> +}
> +
> +static const uint32_t fsl_dcu_drm_plane_formats[] = {
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_RGB888,
> +	DRM_FORMAT_ARGB8888,
> +	DRM_FORMAT_ARGB4444,
> +	DRM_FORMAT_ARGB1555,
> +	DRM_FORMAT_YUV422,
> +};
> +
> +static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
> +	.update_plane = drm_plane_helper_update,
> +	.disable_plane = drm_plane_helper_disable,

These are the transitional helpers used for converting drivers, please
switch to the atomic helpers in drm_atomic_helper.c.

> +	.destroy = fsl_dcu_drm_plane_destroy,
> +	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> +	.reset = drm_atomic_helper_plane_reset,
> +};
> +
> +static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
> +	.prepare_fb = fsl_dcu_drm_plane_prepare_fb,
> +	.cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
> +	.atomic_check = fsl_dcu_drm_plane_atomic_check,
> +	.atomic_update = fsl_dcu_drm_plane_atomic_update,
> +	.atomic_disable = fsl_dcu_drm_plane_atomic_disable,
> +};
> +
> +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
> +{
> +	struct drm_plane *primary;
> +	int ret;
> +
> +	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> +	if (!primary) {
> +		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
> +		return NULL;
> +	}
> +
> +	/* possible_crtc's will be filled in later by crtc_init */
> +	ret = drm_universal_plane_init(dev, primary, 0,
> +				       &fsl_dcu_drm_plane_funcs,
> +				       fsl_dcu_drm_plane_formats,
> +				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
> +				       DRM_PLANE_TYPE_PRIMARY);
> +	if (ret) {
> +		kfree(primary);
> +		primary = NULL;
> +	}
> +	drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
> +
> +	return primary;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> new file mode 100644
> index 0000000..ccbfa61
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> @@ -0,0 +1,23 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_PLANE_H__
> +#define __FSL_DCU_DRM_PLANE_H__
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_plane {
> +	struct drm_plane plane;
> +	unsigned int index;
> +};
> +
> +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev);
> +
> +#endif /* __FSL_DCU_DRM_PLANE_H__ */
> diff --git a/include/linux/fsl/dcu.h b/include/linux/fsl/dcu.h
> new file mode 100644
> index 0000000..1873057
> --- /dev/null
> +++ b/include/linux/fsl/dcu.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_H__
> +#define __FSL_DCU_H__
> +
> +#define SCFG_PIXCLKCR			0x28
> +#define PXCK_ENABLE			BIT(31)
> +#define PXCK_DISABLE			0
> +
> +void dcu_pixclk_enable(void);
> +void dcu_pixclk_disable(void);
> +
> +#endif /* __FSL_DCU_H__ */
> -- 
> 2.1.0.27.g96db324
> 

> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver
@ 2015-03-19 14:30   ` Daniel Vetter
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Vetter @ 2015-03-19 14:30 UTC (permalink / raw)
  To: Jianwei Wang
  Cc: Xiubo Li, Alison Wang, linux-kernel, dri-devel, Jason.Jin,
	scottwood, linux-arm-kernel

On Fri, Mar 13, 2015 at 05:44:17PM +0800, Jianwei Wang wrote:
> This patch add support for Two Dimensional Animation and Compositing
> Engine (2D-ACE) on Freescale SoCs.
> 
> 2D-ACE is a Freescale display controller. It provide an hardware
> cursor.
> 
> This is a simplified version, only a primary plane, a fb created for
> fbdev, a crtc, a connector for TFT LCD panel, an encoder, and the
> encoder is not in use.
> 
> Signed-off-by: Alison Wang <b18965@freescale.com>
> Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> Signed-off-by: Jianwei Wang <b52261@freescale.com>

I've spotted two more places where you need to upgrade to atomic functions
for legacy entry points. Otherwise it looks good from that pov. See
comments below.

Thanks, Daniel

> ---
> 
> Changed in v2: 
> - Add atomic support
> - Modify bindings file
> - Rename node for compatibility
> - Move platform related code out for compatibility
> 
> Added in v1: 
> - Add support for DCU display controller on the Freescale LS102x SoCs.
> - Create a primary plane, a fb created for fbdev, a crtc, a connector
> for TFT LCD panel, an encoder.
> 
>  arch/arm/mach-imx/mach-ls1021a.c            |  36 ++++
>  drivers/gpu/drm/Kconfig                     |   2 +
>  drivers/gpu/drm/Makefile                    |   1 +
>  drivers/gpu/drm/fsl/Kconfig                 |  17 ++
>  drivers/gpu/drm/fsl/Makefile                |   8 +
>  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c | 203 ++++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h |  28 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c      | 164 ++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h      |  26 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c       | 288 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h       | 168 ++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c     |  26 +++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c       |  42 ++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h       |  17 ++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c     | 187 ++++++++++++++++++
>  drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h     |  23 +++
>  include/linux/fsl/dcu.h                     |  22 +++
>  17 files changed, 1258 insertions(+)
>  create mode 100644 drivers/gpu/drm/fsl/Kconfig
>  create mode 100644 drivers/gpu/drm/fsl/Makefile
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
>  create mode 100644 drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
>  create mode 100644 include/linux/fsl/dcu.h
> 
> diff --git a/arch/arm/mach-imx/mach-ls1021a.c b/arch/arm/mach-imx/mach-ls1021a.c
> index b89c858..4fb346d 100644
> --- a/arch/arm/mach-imx/mach-ls1021a.c
> +++ b/arch/arm/mach-imx/mach-ls1021a.c
> @@ -8,9 +8,44 @@
>   */
>  
>  #include <asm/mach/arch.h>
> +#include <linux/of_platform.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <linux/fsl/dcu.h>
>  
>  #include "common.h"
>  
> +void dcu_pixclk_disable(void)
> +{
> +	struct regmap *scfg_regmap;
> +
> +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> +	if (IS_ERR(scfg_regmap)) {
> +		pr_err("No syscfg phandle specified\n");
> +		return;
> +	}
> +
> +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_DISABLE);
> +}
> +
> +void dcu_pixclk_enable(void)
> +{
> +	struct regmap *scfg_regmap;
> +
> +	scfg_regmap = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
> +	if (IS_ERR(scfg_regmap)) {
> +		pr_err("No syscfg phandle specified\n");
> +		return;
> +	}
> +
> +	regmap_write(scfg_regmap, SCFG_PIXCLKCR, PXCK_ENABLE);
> +}
> +
> +static void __init ls1021a_init_machine(void)
> +{
> +	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> +	dcu_pixclk_enable();
> +}
>  static const char * const ls1021a_dt_compat[] __initconst = {
>  	"fsl,ls1021a",
>  	NULL,
> @@ -18,5 +53,6 @@ static const char * const ls1021a_dt_compat[] __initconst = {
>  
>  DT_MACHINE_START(LS1021A, "Freescale LS1021A")
>  	.smp		= smp_ops(ls1021a_smp_ops),
> +	.init_machine	= ls1021a_init_machine,
>  	.dt_compat	= ls1021a_dt_compat,
>  MACHINE_END
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index 151a050..a6957aa 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -199,6 +199,8 @@ source "drivers/gpu/drm/bochs/Kconfig"
>  
>  source "drivers/gpu/drm/msm/Kconfig"
>  
> +source "drivers/gpu/drm/fsl/Kconfig"
> +
>  source "drivers/gpu/drm/tegra/Kconfig"
>  
>  source "drivers/gpu/drm/panel/Kconfig"
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 2c239b9..ab5b9ef 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -56,6 +56,7 @@ obj-$(CONFIG_DRM_UDL) += udl/
>  obj-$(CONFIG_DRM_AST) += ast/
>  obj-$(CONFIG_DRM_ARMADA) += armada/
>  obj-$(CONFIG_DRM_ATMEL_HLCDC)	+= atmel-hlcdc/
> +obj-$(CONFIG_DRM_FSL_DCU) += fsl/
>  obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
>  obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
>  obj-$(CONFIG_DRM_OMAP)	+= omapdrm/
> diff --git a/drivers/gpu/drm/fsl/Kconfig b/drivers/gpu/drm/fsl/Kconfig
> new file mode 100644
> index 0000000..e4f8df0
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/Kconfig
> @@ -0,0 +1,17 @@
> +config DRM_FSL_DCU
> +	tristate "DRM Support for Freescale DCU"
> +	depends on DRM && OF && ARM
> +	select DRM_KMS_HELPER
> +	select DRM_KMS_CMA_HELPER
> +	select VIDEOMODE_HELPERS
> +	select BACKLIGHT_CLASS_DEVICE
> +	select BACKLIGHT_LCD_SUPPORT
> +	select REGMAP_MMIO
> +	select DRM_KMS_FB_HELPER
> +	select FB_SYS_FILLRECT
> +	select FB_SYS_COPYAREA
> +	select FB_SYS_IMAGEBLIT
> +	select FB_SYS_FOPS
> +	help
> +	  Choose this option if you have an Freescale DCU chipset.
> +	  If M is selected the module will be called fsl-dcu-drm.
> diff --git a/drivers/gpu/drm/fsl/Makefile b/drivers/gpu/drm/fsl/Makefile
> new file mode 100644
> index 0000000..5f74aee
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/Makefile
> @@ -0,0 +1,8 @@
> +fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
> +	       fsl_dcu_drm_kms.o \
> +	       fsl_dcu_drm_connector.o \
> +	       fsl_dcu_drm_plane.o \
> +	       fsl_dcu_drm_crtc.o \
> +	       fsl_dcu_drm_fbdev.o \
> +
> +obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> new file mode 100644
> index 0000000..178d647
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.c
> @@ -0,0 +1,203 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/backlight.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <video/of_display_timing.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_connector.h"
> +
> +static void fsl_dcu_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
> +{
> +}
> +
> +/* Disable the encoders as the first thing we do. */
> +static void fsl_dcu_drm_encoder_mode_prepare(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_mode_set(struct drm_encoder *encoder,
> +					 struct drm_display_mode *mode,
> +					 struct drm_display_mode *adjusted_mode)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_mode_commit(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
> +{
> +}
> +
> +static int
> +fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
> +				 struct drm_crtc_state *crtc_state,
> +				 struct drm_connector_state *conn_state)
> +{
> +	return 0;
> +}
> +
> +static bool
> +fsl_dcu_drm_encoder_mode_fixup(struct drm_encoder *encoder,
> +			       const struct drm_display_mode *mode,
> +			       struct drm_display_mode *adjusted_mode)
> +{
> +	return true;
> +}
> +
> +static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
> +{
> +	drm_encoder_cleanup(encoder);
> +}
> +
> +static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
> +	.dpms = fsl_dcu_drm_encoder_dpms,
> +	.prepare = fsl_dcu_drm_encoder_mode_prepare,
> +	.commit = fsl_dcu_drm_encoder_mode_commit,
> +	.mode_set = fsl_dcu_drm_encoder_mode_set,
> +	.disable = fsl_dcu_drm_encoder_disable,
> +	.atomic_check = fsl_dcu_drm_encoder_atomic_check,
> +	.mode_fixup = fsl_dcu_drm_encoder_mode_fixup,
> +};
> +
> +static const struct drm_encoder_funcs encoder_funcs = {
> +	.destroy = fsl_dcu_drm_encoder_destroy,
> +};
> +
> +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	struct drm_encoder *encoder = &fsl_dev->encoder;
> +	int ret;
> +
> +	encoder->possible_crtcs = 1;
> +
> +	ret = drm_encoder_init(fsl_dev->ddev, encoder, &encoder_funcs,
> +			       DRM_MODE_ENCODER_LVDS);
> +	if (ret < 0)
> +		return ret;
> +
> +	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
> +
> +	return 0;
> +}
> +
> +#define to_fsl_dcu_connector(connector) \
> +	container_of(connector, struct fsl_dcu_drm_connector, connector)
> +
> +static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector)
> +{
> +	struct drm_device *dev = connector->dev;
> +	struct device_node *display_np, *np = dev->dev->of_node;
> +	struct drm_display_mode *mode = drm_mode_create(connector->dev);
> +	int num_modes = 0;
> +
> +	if (np) {
> +		display_np = of_parse_phandle(np, "display", 0);
> +		if (!display_np) {
> +			dev_err(dev->dev, "failed to find display phandle\n");
> +			return num_modes;
> +		}
> +		of_get_drm_display_mode(display_np, mode, OF_USE_NATIVE_MODE);
> +		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
> +		drm_mode_probed_add(connector, mode);
> +		num_modes++;
> +	}
> +
> +	return num_modes;
> +}
> +
> +static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
> +					    struct drm_display_mode *mode)
> +{
> +	return MODE_OK;
> +}
> +
> +static struct drm_encoder *
> +fsl_dcu_drm_connector_best_encoder(struct drm_connector *connector)
> +{
> +	struct fsl_dcu_drm_connector *fsl_con = to_fsl_dcu_connector(connector);
> +
> +	return fsl_con->encoder;
> +}
> +
> +static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_connector_unregister(connector);
> +	drm_connector_cleanup(connector);
> +}
> +
> +static enum drm_connector_status
> +fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	return connector_status_connected;
> +}
> +
> +static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
> +	.dpms = drm_atomic_helper_connector_dpms,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.detect = fsl_dcu_drm_connector_detect,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.destroy = fsl_dcu_drm_connector_destroy,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static const struct drm_connector_helper_funcs connector_helper_funcs = {
> +	.get_modes = fsl_dcu_drm_connector_get_modes,
> +	.mode_valid = fsl_dcu_drm_connector_mode_valid,
> +	.best_encoder = fsl_dcu_drm_connector_best_encoder,
> +};
> +
> +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> +				 struct drm_encoder *encoder)
> +{
> +	struct drm_connector *connector = &fsl_dev->connector.connector;
> +	int ret;
> +
> +	fsl_dev->connector.encoder = encoder;
> +
> +	connector->display_info.width_mm = 0;
> +	connector->display_info.height_mm = 0;
> +
> +	ret = drm_connector_init(fsl_dev->ddev, connector,
> +				 &fsl_dcu_drm_connector_funcs,
> +				 DRM_MODE_CONNECTOR_LVDS);
> +	if (ret < 0)
> +		return ret;
> +
> +	connector->dpms = DRM_MODE_DPMS_OFF;
> +	drm_connector_helper_add(connector, &connector_helper_funcs);
> +	ret = drm_connector_register(connector);
> +	if (ret < 0)
> +		goto err_cleanup;
> +
> +	ret = drm_mode_connector_attach_encoder(connector, encoder);
> +	if (ret < 0)
> +		goto err_sysfs;
> +
> +	connector->encoder = encoder;
> +
> +	drm_object_property_set_value
> +		(&connector->base, fsl_dev->ddev->mode_config.dpms_property,
> +		DRM_MODE_DPMS_OFF);
> +
> +	return 0;
> +
> +err_sysfs:
> +	drm_connector_unregister(connector);
> +err_cleanup:
> +	drm_connector_cleanup(connector);
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> new file mode 100644
> index 0000000..afe44ab
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_connector.h
> @@ -0,0 +1,28 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_CONNECTOR_H__
> +#define __FSL_DCU_DRM_CONNECTOR_H__
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_connector {
> +	struct drm_connector connector;
> +	struct drm_encoder *encoder;
> +};
> +
> +int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev);
> +int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
> +				 struct drm_encoder *encoder);
> +
> +#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> new file mode 100644
> index 0000000..a43e7ce
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.c
> @@ -0,0 +1,164 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/regmap.h>
> +#include <linux/clk.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_plane.h"
> +
> +#define to_fsl_dcu_crtc(c)	container_of(c, struct fsl_dcu_drm_crtc, crtc)
> +
> +void fsl_dcu_drm_crtc_suspend(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
> +	struct drm_display_mode *mode = &crtc->state->mode;
> +	uint32_t hbp, hfp, hsw, vbp, vfp, vsw, div, index;
> +
> +	DBG(": set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
> +	    mode->base.id, mode->name,
> +	    mode->vrefresh, mode->clock,
> +	    mode->hdisplay, mode->hsync_start,
> +	    mode->hsync_end, mode->htotal,
> +	    mode->vdisplay, mode->vsync_start,
> +	    mode->vsync_end, mode->vtotal,
> +	    mode->type, mode->flags);
> +
> +	index = drm_crtc_index(crtc);
> +	div = (uint32_t)clk_get_rate(fsl_dev->clk) / mode->clock / 1000;
> +
> +	/* Configure timings: */
> +	hbp = mode->htotal - mode->hsync_end;
> +	hfp = mode->hsync_start - mode->hdisplay;
> +	hsw = mode->hsync_end - mode->hsync_start;
> +	vbp = mode->vtotal - mode->vsync_end;
> +	vfp = mode->vsync_start - mode->vdisplay;
> +	vsw = mode->vsync_end - mode->vsync_start;
> +
> +	regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
> +		     DCU_HSYN_PARA_BP(hbp) |
> +		     DCU_HSYN_PARA_PW(hsw) |
> +		     DCU_HSYN_PARA_FP(hfp));
> +	regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
> +		     DCU_VSYN_PARA_BP(vbp) |
> +		     DCU_VSYN_PARA_PW(vsw) |
> +		     DCU_VSYN_PARA_FP(vfp));
> +	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
> +		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
> +		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
> +	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +}
> +
> +static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
> +					const struct drm_display_mode *mode,
> +					struct drm_display_mode *adjusted_mode)
> +{
> +	return true;
> +}
> +
> +static void fsl_dcu_drm_crtc_prepare(struct drm_crtc *crtc)
> +{
> +}
> +
> +/* Now enable the clocks, plane, pipe, and connectors that we set up. */
> +static void fsl_dcu_drm_crtc_mode_commit(struct drm_crtc *crtc)
> +{
> +}
> +
> +static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
> +					 struct drm_crtc_state *state)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc)
> +{
> +}
> +
> +static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
> +{
> +}
> +
> +static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
> +	.page_flip = drm_atomic_helper_page_flip,
> +	.set_config = drm_crtc_helper_set_config,

This is the legacy function, please use the atomic one instead from
drm_atomic_helper.c for ->set_config.

> +	.destroy = drm_crtc_cleanup,
> +	.reset = drm_atomic_helper_crtc_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> +};
> +
> +static void fsl_dcu_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
> +{
> +}
> +
> +static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
> +	.disable = fsl_dcu_drm_disable_crtc,
> +	.mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
> +	.mode_set = drm_helper_crtc_mode_set,
> +	.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
> +	.mode_set_base = drm_helper_crtc_mode_set_base,
> +	.prepare = fsl_dcu_drm_crtc_prepare,
> +	.commit = fsl_dcu_drm_crtc_mode_commit,
> +	.atomic_check = fsl_dcu_drm_crtc_atomic_check,
> +	.atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
> +	.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
> +	.dpms = fsl_dcu_drm_crtc_dpms,
> +};
> +
> +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	struct drm_plane *primary;
> +	struct drm_crtc *crtc = &fsl_dev->crtc.crtc;
> +	int ret;
> +
> +	fsl_dev->crtc.dpms = DRM_MODE_DPMS_OFF;
> +
> +	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->ddev);
> +	ret = drm_crtc_init_with_planes(fsl_dev->ddev, crtc, primary, NULL,
> +					&fsl_dcu_drm_crtc_funcs);
> +	if (ret < 0)
> +		return ret;
> +
> +	drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
> +
> +	regmap_write(fsl_dev->regmap, DCU_SYN_POL,
> +		     DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
> +	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
> +		     DCU_BGND_G(0) | DCU_BGND_B(0));
> +	regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
> +		     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
> +	regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
> +		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
> +		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
> +		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
> +	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
> +			   DCU_MODE_DCU_MODE_MASK,
> +			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> new file mode 100644
> index 0000000..d44b564
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_crtc.h
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_CRTC_H__
> +#define __FSL_DCU_DRM_CRTC_H__
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_crtc {
> +	struct drm_crtc crtc;
> +	int dpms;
> +};
> +
> +int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev);
> +
> +#endif /* __FSL_DCU_DRM_CRTC_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> new file mode 100644
> index 0000000..10975ee
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.c
> @@ -0,0 +1,288 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/mm.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> +
> +#include <drm/drmP.h>
> +#include <linux/fsl/dcu.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_kms.h"
> +
> +static int fsl_dcu_unload(struct drm_device *dev)
> +{
> +	drm_mode_config_cleanup(dev);
> +	drm_vblank_cleanup(dev);
> +	drm_irq_uninstall(dev);
> +
> +	dev->dev_private = NULL;
> +
> +	return 0;
> +}
> +
> +static struct regmap_config fsl_dcu_regmap_config = {
> +	.reg_bits = 32,
> +	.reg_stride = 4,
> +	.val_bits = 32,
> +};
> +
> +static int fsl_dcu_bypass_tcon(struct fsl_dcu_drm_device *fsl_dev,
> +			       struct device_node *np)
> +{
> +	struct device_node *tcon_np;
> +	struct platform_device *pdev;
> +	struct clk *tcon_clk;
> +	struct resource *res;
> +	void __iomem *base;
> +
> +	tcon_np = of_parse_phandle(np, "tcon-controller", 0);
> +	if (!tcon_np)
> +		return -EINVAL;
> +
> +	pdev = of_find_device_by_node(tcon_np);
> +	if (!pdev)
> +		return -EINVAL;
> +
> +	tcon_clk = devm_clk_get(&pdev->dev, "tcon");
> +	if (IS_ERR(tcon_clk))
> +		return PTR_ERR(tcon_clk);
> +	clk_prepare_enable(tcon_clk);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -ENODEV;
> +
> +	base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	fsl_dev->tcon_regmap = devm_regmap_init_mmio_clk(&pdev->dev,
> +			"tcon", base, &fsl_dcu_regmap_config);
> +	if (IS_ERR(fsl_dev->tcon_regmap)) {
> +		dev_err(&pdev->dev, "regmap init failed\n");
> +		return PTR_ERR(fsl_dev->tcon_regmap);
> +	}
> +
> +	regmap_write(fsl_dev->tcon_regmap, TCON_CTRL1, TCON_BYPASS_ENABLE);
> +	return 0;
> +}
> +
> +static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
> +{
> +	struct platform_device *pdev = dev->platformdev;
> +	struct fsl_dcu_drm_device *fsl_dev;
> +	struct resource *res;
> +	void __iomem *base;
> +	int ret;
> +
> +	fsl_dev = devm_kzalloc(&pdev->dev, sizeof(*fsl_dev), GFP_KERNEL);
> +	if (!fsl_dev)
> +		return -ENOMEM;
> +
> +	fsl_dev->dev = &pdev->dev;
> +	fsl_dev->ddev = dev;
> +	dev->dev_private = fsl_dev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(base)) {
> +		ret = PTR_ERR(base);
> +		return ret;
> +	}
> +
> +	fsl_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
> +			base, &fsl_dcu_regmap_config);
> +	if (IS_ERR(fsl_dev->regmap)) {
> +		dev_err(&pdev->dev, "regmap init failed\n");
> +		return PTR_ERR(fsl_dev->regmap);
> +	}
> +
> +	ret = fsl_dcu_drm_modeset_init(fsl_dev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to initialize mode setting\n");
> +		return ret;
> +	}
> +
> +	ret = drm_vblank_init(dev, 1);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to initialize vblank\n");
> +		goto done;
> +	}
> +
> +	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to install IRQ handler\n");
> +		goto done;
> +	}
> +
> +	/* Put TCON in bypass mode, so the input signals from DCU are passed
> +	 * through TCON unchanged */
> +	fsl_dcu_bypass_tcon(fsl_dev, pdev->dev.of_node);
> +
> +	fsl_dev->clk = devm_clk_get(&pdev->dev, "dcu");
> +	if (IS_ERR(fsl_dev->clk)) {
> +		ret = PTR_ERR(fsl_dev->clk);
> +		dev_err(&pdev->dev, "could not get clock\n");
> +		return ret;
> +	}
> +	clk_prepare_enable(fsl_dev->clk);
> +
> +	dev_set_drvdata(dev->dev, fsl_dev);
> +
> +	fsl_dcu_fbdev_init(dev);
> +
> +	return 0;
> +done:
> +	if (ret)
> +		fsl_dcu_unload(dev);
> +
> +	return ret;
> +}
> +
> +static void fsl_dcu_drm_preclose(struct drm_device *dev, struct drm_file *file)
> +{
> +	;
> +}
> +
> +static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
> +{
> +	return IRQ_HANDLED;
> +}
> +
> +static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int crtc)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int crtc)
> +{
> +	;
> +}
> +
> +static const struct file_operations fsl_dcu_drm_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= drm_open,
> +	.release	= drm_release,
> +	.unlocked_ioctl	= drm_ioctl,
> +#ifdef CONFIG_COMPAT
> +	.compat_ioctl	= drm_compat_ioctl,
> +#endif
> +	.poll		= drm_poll,
> +	.read		= drm_read,
> +	.llseek		= no_llseek,
> +	.mmap		= drm_gem_cma_mmap,
> +};
> +
> +static struct drm_driver fsl_dcu_drm_driver = {
> +	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
> +				| DRIVER_PRIME,
> +	.load			= fsl_dcu_load,
> +	.unload			= fsl_dcu_unload,
> +	.preclose		= fsl_dcu_drm_preclose,
> +	.irq_handler		= fsl_dcu_drm_irq,
> +	.get_vblank_counter	= drm_vblank_count,
> +	.enable_vblank		= fsl_dcu_drm_enable_vblank,
> +	.disable_vblank		= fsl_dcu_drm_disable_vblank,
> +	.gem_free_object	= drm_gem_cma_free_object,
> +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
> +	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
> +	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
> +	.gem_prime_import	= drm_gem_prime_import,
> +	.gem_prime_export	= drm_gem_prime_export,
> +	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
> +	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> +	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
> +	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
> +	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
> +	.dumb_create		= drm_gem_cma_dumb_create,
> +	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
> +	.dumb_destroy		= drm_gem_dumb_destroy,
> +	.fops			= &fsl_dcu_drm_fops,
> +	.name			= "fsl-dcu-drm",
> +	.desc			= "Freescale DCU DRM",
> +	.date			= "20150213",
> +	.major			= 1,
> +	.minor			= 0,
> +};
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int fsl_dcu_drm_pm_suspend(struct device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> +
> +	dcu_pixclk_disable();
> +	drm_kms_helper_poll_disable(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_suspend(&fsl_dev->crtc);
> +
> +	return 0;
> +}
> +
> +static int fsl_dcu_drm_pm_resume(struct device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
> +
> +	drm_modeset_lock_all(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_resume(&fsl_dev->crtc);
> +	drm_modeset_unlock_all(fsl_dev->ddev);
> +	drm_kms_helper_poll_enable(fsl_dev->ddev);
> +	dcu_pixclk_enable();
> +	return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops fsl_dcu_drm_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_drm_pm_suspend, fsl_dcu_drm_pm_resume)
> +};
> +
> +static int fsl_dcu_drm_probe(struct platform_device *pdev)
> +{
> +	return drm_platform_init(&fsl_dcu_drm_driver, pdev);
> +}
> +
> +static int fsl_dcu_drm_remove(struct platform_device *pdev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
> +
> +	drm_put_dev(fsl_dev->ddev);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id fsl_dcu_of_match[] = {
> +		{ .compatible = "fsl,dcu", },
> +		{ },
> +};
> +MODULE_DEVICE_TABLE(of, fsl_dcu_of_match);
> +
> +static struct platform_driver fsl_dcu_drm_platform_driver = {
> +	.probe		= fsl_dcu_drm_probe,
> +	.remove		= fsl_dcu_drm_remove,
> +	.driver		= {
> +		.owner	= THIS_MODULE,
> +		.name	= "fsl,dcu",
> +		.pm	= &fsl_dcu_drm_pm_ops,
> +		.of_match_table = fsl_dcu_of_match,
> +	},
> +};
> +
> +module_platform_driver(fsl_dcu_drm_platform_driver);
> +
> +MODULE_ALIAS("platform:fsl-dcu-drm");
> +MODULE_DESCRIPTION("Freescale DCU DRM Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> new file mode 100644
> index 0000000..cbdfefc
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_drv.h
> @@ -0,0 +1,168 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_DRV_H__
> +#define __FSL_DCU_DRM_DRV_H__
> +
> +#include <linux/kernel.h>
> +#include <linux/spinlock.h>
> +#include <stddef.h>
> +#include <drm/drm.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_plane.h"
> +#include "fsl_dcu_drm_connector.h"
> +#define DRIVER_NAME			"fsl-dcu-fb"
> +
> +#define DCU_DCU_MODE			0x0010
> +#define DCU_MODE_BLEND_ITER(x)		((x) << 20)
> +#define DCU_MODE_RASTER_EN		BIT(14)
> +#define DCU_MODE_DCU_MODE(x)		(x)
> +#define DCU_MODE_DCU_MODE_MASK		0x03
> +#define DCU_MODE_OFF			0
> +#define DCU_MODE_NORMAL			1
> +#define DCU_MODE_TEST			2
> +#define DCU_MODE_COLORBAR		3
> +
> +#define DCU_BGND			0x0014
> +#define DCU_BGND_R(x)			((x) << 16)
> +#define DCU_BGND_G(x)			((x) << 8)
> +#define DCU_BGND_B(x)			(x)
> +
> +#define DCU_DISP_SIZE			0x0018
> +#define DCU_DISP_SIZE_DELTA_Y(x)	((x) << 16)
> +/*Regisiter value 1/16 of horizontal resolution*/
> +#define DCU_DISP_SIZE_DELTA_X(x)	((x) >> 4)
> +
> +#define DCU_HSYN_PARA			0x001c
> +#define DCU_HSYN_PARA_BP(x)		((x) << 22)
> +#define DCU_HSYN_PARA_PW(x)		((x) << 11)
> +#define DCU_HSYN_PARA_FP(x)		(x)
> +
> +#define DCU_VSYN_PARA			0x0020
> +#define DCU_VSYN_PARA_BP(x)		((x) << 22)
> +#define DCU_VSYN_PARA_PW(x)		((x) << 11)
> +#define DCU_VSYN_PARA_FP(x)		(x)
> +
> +#define DCU_SYN_POL			0x0024
> +#define DCU_SYN_POL_INV_PXCK_FALL	(0 << 6)
> +#define DCU_SYN_POL_NEG_REMAIN		(0 << 5)
> +#define DCU_SYN_POL_INV_VS_LOW		BIT(1)
> +#define DCU_SYN_POL_INV_HS_LOW		(1)
> +
> +#define DCU_THRESHOLD			0x0028
> +#define DCU_THRESHOLD_LS_BF_VS(x)	((x) << 16)
> +#define DCU_THRESHOLD_OUT_BUF_HIGH(x)	((x) << 8)
> +#define DCU_THRESHOLD_OUT_BUF_LOW(x)	(x)
> +#define BF_VS_VAL			0x03
> +#define BUF_MAX_VAL			0x78
> +#define BUF_MIN_VAL			0x0a
> +
> +#define DCU_INT_STATUS			0x002C
> +#define DCU_INT_STATUS_UNDRUN		BIT(1)
> +
> +#define DCU_INT_MASK			0x0030
> +#define DCU_INT_MASK_UNDRUN		BIT(1)
> +#define DCU_INT_MASK_VBLANK		BIT(3)
> +
> +#define DCU_DIV_RATIO			0x0054
> +
> +#define DCU_UPDATE_MODE			0x00cc
> +#define DCU_UPDATE_MODE_MODE		BIT(31)
> +#define DCU_UPDATE_MODE_READREG		BIT(30)
> +
> +#define DCU_DCFB_MAX			0x300
> +
> +#define DCU_CTRLDESCLN_1(x)		(0x200 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_1_HEIGHT(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_1_WIDTH(x)	(x)
> +
> +#define DCU_CTRLDESCLN_2(x)		(0x204 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_2_POSY(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_2_POSX(x)	(x)
> +
> +#define DCU_CTRLDESCLN_3(x)		(0x208 + (x) * 0x40)
> +
> +#define DCU_CTRLDESCLN_4(x)		(0x20c + (x) * 0x40)
> +#define DCU_CTRLDESCLN_4_EN		BIT(31)
> +#define DCU_CTRLDESCLN_4_TILE_EN	BIT(30)
> +#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT	BIT(29)
> +#define DCU_CTRLDESCLN_4_SAFETY_EN	BIT(28)
> +#define DCU_CTRLDESCLN_4_TRANS(x)	((x) << 20)
> +#define DCU_CTRLDESCLN_4_BPP(x)		((x) << 16)
> +#define DCU_CTRLDESCLN_4_RLE_EN		BIT(15)
> +#define DCU_CTRLDESCLN_4_LUOFFS(x)	((x) << 4)
> +#define DCU_CTRLDESCLN_4_BB_ON		BIT(2)
> +#define DCU_CTRLDESCLN_4_AB(x)		(x)
> +
> +#define DCU_CTRLDESCLN_5(x)		(0x210 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_5_CKMAX_R(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_5_CKMAX_G(x)	((x) << 8)
> +#define DCU_CTRLDESCLN_5_CKMAX_B(x)	(x)
> +
> +#define DCU_CTRLDESCLN_6(x)		(0x214 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_6_CKMIN_R(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_6_CKMIN_G(x)	((x) << 8)
> +#define DCU_CTRLDESCLN_6_CKMIN_B(x)	(x)
> +
> +#define DCU_CTRLDESCLN_7(x)		(0x218 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_7_TILE_VER(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_7_TILE_HOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_8(x)		(0x21c + (x) * 0x40)
> +#define DCU_CTRLDESCLN_8_FG_FCOLOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_9(x)		(0x220 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_9_BG_BCOLOR(x)	(x)
> +
> +#define DCU_CTRLDESCLN_10(x)		(0x224 + (x) * 0x40)
> +#define DCU_CTRLDESCLN_10_POST_SKIP(x)	((x) << 16)
> +#define DCU_CTRLDESCLN_10_PRE_SKIP(x)	(x)
> +
> +#define FSL_DCU_RGB565			4
> +#define FSL_DCU_RGB888			5
> +#define FSL_DCU_ARGB8888		6
> +#define FSL_DCU_ARGB1555		11
> +#define FSL_DCU_ARGB4444		12
> +#define FSL_DCU_YUV422			14
> +
> +#define TCON_CTRL1			0x0000
> +#define TCON_BYPASS_ENABLE		BIT(29)
> +
> +#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
> +
> +struct clk;
> +struct device;
> +struct drm_device;
> +
> +struct fsl_dcu_drm_device {
> +	struct device *dev;
> +	struct regmap *regmap;
> +	struct regmap *tcon_regmap;
> +	unsigned int irq;
> +	struct clk *clk;
> +	/*protects hardware register*/
> +	spinlock_t irq_lock;
> +	struct drm_device *ddev;
> +	struct drm_fbdev_cma *fbdev;
> +	struct fsl_dcu_drm_crtc crtc;
> +	struct drm_encoder encoder;
> +	struct fsl_dcu_drm_connector connector;
> +};
> +
> +void fsl_dcu_fbdev_init(struct drm_device *dev);
> +
> +#endif /* __FSL_DCU_DRM_DRV_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> new file mode 100644
> index 0000000..f8ef0e1
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_fbdev.c
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_cma_helper.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +
> +/* initialize fbdev helper */
> +void fsl_dcu_fbdev_init(struct drm_device *dev)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
> +
> +	fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1);
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> new file mode 100644
> index 0000000..4a840fb
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.c
> @@ -0,0 +1,42 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "fsl_dcu_drm_crtc.h"
> +#include "fsl_dcu_drm_connector.h"
> +#include "fsl_dcu_drm_drv.h"
> +
> +static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs = {
> +	.fb_create = drm_fb_cma_create,
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
> +{
> +	drm_mode_config_init(fsl_dev->ddev);
> +
> +	fsl_dev->ddev->mode_config.min_width = 0;
> +	fsl_dev->ddev->mode_config.min_height = 0;
> +	fsl_dev->ddev->mode_config.max_width = 2031;
> +	fsl_dev->ddev->mode_config.max_height = 2047;
> +	fsl_dev->ddev->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;
> +
> +	drm_kms_helper_poll_init(fsl_dev->ddev);
> +	fsl_dcu_drm_crtc_create(fsl_dev);
> +	fsl_dcu_drm_encoder_create(fsl_dev);
> +	fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
> +	drm_mode_config_reset(fsl_dev->ddev);
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> new file mode 100644
> index 0000000..b9bd299
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_kms.h
> @@ -0,0 +1,17 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_KMS_H__
> +#define __FSL_DCU_DRM_KMS_H__
> +
> +int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
> +
> +#endif /* __FSL_DCU_DRM_KMS_H__ */
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> new file mode 100644
> index 0000000..b7b4405
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.c
> @@ -0,0 +1,187 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <linux/regmap.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "fsl_dcu_drm_drv.h"
> +#include "fsl_dcu_drm_kms.h"
> +#include "fsl_dcu_drm_plane.h"
> +
> +#define to_fsl_dcu_plane(plane) \
> +	container_of(plane, struct fsl_dcu_drm_plane, plane)
> +
> +static int
> +fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
> +			     struct drm_framebuffer *fb,
> +			     const struct drm_plane_state *new_state)
> +{
> +	return 0;
> +}
> +
> +static void
> +fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
> +			     struct drm_framebuffer *fb,
> +			     const struct drm_plane_state *new_state)
> +{
> +}
> +
> +static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
> +					  struct drm_plane_state *state)
> +{
> +	return 0;
> +}
> +
> +static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
> +					     struct drm_plane_state *old_state)
> +{
> +}
> +
> +void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
> +				     struct drm_plane_state *old_state)
> +{
> +	struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = plane->state->fb;
> +	u32 index, alpha, bpp;
> +	struct drm_gem_cma_object *gem;
> +	struct fsl_dcu_drm_plane *fsl_plane = to_fsl_dcu_plane(plane);
> +
> +	index = fsl_plane->index;
> +	gem = drm_fb_cma_get_gem_obj(fb, 0);
> +
> +	switch (fb->pixel_format) {
> +	case DRM_FORMAT_RGB565:
> +		bpp = FSL_DCU_RGB565;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_RGB888:
> +		bpp = FSL_DCU_RGB888;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_ARGB8888:
> +		bpp = FSL_DCU_ARGB8888;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_BGRA4444:
> +		bpp = FSL_DCU_ARGB4444;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_ARGB1555:
> +		bpp = FSL_DCU_ARGB1555;
> +		alpha = 0xff;
> +		break;
> +	case DRM_FORMAT_YUV422:
> +		bpp = FSL_DCU_YUV422;
> +		alpha = 0xff;
> +		break;
> +	default:
> +		return;
> +	}
> +
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_1(index),
> +		     DCU_CTRLDESCLN_1_HEIGHT(state->crtc_h) |
> +		     DCU_CTRLDESCLN_1_WIDTH(state->crtc_w));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_2(index),
> +		     DCU_CTRLDESCLN_2_POSY(state->crtc_y) |
> +		     DCU_CTRLDESCLN_2_POSX(state->crtc_x));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_3(index), gem->paddr);
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_4(index),
> +		     DCU_CTRLDESCLN_4_EN |
> +		     DCU_CTRLDESCLN_4_TRANS(alpha) |
> +		     DCU_CTRLDESCLN_4_BPP(bpp) |
> +		     DCU_CTRLDESCLN_4_AB(2));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_5(index),
> +		     DCU_CTRLDESCLN_5_CKMAX_R(0xFF) |
> +		     DCU_CTRLDESCLN_5_CKMAX_G(0xFF) |
> +		     DCU_CTRLDESCLN_5_CKMAX_B(0xFF));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_6(index),
> +		     DCU_CTRLDESCLN_6_CKMIN_R(0) |
> +		     DCU_CTRLDESCLN_6_CKMIN_G(0) |
> +		     DCU_CTRLDESCLN_6_CKMIN_B(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_8(index),
> +		     DCU_CTRLDESCLN_8_FG_FCOLOR(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_9(index),
> +		     DCU_CTRLDESCLN_9_BG_BCOLOR(0));
> +	regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN_10(index),
> +		     DCU_CTRLDESCLN_10_POST_SKIP(0) |
> +		     DCU_CTRLDESCLN_10_PRE_SKIP(0));
> +	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
> +}
> +
> +int fsl_dcu_drm_plane_disable(struct drm_plane *plane)
> +{
> +	return 0;
> +}
> +
> +void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
> +{
> +	fsl_dcu_drm_plane_disable(plane);
> +	drm_plane_cleanup(plane);
> +}
> +
> +static const uint32_t fsl_dcu_drm_plane_formats[] = {
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_RGB888,
> +	DRM_FORMAT_ARGB8888,
> +	DRM_FORMAT_ARGB4444,
> +	DRM_FORMAT_ARGB1555,
> +	DRM_FORMAT_YUV422,
> +};
> +
> +static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
> +	.update_plane = drm_plane_helper_update,
> +	.disable_plane = drm_plane_helper_disable,

These are the transitional helpers used for converting drivers, please
switch to the atomic helpers in drm_atomic_helper.c.

> +	.destroy = fsl_dcu_drm_plane_destroy,
> +	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> +	.reset = drm_atomic_helper_plane_reset,
> +};
> +
> +static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
> +	.prepare_fb = fsl_dcu_drm_plane_prepare_fb,
> +	.cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
> +	.atomic_check = fsl_dcu_drm_plane_atomic_check,
> +	.atomic_update = fsl_dcu_drm_plane_atomic_update,
> +	.atomic_disable = fsl_dcu_drm_plane_atomic_disable,
> +};
> +
> +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
> +{
> +	struct drm_plane *primary;
> +	int ret;
> +
> +	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> +	if (!primary) {
> +		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
> +		return NULL;
> +	}
> +
> +	/* possible_crtc's will be filled in later by crtc_init */
> +	ret = drm_universal_plane_init(dev, primary, 0,
> +				       &fsl_dcu_drm_plane_funcs,
> +				       fsl_dcu_drm_plane_formats,
> +				       ARRAY_SIZE(fsl_dcu_drm_plane_formats),
> +				       DRM_PLANE_TYPE_PRIMARY);
> +	if (ret) {
> +		kfree(primary);
> +		primary = NULL;
> +	}
> +	drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
> +
> +	return primary;
> +}
> diff --git a/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> new file mode 100644
> index 0000000..ccbfa61
> --- /dev/null
> +++ b/drivers/gpu/drm/fsl/fsl_dcu_drm_plane.h
> @@ -0,0 +1,23 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_DRM_PLANE_H__
> +#define __FSL_DCU_DRM_PLANE_H__
> +
> +struct fsl_dcu_drm_device;
> +struct fsl_dcu_drm_plane {
> +	struct drm_plane plane;
> +	unsigned int index;
> +};
> +
> +struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev);
> +
> +#endif /* __FSL_DCU_DRM_PLANE_H__ */
> diff --git a/include/linux/fsl/dcu.h b/include/linux/fsl/dcu.h
> new file mode 100644
> index 0000000..1873057
> --- /dev/null
> +++ b/include/linux/fsl/dcu.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright 2015 Freescale Semiconductor, Inc.
> + *
> + * Freescale DCU drm device driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __FSL_DCU_H__
> +#define __FSL_DCU_H__
> +
> +#define SCFG_PIXCLKCR			0x28
> +#define PXCK_ENABLE			BIT(31)
> +#define PXCK_DISABLE			0
> +
> +void dcu_pixclk_enable(void);
> +void dcu_pixclk_disable(void);
> +
> +#endif /* __FSL_DCU_H__ */
> -- 
> 2.1.0.27.g96db324
> 

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


-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node
  2015-02-13 17:28     ` Scott Wood
  (?)
@ 2015-02-15 10:12       ` Jianwei.Wang at freescale.com
  -1 siblings, 0 replies; 26+ messages in thread
From: Jianwei.Wang @ 2015-02-15 10:12 UTC (permalink / raw)
  To: Scott Wood
  Cc: dri-devel, jbarnes, linux-kernel, linux-arm-kernel, Huan Wang, Xiubo Li

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 1771 bytes --]

My careless, I'll add "big¡ªendia" to fsl,dcfb.txt next version.
________________________________________
·¢¼þÈË: Wood Scott-B07421
·¢ËÍʱ¼ä: 2015Äê2ÔÂ14ÈÕ 1:28:08
ÊÕ¼þÈË: Wang Jianwei-B52261
³­ËÍ: dri-devel@lists.freedesktop.org; jbarnes@virtuousgeek.org; linux-kernel@vger.kernel.org; linux-arm-kernel@lists.infradead.org; Wang Huan-B18965; Xiubo Li
Ö÷Ìâ: Re: [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node

On Fri, 2015-02-13 at 19:03 +0800, Jianwei Wang wrote:
> Add DCU node, DCU is a display controller of Freescale
> named 2D-ACE.
>
> Signed-off-by: Alison Wang <b18965@freescale.com>
> Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> Signed-off-by: Jianwei Wang <b52261@freescale.com>
> ---
>  arch/arm/boot/dts/ls1021a.dtsi | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
> index c70bb27..28c37f1 100644
> --- a/arch/arm/boot/dts/ls1021a.dtsi
> +++ b/arch/arm/boot/dts/ls1021a.dtsi
> @@ -383,6 +383,17 @@
>                                <&platform_clk 1>;
>               };
>
> +             dcfb: dcfb@2ce0000 {
> +                     compatible = "fsl,ls1021a-dcfb";
> +                     reg = <0x0 0x2ce0000 0x0 0x10000>;
> +                     interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
> +                     clocks = <&platform_clk 0>;
> +                     clock-names = "dcfb";
> +                     scfg-controller = <&scfg>;
> +                     big-endian;
> +                     status = "disabled";
> +             };

I don't see "big-endian" in the dcfb binding.

-Scott

ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

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

* [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node
@ 2015-02-15 10:12       ` Jianwei.Wang at freescale.com
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei.Wang at freescale.com @ 2015-02-15 10:12 UTC (permalink / raw)
  To: linux-arm-kernel

My careless, I'll add "big?endia" to fsl,dcfb.txt next version.
________________________________________
???: Wood Scott-B07421
????: 2015?2?14? 1:28:08
???: Wang Jianwei-B52261
??: dri-devel at lists.freedesktop.org; jbarnes at virtuousgeek.org; linux-kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org; Wang Huan-B18965; Xiubo Li
??: Re: [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node

On Fri, 2015-02-13 at 19:03 +0800, Jianwei Wang wrote:
> Add DCU node, DCU is a display controller of Freescale
> named 2D-ACE.
>
> Signed-off-by: Alison Wang <b18965@freescale.com>
> Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> Signed-off-by: Jianwei Wang <b52261@freescale.com>
> ---
>  arch/arm/boot/dts/ls1021a.dtsi | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
> index c70bb27..28c37f1 100644
> --- a/arch/arm/boot/dts/ls1021a.dtsi
> +++ b/arch/arm/boot/dts/ls1021a.dtsi
> @@ -383,6 +383,17 @@
>                                <&platform_clk 1>;
>               };
>
> +             dcfb: dcfb at 2ce0000 {
> +                     compatible = "fsl,ls1021a-dcfb";
> +                     reg = <0x0 0x2ce0000 0x0 0x10000>;
> +                     interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
> +                     clocks = <&platform_clk 0>;
> +                     clock-names = "dcfb";
> +                     scfg-controller = <&scfg>;
> +                     big-endian;
> +                     status = "disabled";
> +             };

I don't see "big-endian" in the dcfb binding.

-Scott

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

* Re: [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node
@ 2015-02-15 10:12       ` Jianwei.Wang at freescale.com
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei.Wang @ 2015-02-15 10:12 UTC (permalink / raw)
  To: Scott Wood
  Cc: dri-devel, jbarnes, linux-kernel, linux-arm-kernel, Huan Wang, Xiubo Li

My careless, I'll add "big―endia" to fsl,dcfb.txt next version.
________________________________________
发件人: Wood Scott-B07421
发送时间: 2015年2月14日 1:28:08
收件人: Wang Jianwei-B52261
抄送: dri-devel@lists.freedesktop.org; jbarnes@virtuousgeek.org; linux-kernel@vger.kernel.org; linux-arm-kernel@lists.infradead.org; Wang Huan-B18965; Xiubo Li
主题: Re: [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node

On Fri, 2015-02-13 at 19:03 +0800, Jianwei Wang wrote:
> Add DCU node, DCU is a display controller of Freescale
> named 2D-ACE.
>
> Signed-off-by: Alison Wang <b18965@freescale.com>
> Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> Signed-off-by: Jianwei Wang <b52261@freescale.com>
> ---
>  arch/arm/boot/dts/ls1021a.dtsi | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
> index c70bb27..28c37f1 100644
> --- a/arch/arm/boot/dts/ls1021a.dtsi
> +++ b/arch/arm/boot/dts/ls1021a.dtsi
> @@ -383,6 +383,17 @@
>                                <&platform_clk 1>;
>               };
>
> +             dcfb: dcfb@2ce0000 {
> +                     compatible = "fsl,ls1021a-dcfb";
> +                     reg = <0x0 0x2ce0000 0x0 0x10000>;
> +                     interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
> +                     clocks = <&platform_clk 0>;
> +                     clock-names = "dcfb";
> +                     scfg-controller = <&scfg>;
> +                     big-endian;
> +                     status = "disabled";
> +             };

I don't see "big-endian" in the dcfb binding.

-Scott


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

* Re: [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node
  2015-02-13 11:03   ` Jianwei Wang
  (?)
@ 2015-02-13 17:28     ` Scott Wood
  -1 siblings, 0 replies; 26+ messages in thread
From: Scott Wood @ 2015-02-13 17:28 UTC (permalink / raw)
  To: Jianwei Wang
  Cc: dri-devel, jbarnes, linux-kernel, linux-arm-kernel, Alison Wang,
	Xiubo Li

On Fri, 2015-02-13 at 19:03 +0800, Jianwei Wang wrote:
> Add DCU node, DCU is a display controller of Freescale
> named 2D-ACE.
> 
> Signed-off-by: Alison Wang <b18965@freescale.com>
> Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> Signed-off-by: Jianwei Wang <b52261@freescale.com>
> ---
>  arch/arm/boot/dts/ls1021a.dtsi | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
> index c70bb27..28c37f1 100644
> --- a/arch/arm/boot/dts/ls1021a.dtsi
> +++ b/arch/arm/boot/dts/ls1021a.dtsi
> @@ -383,6 +383,17 @@
>  				 <&platform_clk 1>;
>  		};
>  
> +		dcfb: dcfb@2ce0000 {
> +			compatible = "fsl,ls1021a-dcfb";
> +			reg = <0x0 0x2ce0000 0x0 0x10000>;
> +			interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&platform_clk 0>;
> +			clock-names = "dcfb";
> +			scfg-controller = <&scfg>;
> +			big-endian;
> +			status = "disabled";
> +		};

I don't see "big-endian" in the dcfb binding.

-Scott


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

* [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node
@ 2015-02-13 17:28     ` Scott Wood
  0 siblings, 0 replies; 26+ messages in thread
From: Scott Wood @ 2015-02-13 17:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2015-02-13 at 19:03 +0800, Jianwei Wang wrote:
> Add DCU node, DCU is a display controller of Freescale
> named 2D-ACE.
> 
> Signed-off-by: Alison Wang <b18965@freescale.com>
> Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> Signed-off-by: Jianwei Wang <b52261@freescale.com>
> ---
>  arch/arm/boot/dts/ls1021a.dtsi | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
> index c70bb27..28c37f1 100644
> --- a/arch/arm/boot/dts/ls1021a.dtsi
> +++ b/arch/arm/boot/dts/ls1021a.dtsi
> @@ -383,6 +383,17 @@
>  				 <&platform_clk 1>;
>  		};
>  
> +		dcfb: dcfb at 2ce0000 {
> +			compatible = "fsl,ls1021a-dcfb";
> +			reg = <0x0 0x2ce0000 0x0 0x10000>;
> +			interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&platform_clk 0>;
> +			clock-names = "dcfb";
> +			scfg-controller = <&scfg>;
> +			big-endian;
> +			status = "disabled";
> +		};

I don't see "big-endian" in the dcfb binding.

-Scott

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

* Re: [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node
@ 2015-02-13 17:28     ` Scott Wood
  0 siblings, 0 replies; 26+ messages in thread
From: Scott Wood @ 2015-02-13 17:28 UTC (permalink / raw)
  To: Jianwei Wang
  Cc: dri-devel, jbarnes, linux-kernel, linux-arm-kernel, Alison Wang,
	Xiubo Li

On Fri, 2015-02-13 at 19:03 +0800, Jianwei Wang wrote:
> Add DCU node, DCU is a display controller of Freescale
> named 2D-ACE.
> 
> Signed-off-by: Alison Wang <b18965@freescale.com>
> Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
> Signed-off-by: Jianwei Wang <b52261@freescale.com>
> ---
>  arch/arm/boot/dts/ls1021a.dtsi | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
> index c70bb27..28c37f1 100644
> --- a/arch/arm/boot/dts/ls1021a.dtsi
> +++ b/arch/arm/boot/dts/ls1021a.dtsi
> @@ -383,6 +383,17 @@
>  				 <&platform_clk 1>;
>  		};
>  
> +		dcfb: dcfb@2ce0000 {
> +			compatible = "fsl,ls1021a-dcfb";
> +			reg = <0x0 0x2ce0000 0x0 0x10000>;
> +			interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&platform_clk 0>;
> +			clock-names = "dcfb";
> +			scfg-controller = <&scfg>;
> +			big-endian;
> +			status = "disabled";
> +		};

I don't see "big-endian" in the dcfb binding.

-Scott

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

* [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node
  2015-02-13 11:03 Jianwei Wang
  2015-02-13 11:03   ` Jianwei Wang
@ 2015-02-13 11:03   ` Jianwei Wang
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei Wang @ 2015-02-13 11:03 UTC (permalink / raw)
  To: dri-devel, jbarnes, scottwood
  Cc: linux-kernel, linux-arm-kernel, Jianwei Wang, Alison Wang, Xiubo Li

Add DCU node, DCU is a display controller of Freescale
named 2D-ACE.

Signed-off-by: Alison Wang <b18965@freescale.com>
Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Jianwei Wang <b52261@freescale.com>
---
 arch/arm/boot/dts/ls1021a.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index c70bb27..28c37f1 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -383,6 +383,17 @@
 				 <&platform_clk 1>;
 		};
 
+		dcfb: dcfb@2ce0000 {
+			compatible = "fsl,ls1021a-dcfb";
+			reg = <0x0 0x2ce0000 0x0 0x10000>;
+			interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&platform_clk 0>;
+			clock-names = "dcfb";
+			scfg-controller = <&scfg>;
+			big-endian;
+			status = "disabled";
+		};
+
 		mdio0: mdio@2d24000 {
 			compatible = "gianfar";
 			device_type = "mdio";
-- 
2.1.0.27.g96db324


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

* [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node
@ 2015-02-13 11:03   ` Jianwei Wang
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei Wang @ 2015-02-13 11:03 UTC (permalink / raw)
  To: linux-arm-kernel

Add DCU node, DCU is a display controller of Freescale
named 2D-ACE.

Signed-off-by: Alison Wang <b18965@freescale.com>
Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Jianwei Wang <b52261@freescale.com>
---
 arch/arm/boot/dts/ls1021a.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index c70bb27..28c37f1 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -383,6 +383,17 @@
 				 <&platform_clk 1>;
 		};
 
+		dcfb: dcfb at 2ce0000 {
+			compatible = "fsl,ls1021a-dcfb";
+			reg = <0x0 0x2ce0000 0x0 0x10000>;
+			interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&platform_clk 0>;
+			clock-names = "dcfb";
+			scfg-controller = <&scfg>;
+			big-endian;
+			status = "disabled";
+		};
+
 		mdio0: mdio at 2d24000 {
 			compatible = "gianfar";
 			device_type = "mdio";
-- 
2.1.0.27.g96db324

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

* [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node
@ 2015-02-13 11:03   ` Jianwei Wang
  0 siblings, 0 replies; 26+ messages in thread
From: Jianwei Wang @ 2015-02-13 11:03 UTC (permalink / raw)
  To: dri-devel, jbarnes, scottwood
  Cc: Xiubo Li, Alison Wang, linux-kernel, linux-arm-kernel, Jianwei Wang

Add DCU node, DCU is a display controller of Freescale
named 2D-ACE.

Signed-off-by: Alison Wang <b18965@freescale.com>
Signed-off-by: Xiubo Li <lixiubo@cmss.chinamobile.com>
Signed-off-by: Jianwei Wang <b52261@freescale.com>
---
 arch/arm/boot/dts/ls1021a.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index c70bb27..28c37f1 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -383,6 +383,17 @@
 				 <&platform_clk 1>;
 		};
 
+		dcfb: dcfb@2ce0000 {
+			compatible = "fsl,ls1021a-dcfb";
+			reg = <0x0 0x2ce0000 0x0 0x10000>;
+			interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&platform_clk 0>;
+			clock-names = "dcfb";
+			scfg-controller = <&scfg>;
+			big-endian;
+			status = "disabled";
+		};
+
 		mdio0: mdio@2d24000 {
 			compatible = "gianfar";
 			device_type = "mdio";
-- 
2.1.0.27.g96db324

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

end of thread, other threads:[~2015-03-19 14:30 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-13  9:44 [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver Jianwei Wang
2015-03-13  9:44 ` Jianwei Wang
2015-03-13  9:44 ` Jianwei Wang
2015-03-13  9:44 ` [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node Jianwei Wang
2015-03-13  9:44   ` Jianwei Wang
2015-03-13  9:44   ` Jianwei Wang
2015-03-13  9:44 ` [PATCH 3/3] arm/dts/ls1021a: Add a TFT LCD panel dts node for DCU Jianwei Wang
2015-03-13  9:44   ` Jianwei Wang
2015-03-13  9:44   ` Jianwei Wang
2015-03-18 22:58 ` [PATCH 1/3] drm/layerscape: Add fsl dcu DRM driver Stefan Agner
2015-03-18 22:58   ` Stefan Agner
2015-03-19  1:41   ` Jianwei.Wang
2015-03-19  1:41     ` Jianwei.Wang
2015-03-19  1:41     ` Jianwei.Wang at freescale.com
2015-03-19 14:30 ` Daniel Vetter
2015-03-19 14:30   ` Daniel Vetter
2015-03-19 14:30   ` Daniel Vetter
  -- strict thread matches above, loose matches on Subject: below --
2015-02-13 11:03 Jianwei Wang
2015-02-13 11:03 ` [PATCH 2/3] arm/dts/ls1021a: Add DCU dts node Jianwei Wang
2015-02-13 11:03   ` Jianwei Wang
2015-02-13 11:03   ` Jianwei Wang
2015-02-13 17:28   ` Scott Wood
2015-02-13 17:28     ` Scott Wood
2015-02-13 17:28     ` Scott Wood
2015-02-15 10:12     ` Jianwei.Wang
2015-02-15 10:12       ` Jianwei.Wang
2015-02-15 10:12       ` Jianwei.Wang at freescale.com

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