All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver
@ 2013-10-29 16:12 Sean Paul
  2013-10-29 16:12 ` [PATCH v3 01/32] drm/exynos: Remove useless slab.h include Sean Paul
                   ` (32 more replies)
  0 siblings, 33 replies; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patchset refactors parts of the exynos driver to move it closer to a proper
drm driver (rather than just implementing a drm layer on top of the hardware
drivers). The hope is to get to a point where the dp/hdmi drivers can implement
drm_connector/drm_encoder directly, and fimd/mixer can directly implement
drm_crtc.

The notable changes in this set:
	- drm_encoder funcs no longer route through the crtc
	- DP driver has been moved from video into the drm driver
	- fimd no longer implements encoder callbacks
	- exynos_drm_hdmi is removed in favor of generic manager/display
	  handling

At a glance, differences between v1 and v2:
	- Passing manager/display in callbacks instead of ctx
	- Tacked on some dpms patches on the end to handle suspend/resume
	  through the dpms path

At a glance, differences between v2 and v3:
	- Fixed vidi issues
	- Moved exynos_drm_hdmi.c removal to the right place
	- Added the exynos_drm_connector removal patches on the end

Sean


Daniel Kurtz (1):
  drm/exynos: hdmi: remove the i2c drivers and use devtree

Sean Paul (30):
  drm/exynos: Merge overlay_ops into manager_ops
  drm/exynos: Add an initialize function to manager and display
  drm/exynos: Use manager_op initialize in fimd
  drm/exynos: hdmi: Implement initialize op for hdmi
  drm/exynos: Pass exynos_drm_manager in manager ops instead of dev
  drm/exynos: Remove apply manager callback
  drm/exynos: Remove dpms link between encoder/connector
  drm/exynos: Rename display_op power_on to dpms
  drm/exynos: Don't keep dpms state in encoder
  drm/exynos: Use unsigned long for possible_crtcs
  drm/exynos: Split manager/display/subdrv
  drm/exynos: Remove exynos_drm_hdmi shim
  drm/exynos: Use drm_mode_copy to copy modes
  drm/exynos: Disable unused crtc planes from crtc
  drm/exynos: Add mode_set manager operation
  drm/exynos: Implement mode_fixup manager operation
  drm/exynos: Use mode_set to configure fimd
  drm/exynos: Remove unused/useless fimd_context members
  drm/exynos: Move dp driver from video/ to drm/
  drm/exynos: Move display implementation into dp
  ARM: dts: Move display-timings node from fimd to dp
  drm/exynos: Implement dpms display callback in DP
  drm/exynos: Clean up FIMD power on/off routines
  drm/exynos: Consolidate suspend/resume in drm_drv
  drm/exynos: Add create_connector callback
  drm/exynos: Implement drm_connector in hdmi directly
  drm/exynos: Implement drm_connector directly in dp driver
  drm/exynos: Implement drm_connector directly in vidi driver
  drm/exynos: Move lvds bridge discovery into DP driver
  drm/exynos: Remove the exynos_drm_connector shim

Stéphane Marchesin (1):
  drm/exynos: Remove useless slab.h include

 .../devicetree/bindings/video/exynos_dp.txt        |   17 +
 .../devicetree/bindings/video/samsung-fimd.txt     |    2 +
 arch/arm/boot/dts/exynos5250-arndale.dts           |    7 +-
 arch/arm/boot/dts/exynos5250-smdk5250.dts          |    7 +-
 arch/arm/boot/dts/exynos5250-snow.dts              |    7 +-
 arch/arm/boot/dts/exynos5420-smdk5420.dts          |    7 +-
 drivers/gpu/drm/exynos/Kconfig                     |    7 +
 drivers/gpu/drm/exynos/Makefile                    |    7 +-
 drivers/gpu/drm/exynos/exynos_ddc.c                |   63 -
 drivers/gpu/drm/exynos/exynos_dp_core.c            | 1399 ++++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_dp_core.h            |  220 +++
 drivers/gpu/drm/exynos/exynos_dp_reg.c             | 1245 +++++++++++++++++
 drivers/gpu/drm/exynos/exynos_dp_reg.h             |  366 +++++
 drivers/gpu/drm/exynos/exynos_drm_connector.c      |  304 -----
 drivers/gpu/drm/exynos/exynos_drm_connector.h      |   24 -
 drivers/gpu/drm/exynos/exynos_drm_core.c           |  233 ++--
 drivers/gpu/drm/exynos/exynos_drm_crtc.c           |  139 +-
 drivers/gpu/drm/exynos/exynos_drm_crtc.h           |   20 +-
 drivers/gpu/drm/exynos/exynos_drm_drv.c            |  155 ++-
 drivers/gpu/drm/exynos/exynos_drm_drv.h            |  154 ++-
 drivers/gpu/drm/exynos/exynos_drm_encoder.c        |  357 +----
 drivers/gpu/drm/exynos/exynos_drm_encoder.h        |   18 +-
 drivers/gpu/drm/exynos/exynos_drm_fb.c             |    4 +-
 drivers/gpu/drm/exynos/exynos_drm_fimd.c           |  875 ++++++------
 drivers/gpu/drm/exynos/exynos_drm_hdmi.c           |  439 ------
 drivers/gpu/drm/exynos/exynos_drm_hdmi.h           |   67 -
 drivers/gpu/drm/exynos/exynos_drm_plane.c          |   17 +-
 drivers/gpu/drm/exynos/exynos_drm_plane.h          |    2 +-
 drivers/gpu/drm/exynos/exynos_drm_vidi.c           |  434 +++---
 drivers/gpu/drm/exynos/exynos_hdmi.c               |  360 ++---
 drivers/gpu/drm/exynos/exynos_hdmi.h               |   23 -
 drivers/gpu/drm/exynos/exynos_hdmiphy.c            |   65 -
 drivers/gpu/drm/exynos/exynos_mixer.c              |  280 ++--
 drivers/gpu/drm/exynos/exynos_mixer.h              |   20 +
 drivers/video/exynos/Kconfig                       |    7 -
 drivers/video/exynos/Makefile                      |    1 -
 drivers/video/exynos/exynos_dp_core.c              | 1214 -----------------
 drivers/video/exynos/exynos_dp_core.h              |  210 ---
 drivers/video/exynos/exynos_dp_reg.c               | 1245 -----------------
 drivers/video/exynos/exynos_dp_reg.h               |  366 -----
 40 files changed, 4735 insertions(+), 5652 deletions(-)
 delete mode 100644 drivers/gpu/drm/exynos/exynos_ddc.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h
 create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.h
 delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.c
 delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.h
 delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.c
 delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.h
 delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmi.h
 delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_mixer.h
 delete mode 100644 drivers/video/exynos/exynos_dp_core.c
 delete mode 100644 drivers/video/exynos/exynos_dp_core.h
 delete mode 100644 drivers/video/exynos/exynos_dp_reg.c
 delete mode 100644 drivers/video/exynos/exynos_dp_reg.h

-- 
1.8.4

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

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

* [PATCH v3 01/32] drm/exynos: Remove useless slab.h include
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-10-31 10:24   ` Inki Dae
  2013-10-31 23:32   ` Tomasz Figa
  2013-10-29 16:12 ` [PATCH v3 02/32] drm/exynos: Merge overlay_ops into manager_ops Sean Paul
                   ` (31 subsequent siblings)
  32 siblings, 2 replies; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

From: Stéphane Marchesin <marcheu@chromium.org>

Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/video/exynos/exynos_dp_core.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index 12bbede..089ae22 100644
--- a/drivers/video/exynos/exynos_dp_core.c
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -12,7 +12,6 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-- 
1.8.4

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

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

* [PATCH v3 02/32] drm/exynos: Merge overlay_ops into manager_ops
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
  2013-10-29 16:12 ` [PATCH v3 01/32] drm/exynos: Remove useless slab.h include Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-10-31 23:39   ` Tomasz Figa
  2013-10-29 16:12 ` [PATCH v3 03/32] drm/exynos: Add an initialize function to manager and display Sean Paul
                   ` (30 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch merges overlay_ops into manager_ops. In all cases,
overlay_ops is implemented in the same place as manager ops, it doesn't
serve a functional purpose, and doesn't make things more clear.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_drv.h     |  29 +--
 drivers/gpu/drm/exynos/exynos_drm_encoder.c |  26 +-
 drivers/gpu/drm/exynos/exynos_drm_fimd.c    | 363 ++++++++++++++--------------
 drivers/gpu/drm/exynos/exynos_drm_hdmi.c    |  36 ++-
 drivers/gpu/drm/exynos/exynos_drm_vidi.c    |  29 +--
 drivers/gpu/drm/exynos/exynos_mixer.c       |   2 -
 6 files changed, 229 insertions(+), 256 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index eaa1966..6f31839 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -54,22 +54,6 @@ enum exynos_drm_output_type {
 };
 
 /*
- * Exynos drm overlay ops structure.
- *
- * @mode_set: copy drm overlay info to hw specific overlay info.
- * @commit: apply hardware specific overlay data to registers.
- * @enable: enable hardware specific overlay.
- * @disable: disable hardware specific overlay.
- */
-struct exynos_drm_overlay_ops {
-	void (*mode_set)(struct device *subdrv_dev,
-			 struct exynos_drm_overlay *overlay);
-	void (*commit)(struct device *subdrv_dev, int zpos);
-	void (*enable)(struct device *subdrv_dev, int zpos);
-	void (*disable)(struct device *subdrv_dev, int zpos);
-};
-
-/*
  * Exynos drm common overlay structure.
  *
  * @fb_x: offset x on a framebuffer to be displayed.
@@ -169,6 +153,10 @@ struct exynos_drm_display_ops {
  * @disable_vblank: specific driver callback for disabling vblank interrupt.
  * @wait_for_vblank: wait for vblank interrupt to make sure that
  *	hardware overlay is updated.
+ * @win_mode_set: copy drm overlay info to hw specific overlay info.
+ * @win_commit: apply hardware specific overlay data to registers.
+ * @win_enable: enable hardware specific overlay.
+ * @win_disable: disable hardware specific overlay.
  */
 struct exynos_drm_manager_ops {
 	void (*dpms)(struct device *subdrv_dev, int mode);
@@ -184,6 +172,11 @@ struct exynos_drm_manager_ops {
 	int (*enable_vblank)(struct device *subdrv_dev);
 	void (*disable_vblank)(struct device *subdrv_dev);
 	void (*wait_for_vblank)(struct device *subdrv_dev);
+	void (*win_mode_set)(struct device *subdrv_dev,
+				struct exynos_drm_overlay *overlay);
+	void (*win_commit)(struct device *subdrv_dev, int zpos);
+	void (*win_enable)(struct device *subdrv_dev, int zpos);
+	void (*win_disable)(struct device *subdrv_dev, int zpos);
 };
 
 /*
@@ -195,9 +188,6 @@ struct exynos_drm_manager_ops {
  * @ops: pointer to callbacks for exynos drm specific framebuffer.
  *	these callbacks should be set by specific drivers such fimd
  *	or hdmi driver and are used to control hardware global registers.
- * @overlay_ops: pointer to callbacks for exynos drm specific framebuffer.
- *	these callbacks should be set by specific drivers such fimd
- *	or hdmi driver and are used to control hardware overlay reigsters.
  * @display: pointer to callbacks for exynos drm specific framebuffer.
  *	these callbacks should be set by specific drivers such fimd
  *	or hdmi driver and are used to control display devices such as
@@ -207,7 +197,6 @@ struct exynos_drm_manager {
 	struct device *dev;
 	int pipe;
 	struct exynos_drm_manager_ops *ops;
-	struct exynos_drm_overlay_ops *overlay_ops;
 	struct exynos_drm_display_ops *display_ops;
 };
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index 06f1b2a..c255341 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -133,7 +133,7 @@ static void disable_plane_to_crtc(struct drm_device *dev,
 			 *
 			 * plane->funcs->disable_plane call checks
 			 * if encoder->crtc is same as plane->crtc and if same
-			 * then overlay_ops->disable callback will be called
+			 * then manager_ops->win_disable callback will be called
 			 * to diasble current hw overlay so plane->crtc should
 			 * have new_crtc because new_crtc was set to
 			 * encoder->crtc in advance.
@@ -442,51 +442,51 @@ void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data)
 {
 	struct exynos_drm_manager *manager =
 		to_exynos_encoder(encoder)->manager;
-	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
 	struct exynos_drm_overlay *overlay = data;
 
-	if (overlay_ops && overlay_ops->mode_set)
-		overlay_ops->mode_set(manager->dev, overlay);
+	if (manager_ops && manager_ops->win_mode_set)
+		manager_ops->win_mode_set(manager->dev, overlay);
 }
 
 void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data)
 {
 	struct exynos_drm_manager *manager =
 		to_exynos_encoder(encoder)->manager;
-	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
 	int zpos = DEFAULT_ZPOS;
 
 	if (data)
 		zpos = *(int *)data;
 
-	if (overlay_ops && overlay_ops->commit)
-		overlay_ops->commit(manager->dev, zpos);
+	if (manager_ops && manager_ops->win_commit)
+		manager_ops->win_commit(manager->dev, zpos);
 }
 
 void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data)
 {
 	struct exynos_drm_manager *manager =
 		to_exynos_encoder(encoder)->manager;
-	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
 	int zpos = DEFAULT_ZPOS;
 
 	if (data)
 		zpos = *(int *)data;
 
-	if (overlay_ops && overlay_ops->enable)
-		overlay_ops->enable(manager->dev, zpos);
+	if (manager_ops && manager_ops->win_enable)
+		manager_ops->win_enable(manager->dev, zpos);
 }
 
 void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
 {
 	struct exynos_drm_manager *manager =
 		to_exynos_encoder(encoder)->manager;
-	struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+	struct exynos_drm_manager_ops *manager_ops = manager->ops;
 	int zpos = DEFAULT_ZPOS;
 
 	if (data)
 		zpos = *(int *)data;
 
-	if (overlay_ops && overlay_ops->disable)
-		overlay_ops->disable(manager->dev, zpos);
+	if (manager_ops && manager_ops->win_disable)
+		manager_ops->win_disable(manager->dev, zpos);
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 868a14d..f271f22 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -181,185 +181,6 @@ static struct exynos_drm_display_ops fimd_display_ops = {
 	.power_on = fimd_display_power_on,
 };
 
-static void fimd_dpms(struct device *subdrv_dev, int mode)
-{
-	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
-
-	DRM_DEBUG_KMS("%d\n", mode);
-
-	mutex_lock(&ctx->lock);
-
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		/*
-		 * enable fimd hardware only if suspended status.
-		 *
-		 * P.S. fimd_dpms function would be called at booting time so
-		 * clk_enable could be called double time.
-		 */
-		if (ctx->suspended)
-			pm_runtime_get_sync(subdrv_dev);
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-	case DRM_MODE_DPMS_OFF:
-		if (!ctx->suspended)
-			pm_runtime_put_sync(subdrv_dev);
-		break;
-	default:
-		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
-		break;
-	}
-
-	mutex_unlock(&ctx->lock);
-}
-
-static void fimd_apply(struct device *subdrv_dev)
-{
-	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
-	struct exynos_drm_manager *mgr = ctx->subdrv.manager;
-	struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
-	struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
-	struct fimd_win_data *win_data;
-	int i;
-
-	for (i = 0; i < WINDOWS_NR; i++) {
-		win_data = &ctx->win_data[i];
-		if (win_data->enabled && (ovl_ops && ovl_ops->commit))
-			ovl_ops->commit(subdrv_dev, i);
-	}
-
-	if (mgr_ops && mgr_ops->commit)
-		mgr_ops->commit(subdrv_dev);
-}
-
-static void fimd_commit(struct device *dev)
-{
-	struct fimd_context *ctx = get_fimd_context(dev);
-	struct exynos_drm_panel_info *panel = &ctx->panel;
-	struct videomode *vm = &panel->vm;
-	struct fimd_driver_data *driver_data;
-	u32 val;
-
-	driver_data = ctx->driver_data;
-	if (ctx->suspended)
-		return;
-
-	/* setup polarity values from machine code. */
-	writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
-
-	/* setup vertical timing values. */
-	val = VIDTCON0_VBPD(vm->vback_porch - 1) |
-	       VIDTCON0_VFPD(vm->vfront_porch - 1) |
-	       VIDTCON0_VSPW(vm->vsync_len - 1);
-	writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
-
-	/* setup horizontal timing values.  */
-	val = VIDTCON1_HBPD(vm->hback_porch - 1) |
-	       VIDTCON1_HFPD(vm->hfront_porch - 1) |
-	       VIDTCON1_HSPW(vm->hsync_len - 1);
-	writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
-
-	/* setup horizontal and vertical display size. */
-	val = VIDTCON2_LINEVAL(vm->vactive - 1) |
-	       VIDTCON2_HOZVAL(vm->hactive - 1) |
-	       VIDTCON2_LINEVAL_E(vm->vactive - 1) |
-	       VIDTCON2_HOZVAL_E(vm->hactive - 1);
-	writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
-
-	/* setup clock source, clock divider, enable dma. */
-	val = ctx->vidcon0;
-	val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
-
-	if (ctx->driver_data->has_clksel) {
-		val &= ~VIDCON0_CLKSEL_MASK;
-		val |= VIDCON0_CLKSEL_LCD;
-	}
-
-	if (ctx->clkdiv > 1)
-		val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
-	else
-		val &= ~VIDCON0_CLKDIR;	/* 1:1 clock */
-
-	/*
-	 * fields of register with prefix '_F' would be updated
-	 * at vsync(same as dma start)
-	 */
-	val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
-	writel(val, ctx->regs + VIDCON0);
-}
-
-static int fimd_enable_vblank(struct device *dev)
-{
-	struct fimd_context *ctx = get_fimd_context(dev);
-	u32 val;
-
-	if (ctx->suspended)
-		return -EPERM;
-
-	if (!test_and_set_bit(0, &ctx->irq_flags)) {
-		val = readl(ctx->regs + VIDINTCON0);
-
-		val |= VIDINTCON0_INT_ENABLE;
-		val |= VIDINTCON0_INT_FRAME;
-
-		val &= ~VIDINTCON0_FRAMESEL0_MASK;
-		val |= VIDINTCON0_FRAMESEL0_VSYNC;
-		val &= ~VIDINTCON0_FRAMESEL1_MASK;
-		val |= VIDINTCON0_FRAMESEL1_NONE;
-
-		writel(val, ctx->regs + VIDINTCON0);
-	}
-
-	return 0;
-}
-
-static void fimd_disable_vblank(struct device *dev)
-{
-	struct fimd_context *ctx = get_fimd_context(dev);
-	u32 val;
-
-	if (ctx->suspended)
-		return;
-
-	if (test_and_clear_bit(0, &ctx->irq_flags)) {
-		val = readl(ctx->regs + VIDINTCON0);
-
-		val &= ~VIDINTCON0_INT_FRAME;
-		val &= ~VIDINTCON0_INT_ENABLE;
-
-		writel(val, ctx->regs + VIDINTCON0);
-	}
-}
-
-static void fimd_wait_for_vblank(struct device *dev)
-{
-	struct fimd_context *ctx = get_fimd_context(dev);
-
-	if (ctx->suspended)
-		return;
-
-	atomic_set(&ctx->wait_vsync_event, 1);
-
-	/*
-	 * wait for FIMD to signal VSYNC interrupt or return after
-	 * timeout which is set to 50ms (refresh rate of 20).
-	 */
-	if (!wait_event_timeout(ctx->wait_vsync_queue,
-				!atomic_read(&ctx->wait_vsync_event),
-				DRM_HZ/20))
-		DRM_DEBUG_KMS("vblank wait timed out.\n");
-}
-
-static struct exynos_drm_manager_ops fimd_manager_ops = {
-	.dpms = fimd_dpms,
-	.apply = fimd_apply,
-	.commit = fimd_commit,
-	.enable_vblank = fimd_enable_vblank,
-	.disable_vblank = fimd_disable_vblank,
-	.wait_for_vblank = fimd_wait_for_vblank,
-};
-
 static void fimd_win_mode_set(struct device *dev,
 			      struct exynos_drm_overlay *overlay)
 {
@@ -669,16 +490,190 @@ static void fimd_win_disable(struct device *dev, int zpos)
 	win_data->enabled = false;
 }
 
-static struct exynos_drm_overlay_ops fimd_overlay_ops = {
-	.mode_set = fimd_win_mode_set,
-	.commit = fimd_win_commit,
-	.disable = fimd_win_disable,
+static void fimd_dpms(struct device *subdrv_dev, int mode)
+{
+	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
+
+	DRM_DEBUG_KMS("%d\n", mode);
+
+	mutex_lock(&ctx->lock);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		/*
+		 * enable fimd hardware only if suspended status.
+		 *
+		 * P.S. fimd_dpms function would be called at booting time so
+		 * clk_enable could be called double time.
+		 */
+		if (ctx->suspended)
+			pm_runtime_get_sync(subdrv_dev);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		if (!ctx->suspended)
+			pm_runtime_put_sync(subdrv_dev);
+		break;
+	default:
+		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
+		break;
+	}
+
+	mutex_unlock(&ctx->lock);
+}
+
+static void fimd_apply(struct device *subdrv_dev)
+{
+	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
+	struct exynos_drm_manager *mgr = ctx->subdrv.manager;
+	struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
+	struct fimd_win_data *win_data;
+	int i;
+
+	for (i = 0; i < WINDOWS_NR; i++) {
+		win_data = &ctx->win_data[i];
+		if (win_data->enabled && (mgr_ops && mgr_ops->win_commit))
+			mgr_ops->win_commit(subdrv_dev, i);
+	}
+
+	if (mgr_ops && mgr_ops->commit)
+		mgr_ops->commit(subdrv_dev);
+}
+
+static void fimd_commit(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	struct exynos_drm_panel_info *panel = &ctx->panel;
+	struct videomode *vm = &panel->vm;
+	struct fimd_driver_data *driver_data;
+	u32 val;
+
+	driver_data = ctx->driver_data;
+	if (ctx->suspended)
+		return;
+
+	/* setup polarity values from machine code. */
+	writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
+
+	/* setup vertical timing values. */
+	val = VIDTCON0_VBPD(vm->vback_porch - 1) |
+	       VIDTCON0_VFPD(vm->vfront_porch - 1) |
+	       VIDTCON0_VSPW(vm->vsync_len - 1);
+	writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
+
+	/* setup horizontal timing values.  */
+	val = VIDTCON1_HBPD(vm->hback_porch - 1) |
+	       VIDTCON1_HFPD(vm->hfront_porch - 1) |
+	       VIDTCON1_HSPW(vm->hsync_len - 1);
+	writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
+
+	/* setup horizontal and vertical display size. */
+	val = VIDTCON2_LINEVAL(vm->vactive - 1) |
+	       VIDTCON2_HOZVAL(vm->hactive - 1) |
+	       VIDTCON2_LINEVAL_E(vm->vactive - 1) |
+	       VIDTCON2_HOZVAL_E(vm->hactive - 1);
+	writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
+
+	/* setup clock source, clock divider, enable dma. */
+	val = ctx->vidcon0;
+	val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
+
+	if (ctx->driver_data->has_clksel) {
+		val &= ~VIDCON0_CLKSEL_MASK;
+		val |= VIDCON0_CLKSEL_LCD;
+	}
+
+	if (ctx->clkdiv > 1)
+		val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
+	else
+		val &= ~VIDCON0_CLKDIR;	/* 1:1 clock */
+
+	/*
+	 * fields of register with prefix '_F' would be updated
+	 * at vsync(same as dma start)
+	 */
+	val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
+	writel(val, ctx->regs + VIDCON0);
+}
+
+static int fimd_enable_vblank(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	u32 val;
+
+	if (ctx->suspended)
+		return -EPERM;
+
+	if (!test_and_set_bit(0, &ctx->irq_flags)) {
+		val = readl(ctx->regs + VIDINTCON0);
+
+		val |= VIDINTCON0_INT_ENABLE;
+		val |= VIDINTCON0_INT_FRAME;
+
+		val &= ~VIDINTCON0_FRAMESEL0_MASK;
+		val |= VIDINTCON0_FRAMESEL0_VSYNC;
+		val &= ~VIDINTCON0_FRAMESEL1_MASK;
+		val |= VIDINTCON0_FRAMESEL1_NONE;
+
+		writel(val, ctx->regs + VIDINTCON0);
+	}
+
+	return 0;
+}
+
+static void fimd_disable_vblank(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+	u32 val;
+
+	if (ctx->suspended)
+		return;
+
+	if (test_and_clear_bit(0, &ctx->irq_flags)) {
+		val = readl(ctx->regs + VIDINTCON0);
+
+		val &= ~VIDINTCON0_INT_FRAME;
+		val &= ~VIDINTCON0_INT_ENABLE;
+
+		writel(val, ctx->regs + VIDINTCON0);
+	}
+}
+
+static void fimd_wait_for_vblank(struct device *dev)
+{
+	struct fimd_context *ctx = get_fimd_context(dev);
+
+	if (ctx->suspended)
+		return;
+
+	atomic_set(&ctx->wait_vsync_event, 1);
+
+	/*
+	 * wait for FIMD to signal VSYNC interrupt or return after
+	 * timeout which is set to 50ms (refresh rate of 20).
+	 */
+	if (!wait_event_timeout(ctx->wait_vsync_queue,
+				!atomic_read(&ctx->wait_vsync_event),
+				DRM_HZ/20))
+		DRM_DEBUG_KMS("vblank wait timed out.\n");
+}
+
+static struct exynos_drm_manager_ops fimd_manager_ops = {
+	.dpms = fimd_dpms,
+	.apply = fimd_apply,
+	.commit = fimd_commit,
+	.enable_vblank = fimd_enable_vblank,
+	.disable_vblank = fimd_disable_vblank,
+	.wait_for_vblank = fimd_wait_for_vblank,
+	.win_mode_set = fimd_win_mode_set,
+	.win_commit = fimd_win_commit,
+	.win_disable = fimd_win_disable,
 };
 
 static struct exynos_drm_manager fimd_manager = {
 	.pipe		= -1,
 	.ops		= &fimd_manager_ops,
-	.overlay_ops	= &fimd_overlay_ops,
 	.display_ops	= &fimd_display_ops,
 };
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index 8548b97..a1ef3c9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -284,19 +284,7 @@ static void drm_hdmi_apply(struct device *subdrv_dev)
 		hdmi_ops->commit(ctx->hdmi_ctx->ctx);
 }
 
-static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
-	.dpms = drm_hdmi_dpms,
-	.apply = drm_hdmi_apply,
-	.enable_vblank = drm_hdmi_enable_vblank,
-	.disable_vblank = drm_hdmi_disable_vblank,
-	.wait_for_vblank = drm_hdmi_wait_for_vblank,
-	.mode_fixup = drm_hdmi_mode_fixup,
-	.mode_set = drm_hdmi_mode_set,
-	.get_max_resol = drm_hdmi_get_max_resol,
-	.commit = drm_hdmi_commit,
-};
-
-static void drm_mixer_mode_set(struct device *subdrv_dev,
+static void drm_mixer_win_mode_set(struct device *subdrv_dev,
 		struct exynos_drm_overlay *overlay)
 {
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
@@ -305,7 +293,7 @@ static void drm_mixer_mode_set(struct device *subdrv_dev,
 		mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
 }
 
-static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
+static void drm_mixer_win_commit(struct device *subdrv_dev, int zpos)
 {
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 	int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
@@ -321,7 +309,7 @@ static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
 	ctx->enabled[win] = true;
 }
 
-static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
+static void drm_mixer_win_disable(struct device *subdrv_dev, int zpos)
 {
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
 	int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
@@ -337,16 +325,24 @@ static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
 	ctx->enabled[win] = false;
 }
 
-static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
-	.mode_set = drm_mixer_mode_set,
-	.commit = drm_mixer_commit,
-	.disable = drm_mixer_disable,
+static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
+	.dpms = drm_hdmi_dpms,
+	.apply = drm_hdmi_apply,
+	.enable_vblank = drm_hdmi_enable_vblank,
+	.disable_vblank = drm_hdmi_disable_vblank,
+	.wait_for_vblank = drm_hdmi_wait_for_vblank,
+	.mode_fixup = drm_hdmi_mode_fixup,
+	.mode_set = drm_hdmi_mode_set,
+	.get_max_resol = drm_hdmi_get_max_resol,
+	.commit = drm_hdmi_commit,
+	.win_mode_set = drm_mixer_win_mode_set,
+	.win_commit = drm_mixer_win_commit,
+	.win_disable = drm_mixer_win_disable,
 };
 
 static struct exynos_drm_manager hdmi_manager = {
 	.pipe		= -1,
 	.ops		= &drm_hdmi_manager_ops,
-	.overlay_ops	= &drm_hdmi_overlay_ops,
 	.display_ops	= &drm_hdmi_display_ops,
 };
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 4400330..15a97ce 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -182,14 +182,13 @@ static void vidi_apply(struct device *subdrv_dev)
 	struct vidi_context *ctx = get_vidi_context(subdrv_dev);
 	struct exynos_drm_manager *mgr = ctx->subdrv.manager;
 	struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
-	struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
 	struct vidi_win_data *win_data;
 	int i;
 
 	for (i = 0; i < WINDOWS_NR; i++) {
 		win_data = &ctx->win_data[i];
-		if (win_data->enabled && (ovl_ops && ovl_ops->commit))
-			ovl_ops->commit(subdrv_dev, i);
+		if (win_data->enabled && (mgr_ops && mgr_ops->win_commit))
+			mgr_ops->win_commit(subdrv_dev, i);
 	}
 
 	if (mgr_ops && mgr_ops->commit)
@@ -219,7 +218,7 @@ static int vidi_enable_vblank(struct device *dev)
 	/*
 	 * in case of page flip request, vidi_finish_pageflip function
 	 * will not be called because direct_vblank is true and then
-	 * that function will be called by overlay_ops->commit callback
+	 * that function will be called by manager_ops->win_commit callback
 	 */
 	schedule_work(&ctx->work);
 
@@ -237,14 +236,6 @@ static void vidi_disable_vblank(struct device *dev)
 		ctx->vblank_on = false;
 }
 
-static struct exynos_drm_manager_ops vidi_manager_ops = {
-	.dpms = vidi_dpms,
-	.apply = vidi_apply,
-	.commit = vidi_commit,
-	.enable_vblank = vidi_enable_vblank,
-	.disable_vblank = vidi_disable_vblank,
-};
-
 static void vidi_win_mode_set(struct device *dev,
 			      struct exynos_drm_overlay *overlay)
 {
@@ -341,16 +332,20 @@ static void vidi_win_disable(struct device *dev, int zpos)
 	/* TODO. */
 }
 
-static struct exynos_drm_overlay_ops vidi_overlay_ops = {
-	.mode_set = vidi_win_mode_set,
-	.commit = vidi_win_commit,
-	.disable = vidi_win_disable,
+static struct exynos_drm_manager_ops vidi_manager_ops = {
+	.dpms = vidi_dpms,
+	.apply = vidi_apply,
+	.commit = vidi_commit,
+	.enable_vblank = vidi_enable_vblank,
+	.disable_vblank = vidi_disable_vblank,
+	.win_mode_set = vidi_win_mode_set,
+	.win_commit = vidi_win_commit,
+	.win_disable = vidi_win_disable,
 };
 
 static struct exynos_drm_manager vidi_manager = {
 	.pipe		= -1,
 	.ops		= &vidi_manager_ops,
-	.overlay_ops	= &vidi_overlay_ops,
 	.display_ops	= &vidi_display_ops,
 };
 
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 63bc5f9..9634188 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -975,8 +975,6 @@ static struct exynos_mixer_ops mixer_ops = {
 	.disable_vblank		= mixer_disable_vblank,
 	.wait_for_vblank	= mixer_wait_for_vblank,
 	.dpms			= mixer_dpms,
-
-	/* overlay */
 	.win_mode_set		= mixer_win_mode_set,
 	.win_commit		= mixer_win_commit,
 	.win_disable		= mixer_win_disable,
-- 
1.8.4

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

* [PATCH v3 03/32] drm/exynos: Add an initialize function to manager and display
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
  2013-10-29 16:12 ` [PATCH v3 01/32] drm/exynos: Remove useless slab.h include Sean Paul
  2013-10-29 16:12 ` [PATCH v3 02/32] drm/exynos: Merge overlay_ops into manager_ops Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-10-31 23:42   ` Tomasz Figa
  2013-10-29 16:12 ` [PATCH v3 04/32] drm/exynos: Use manager_op initialize in fimd Sean Paul
                   ` (29 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch adds an initialize function to the manager and display
operations. This allows them to keep track of drm_device in their
local context, as well as adds an initialization hook right after
the encoder is created.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_drv.h     |  5 +++++
 drivers/gpu/drm/exynos/exynos_drm_encoder.c | 21 +++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 6f31839..09bfe60 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -123,6 +123,7 @@ struct exynos_drm_overlay {
  *	- this structure is common to analog tv, digital tv and lcd panel.
  *
  * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
+ * @initialize: initializes the display with drm_dev
  * @is_connected: check for that display is connected or not.
  * @get_edid: get edid modes from display driver.
  * @get_panel: get panel object from display driver.
@@ -131,6 +132,7 @@ struct exynos_drm_overlay {
  */
 struct exynos_drm_display_ops {
 	enum exynos_drm_output_type type;
+	int (*initialize)(struct device *dev, struct drm_device *drm_dev);
 	bool (*is_connected)(struct device *dev);
 	struct edid *(*get_edid)(struct device *dev,
 			struct drm_connector *connector);
@@ -142,6 +144,7 @@ struct exynos_drm_display_ops {
 /*
  * Exynos drm manager ops
  *
+ * @initialize: initializes the manager with drm_dev
  * @dpms: control device power.
  * @apply: set timing, vblank and overlay data to registers.
  * @mode_fixup: fix mode data comparing to hw specific display mode.
@@ -159,6 +162,8 @@ struct exynos_drm_display_ops {
  * @win_disable: disable hardware specific overlay.
  */
 struct exynos_drm_manager_ops {
+	int (*initialize)(struct device *subdrv_dev,
+			struct drm_device *drm_dev);
 	void (*dpms)(struct device *subdrv_dev, int mode);
 	void (*apply)(struct device *subdrv_dev);
 	void (*mode_fixup)(struct device *subdrv_dev,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index c255341..a9eb2b0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -316,6 +316,7 @@ exynos_drm_encoder_create(struct drm_device *dev,
 {
 	struct drm_encoder *encoder;
 	struct exynos_drm_encoder *exynos_encoder;
+	int ret;
 
 	if (!manager || !possible_crtcs)
 		return NULL;
@@ -339,9 +340,29 @@ exynos_drm_encoder_create(struct drm_device *dev,
 
 	drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs);
 
+	if (manager->ops && manager->ops->initialize) {
+		ret = manager->ops->initialize(manager->dev, dev);
+		if (ret) {
+			DRM_ERROR("Manager initialize failed %d\n", ret);
+			goto error;
+		}
+	}
+
+	if (manager->display_ops && manager->display_ops->initialize) {
+		ret = manager->display_ops->initialize(manager->dev, dev);
+		if (ret) {
+			DRM_ERROR("Display initialize failed %d\n", ret);
+			goto error;
+		}
+	}
+
 	DRM_DEBUG_KMS("encoder has been created\n");
 
 	return encoder;
+
+error:
+	exynos_drm_encoder_destroy(&exynos_encoder->drm_encoder);
+	return NULL;
 }
 
 struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder)
-- 
1.8.4

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

* [PATCH v3 04/32] drm/exynos: Use manager_op initialize in fimd
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (2 preceding siblings ...)
  2013-10-29 16:12 ` [PATCH v3 03/32] drm/exynos: Add an initialize function to manager and display Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-10-31 23:49   ` Tomasz Figa
  2013-10-29 16:12 ` [PATCH v3 05/32] drm/exynos: hdmi: Implement initialize op for hdmi Sean Paul
                   ` (28 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch implements the intitialize manager op in fimd.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_fimd.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index f271f22..90fcd6f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -106,6 +106,7 @@ struct fimd_win_data {
 
 struct fimd_context {
 	struct exynos_drm_subdrv	subdrv;
+	struct drm_device		*drm_dev;
 	int				irq;
 	struct drm_crtc			*crtc;
 	struct clk			*bus_clk;
@@ -490,6 +491,16 @@ static void fimd_win_disable(struct device *dev, int zpos)
 	win_data->enabled = false;
 }
 
+static int fimd_mgr_initialize(struct device *subdrv_dev,
+		struct drm_device *drm_dev)
+{
+	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
+
+	ctx->drm_dev = drm_dev;
+
+	return 0;
+}
+
 static void fimd_dpms(struct device *subdrv_dev, int mode)
 {
 	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
@@ -660,6 +671,7 @@ static void fimd_wait_for_vblank(struct device *dev)
 }
 
 static struct exynos_drm_manager_ops fimd_manager_ops = {
+	.initialize = fimd_mgr_initialize,
 	.dpms = fimd_dpms,
 	.apply = fimd_apply,
 	.commit = fimd_commit,
@@ -681,7 +693,6 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
 {
 	struct fimd_context *ctx = (struct fimd_context *)dev_id;
 	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-	struct drm_device *drm_dev = subdrv->drm_dev;
 	struct exynos_drm_manager *manager = subdrv->manager;
 	u32 val;
 
@@ -692,11 +703,11 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
 		writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
 
 	/* check the crtc is detached already from encoder */
-	if (manager->pipe < 0)
+	if (manager->pipe < 0 || !ctx->drm_dev)
 		goto out;
 
-	drm_handle_vblank(drm_dev, manager->pipe);
-	exynos_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
+	drm_handle_vblank(ctx->drm_dev, manager->pipe);
+	exynos_drm_crtc_finish_pageflip(ctx->drm_dev, manager->pipe);
 
 	/* set wait vsync event to zero and wake up queue. */
 	if (atomic_read(&ctx->wait_vsync_event)) {
-- 
1.8.4

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

* [PATCH v3 05/32] drm/exynos: hdmi: Implement initialize op for hdmi
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (3 preceding siblings ...)
  2013-10-29 16:12 ` [PATCH v3 04/32] drm/exynos: Use manager_op initialize in fimd Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-10-31 23:53   ` Tomasz Figa
  2013-10-29 16:12 ` [PATCH v3 06/32] drm/exynos: Pass exynos_drm_manager in manager ops instead of dev Sean Paul
                   ` (27 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch implements the initialize callback in the hdmi and mixer
manager. This allows us to get rid of drm_dev in the drm_hdmi level and
track it in the mixer and hdmi drivers. This is one of the things
holding back the complete removal of the drm_hdmi layer.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 35 ++++++++++++++++++++++++++------
 drivers/gpu/drm/exynos/exynos_drm_hdmi.h |  3 ++-
 drivers/gpu/drm/exynos/exynos_hdmi.c     | 18 ++++++++++++----
 drivers/gpu/drm/exynos/exynos_mixer.c    | 35 +++++++++++++++++++-------------
 4 files changed, 66 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index a1ef3c9..aebcc0e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -97,6 +97,18 @@ void exynos_mixer_ops_register(struct exynos_mixer_ops *ops)
 		mixer_ops = ops;
 }
 
+static int drm_hdmi_display_initialize(struct device *dev,
+		struct drm_device *drm_dev)
+{
+	struct drm_hdmi_context *ctx = to_context(dev);
+
+	if (hdmi_ops && hdmi_ops->initialize)
+		return hdmi_ops->initialize(ctx->hdmi_ctx->ctx, drm_dev);
+
+	return 0;
+}
+
+
 static bool drm_hdmi_is_connected(struct device *dev)
 {
 	struct drm_hdmi_context *ctx = to_context(dev);
@@ -153,6 +165,7 @@ static int drm_hdmi_power_on(struct device *dev, int mode)
 
 static struct exynos_drm_display_ops drm_hdmi_display_ops = {
 	.type = EXYNOS_DISPLAY_TYPE_HDMI,
+	.initialize = drm_hdmi_display_initialize,
 	.is_connected = drm_hdmi_is_connected,
 	.get_edid = drm_hdmi_get_edid,
 	.check_mode = drm_hdmi_check_mode,
@@ -257,6 +270,21 @@ static void drm_hdmi_commit(struct device *subdrv_dev)
 		hdmi_ops->commit(ctx->hdmi_ctx->ctx);
 }
 
+static int drm_hdmi_mgr_initialize(struct device *subdrv_dev,
+		struct drm_device *drm_dev)
+{
+	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	int ret = 0;
+
+	if (mixer_ops && mixer_ops->initialize)
+		ret = mixer_ops->initialize(ctx->mixer_ctx->ctx, drm_dev);
+
+	if (mixer_ops->iommu_on)
+		mixer_ops->iommu_on(ctx->mixer_ctx->ctx, true);
+
+	return ret;
+}
+
 static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
 {
 	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
@@ -326,6 +354,7 @@ static void drm_mixer_win_disable(struct device *subdrv_dev, int zpos)
 }
 
 static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
+	.initialize = drm_hdmi_mgr_initialize,
 	.dpms = drm_hdmi_dpms,
 	.apply = drm_hdmi_apply,
 	.enable_vblank = drm_hdmi_enable_vblank,
@@ -372,12 +401,6 @@ static int hdmi_subdrv_probe(struct drm_device *drm_dev,
 	ctx->hdmi_ctx = hdmi_ctx;
 	ctx->mixer_ctx = mixer_ctx;
 
-	ctx->hdmi_ctx->drm_dev = drm_dev;
-	ctx->mixer_ctx->drm_dev = drm_dev;
-
-	if (mixer_ops->iommu_on)
-		mixer_ops->iommu_on(ctx->mixer_ctx->ctx, true);
-
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
index 724cab1..cf7b1da 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
@@ -23,12 +23,12 @@
  *	this context should be hdmi_context or mixer_context.
  */
 struct exynos_drm_hdmi_context {
-	struct drm_device	*drm_dev;
 	void			*ctx;
 };
 
 struct exynos_hdmi_ops {
 	/* display */
+	int (*initialize)(void *ctx, struct drm_device *drm_dev);
 	bool (*is_connected)(void *ctx);
 	struct edid *(*get_edid)(void *ctx,
 			struct drm_connector *connector);
@@ -45,6 +45,7 @@ struct exynos_hdmi_ops {
 
 struct exynos_mixer_ops {
 	/* manager */
+	int (*initialize)(void *ctx, struct drm_device *drm_dev);
 	int (*iommu_on)(void *ctx, bool enable);
 	int (*enable_vblank)(void *ctx, int pipe);
 	void (*disable_vblank)(void *ctx);
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index fcfa23a..00704e9 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -741,6 +741,15 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
 	}
 }
 
+static int hdmi_initialize(void *ctx, struct drm_device *drm_dev)
+{
+	struct hdmi_context *hdata = ctx;
+
+	hdata->drm_dev = drm_dev;
+
+	return 0;
+}
+
 static bool hdmi_is_connected(void *ctx)
 {
 	struct hdmi_context *hdata = ctx;
@@ -1746,6 +1755,7 @@ static void hdmi_dpms(void *ctx, int mode)
 
 static struct exynos_hdmi_ops hdmi_ops = {
 	/* display */
+	.initialize	= hdmi_initialize,
 	.is_connected	= hdmi_is_connected,
 	.get_edid	= hdmi_get_edid,
 	.check_mode	= hdmi_check_mode,
@@ -1766,8 +1776,8 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg)
 	hdata->hpd = gpio_get_value(hdata->hpd_gpio);
 	mutex_unlock(&hdata->hdmi_mutex);
 
-	if (ctx->drm_dev)
-		drm_helper_hpd_irq_event(ctx->drm_dev);
+	if (hdata->drm_dev)
+		drm_helper_hpd_irq_event(hdata->drm_dev);
 
 	return IRQ_HANDLED;
 }
@@ -2020,8 +2030,8 @@ static int hdmi_suspend(struct device *dev)
 	disable_irq(hdata->irq);
 
 	hdata->hpd = false;
-	if (ctx->drm_dev)
-		drm_helper_hpd_irq_event(ctx->drm_dev);
+	if (hdata->drm_dev)
+		drm_helper_hpd_irq_event(hdata->drm_dev);
 
 	if (pm_runtime_suspended(dev)) {
 		DRM_DEBUG_KMS("Already suspended\n");
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 9634188..2f204c1 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -685,20 +685,25 @@ static void mixer_win_reset(struct mixer_context *ctx)
 	spin_unlock_irqrestore(&res->reg_slock, flags);
 }
 
+static int mixer_initialize(void *ctx, struct drm_device *drm_dev)
+{
+	struct mixer_context *mixer_ctx = ctx;
+
+	mixer_ctx->drm_dev = drm_dev;
+
+	return 0;
+}
+
 static int mixer_iommu_on(void *ctx, bool enable)
 {
-	struct exynos_drm_hdmi_context *drm_hdmi_ctx;
 	struct mixer_context *mdata = ctx;
-	struct drm_device *drm_dev;
-
-	drm_hdmi_ctx = mdata->parent_ctx;
-	drm_dev = drm_hdmi_ctx->drm_dev;
 
-	if (is_drm_iommu_supported(drm_dev)) {
+	if (is_drm_iommu_supported(mdata->drm_dev)) {
 		if (enable)
-			return drm_iommu_attach_device(drm_dev, mdata->dev);
+			return drm_iommu_attach_device(mdata->drm_dev,
+					mdata->dev);
 
-		drm_iommu_detach_device(drm_dev, mdata->dev);
+		drm_iommu_detach_device(mdata->drm_dev, mdata->dev);
 	}
 	return 0;
 }
@@ -970,6 +975,7 @@ static void mixer_dpms(void *ctx, int mode)
 
 static struct exynos_mixer_ops mixer_ops = {
 	/* manager */
+	.initialize		= mixer_initialize,
 	.iommu_on		= mixer_iommu_on,
 	.enable_vblank		= mixer_enable_vblank,
 	.disable_vblank		= mixer_disable_vblank,
@@ -985,8 +991,7 @@ static struct exynos_mixer_ops mixer_ops = {
 
 static irqreturn_t mixer_irq_handler(int irq, void *arg)
 {
-	struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
-	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
+	struct mixer_context *ctx = arg;
 	struct mixer_resources *res = &ctx->mixer_res;
 	u32 val, base, shadow;
 
@@ -995,6 +1000,9 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
 	/* read interrupt status for handling and clearing flags for VSYNC */
 	val = mixer_reg_read(res, MXR_INT_STATUS);
 
+	if (!ctx->drm_dev)
+		goto out;
+
 	/* handling VSYNC */
 	if (val & MXR_INT_STATUS_VSYNC) {
 		/* interlace scan need to check shadow register */
@@ -1010,9 +1018,8 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
 				goto out;
 		}
 
-		drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
-		exynos_drm_crtc_finish_pageflip(drm_hdmi_ctx->drm_dev,
-				ctx->pipe);
+		drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+		exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
 
 		/* set wait vsync event to zero and wake up queue. */
 		if (atomic_read(&ctx->wait_vsync_event)) {
@@ -1077,7 +1084,7 @@ static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
 	}
 
 	ret = devm_request_irq(dev, res->start, mixer_irq_handler,
-							0, "drm_mixer", ctx);
+						0, "drm_mixer", mixer_ctx);
 	if (ret) {
 		dev_err(dev, "request interrupt failed.\n");
 		return ret;
-- 
1.8.4

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

* [PATCH v3 06/32] drm/exynos: Pass exynos_drm_manager in manager ops instead of dev
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (4 preceding siblings ...)
  2013-10-29 16:12 ` [PATCH v3 05/32] drm/exynos: hdmi: Implement initialize op for hdmi Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-11-01  0:19   ` Tomasz Figa
  2013-10-29 16:12 ` [PATCH v3 07/32] drm/exynos: Remove apply manager callback Sean Paul
                   ` (26 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch changes the manager ops callbacks from accepting the subdrv
device pointer to taking a pointer to the manager. This will allow us
to move closer to decoupling manager/display from subdrv, and subsequently
decoupling the crtc/plane from the encoder.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2:
	- Instead of passing context, pass manager
	- Properly assign ctx->dev in fimd driver
Changes in v3:
	- Added vidi implementation

 drivers/gpu/drm/exynos/exynos_drm_connector.c |   2 +-
 drivers/gpu/drm/exynos/exynos_drm_drv.h       |  35 ++++----
 drivers/gpu/drm/exynos/exynos_drm_encoder.c   |  27 +++---
 drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 114 ++++++++++++++------------
 drivers/gpu/drm/exynos/exynos_drm_hdmi.c      |  72 ++++++++--------
 drivers/gpu/drm/exynos/exynos_drm_vidi.c      |  83 ++++++++++---------
 6 files changed, 180 insertions(+), 153 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index e082efb..23b69d8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -198,7 +198,7 @@ static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
 	 * resolution then get max width and height from that driver.
 	 */
 	if (ops && ops->get_max_resol)
-		ops->get_max_resol(manager->dev, &width, &height);
+		ops->get_max_resol(manager, &width, &height);
 
 	return drm_helper_probe_single_connector_modes(connector, width,
 							height);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 09bfe60..8eb8b83 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -161,27 +161,28 @@ struct exynos_drm_display_ops {
  * @win_enable: enable hardware specific overlay.
  * @win_disable: disable hardware specific overlay.
  */
+struct exynos_drm_manager;
 struct exynos_drm_manager_ops {
-	int (*initialize)(struct device *subdrv_dev,
-			struct drm_device *drm_dev);
-	void (*dpms)(struct device *subdrv_dev, int mode);
-	void (*apply)(struct device *subdrv_dev);
-	void (*mode_fixup)(struct device *subdrv_dev,
+	int (*initialize)(struct exynos_drm_manager *mgr,
+				struct drm_device *drm_dev);
+	void (*dpms)(struct exynos_drm_manager *mgr, int mode);
+	void (*apply)(struct exynos_drm_manager *mgr);
+	void (*mode_fixup)(struct exynos_drm_manager *mgr,
 				struct drm_connector *connector,
 				const struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode);
-	void (*mode_set)(struct device *subdrv_dev, void *mode);
-	void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width,
-				unsigned int *height);
-	void (*commit)(struct device *subdrv_dev);
-	int (*enable_vblank)(struct device *subdrv_dev);
-	void (*disable_vblank)(struct device *subdrv_dev);
-	void (*wait_for_vblank)(struct device *subdrv_dev);
-	void (*win_mode_set)(struct device *subdrv_dev,
+	void (*mode_set)(struct exynos_drm_manager *mgr, void *mode);
+	void (*get_max_resol)(struct exynos_drm_manager *mgr,
+				unsigned int *width, unsigned int *height);
+	void (*commit)(struct exynos_drm_manager *mgr);
+	int (*enable_vblank)(struct exynos_drm_manager *mgr);
+	void (*disable_vblank)(struct exynos_drm_manager *mgr);
+	void (*wait_for_vblank)(struct exynos_drm_manager *mgr);
+	void (*win_mode_set)(struct exynos_drm_manager *mgr,
 				struct exynos_drm_overlay *overlay);
-	void (*win_commit)(struct device *subdrv_dev, int zpos);
-	void (*win_enable)(struct device *subdrv_dev, int zpos);
-	void (*win_disable)(struct device *subdrv_dev, int zpos);
+	void (*win_commit)(struct exynos_drm_manager *mgr, int zpos);
+	void (*win_enable)(struct exynos_drm_manager *mgr, int zpos);
+	void (*win_disable)(struct exynos_drm_manager *mgr, int zpos);
 };
 
 /*
@@ -197,12 +198,14 @@ struct exynos_drm_manager_ops {
  *	these callbacks should be set by specific drivers such fimd
  *	or hdmi driver and are used to control display devices such as
  *	analog tv, digital tv and lcd panel and also get timing data for them.
+ * @ctx: A pointer to the manager's implementation specific context
  */
 struct exynos_drm_manager {
 	struct device *dev;
 	int pipe;
 	struct exynos_drm_manager_ops *ops;
 	struct exynos_drm_display_ops *display_ops;
+	void *ctx;
 };
 
 struct exynos_drm_g2d_private {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index a9eb2b0..ec627fa 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -74,7 +74,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 	case DRM_MODE_DPMS_ON:
 		if (manager_ops && manager_ops->apply)
 			if (!exynos_encoder->updated)
-				manager_ops->apply(manager->dev);
+				manager_ops->apply(manager);
 
 		exynos_drm_connector_power(encoder, mode);
 		exynos_encoder->dpms = mode;
@@ -107,7 +107,7 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		if (connector->encoder == encoder)
 			if (manager_ops && manager_ops->mode_fixup)
-				manager_ops->mode_fixup(manager->dev, connector,
+				manager_ops->mode_fixup(manager, connector,
 							mode, adjusted_mode);
 	}
 
@@ -175,8 +175,7 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
 			manager_ops = manager->ops;
 
 			if (manager_ops && manager_ops->mode_set)
-				manager_ops->mode_set(manager->dev,
-							adjusted_mode);
+				manager_ops->mode_set(manager, adjusted_mode);
 
 			exynos_encoder->old_crtc = encoder->crtc;
 		}
@@ -195,7 +194,7 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 	struct exynos_drm_manager_ops *manager_ops = manager->ops;
 
 	if (manager_ops && manager_ops->commit)
-		manager_ops->commit(manager->dev);
+		manager_ops->commit(manager);
 
 	/*
 	 * this will avoid one issue that overlay data is updated to
@@ -233,7 +232,7 @@ void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb)
 		 *	real hardware.
 		 */
 		if (ops->wait_for_vblank)
-			ops->wait_for_vblank(exynos_encoder->manager->dev);
+			ops->wait_for_vblank(exynos_encoder->manager);
 	}
 }
 
@@ -341,7 +340,7 @@ exynos_drm_encoder_create(struct drm_device *dev,
 	drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs);
 
 	if (manager->ops && manager->ops->initialize) {
-		ret = manager->ops->initialize(manager->dev, dev);
+		ret = manager->ops->initialize(manager, dev);
 		if (ret) {
 			DRM_ERROR("Manager initialize failed %d\n", ret);
 			goto error;
@@ -408,7 +407,7 @@ void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data)
 		return;
 
 	if (manager_ops->enable_vblank)
-		manager_ops->enable_vblank(manager->dev);
+		manager_ops->enable_vblank(manager);
 }
 
 void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
@@ -422,7 +421,7 @@ void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
 		return;
 
 	if (manager_ops->disable_vblank)
-		manager_ops->disable_vblank(manager->dev);
+		manager_ops->disable_vblank(manager);
 }
 
 void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
@@ -433,7 +432,7 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
 	int mode = *(int *)data;
 
 	if (manager_ops && manager_ops->dpms)
-		manager_ops->dpms(manager->dev, mode);
+		manager_ops->dpms(manager, mode);
 
 	/*
 	 * if this condition is ok then it means that the crtc is already
@@ -467,7 +466,7 @@ void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data)
 	struct exynos_drm_overlay *overlay = data;
 
 	if (manager_ops && manager_ops->win_mode_set)
-		manager_ops->win_mode_set(manager->dev, overlay);
+		manager_ops->win_mode_set(manager, overlay);
 }
 
 void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data)
@@ -481,7 +480,7 @@ void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data)
 		zpos = *(int *)data;
 
 	if (manager_ops && manager_ops->win_commit)
-		manager_ops->win_commit(manager->dev, zpos);
+		manager_ops->win_commit(manager, zpos);
 }
 
 void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data)
@@ -495,7 +494,7 @@ void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data)
 		zpos = *(int *)data;
 
 	if (manager_ops && manager_ops->win_enable)
-		manager_ops->win_enable(manager->dev, zpos);
+		manager_ops->win_enable(manager, zpos);
 }
 
 void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
@@ -509,5 +508,5 @@ void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
 		zpos = *(int *)data;
 
 	if (manager_ops && manager_ops->win_disable)
-		manager_ops->win_disable(manager->dev, zpos);
+		manager_ops->win_disable(manager, zpos);
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 90fcd6f..2769eb3 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -62,7 +62,7 @@
 /* FIMD has totally five hardware windows. */
 #define WINDOWS_NR	5
 
-#define get_fimd_context(dev)	platform_get_drvdata(to_platform_device(dev))
+#define get_fimd_manager(mgr)	platform_get_drvdata(to_platform_device(dev))
 
 struct fimd_driver_data {
 	unsigned int timing_base;
@@ -106,6 +106,7 @@ struct fimd_win_data {
 
 struct fimd_context {
 	struct exynos_drm_subdrv	subdrv;
+	struct device			*dev;
 	struct drm_device		*drm_dev;
 	int				irq;
 	struct drm_crtc			*crtc;
@@ -155,7 +156,8 @@ static bool fimd_display_is_connected(struct device *dev)
 
 static void *fimd_get_panel(struct device *dev)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
+	struct fimd_context *ctx = mgr->ctx;
 
 	return &ctx->panel;
 }
@@ -182,16 +184,16 @@ static struct exynos_drm_display_ops fimd_display_ops = {
 	.power_on = fimd_display_power_on,
 };
 
-static void fimd_win_mode_set(struct device *dev,
-			      struct exynos_drm_overlay *overlay)
+static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
+			struct exynos_drm_overlay *overlay)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_context *ctx = mgr->ctx;
 	struct fimd_win_data *win_data;
 	int win;
 	unsigned long offset;
 
 	if (!overlay) {
-		dev_err(dev, "overlay is NULL\n");
+		DRM_ERROR("overlay is NULL\n");
 		return;
 	}
 
@@ -231,9 +233,8 @@ static void fimd_win_mode_set(struct device *dev,
 			overlay->fb_width, overlay->crtc_width);
 }
 
-static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
+static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
 	struct fimd_win_data *win_data = &ctx->win_data[win];
 	unsigned long val;
 
@@ -289,9 +290,8 @@ static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
 	writel(val, ctx->regs + WINCON(win));
 }
 
-static void fimd_win_set_colkey(struct device *dev, unsigned int win)
+static void fimd_win_set_colkey(struct fimd_context *ctx, unsigned int win)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
 	unsigned int keycon0 = 0, keycon1 = 0;
 
 	keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
@@ -330,9 +330,9 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
 	writel(val, ctx->regs + reg);
 }
 
-static void fimd_win_commit(struct device *dev, int zpos)
+static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_context *ctx = mgr->ctx;
 	struct fimd_win_data *win_data;
 	int win = zpos;
 	unsigned long val, alpha, size;
@@ -427,11 +427,11 @@ static void fimd_win_commit(struct device *dev, int zpos)
 		DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
 	}
 
-	fimd_win_set_pixfmt(dev, win);
+	fimd_win_set_pixfmt(ctx, win);
 
 	/* hardware window 0 doesn't support color key. */
 	if (win != 0)
-		fimd_win_set_colkey(dev, win);
+		fimd_win_set_colkey(ctx, win);
 
 	/* wincon */
 	val = readl(ctx->regs + WINCON(win));
@@ -450,9 +450,9 @@ static void fimd_win_commit(struct device *dev, int zpos)
 	win_data->enabled = true;
 }
 
-static void fimd_win_disable(struct device *dev, int zpos)
+static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_context *ctx = mgr->ctx;
 	struct fimd_win_data *win_data;
 	int win = zpos;
 	u32 val;
@@ -491,19 +491,19 @@ static void fimd_win_disable(struct device *dev, int zpos)
 	win_data->enabled = false;
 }
 
-static int fimd_mgr_initialize(struct device *subdrv_dev,
-		struct drm_device *drm_dev)
+static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,
+			struct drm_device *drm_dev)
 {
-	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
+	struct fimd_context *ctx = mgr->ctx;
 
 	ctx->drm_dev = drm_dev;
 
 	return 0;
 }
 
-static void fimd_dpms(struct device *subdrv_dev, int mode)
+static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
 {
-	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
+	struct fimd_context *ctx = mgr->ctx;
 
 	DRM_DEBUG_KMS("%d\n", mode);
 
@@ -518,13 +518,13 @@ static void fimd_dpms(struct device *subdrv_dev, int mode)
 		 * clk_enable could be called double time.
 		 */
 		if (ctx->suspended)
-			pm_runtime_get_sync(subdrv_dev);
+			pm_runtime_get_sync(ctx->dev);
 		break;
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
 		if (!ctx->suspended)
-			pm_runtime_put_sync(subdrv_dev);
+			pm_runtime_put_sync(ctx->dev);
 		break;
 	default:
 		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
@@ -534,10 +534,9 @@ static void fimd_dpms(struct device *subdrv_dev, int mode)
 	mutex_unlock(&ctx->lock);
 }
 
-static void fimd_apply(struct device *subdrv_dev)
+static void fimd_apply(struct exynos_drm_manager *mgr)
 {
-	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
-	struct exynos_drm_manager *mgr = ctx->subdrv.manager;
+	struct fimd_context *ctx = mgr->ctx;
 	struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
 	struct fimd_win_data *win_data;
 	int i;
@@ -545,16 +544,16 @@ static void fimd_apply(struct device *subdrv_dev)
 	for (i = 0; i < WINDOWS_NR; i++) {
 		win_data = &ctx->win_data[i];
 		if (win_data->enabled && (mgr_ops && mgr_ops->win_commit))
-			mgr_ops->win_commit(subdrv_dev, i);
+			mgr_ops->win_commit(mgr, i);
 	}
 
 	if (mgr_ops && mgr_ops->commit)
-		mgr_ops->commit(subdrv_dev);
+		mgr_ops->commit(mgr);
 }
 
-static void fimd_commit(struct device *dev)
+static void fimd_commit(struct exynos_drm_manager *mgr)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_context *ctx = mgr->ctx;
 	struct exynos_drm_panel_info *panel = &ctx->panel;
 	struct videomode *vm = &panel->vm;
 	struct fimd_driver_data *driver_data;
@@ -608,9 +607,9 @@ static void fimd_commit(struct device *dev)
 	writel(val, ctx->regs + VIDCON0);
 }
 
-static int fimd_enable_vblank(struct device *dev)
+static int fimd_enable_vblank(struct exynos_drm_manager *mgr)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_context *ctx = mgr->ctx;
 	u32 val;
 
 	if (ctx->suspended)
@@ -633,9 +632,9 @@ static int fimd_enable_vblank(struct device *dev)
 	return 0;
 }
 
-static void fimd_disable_vblank(struct device *dev)
+static void fimd_disable_vblank(struct exynos_drm_manager *mgr)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_context *ctx = mgr->ctx;
 	u32 val;
 
 	if (ctx->suspended)
@@ -651,9 +650,9 @@ static void fimd_disable_vblank(struct device *dev)
 	}
 }
 
-static void fimd_wait_for_vblank(struct device *dev)
+static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct fimd_context *ctx = mgr->ctx;
 
 	if (ctx->suspended)
 		return;
@@ -838,21 +837,23 @@ static int fimd_clock(struct fimd_context *ctx, bool enable)
 
 static void fimd_window_suspend(struct device *dev)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
+	struct fimd_context *ctx = mgr->ctx;
 	struct fimd_win_data *win_data;
 	int i;
 
 	for (i = 0; i < WINDOWS_NR; i++) {
 		win_data = &ctx->win_data[i];
 		win_data->resume = win_data->enabled;
-		fimd_win_disable(dev, i);
+		fimd_win_disable(mgr, i);
 	}
-	fimd_wait_for_vblank(dev);
+	fimd_wait_for_vblank(mgr);
 }
 
 static void fimd_window_resume(struct device *dev)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
+	struct fimd_context *ctx = mgr->ctx;
 	struct fimd_win_data *win_data;
 	int i;
 
@@ -863,9 +864,11 @@ static void fimd_window_resume(struct device *dev)
 	}
 }
 
-static int fimd_activate(struct fimd_context *ctx, bool enable)
+static int fimd_activate(struct exynos_drm_manager *mgr, bool enable)
 {
+	struct fimd_context *ctx = mgr->ctx;
 	struct device *dev = ctx->subdrv.dev;
+
 	if (enable) {
 		int ret;
 
@@ -877,7 +880,7 @@ static int fimd_activate(struct fimd_context *ctx, bool enable)
 
 		/* if vblank was enabled status, enable it again. */
 		if (test_and_clear_bit(0, &ctx->irq_flags))
-			fimd_enable_vblank(dev);
+			fimd_enable_vblank(mgr);
 
 		fimd_window_resume(dev);
 	} else {
@@ -930,6 +933,8 @@ static int fimd_probe(struct platform_device *pdev)
 	if (!ctx)
 		return -ENOMEM;
 
+	ctx->dev = dev;
+
 	ret = fimd_get_platform_data(ctx, dev);
 	if (ret)
 		return ret;
@@ -963,6 +968,8 @@ static int fimd_probe(struct platform_device *pdev)
 	DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
 	atomic_set(&ctx->wait_vsync_event, 0);
 
+	fimd_manager.ctx = ctx;
+
 	subdrv = &ctx->subdrv;
 
 	subdrv->dev = dev;
@@ -972,7 +979,7 @@ static int fimd_probe(struct platform_device *pdev)
 
 	mutex_init(&ctx->lock);
 
-	platform_set_drvdata(pdev, ctx);
+	platform_set_drvdata(pdev, &fimd_manager);
 
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
@@ -988,7 +995,8 @@ static int fimd_probe(struct platform_device *pdev)
 static int fimd_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct fimd_context *ctx = platform_get_drvdata(pdev);
+	struct exynos_drm_manager *mgr = platform_get_drvdata(pdev);
+	struct fimd_context *ctx = mgr->ctx;
 
 	exynos_drm_subdrv_unregister(&ctx->subdrv);
 
@@ -1007,7 +1015,7 @@ out:
 #ifdef CONFIG_PM_SLEEP
 static int fimd_suspend(struct device *dev)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
 
 	/*
 	 * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
@@ -1015,14 +1023,14 @@ static int fimd_suspend(struct device *dev)
 	 * because the usage_count of pm runtime is more than 1.
 	 */
 	if (!pm_runtime_suspended(dev))
-		return fimd_activate(ctx, false);
+		return fimd_activate(mgr, false);
 
 	return 0;
 }
 
 static int fimd_resume(struct device *dev)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
 
 	/*
 	 * if entered to sleep when lcd panel was on, the usage_count
@@ -1032,7 +1040,7 @@ static int fimd_resume(struct device *dev)
 	if (!pm_runtime_suspended(dev)) {
 		int ret;
 
-		ret = fimd_activate(ctx, true);
+		ret = fimd_activate(mgr, true);
 		if (ret < 0)
 			return ret;
 
@@ -1042,7 +1050,7 @@ static int fimd_resume(struct device *dev)
 		 * registers but in case of sleep wakeup, it's not.
 		 * so fimd_apply function should be called at here.
 		 */
-		fimd_apply(dev);
+		fimd_apply(mgr);
 	}
 
 	return 0;
@@ -1052,16 +1060,16 @@ static int fimd_resume(struct device *dev)
 #ifdef CONFIG_PM_RUNTIME
 static int fimd_runtime_suspend(struct device *dev)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
 
-	return fimd_activate(ctx, false);
+	return fimd_activate(mgr, false);
 }
 
 static int fimd_runtime_resume(struct device *dev)
 {
-	struct fimd_context *ctx = get_fimd_context(dev);
+	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
 
-	return fimd_activate(ctx, true);
+	return fimd_activate(mgr, true);
 }
 #endif
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index aebcc0e..ca0a87f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -129,11 +129,9 @@ static struct edid *drm_hdmi_get_edid(struct device *dev,
 
 	return NULL;
 }
-
-static int drm_hdmi_check_mode(struct device *dev,
+static int drm_hdmi_check_mode_ctx(struct drm_hdmi_context *ctx,
 		struct drm_display_mode *mode)
 {
-	struct drm_hdmi_context *ctx = to_context(dev);
 	int ret = 0;
 
 	/*
@@ -153,6 +151,14 @@ static int drm_hdmi_check_mode(struct device *dev,
 	return 0;
 }
 
+static int drm_hdmi_check_mode(struct device *dev,
+		struct drm_display_mode *mode)
+{
+	struct drm_hdmi_context *ctx = to_context(dev);
+
+	return drm_hdmi_check_mode_ctx(ctx, mode);
+}
+
 static int drm_hdmi_power_on(struct device *dev, int mode)
 {
 	struct drm_hdmi_context *ctx = to_context(dev);
@@ -172,9 +178,9 @@ static struct exynos_drm_display_ops drm_hdmi_display_ops = {
 	.power_on = drm_hdmi_power_on,
 };
 
-static int drm_hdmi_enable_vblank(struct device *subdrv_dev)
+static int drm_hdmi_enable_vblank(struct exynos_drm_manager *mgr)
 {
-	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	struct drm_hdmi_context *ctx = mgr->ctx;
 	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
 	struct exynos_drm_manager *manager = subdrv->manager;
 
@@ -185,33 +191,34 @@ static int drm_hdmi_enable_vblank(struct device *subdrv_dev)
 	return 0;
 }
 
-static void drm_hdmi_disable_vblank(struct device *subdrv_dev)
+static void drm_hdmi_disable_vblank(struct exynos_drm_manager *mgr)
 {
-	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	struct drm_hdmi_context *ctx = mgr->ctx;
 
 	if (mixer_ops && mixer_ops->disable_vblank)
 		return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
 }
 
-static void drm_hdmi_wait_for_vblank(struct device *subdrv_dev)
+static void drm_hdmi_wait_for_vblank(struct exynos_drm_manager *mgr)
 {
-	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	struct drm_hdmi_context *ctx = mgr->ctx;
 
 	if (mixer_ops && mixer_ops->wait_for_vblank)
 		mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx);
 }
 
-static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
+static void drm_hdmi_mode_fixup(struct exynos_drm_manager *mgr,
 				struct drm_connector *connector,
 				const struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
 {
+	struct drm_hdmi_context *ctx = mgr->ctx;
 	struct drm_display_mode *m;
 	int mode_ok;
 
 	drm_mode_set_crtcinfo(adjusted_mode, 0);
 
-	mode_ok = drm_hdmi_check_mode(subdrv_dev, adjusted_mode);
+	mode_ok = drm_hdmi_check_mode_ctx(ctx, adjusted_mode);
 
 	/* just return if user desired mode exists. */
 	if (mode_ok == 0)
@@ -222,7 +229,7 @@ static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
 	 * to adjusted_mode.
 	 */
 	list_for_each_entry(m, &connector->modes, head) {
-		mode_ok = drm_hdmi_check_mode(subdrv_dev, m);
+		mode_ok = drm_hdmi_check_mode_ctx(ctx, m);
 
 		if (mode_ok == 0) {
 			struct drm_mode_object base;
@@ -245,35 +252,34 @@ static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
 	}
 }
 
-static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
+static void drm_hdmi_mode_set(struct exynos_drm_manager *mgr, void *mode)
 {
-	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	struct drm_hdmi_context *ctx = mgr->ctx;
 
 	if (hdmi_ops && hdmi_ops->mode_set)
 		hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
 }
 
-static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
+static void drm_hdmi_get_max_resol(struct exynos_drm_manager *mgr,
 				unsigned int *width, unsigned int *height)
 {
-	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	struct drm_hdmi_context *ctx = mgr->ctx;
 
 	if (hdmi_ops && hdmi_ops->get_max_resol)
 		hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height);
 }
 
-static void drm_hdmi_commit(struct device *subdrv_dev)
+static void drm_hdmi_commit(struct exynos_drm_manager *mgr)
 {
-	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	struct drm_hdmi_context *ctx = mgr->ctx;
 
 	if (hdmi_ops && hdmi_ops->commit)
 		hdmi_ops->commit(ctx->hdmi_ctx->ctx);
 }
 
-static int drm_hdmi_mgr_initialize(struct device *subdrv_dev,
-		struct drm_device *drm_dev)
+static int drm_hdmi_mgr_initialize(struct exynos_drm_manager *mgr, struct drm_device *drm_dev)
 {
-	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	struct drm_hdmi_context *ctx = mgr->ctx;
 	int ret = 0;
 
 	if (mixer_ops && mixer_ops->initialize)
@@ -285,9 +291,9 @@ static int drm_hdmi_mgr_initialize(struct device *subdrv_dev,
 	return ret;
 }
 
-static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
+static void drm_hdmi_dpms(struct exynos_drm_manager *mgr, int mode)
 {
-	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	struct drm_hdmi_context *ctx = mgr->ctx;
 
 	if (mixer_ops && mixer_ops->dpms)
 		mixer_ops->dpms(ctx->mixer_ctx->ctx, mode);
@@ -296,9 +302,9 @@ static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
 		hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
 }
 
-static void drm_hdmi_apply(struct device *subdrv_dev)
+static void drm_hdmi_apply(struct exynos_drm_manager *mgr)
 {
-	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	struct drm_hdmi_context *ctx = mgr->ctx;
 	int i;
 
 	for (i = 0; i < MIXER_WIN_NR; i++) {
@@ -312,18 +318,18 @@ static void drm_hdmi_apply(struct device *subdrv_dev)
 		hdmi_ops->commit(ctx->hdmi_ctx->ctx);
 }
 
-static void drm_mixer_win_mode_set(struct device *subdrv_dev,
-		struct exynos_drm_overlay *overlay)
+static void drm_mixer_win_mode_set(struct exynos_drm_manager *mgr,
+				struct exynos_drm_overlay *overlay)
 {
-	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	struct drm_hdmi_context *ctx = mgr->ctx;
 
 	if (mixer_ops && mixer_ops->win_mode_set)
 		mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
 }
 
-static void drm_mixer_win_commit(struct device *subdrv_dev, int zpos)
+static void drm_mixer_win_commit(struct exynos_drm_manager *mgr, int zpos)
 {
-	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	struct drm_hdmi_context *ctx = mgr->ctx;
 	int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
 
 	if (win < 0 || win >= MIXER_WIN_NR) {
@@ -337,9 +343,9 @@ static void drm_mixer_win_commit(struct device *subdrv_dev, int zpos)
 	ctx->enabled[win] = true;
 }
 
-static void drm_mixer_win_disable(struct device *subdrv_dev, int zpos)
+static void drm_mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
 {
-	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
+	struct drm_hdmi_context *ctx = mgr->ctx;
 	int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
 
 	if (win < 0 || win >= MIXER_WIN_NR) {
@@ -425,6 +431,8 @@ static int exynos_drm_hdmi_probe(struct platform_device *pdev)
 	if (!ctx)
 		return -ENOMEM;
 
+	hdmi_manager.ctx = ctx;
+
 	subdrv = &ctx->subdrv;
 
 	subdrv->dev = dev;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 15a97ce..b7568de 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -28,7 +28,7 @@
 /* vidi has totally three virtual windows. */
 #define WINDOWS_NR		3
 
-#define get_vidi_context(dev)	platform_get_drvdata(to_platform_device(dev))
+#define get_vidi_mgr(dev)	platform_get_drvdata(to_platform_device(dev))
 
 struct vidi_win_data {
 	unsigned int		offset_x;
@@ -87,7 +87,8 @@ static const char fake_edid_info[] = {
 
 static bool vidi_display_is_connected(struct device *dev)
 {
-	struct vidi_context *ctx = get_vidi_context(dev);
+	struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
+	struct vidi_context *ctx = mgr->ctx;
 
 	/*
 	 * connection request would come from user side
@@ -99,7 +100,8 @@ static bool vidi_display_is_connected(struct device *dev)
 static struct edid *vidi_get_edid(struct device *dev,
 			struct drm_connector *connector)
 {
-	struct vidi_context *ctx = get_vidi_context(dev);
+	struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
+	struct vidi_context *ctx = mgr->ctx;
 	struct edid *edid;
 	int edid_len;
 
@@ -152,9 +154,9 @@ static struct exynos_drm_display_ops vidi_display_ops = {
 	.power_on = vidi_display_power_on,
 };
 
-static void vidi_dpms(struct device *subdrv_dev, int mode)
+static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
 {
-	struct vidi_context *ctx = get_vidi_context(subdrv_dev);
+	struct vidi_context *ctx = mgr->ctx;
 
 	DRM_DEBUG_KMS("%d\n", mode);
 
@@ -177,10 +179,9 @@ static void vidi_dpms(struct device *subdrv_dev, int mode)
 	mutex_unlock(&ctx->lock);
 }
 
-static void vidi_apply(struct device *subdrv_dev)
+static void vidi_apply(struct exynos_drm_manager *mgr)
 {
-	struct vidi_context *ctx = get_vidi_context(subdrv_dev);
-	struct exynos_drm_manager *mgr = ctx->subdrv.manager;
+	struct vidi_context *ctx = mgr->ctx;
 	struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
 	struct vidi_win_data *win_data;
 	int i;
@@ -188,24 +189,24 @@ static void vidi_apply(struct device *subdrv_dev)
 	for (i = 0; i < WINDOWS_NR; i++) {
 		win_data = &ctx->win_data[i];
 		if (win_data->enabled && (mgr_ops && mgr_ops->win_commit))
-			mgr_ops->win_commit(subdrv_dev, i);
+			mgr_ops->win_commit(mgr, i);
 	}
 
 	if (mgr_ops && mgr_ops->commit)
-		mgr_ops->commit(subdrv_dev);
+		mgr_ops->commit(mgr);
 }
 
-static void vidi_commit(struct device *dev)
+static void vidi_commit(struct exynos_drm_manager *mgr)
 {
-	struct vidi_context *ctx = get_vidi_context(dev);
+	struct vidi_context *ctx = mgr->ctx;
 
 	if (ctx->suspended)
 		return;
 }
 
-static int vidi_enable_vblank(struct device *dev)
+static int vidi_enable_vblank(struct exynos_drm_manager *mgr)
 {
-	struct vidi_context *ctx = get_vidi_context(dev);
+	struct vidi_context *ctx = mgr->ctx;
 
 	if (ctx->suspended)
 		return -EPERM;
@@ -225,9 +226,9 @@ static int vidi_enable_vblank(struct device *dev)
 	return 0;
 }
 
-static void vidi_disable_vblank(struct device *dev)
+static void vidi_disable_vblank(struct exynos_drm_manager *mgr)
 {
-	struct vidi_context *ctx = get_vidi_context(dev);
+	struct vidi_context *ctx = mgr->ctx;
 
 	if (ctx->suspended)
 		return;
@@ -236,16 +237,16 @@ static void vidi_disable_vblank(struct device *dev)
 		ctx->vblank_on = false;
 }
 
-static void vidi_win_mode_set(struct device *dev,
-			      struct exynos_drm_overlay *overlay)
+static void vidi_win_mode_set(struct exynos_drm_manager *mgr,
+			struct exynos_drm_overlay *overlay)
 {
-	struct vidi_context *ctx = get_vidi_context(dev);
+	struct vidi_context *ctx = mgr->ctx;
 	struct vidi_win_data *win_data;
 	int win;
 	unsigned long offset;
 
 	if (!overlay) {
-		dev_err(dev, "overlay is NULL\n");
+		DRM_ERROR("overlay is NULL\n");
 		return;
 	}
 
@@ -289,9 +290,9 @@ static void vidi_win_mode_set(struct device *dev,
 			overlay->fb_width, overlay->crtc_width);
 }
 
-static void vidi_win_commit(struct device *dev, int zpos)
+static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos)
 {
-	struct vidi_context *ctx = get_vidi_context(dev);
+	struct vidi_context *ctx = mgr->ctx;
 	struct vidi_win_data *win_data;
 	int win = zpos;
 
@@ -314,9 +315,9 @@ static void vidi_win_commit(struct device *dev, int zpos)
 		schedule_work(&ctx->work);
 }
 
-static void vidi_win_disable(struct device *dev, int zpos)
+static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
 {
-	struct vidi_context *ctx = get_vidi_context(dev);
+	struct vidi_context *ctx = mgr->ctx;
 	struct vidi_win_data *win_data;
 	int win = zpos;
 
@@ -403,19 +404,23 @@ static void vidi_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
 	/* TODO. */
 }
 
-static int vidi_power_on(struct vidi_context *ctx, bool enable)
+static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
 {
-	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-	struct device *dev = subdrv->dev;
+	struct vidi_context *ctx = mgr->ctx;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (enable != false && enable != true)
+		return -EINVAL;
 
 	if (enable) {
 		ctx->suspended = false;
 
 		/* if vblank was enabled status, enable it again. */
 		if (test_and_clear_bit(0, &ctx->irq_flags))
-			vidi_enable_vblank(dev);
+			vidi_enable_vblank(mgr);
 
-		vidi_apply(dev);
+		vidi_apply(mgr);
 	} else {
 		ctx->suspended = true;
 	}
@@ -427,7 +432,8 @@ static int vidi_show_connection(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
 	int rc;
-	struct vidi_context *ctx = get_vidi_context(dev);
+	struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
+	struct vidi_context *ctx = mgr->ctx;
 
 	mutex_lock(&ctx->lock);
 
@@ -442,7 +448,8 @@ static int vidi_store_connection(struct device *dev,
 				struct device_attribute *attr,
 				const char *buf, size_t len)
 {
-	struct vidi_context *ctx = get_vidi_context(dev);
+	struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
+	struct vidi_context *ctx = mgr->ctx;
 	int ret;
 
 	ret = kstrtoint(buf, 0, &ctx->connected);
@@ -498,7 +505,7 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
 		display_ops = manager->display_ops;
 
 		if (display_ops->type == EXYNOS_DISPLAY_TYPE_VIDI) {
-			ctx = get_vidi_context(manager->dev);
+			ctx = manager->ctx;
 			break;
 		}
 	}
@@ -558,6 +565,8 @@ static int vidi_probe(struct platform_device *pdev)
 
 	INIT_WORK(&ctx->work, vidi_fake_vblank_handler);
 
+	vidi_manager.ctx = ctx;
+
 	subdrv = &ctx->subdrv;
 	subdrv->dev = dev;
 	subdrv->manager = &vidi_manager;
@@ -566,7 +575,7 @@ static int vidi_probe(struct platform_device *pdev)
 
 	mutex_init(&ctx->lock);
 
-	platform_set_drvdata(pdev, ctx);
+	platform_set_drvdata(pdev, &vidi_manager);
 
 	ret = device_create_file(dev, &dev_attr_connection);
 	if (ret < 0)
@@ -594,16 +603,16 @@ static int vidi_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int vidi_suspend(struct device *dev)
 {
-	struct vidi_context *ctx = get_vidi_context(dev);
+	struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
 
-	return vidi_power_on(ctx, false);
+	return vidi_power_on(mgr, false);
 }
 
 static int vidi_resume(struct device *dev)
 {
-	struct vidi_context *ctx = get_vidi_context(dev);
+	struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
 
-	return vidi_power_on(ctx, true);
+	return vidi_power_on(mgr, true);
 }
 #endif
 
-- 
1.8.4

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

* [PATCH v3 07/32] drm/exynos: Remove apply manager callback
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (5 preceding siblings ...)
  2013-10-29 16:12 ` [PATCH v3 06/32] drm/exynos: Pass exynos_drm_manager in manager ops instead of dev Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-11-08 21:05   ` Tomasz Figa
  2013-10-29 16:12 ` [PATCH v3 08/32] drm/exynos: Remove dpms link between encoder/connector Sean Paul
                   ` (25 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch removes the apply() manager callback in favor of putting the
relevant commits in the individual drivers. This will mitigate some of
the difference between the suspend/resume path and the dpms path

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2:
	- This was previously in another patch, but moved since it warrants its own
Changes in v3:
	- Removed apply() from vidi

 drivers/gpu/drm/exynos/exynos_drm_drv.h     |  2 --
 drivers/gpu/drm/exynos/exynos_drm_encoder.c |  6 ------
 drivers/gpu/drm/exynos/exynos_drm_fimd.c    | 22 +++++-----------------
 drivers/gpu/drm/exynos/exynos_drm_hdmi.c    | 17 -----------------
 drivers/gpu/drm/exynos/exynos_drm_vidi.c    |  1 -
 drivers/gpu/drm/exynos/exynos_hdmi.c        |  1 +
 drivers/gpu/drm/exynos/exynos_mixer.c       |  2 ++
 7 files changed, 8 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 8eb8b83..bff432a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -146,7 +146,6 @@ struct exynos_drm_display_ops {
  *
  * @initialize: initializes the manager with drm_dev
  * @dpms: control device power.
- * @apply: set timing, vblank and overlay data to registers.
  * @mode_fixup: fix mode data comparing to hw specific display mode.
  * @mode_set: convert drm_display_mode to hw specific display mode and
  *	      would be called by encoder->mode_set().
@@ -166,7 +165,6 @@ struct exynos_drm_manager_ops {
 	int (*initialize)(struct exynos_drm_manager *mgr,
 				struct drm_device *drm_dev);
 	void (*dpms)(struct exynos_drm_manager *mgr, int mode);
-	void (*apply)(struct exynos_drm_manager *mgr);
 	void (*mode_fixup)(struct exynos_drm_manager *mgr,
 				struct drm_connector *connector,
 				const struct drm_display_mode *mode,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index ec627fa..19ee84d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -57,8 +57,6 @@ static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
 static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
-	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
-	struct exynos_drm_manager_ops *manager_ops = manager->ops;
 	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
 
 	DRM_DEBUG_KMS("encoder dpms: %d\n", mode);
@@ -72,10 +70,6 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
-		if (manager_ops && manager_ops->apply)
-			if (!exynos_encoder->updated)
-				manager_ops->apply(manager);
-
 		exynos_drm_connector_power(encoder, mode);
 		exynos_encoder->dpms = mode;
 		break;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 2769eb3..f0ac1d5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -672,7 +672,6 @@ static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr)
 static struct exynos_drm_manager_ops fimd_manager_ops = {
 	.initialize = fimd_mgr_initialize,
 	.dpms = fimd_dpms,
-	.apply = fimd_apply,
 	.commit = fimd_commit,
 	.enable_vblank = fimd_enable_vblank,
 	.disable_vblank = fimd_disable_vblank,
@@ -883,6 +882,8 @@ static int fimd_activate(struct exynos_drm_manager *mgr, bool enable)
 			fimd_enable_vblank(mgr);
 
 		fimd_window_resume(dev);
+
+		fimd_apply(mgr);
 	} else {
 		fimd_window_suspend(dev);
 
@@ -1037,23 +1038,10 @@ static int fimd_resume(struct device *dev)
 	 * of pm runtime would still be 1 so in this case, fimd driver
 	 * should be on directly not drawing on pm runtime interface.
 	 */
-	if (!pm_runtime_suspended(dev)) {
-		int ret;
+	if (pm_runtime_suspended(dev))
+		return 0;
 
-		ret = fimd_activate(mgr, true);
-		if (ret < 0)
-			return ret;
-
-		/*
-		 * in case of dpms on(standby), fimd_apply function will
-		 * be called by encoder's dpms callback to update fimd's
-		 * registers but in case of sleep wakeup, it's not.
-		 * so fimd_apply function should be called at here.
-		 */
-		fimd_apply(mgr);
-	}
-
-	return 0;
+	return fimd_activate(mgr, true);
 }
 #endif
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index ca0a87f..c5de00a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -302,22 +302,6 @@ static void drm_hdmi_dpms(struct exynos_drm_manager *mgr, int mode)
 		hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
 }
 
-static void drm_hdmi_apply(struct exynos_drm_manager *mgr)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-	int i;
-
-	for (i = 0; i < MIXER_WIN_NR; i++) {
-		if (!ctx->enabled[i])
-			continue;
-		if (mixer_ops && mixer_ops->win_commit)
-			mixer_ops->win_commit(ctx->mixer_ctx->ctx, i);
-	}
-
-	if (hdmi_ops && hdmi_ops->commit)
-		hdmi_ops->commit(ctx->hdmi_ctx->ctx);
-}
-
 static void drm_mixer_win_mode_set(struct exynos_drm_manager *mgr,
 				struct exynos_drm_overlay *overlay)
 {
@@ -362,7 +346,6 @@ static void drm_mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
 static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
 	.initialize = drm_hdmi_mgr_initialize,
 	.dpms = drm_hdmi_dpms,
-	.apply = drm_hdmi_apply,
 	.enable_vblank = drm_hdmi_enable_vblank,
 	.disable_vblank = drm_hdmi_disable_vblank,
 	.wait_for_vblank = drm_hdmi_wait_for_vblank,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index b7568de..2ca24a3 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -335,7 +335,6 @@ static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
 
 static struct exynos_drm_manager_ops vidi_manager_ops = {
 	.dpms = vidi_dpms,
-	.apply = vidi_apply,
 	.commit = vidi_commit,
 	.enable_vblank = vidi_enable_vblank,
 	.disable_vblank = vidi_disable_vblank,
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 00704e9..2d36d59 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1699,6 +1699,7 @@ static void hdmi_poweron(struct hdmi_context *hdata)
 	clk_prepare_enable(res->sclk_hdmi);
 
 	hdmiphy_poweron(hdata);
+	hdmi_commit(hdata);
 }
 
 static void hdmi_poweroff(struct hdmi_context *hdata)
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 2f204c1..60935c4 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -899,6 +899,8 @@ static void mixer_window_resume(struct mixer_context *ctx)
 		win_data = &ctx->win_data[i];
 		win_data->enabled = win_data->resume;
 		win_data->resume = false;
+		if (win_data->enabled)
+			mixer_win_commit(ctx, i);
 	}
 }
 
-- 
1.8.4

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

* [PATCH v3 08/32] drm/exynos: Remove dpms link between encoder/connector
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (6 preceding siblings ...)
  2013-10-29 16:12 ` [PATCH v3 07/32] drm/exynos: Remove apply manager callback Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-11-08 21:45   ` Tomasz Figa
  2013-10-29 16:12 ` [PATCH v3 09/32] drm/exynos: Rename display_op power_on to dpms Sean Paul
                   ` (24 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch removes the call from encoder dpms into connector dpms (which
will then call back into encoder dpms through the helper function). The
callback is likely to keep connector->dpms in the right state when
initiating dpms from crtc or encoder, but this isn't the right way to do
it. This patch is the first step towards rationalizing power management
in the exynos drm driver.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2:
	- Split out the apply change into a new patch
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_connector.c | 42 ++--------------------
 drivers/gpu/drm/exynos/exynos_drm_connector.h |  4 ---
 drivers/gpu/drm/exynos/exynos_drm_encoder.c   | 50 +++------------------------
 3 files changed, 8 insertions(+), 88 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index 23b69d8..ca270e2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -26,7 +26,6 @@ struct exynos_drm_connector {
 	struct drm_connector	drm_connector;
 	uint32_t		encoder_id;
 	struct exynos_drm_manager *manager;
-	uint32_t		dpms;
 };
 
 static int exynos_drm_connector_get_modes(struct drm_connector *connector)
@@ -119,7 +118,8 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
 	return ret;
 }
 
-struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector)
+static struct drm_encoder *exynos_drm_best_encoder(
+		struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct exynos_drm_connector *exynos_connector =
@@ -146,41 +146,6 @@ static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
 	.best_encoder	= exynos_drm_best_encoder,
 };
 
-void exynos_drm_display_power(struct drm_connector *connector, int mode)
-{
-	struct drm_encoder *encoder = exynos_drm_best_encoder(connector);
-	struct exynos_drm_connector *exynos_connector;
-	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
-	struct exynos_drm_display_ops *display_ops = manager->display_ops;
-
-	exynos_connector = to_exynos_connector(connector);
-
-	if (exynos_connector->dpms == mode) {
-		DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
-		return;
-	}
-
-	if (display_ops && display_ops->power_on)
-		display_ops->power_on(manager->dev, mode);
-
-	exynos_connector->dpms = mode;
-}
-
-static void exynos_drm_connector_dpms(struct drm_connector *connector,
-					int mode)
-{
-	/*
-	 * in case that drm_crtc_helper_set_mode() is called,
-	 * encoder/crtc->funcs->dpms() will be just returned
-	 * because they already were DRM_MODE_DPMS_ON so only
-	 * exynos_drm_display_power() will be called.
-	 */
-	drm_helper_connector_dpms(connector, mode);
-
-	exynos_drm_display_power(connector, mode);
-
-}
-
 static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
 				unsigned int max_width, unsigned int max_height)
 {
@@ -236,7 +201,7 @@ static void exynos_drm_connector_destroy(struct drm_connector *connector)
 }
 
 static struct drm_connector_funcs exynos_connector_funcs = {
-	.dpms		= exynos_drm_connector_dpms,
+	.dpms		= drm_helper_connector_dpms,
 	.fill_modes	= exynos_drm_connector_fill_modes,
 	.detect		= exynos_drm_connector_detect,
 	.destroy	= exynos_drm_connector_destroy,
@@ -281,7 +246,6 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
 
 	exynos_connector->encoder_id = encoder->base.id;
 	exynos_connector->manager = manager;
-	exynos_connector->dpms = DRM_MODE_DPMS_OFF;
 	connector->dpms = DRM_MODE_DPMS_OFF;
 	connector->encoder = encoder;
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.h b/drivers/gpu/drm/exynos/exynos_drm_connector.h
index 547c6b5..4eb20d7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.h
@@ -17,8 +17,4 @@
 struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
 						   struct drm_encoder *encoder);
 
-struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector);
-
-void exynos_drm_display_power(struct drm_connector *connector, int mode);
-
 #endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index 19ee84d..df4b2852 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -29,35 +29,19 @@
  * @manager: specific encoder has its own manager to control a hardware
  *	appropriately and we can access a hardware drawing on this manager.
  * @dpms: store the encoder dpms value.
- * @updated: indicate whether overlay data updating is needed or not.
  */
 struct exynos_drm_encoder {
 	struct drm_crtc			*old_crtc;
 	struct drm_encoder		drm_encoder;
 	struct exynos_drm_manager	*manager;
 	int				dpms;
-	bool				updated;
 };
 
-static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
-{
-	struct drm_device *dev = encoder->dev;
-	struct drm_connector *connector;
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		if (exynos_drm_best_encoder(connector) == encoder) {
-			DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
-					connector->base.id, mode);
-
-			exynos_drm_display_power(connector, mode);
-		}
-	}
-}
-
 static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
-	struct drm_device *dev = encoder->dev;
+	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
 	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+	struct exynos_drm_display_ops *display_ops = manager->display_ops;
 
 	DRM_DEBUG_KMS("encoder dpms: %d\n", mode);
 
@@ -66,26 +50,10 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 		return;
 	}
 
-	mutex_lock(&dev->struct_mutex);
-
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		exynos_drm_connector_power(encoder, mode);
-		exynos_encoder->dpms = mode;
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-	case DRM_MODE_DPMS_OFF:
-		exynos_drm_connector_power(encoder, mode);
-		exynos_encoder->dpms = mode;
-		exynos_encoder->updated = false;
-		break;
-	default:
-		DRM_ERROR("unspecified mode %d\n", mode);
-		break;
-	}
+	if (display_ops && display_ops->power_on)
+		display_ops->power_on(manager->ctx, mode);
 
-	mutex_unlock(&dev->struct_mutex);
+	exynos_encoder->dpms = mode;
 }
 
 static bool
@@ -191,14 +159,6 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 		manager_ops->commit(manager);
 
 	/*
-	 * this will avoid one issue that overlay data is updated to
-	 * real hardware two times.
-	 * And this variable will be used to check if the data was
-	 * already updated or not by exynos_drm_encoder_dpms function.
-	 */
-	exynos_encoder->updated = true;
-
-	/*
 	 * In case of setcrtc, there is no way to update encoder's dpms
 	 * so update it here.
 	 */
-- 
1.8.4

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

* [PATCH v3 09/32] drm/exynos: Rename display_op power_on to dpms
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (7 preceding siblings ...)
  2013-10-29 16:12 ` [PATCH v3 08/32] drm/exynos: Remove dpms link between encoder/connector Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-11-08 22:09   ` Tomasz Figa
  2013-10-29 16:12 ` [PATCH v3 10/32] drm/exynos: Don't keep dpms state in encoder Sean Paul
                   ` (23 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch renames the display_op power_on to dpms to accurately reflect
what the function does.

The side-effect of this patch is that the new hdmi dpms callback is now
invoked twice in the dpms path. This is safe and will be dealt with when
the exynos_drm shim goes away.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3:
	- Changed vidi to dpms as well

 drivers/gpu/drm/exynos/exynos_drm_drv.h     | 4 ++--
 drivers/gpu/drm/exynos/exynos_drm_encoder.c | 4 ++--
 drivers/gpu/drm/exynos/exynos_drm_fimd.c    | 8 --------
 drivers/gpu/drm/exynos/exynos_drm_hdmi.c    | 8 ++++----
 drivers/gpu/drm/exynos/exynos_drm_hdmi.h    | 3 +--
 drivers/gpu/drm/exynos/exynos_drm_vidi.c    | 8 --------
 drivers/gpu/drm/exynos/exynos_hdmi.c        | 2 +-
 7 files changed, 10 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index bff432a..e31c088 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -128,7 +128,7 @@ struct exynos_drm_overlay {
  * @get_edid: get edid modes from display driver.
  * @get_panel: get panel object from display driver.
  * @check_mode: check if mode is valid or not.
- * @power_on: display device on or off.
+ * @dpms: display device on or off.
  */
 struct exynos_drm_display_ops {
 	enum exynos_drm_output_type type;
@@ -138,7 +138,7 @@ struct exynos_drm_display_ops {
 			struct drm_connector *connector);
 	void *(*get_panel)(struct device *dev);
 	int (*check_mode)(struct device *dev, struct drm_display_mode *mode);
-	int (*power_on)(struct device *dev, int mode);
+	int (*dpms)(struct device *dev, int mode);
 };
 
 /*
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index df4b2852..5bf1e1e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -50,8 +50,8 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 		return;
 	}
 
-	if (display_ops && display_ops->power_on)
-		display_ops->power_on(manager->ctx, mode);
+	if (display_ops && display_ops->dpms)
+		display_ops->dpms(manager->ctx, mode);
 
 	exynos_encoder->dpms = mode;
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index f0ac1d5..b980b05 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -169,19 +169,11 @@ static int fimd_check_mode(struct device *dev, struct drm_display_mode *mode)
 	return 0;
 }
 
-static int fimd_display_power_on(struct device *dev, int mode)
-{
-	/* TODO */
-
-	return 0;
-}
-
 static struct exynos_drm_display_ops fimd_display_ops = {
 	.type = EXYNOS_DISPLAY_TYPE_LCD,
 	.is_connected = fimd_display_is_connected,
 	.get_panel = fimd_get_panel,
 	.check_mode = fimd_check_mode,
-	.power_on = fimd_display_power_on,
 };
 
 static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index c5de00a..f9a9324 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -159,12 +159,12 @@ static int drm_hdmi_check_mode(struct device *dev,
 	return drm_hdmi_check_mode_ctx(ctx, mode);
 }
 
-static int drm_hdmi_power_on(struct device *dev, int mode)
+static int drm_hdmi_display_dpms(struct device *dev, int mode)
 {
 	struct drm_hdmi_context *ctx = to_context(dev);
 
-	if (hdmi_ops && hdmi_ops->power_on)
-		return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode);
+	if (hdmi_ops && hdmi_ops->dpms)
+		hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
 
 	return 0;
 }
@@ -175,7 +175,7 @@ static struct exynos_drm_display_ops drm_hdmi_display_ops = {
 	.is_connected = drm_hdmi_is_connected,
 	.get_edid = drm_hdmi_get_edid,
 	.check_mode = drm_hdmi_check_mode,
-	.power_on = drm_hdmi_power_on,
+	.dpms = drm_hdmi_display_dpms,
 };
 
 static int drm_hdmi_enable_vblank(struct exynos_drm_manager *mgr)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
index cf7b1da..923239b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
@@ -33,14 +33,13 @@ struct exynos_hdmi_ops {
 	struct edid *(*get_edid)(void *ctx,
 			struct drm_connector *connector);
 	int (*check_mode)(void *ctx, struct drm_display_mode *mode);
-	int (*power_on)(void *ctx, int mode);
+	void (*dpms)(void *ctx, int mode);
 
 	/* manager */
 	void (*mode_set)(void *ctx, struct drm_display_mode *mode);
 	void (*get_max_resol)(void *ctx, unsigned int *width,
 				unsigned int *height);
 	void (*commit)(void *ctx);
-	void (*dpms)(void *ctx, int mode);
 };
 
 struct exynos_mixer_ops {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 2ca24a3..ce0e2ea 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -138,20 +138,12 @@ static int vidi_check_mode(struct device *dev, struct drm_display_mode *mode)
 	return 0;
 }
 
-static int vidi_display_power_on(struct device *dev, int mode)
-{
-	/* TODO */
-
-	return 0;
-}
-
 static struct exynos_drm_display_ops vidi_display_ops = {
 	.type = EXYNOS_DISPLAY_TYPE_VIDI,
 	.is_connected = vidi_display_is_connected,
 	.get_edid = vidi_get_edid,
 	.get_panel = vidi_get_panel,
 	.check_mode = vidi_check_mode,
-	.power_on = vidi_display_power_on,
 };
 
 static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 2d36d59..d35ab2a 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1760,12 +1760,12 @@ static struct exynos_hdmi_ops hdmi_ops = {
 	.is_connected	= hdmi_is_connected,
 	.get_edid	= hdmi_get_edid,
 	.check_mode	= hdmi_check_mode,
+	.dpms		= hdmi_dpms,
 
 	/* manager */
 	.mode_set	= hdmi_mode_set,
 	.get_max_resol	= hdmi_get_max_resol,
 	.commit		= hdmi_commit,
-	.dpms		= hdmi_dpms,
 };
 
 static irqreturn_t hdmi_irq_thread(int irq, void *arg)
-- 
1.8.4

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

* [PATCH v3 10/32] drm/exynos: Don't keep dpms state in encoder
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (8 preceding siblings ...)
  2013-10-29 16:12 ` [PATCH v3 09/32] drm/exynos: Rename display_op power_on to dpms Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-11-10 20:47   ` Tomasz Figa
  2013-10-29 16:12 ` [PATCH v3 11/32] drm/exynos: Use unsigned long for possible_crtcs Sean Paul
                   ` (22 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch removes the dpms state tracking in encoder. This
state is at best confusing and at worst incorrect since the display
drivers can turn on and off without propagating the value.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_encoder.c | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index 5bf1e1e..a823d53 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -28,32 +28,22 @@
  * @drm_encoder: encoder object.
  * @manager: specific encoder has its own manager to control a hardware
  *	appropriately and we can access a hardware drawing on this manager.
- * @dpms: store the encoder dpms value.
  */
 struct exynos_drm_encoder {
 	struct drm_crtc			*old_crtc;
 	struct drm_encoder		drm_encoder;
 	struct exynos_drm_manager	*manager;
-	int				dpms;
 };
 
 static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
-	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
 	struct exynos_drm_display_ops *display_ops = manager->display_ops;
 
 	DRM_DEBUG_KMS("encoder dpms: %d\n", mode);
 
-	if (exynos_encoder->dpms == mode) {
-		DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
-		return;
-	}
-
 	if (display_ops && display_ops->dpms)
 		display_ops->dpms(manager->ctx, mode);
-
-	exynos_encoder->dpms = mode;
 }
 
 static bool
@@ -157,12 +147,6 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 
 	if (manager_ops && manager_ops->commit)
 		manager_ops->commit(manager);
-
-	/*
-	 * In case of setcrtc, there is no way to update encoder's dpms
-	 * so update it here.
-	 */
-	exynos_encoder->dpms = DRM_MODE_DPMS_ON;
 }
 
 void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb)
@@ -281,7 +265,6 @@ exynos_drm_encoder_create(struct drm_device *dev,
 	if (!exynos_encoder)
 		return NULL;
 
-	exynos_encoder->dpms = DRM_MODE_DPMS_OFF;
 	exynos_encoder->manager = manager;
 	encoder = &exynos_encoder->drm_encoder;
 	encoder->possible_crtcs = possible_crtcs;
-- 
1.8.4

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

* [PATCH v3 11/32] drm/exynos: Use unsigned long for possible_crtcs
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (9 preceding siblings ...)
  2013-10-29 16:12 ` [PATCH v3 10/32] drm/exynos: Don't keep dpms state in encoder Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-11-10 20:47   ` Tomasz Figa
  2013-10-29 16:12 ` [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv Sean Paul
                   ` (21 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

Change all instances of possible_crtcs in the exynos drm driver to be
unsigned long. This matches the type used in the drm layer.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_drv.c     | 2 +-
 drivers/gpu/drm/exynos/exynos_drm_encoder.c | 2 +-
 drivers/gpu/drm/exynos/exynos_drm_encoder.h | 2 +-
 drivers/gpu/drm/exynos/exynos_drm_plane.c   | 2 +-
 drivers/gpu/drm/exynos/exynos_drm_plane.h   | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index bb82ef7..617748e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -84,7 +84,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 
 	for (nr = 0; nr < MAX_PLANE; nr++) {
 		struct drm_plane *plane;
-		unsigned int possible_crtcs = (1 << MAX_CRTC) - 1;
+		unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;
 
 		plane = exynos_plane_init(dev, possible_crtcs, false);
 		if (!plane)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index a823d53..efe4e60 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -249,7 +249,7 @@ void exynos_drm_encoder_setup(struct drm_device *dev)
 struct drm_encoder *
 exynos_drm_encoder_create(struct drm_device *dev,
 			   struct exynos_drm_manager *manager,
-			   unsigned int possible_crtcs)
+			   unsigned long possible_crtcs)
 {
 	struct drm_encoder *encoder;
 	struct exynos_drm_encoder *exynos_encoder;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h
index 89e2fb0..0f3e5e2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.h
@@ -19,7 +19,7 @@ struct exynos_drm_manager;
 void exynos_drm_encoder_setup(struct drm_device *dev);
 struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev,
 					       struct exynos_drm_manager *mgr,
-					       unsigned int possible_crtcs);
+					       unsigned long possible_crtcs);
 struct exynos_drm_manager *
 exynos_drm_get_manager(struct drm_encoder *encoder);
 void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index fcb0652..cff3aed 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -259,7 +259,7 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
 }
 
 struct drm_plane *exynos_plane_init(struct drm_device *dev,
-				    unsigned int possible_crtcs, bool priv)
+				    unsigned long possible_crtcs, bool priv)
 {
 	struct exynos_plane *exynos_plane;
 	int err;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 8831245..84d464c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -17,4 +17,4 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
 void exynos_plane_commit(struct drm_plane *plane);
 void exynos_plane_dpms(struct drm_plane *plane, int mode);
 struct drm_plane *exynos_plane_init(struct drm_device *dev,
-				    unsigned int possible_crtcs, bool priv);
+				    unsigned long possible_crtcs, bool priv);
-- 
1.8.4

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

* [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (10 preceding siblings ...)
  2013-10-29 16:12 ` [PATCH v3 11/32] drm/exynos: Use unsigned long for possible_crtcs Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-10-31 10:30   ` Inki Dae
  2013-11-10 21:09   ` Tomasz Figa
  2013-10-29 16:12 ` [PATCH v3 13/32] drm/exynos: hdmi: remove the i2c drivers and use devtree Sean Paul
                   ` (20 subsequent siblings)
  32 siblings, 2 replies; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch splits display and manager from subdrv. The result is that
crtc functions can directly call into manager callbacks and encoder
functions can directly call into display callbacks. This will allow
us to remove the exynos_drm_hdmi shim and support mixer/hdmi & fimd/dp
with common code.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2:
	- Pass display into display_ops instead of context
Changes in v3:
	- Changed vidi args to exynos_drm_display instead of void
	- Moved exynos_drm_hdmi.c removal into next patch

 drivers/gpu/drm/exynos/exynos_drm_connector.c |  50 ++---
 drivers/gpu/drm/exynos/exynos_drm_core.c      | 181 +++++++++++++-----
 drivers/gpu/drm/exynos/exynos_drm_crtc.c      | 115 +++++++++---
 drivers/gpu/drm/exynos/exynos_drm_crtc.h      |  20 +-
 drivers/gpu/drm/exynos/exynos_drm_drv.c       |  29 +--
 drivers/gpu/drm/exynos/exynos_drm_drv.h       | 106 +++++++----
 drivers/gpu/drm/exynos/exynos_drm_encoder.c   | 258 ++++----------------------
 drivers/gpu/drm/exynos/exynos_drm_encoder.h   |  18 +-
 drivers/gpu/drm/exynos/exynos_drm_fb.c        |   4 +-
 drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 161 ++++++++--------
 drivers/gpu/drm/exynos/exynos_drm_hdmi.c      | 211 +++++++++------------
 drivers/gpu/drm/exynos/exynos_drm_hdmi.h      |   2 +
 drivers/gpu/drm/exynos/exynos_drm_plane.c     |  15 +-
 drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 129 ++++++-------
 14 files changed, 615 insertions(+), 684 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index ca270e2..9a16dbe 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -23,26 +23,20 @@
 				drm_connector)
 
 struct exynos_drm_connector {
-	struct drm_connector	drm_connector;
-	uint32_t		encoder_id;
-	struct exynos_drm_manager *manager;
+	struct drm_connector		drm_connector;
+	uint32_t			encoder_id;
+	struct exynos_drm_display	*display;
 };
 
 static int exynos_drm_connector_get_modes(struct drm_connector *connector)
 {
 	struct exynos_drm_connector *exynos_connector =
 					to_exynos_connector(connector);
-	struct exynos_drm_manager *manager = exynos_connector->manager;
-	struct exynos_drm_display_ops *display_ops = manager->display_ops;
+	struct exynos_drm_display *display = exynos_connector->display;
 	struct edid *edid = NULL;
 	unsigned int count = 0;
 	int ret;
 
-	if (!display_ops) {
-		DRM_DEBUG_KMS("display_ops is null.\n");
-		return 0;
-	}
-
 	/*
 	 * if get_edid() exists then get_edid() callback of hdmi side
 	 * is called to get edid data through i2c interface else
@@ -51,8 +45,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
 	 * P.S. in case of lcd panel, count is always 1 if success
 	 * because lcd panel has only one mode.
 	 */
-	if (display_ops->get_edid) {
-		edid = display_ops->get_edid(manager->dev, connector);
+	if (display->ops->get_edid) {
+		edid = display->ops->get_edid(display, connector);
 		if (IS_ERR_OR_NULL(edid)) {
 			ret = PTR_ERR(edid);
 			edid = NULL;
@@ -75,8 +69,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
 			return 0;
 		}
 
-		if (display_ops->get_panel)
-			panel = display_ops->get_panel(manager->dev);
+		if (display->ops->get_panel)
+			panel = display->ops->get_panel(display);
 		else {
 			drm_mode_destroy(connector->dev, mode);
 			return 0;
@@ -105,14 +99,13 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
 {
 	struct exynos_drm_connector *exynos_connector =
 					to_exynos_connector(connector);
-	struct exynos_drm_manager *manager = exynos_connector->manager;
-	struct exynos_drm_display_ops *display_ops = manager->display_ops;
+	struct exynos_drm_display *display = exynos_connector->display;
 	int ret = MODE_BAD;
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
-	if (display_ops && display_ops->check_mode)
-		if (!display_ops->check_mode(manager->dev, mode))
+	if (display->ops->check_mode)
+		if (!display->ops->check_mode(display, mode))
 			ret = MODE_OK;
 
 	return ret;
@@ -151,8 +144,7 @@ static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
 {
 	struct exynos_drm_connector *exynos_connector =
 					to_exynos_connector(connector);
-	struct exynos_drm_manager *manager = exynos_connector->manager;
-	struct exynos_drm_manager_ops *ops = manager->ops;
+	struct exynos_drm_display *display = exynos_connector->display;
 	unsigned int width, height;
 
 	width = max_width;
@@ -162,8 +154,8 @@ static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
 	 * if specific driver want to find desired_mode using maxmum
 	 * resolution then get max width and height from that driver.
 	 */
-	if (ops && ops->get_max_resol)
-		ops->get_max_resol(manager, &width, &height);
+	if (display->ops->get_max_resol)
+		display->ops->get_max_resol(display, &width, &height);
 
 	return drm_helper_probe_single_connector_modes(connector, width,
 							height);
@@ -175,13 +167,11 @@ exynos_drm_connector_detect(struct drm_connector *connector, bool force)
 {
 	struct exynos_drm_connector *exynos_connector =
 					to_exynos_connector(connector);
-	struct exynos_drm_manager *manager = exynos_connector->manager;
-	struct exynos_drm_display_ops *display_ops =
-					manager->display_ops;
+	struct exynos_drm_display *display = exynos_connector->display;
 	enum drm_connector_status status = connector_status_disconnected;
 
-	if (display_ops && display_ops->is_connected) {
-		if (display_ops->is_connected(manager->dev))
+	if (display->ops->is_connected) {
+		if (display->ops->is_connected(display))
 			status = connector_status_connected;
 		else
 			status = connector_status_disconnected;
@@ -211,7 +201,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
 						   struct drm_encoder *encoder)
 {
 	struct exynos_drm_connector *exynos_connector;
-	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+	struct exynos_drm_display *display = exynos_drm_get_display(encoder);
 	struct drm_connector *connector;
 	int type;
 	int err;
@@ -222,7 +212,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
 
 	connector = &exynos_connector->drm_connector;
 
-	switch (manager->display_ops->type) {
+	switch (display->type) {
 	case EXYNOS_DISPLAY_TYPE_HDMI:
 		type = DRM_MODE_CONNECTOR_HDMIA;
 		connector->interlace_allowed = true;
@@ -245,7 +235,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
 		goto err_connector;
 
 	exynos_connector->encoder_id = encoder->base.id;
-	exynos_connector->manager = manager;
+	exynos_connector->display = display;
 	connector->dpms = DRM_MODE_DPMS_OFF;
 	connector->encoder = encoder;
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
index 08ca4f9..e76098d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_core.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
@@ -16,11 +16,14 @@
 #include <drm/drmP.h>
 #include <drm/bridge/ptn3460.h>
 #include "exynos_drm_drv.h"
+#include "exynos_drm_crtc.h"
 #include "exynos_drm_encoder.h"
 #include "exynos_drm_connector.h"
 #include "exynos_drm_fbdev.h"
 
 static LIST_HEAD(exynos_drm_subdrv_list);
+static LIST_HEAD(exynos_drm_manager_list);
+static LIST_HEAD(exynos_drm_display_list);
 
 struct bridge_init {
 	struct i2c_client *client;
@@ -57,24 +60,28 @@ static int exynos_drm_attach_lcd_bridge(struct drm_device *dev,
 }
 
 static int exynos_drm_create_enc_conn(struct drm_device *dev,
-					struct exynos_drm_subdrv *subdrv)
+					struct exynos_drm_display *display)
 {
 	struct drm_encoder *encoder;
 	struct drm_connector *connector;
+	struct exynos_drm_manager *manager;
 	int ret;
+	unsigned long possible_crtcs = 0;
 
-	subdrv->manager->dev = subdrv->dev;
+	/* Find possible crtcs for this display */
+	list_for_each_entry(manager, &exynos_drm_manager_list, list)
+		if (manager->type == display->type)
+			possible_crtcs |= 1 << manager->pipe;
 
 	/* create and initialize a encoder for this sub driver. */
-	encoder = exynos_drm_encoder_create(dev, subdrv->manager,
-			(1 << MAX_CRTC) - 1);
+	encoder = exynos_drm_encoder_create(dev, display, possible_crtcs);
 	if (!encoder) {
 		DRM_ERROR("failed to create encoder\n");
 		return -EFAULT;
 	}
-	subdrv->encoder = encoder;
+	display->encoder = encoder;
 
-	if (subdrv->manager->display_ops->type == EXYNOS_DISPLAY_TYPE_LCD) {
+	if (display->type == EXYNOS_DISPLAY_TYPE_LCD) {
 		ret = exynos_drm_attach_lcd_bridge(dev, encoder);
 		if (ret)
 			return 0;
@@ -91,7 +98,7 @@ static int exynos_drm_create_enc_conn(struct drm_device *dev,
 		goto err_destroy_encoder;
 	}
 
-	subdrv->connector = connector;
+	display->connector = connector;
 
 	return 0;
 
@@ -100,21 +107,6 @@ err_destroy_encoder:
 	return ret;
 }
 
-static void exynos_drm_destroy_enc_conn(struct exynos_drm_subdrv *subdrv)
-{
-	if (subdrv->encoder) {
-		struct drm_encoder *encoder = subdrv->encoder;
-		encoder->funcs->destroy(encoder);
-		subdrv->encoder = NULL;
-	}
-
-	if (subdrv->connector) {
-		struct drm_connector *connector = subdrv->connector;
-		connector->funcs->destroy(connector);
-		subdrv->connector = NULL;
-	}
-}
-
 static int exynos_drm_subdrv_probe(struct drm_device *dev,
 					struct exynos_drm_subdrv *subdrv)
 {
@@ -146,10 +138,98 @@ static void exynos_drm_subdrv_remove(struct drm_device *dev,
 		subdrv->remove(dev, subdrv->dev);
 }
 
+int exynos_drm_initialize_managers(struct drm_device *dev)
+{
+	struct exynos_drm_manager *manager, *n;
+	int ret, pipe = 0;
+
+	list_for_each_entry(manager, &exynos_drm_manager_list, list) {
+		if (manager->ops->initialize) {
+			ret = manager->ops->initialize(manager, dev, pipe);
+			if (ret) {
+				DRM_ERROR("Mgr init [%d] failed with %d\n",
+						manager->type, ret);
+				goto err;
+			}
+		}
+
+		manager->drm_dev = dev;
+		manager->pipe = pipe++;
+
+		ret = exynos_drm_crtc_create(manager);
+		if (ret) {
+			DRM_ERROR("CRTC create [%d] failed with %d\n",
+					manager->type, ret);
+			goto err;
+		}
+	}
+	return 0;
+
+err:
+	list_for_each_entry_safe(manager, n, &exynos_drm_manager_list, list) {
+		if (pipe-- > 0)
+			exynos_drm_manager_unregister(manager);
+		else
+			list_del(&manager->list);
+	}
+	return ret;
+}
+
+void exynos_drm_remove_managers(struct drm_device *dev)
+{
+	struct exynos_drm_manager *manager, *n;
+
+	list_for_each_entry_safe(manager, n, &exynos_drm_manager_list, list)
+		exynos_drm_manager_unregister(manager);
+}
+
+int exynos_drm_initialize_displays(struct drm_device *dev)
+{
+	struct exynos_drm_display *display, *n;
+	int ret, initialized = 0;
+
+	list_for_each_entry(display, &exynos_drm_display_list, list) {
+		if (display->ops->initialize) {
+			ret = display->ops->initialize(display, dev);
+			if (ret) {
+				DRM_ERROR("Display init [%d] failed with %d\n",
+						display->type, ret);
+				goto err;
+			}
+		}
+
+		initialized++;
+
+		ret = exynos_drm_create_enc_conn(dev, display);
+		if (ret) {
+			DRM_ERROR("Encoder create [%d] failed with %d\n",
+					display->type, ret);
+			goto err;
+		}
+	}
+	return 0;
+
+err:
+	list_for_each_entry_safe(display, n, &exynos_drm_display_list, list) {
+		if (initialized-- > 0)
+			exynos_drm_display_unregister(display);
+		else
+			list_del(&display->list);
+	}
+	return ret;
+}
+
+void exynos_drm_remove_displays(struct drm_device *dev)
+{
+	struct exynos_drm_display *display, *n;
+
+	list_for_each_entry_safe(display, n, &exynos_drm_display_list, list)
+		exynos_drm_display_unregister(display);
+}
+
 int exynos_drm_device_register(struct drm_device *dev)
 {
 	struct exynos_drm_subdrv *subdrv, *n;
-	unsigned int fine_cnt = 0;
 	int err;
 
 	if (!dev)
@@ -162,30 +242,8 @@ int exynos_drm_device_register(struct drm_device *dev)
 			list_del(&subdrv->list);
 			continue;
 		}
-
-		/*
-		 * if manager is null then it means that this sub driver
-		 * doesn't need encoder and connector.
-		 */
-		if (!subdrv->manager) {
-			fine_cnt++;
-			continue;
-		}
-
-		err = exynos_drm_create_enc_conn(dev, subdrv);
-		if (err) {
-			DRM_DEBUG("failed to create encoder and connector.\n");
-			exynos_drm_subdrv_remove(dev, subdrv);
-			list_del(&subdrv->list);
-			continue;
-		}
-
-		fine_cnt++;
 	}
 
-	if (!fine_cnt)
-		return -EINVAL;
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(exynos_drm_device_register);
@@ -201,13 +259,44 @@ int exynos_drm_device_unregister(struct drm_device *dev)
 
 	list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
 		exynos_drm_subdrv_remove(dev, subdrv);
-		exynos_drm_destroy_enc_conn(subdrv);
 	}
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(exynos_drm_device_unregister);
 
+int exynos_drm_manager_register(struct exynos_drm_manager *manager)
+{
+	BUG_ON(!manager->ops);
+	list_add_tail(&manager->list, &exynos_drm_manager_list);
+	return 0;
+}
+
+int exynos_drm_manager_unregister(struct exynos_drm_manager *manager)
+{
+	if (manager->ops->remove)
+		manager->ops->remove(manager);
+
+	list_del(&manager->list);
+	return 0;
+}
+
+int exynos_drm_display_register(struct exynos_drm_display *display)
+{
+	BUG_ON(!display->ops);
+	list_add_tail(&display->list, &exynos_drm_display_list);
+	return 0;
+}
+
+int exynos_drm_display_unregister(struct exynos_drm_display *display)
+{
+	if (display->ops->remove)
+		display->ops->remove(display);
+
+	list_del(&display->list);
+	return 0;
+}
+
 int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
 {
 	if (!subdrv)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index ebc0150..347d62d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -33,6 +33,7 @@ enum exynos_crtc_mode {
  *
  * @drm_crtc: crtc object.
  * @drm_plane: pointer of private plane object for this crtc
+ * @manager: the manager associated with this crtc
  * @pipe: a crtc index created at load() with a new crtc object creation
  *	and the crtc object would be set to private->crtc array
  *	to get a crtc object corresponding to this pipe from private->crtc
@@ -46,6 +47,7 @@ enum exynos_crtc_mode {
 struct exynos_drm_crtc {
 	struct drm_crtc			drm_crtc;
 	struct drm_plane		*plane;
+	struct exynos_drm_manager	*manager;
 	unsigned int			pipe;
 	unsigned int			dpms;
 	enum exynos_crtc_mode		mode;
@@ -56,6 +58,7 @@ struct exynos_drm_crtc {
 static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct exynos_drm_manager *manager = exynos_crtc->manager;
 
 	DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
 
@@ -71,7 +74,9 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
 		drm_vblank_off(crtc->dev, exynos_crtc->pipe);
 	}
 
-	exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms);
+	if (manager->ops->dpms)
+		manager->ops->dpms(manager, mode);
+
 	exynos_crtc->dpms = mode;
 }
 
@@ -83,9 +88,15 @@ static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
 static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
 {
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct exynos_drm_manager *manager = exynos_crtc->manager;
 
 	exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+
 	exynos_plane_commit(exynos_crtc->plane);
+
+	if (manager->ops->commit)
+		manager->ops->commit(manager);
+
 	exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON);
 }
 
@@ -107,7 +118,6 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	struct drm_plane *plane = exynos_crtc->plane;
 	unsigned int crtc_w;
 	unsigned int crtc_h;
-	int pipe = exynos_crtc->pipe;
 	int ret;
 
 	/*
@@ -127,8 +137,6 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	plane->crtc = crtc;
 	plane->fb = crtc->fb;
 
-	exynos_drm_fn_encoder(crtc, &pipe, exynos_drm_encoder_crtc_pipe);
-
 	return 0;
 }
 
@@ -318,21 +326,24 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
 	drm_object_attach_property(&crtc->base, prop, 0);
 }
 
-int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
+int exynos_drm_crtc_create(struct exynos_drm_manager *manager)
 {
 	struct exynos_drm_crtc *exynos_crtc;
-	struct exynos_drm_private *private = dev->dev_private;
+	struct exynos_drm_private *private = manager->drm_dev->dev_private;
 	struct drm_crtc *crtc;
 
 	exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
 	if (!exynos_crtc)
 		return -ENOMEM;
 
-	exynos_crtc->pipe = nr;
-	exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
 	init_waitqueue_head(&exynos_crtc->pending_flip_queue);
 	atomic_set(&exynos_crtc->pending_flip, 0);
-	exynos_crtc->plane = exynos_plane_init(dev, 1 << nr, true);
+
+	exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
+	exynos_crtc->manager = manager;
+	exynos_crtc->pipe = manager->pipe;
+	exynos_crtc->plane = exynos_plane_init(manager->drm_dev,
+				1 << manager->pipe, true);
 	if (!exynos_crtc->plane) {
 		kfree(exynos_crtc);
 		return -ENOMEM;
@@ -340,9 +351,9 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
 
 	crtc = &exynos_crtc->drm_crtc;
 
-	private->crtc[nr] = crtc;
+	private->crtc[manager->pipe] = crtc;
 
-	drm_crtc_init(dev, crtc, &exynos_crtc_funcs);
+	drm_crtc_init(manager->drm_dev, crtc, &exynos_crtc_funcs);
 	drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
 
 	exynos_drm_crtc_attach_mode_property(crtc);
@@ -350,39 +361,41 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
 	return 0;
 }
 
-int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
+int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
 {
 	struct exynos_drm_private *private = dev->dev_private;
 	struct exynos_drm_crtc *exynos_crtc =
-		to_exynos_crtc(private->crtc[crtc]);
+		to_exynos_crtc(private->crtc[pipe]);
+	struct exynos_drm_manager *manager = exynos_crtc->manager;
 
 	if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
 		return -EPERM;
 
-	exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
-			exynos_drm_enable_vblank);
+	if (manager->ops->enable_vblank)
+		manager->ops->enable_vblank(manager);
 
 	return 0;
 }
 
-void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
+void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
 {
 	struct exynos_drm_private *private = dev->dev_private;
 	struct exynos_drm_crtc *exynos_crtc =
-		to_exynos_crtc(private->crtc[crtc]);
+		to_exynos_crtc(private->crtc[pipe]);
+	struct exynos_drm_manager *manager = exynos_crtc->manager;
 
 	if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
 		return;
 
-	exynos_drm_fn_encoder(private->crtc[crtc], &crtc,
-			exynos_drm_disable_vblank);
+	if (manager->ops->disable_vblank)
+		manager->ops->disable_vblank(manager);
 }
 
-void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
+void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
 {
 	struct exynos_drm_private *dev_priv = dev->dev_private;
 	struct drm_pending_vblank_event *e, *t;
-	struct drm_crtc *drm_crtc = dev_priv->crtc[crtc];
+	struct drm_crtc *drm_crtc = dev_priv->crtc[pipe];
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
 	unsigned long flags;
 
@@ -391,15 +404,71 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
 	list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
 			base.link) {
 		/* if event's pipe isn't same as crtc then ignore it. */
-		if (crtc != e->pipe)
+		if (pipe != e->pipe)
 			continue;
 
 		list_del(&e->base.link);
 		drm_send_vblank_event(dev, -1, e);
-		drm_vblank_put(dev, crtc);
+		drm_vblank_put(dev, pipe);
 		atomic_set(&exynos_crtc->pending_flip, 0);
 		wake_up(&exynos_crtc->pending_flip_queue);
 	}
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
+
+void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
+			struct exynos_drm_overlay *overlay)
+{
+	struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
+
+	if (manager->ops->win_mode_set)
+		manager->ops->win_mode_set(manager, overlay);
+}
+
+void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos)
+{
+	struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
+
+	if (manager->ops->win_commit)
+		manager->ops->win_commit(manager, zpos);
+}
+
+void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos)
+{
+	struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
+
+	if (manager->ops->win_enable)
+		manager->ops->win_enable(manager, zpos);
+}
+
+void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos)
+{
+	struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
+
+	if (manager->ops->win_disable)
+		manager->ops->win_disable(manager, zpos);
+}
+
+void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
+{
+	struct exynos_drm_manager *manager;
+	struct drm_device *dev = fb->dev;
+	struct drm_crtc *crtc;
+
+	/*
+	 * make sure that overlay data are updated to real hardware
+	 * for all encoders.
+	 */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		manager = to_exynos_crtc(crtc)->manager;
+
+		/*
+		 * wait for vblank interrupt
+		 * - this makes sure that overlay data are updated to
+		 *	real hardware.
+		 */
+		if (manager->ops->wait_for_vblank)
+			manager->ops->wait_for_vblank(manager);
+	}
+}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index 3e197e6..c27b66c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -15,9 +15,21 @@
 #ifndef _EXYNOS_DRM_CRTC_H_
 #define _EXYNOS_DRM_CRTC_H_
 
-int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr);
-int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
-void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
-void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc);
+struct drm_device;
+struct drm_crtc;
+struct exynos_drm_manager;
+struct exynos_drm_overlay;
+
+int exynos_drm_crtc_create(struct exynos_drm_manager *manager);
+int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe);
+void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe);
+void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe);
+void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);
+
+void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
+			struct exynos_drm_overlay *overlay);
+void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos);
+void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos);
+void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);
 
 #endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 617748e..250903c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -72,15 +72,9 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 
 	exynos_drm_mode_config_init(dev);
 
-	/*
-	 * EXYNOS4 is enough to have two CRTCs and each crtc would be used
-	 * without dependency of hardware.
-	 */
-	for (nr = 0; nr < MAX_CRTC; nr++) {
-		ret = exynos_drm_crtc_create(dev, nr);
-		if (ret)
-			goto err_release_iommu_mapping;
-	}
+	ret = exynos_drm_initialize_managers(dev);
+	if (ret)
+		goto err_mode_config_cleanup;
 
 	for (nr = 0; nr < MAX_PLANE; nr++) {
 		struct drm_plane *plane;
@@ -88,12 +82,16 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 
 		plane = exynos_plane_init(dev, possible_crtcs, false);
 		if (!plane)
-			goto err_release_iommu_mapping;
+			goto err_manager_cleanup;
 	}
 
+	ret = exynos_drm_initialize_displays(dev);
+	if (ret)
+		goto err_manager_cleanup;
+
 	ret = drm_vblank_init(dev, MAX_CRTC);
 	if (ret)
-		goto err_release_iommu_mapping;
+		goto err_display_cleanup;
 
 	/*
 	 * probe sub drivers such as display controller and hdmi driver,
@@ -125,7 +123,12 @@ err_drm_device:
 	exynos_drm_device_unregister(dev);
 err_vblank:
 	drm_vblank_cleanup(dev);
-err_release_iommu_mapping:
+err_display_cleanup:
+	exynos_drm_remove_displays(dev);
+err_manager_cleanup:
+	exynos_drm_remove_managers(dev);
+err_mode_config_cleanup:
+	drm_mode_config_cleanup(dev);
 	drm_release_iommu_mapping(dev);
 err_crtc:
 	drm_mode_config_cleanup(dev);
@@ -140,6 +143,8 @@ static int exynos_drm_unload(struct drm_device *dev)
 	exynos_drm_device_unregister(dev);
 	drm_vblank_cleanup(dev);
 	drm_kms_helper_poll_fini(dev);
+	exynos_drm_remove_displays(dev);
+	exynos_drm_remove_managers(dev);
 	drm_mode_config_cleanup(dev);
 
 	drm_release_iommu_mapping(dev);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index e31c088..dc730e5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -122,34 +122,68 @@ struct exynos_drm_overlay {
  * Exynos DRM Display Structure.
  *	- this structure is common to analog tv, digital tv and lcd panel.
  *
- * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
  * @initialize: initializes the display with drm_dev
+ * @remove: cleans up the display for removal
  * @is_connected: check for that display is connected or not.
+ * @get_max_resol: get maximum resolution to specific hardware.
  * @get_edid: get edid modes from display driver.
  * @get_panel: get panel object from display driver.
+ * @mode_fixup: fix mode data comparing to hw specific display mode.
+ * @mode_set: convert drm_display_mode to hw specific display mode and
+ *	      would be called by encoder->mode_set().
  * @check_mode: check if mode is valid or not.
  * @dpms: display device on or off.
+ * @commit: apply changes to hw
  */
+struct exynos_drm_display;
 struct exynos_drm_display_ops {
+	int (*initialize)(struct exynos_drm_display *display,
+				struct drm_device *drm_dev);
+	void (*remove)(struct exynos_drm_display *display);
+	bool (*is_connected)(struct exynos_drm_display *display);
+	void (*get_max_resol)(struct exynos_drm_display *display,
+				unsigned int *width,
+				unsigned int *height);
+	struct edid *(*get_edid)(struct exynos_drm_display *display,
+				struct drm_connector *connector);
+	void *(*get_panel)(struct exynos_drm_display *display);
+	void (*mode_fixup)(struct exynos_drm_display *display,
+				struct drm_connector *connector,
+				const struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode);
+	void (*mode_set)(struct exynos_drm_display *display,
+				struct drm_display_mode *mode);
+	int (*check_mode)(struct exynos_drm_display *display,
+				struct drm_display_mode *mode);
+	void (*dpms)(struct exynos_drm_display *display, int mode);
+	void (*commit)(struct exynos_drm_display *display);
+};
+
+/*
+ * Exynos drm display structure, maps 1:1 with an encoder/connector
+ *
+ * @list: the list entry for this manager
+ * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
+ * @encoder: encoder object this display maps to
+ * @connector: connector object this display maps to
+ * @ops: pointer to callbacks for exynos drm specific functionality
+ * @ctx: A pointer to the display's implementation specific context
+ */
+struct exynos_drm_display {
+	struct list_head list;
 	enum exynos_drm_output_type type;
-	int (*initialize)(struct device *dev, struct drm_device *drm_dev);
-	bool (*is_connected)(struct device *dev);
-	struct edid *(*get_edid)(struct device *dev,
-			struct drm_connector *connector);
-	void *(*get_panel)(struct device *dev);
-	int (*check_mode)(struct device *dev, struct drm_display_mode *mode);
-	int (*dpms)(struct device *dev, int mode);
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	struct exynos_drm_display_ops *ops;
+	void *ctx;
 };
 
 /*
  * Exynos drm manager ops
  *
  * @initialize: initializes the manager with drm_dev
+ * @remove: cleans up the manager for removal
  * @dpms: control device power.
- * @mode_fixup: fix mode data comparing to hw specific display mode.
- * @mode_set: convert drm_display_mode to hw specific display mode and
- *	      would be called by encoder->mode_set().
- * @get_max_resol: get maximum resolution to specific hardware.
  * @commit: set current hw specific display mode to hw.
  * @enable_vblank: specific driver callback for enabling vblank interrupt.
  * @disable_vblank: specific driver callback for disabling vblank interrupt.
@@ -163,15 +197,9 @@ struct exynos_drm_display_ops {
 struct exynos_drm_manager;
 struct exynos_drm_manager_ops {
 	int (*initialize)(struct exynos_drm_manager *mgr,
-				struct drm_device *drm_dev);
+				struct drm_device *drm_dev, int pipe);
+	void (*remove)(struct exynos_drm_manager *mgr);
 	void (*dpms)(struct exynos_drm_manager *mgr, int mode);
-	void (*mode_fixup)(struct exynos_drm_manager *mgr,
-				struct drm_connector *connector,
-				const struct drm_display_mode *mode,
-				struct drm_display_mode *adjusted_mode);
-	void (*mode_set)(struct exynos_drm_manager *mgr, void *mode);
-	void (*get_max_resol)(struct exynos_drm_manager *mgr,
-				unsigned int *width, unsigned int *height);
 	void (*commit)(struct exynos_drm_manager *mgr);
 	int (*enable_vblank)(struct exynos_drm_manager *mgr);
 	void (*disable_vblank)(struct exynos_drm_manager *mgr);
@@ -184,25 +212,21 @@ struct exynos_drm_manager_ops {
 };
 
 /*
- * Exynos drm common manager structure.
+ * Exynos drm common manager structure, maps 1:1 with a crtc
  *
- * @dev: pointer to device object for subdrv device driver.
- *	sub drivers such as display controller or hdmi driver,
- *	have their own device object.
- * @ops: pointer to callbacks for exynos drm specific framebuffer.
- *	these callbacks should be set by specific drivers such fimd
- *	or hdmi driver and are used to control hardware global registers.
- * @display: pointer to callbacks for exynos drm specific framebuffer.
- *	these callbacks should be set by specific drivers such fimd
- *	or hdmi driver and are used to control display devices such as
- *	analog tv, digital tv and lcd panel and also get timing data for them.
+ * @list: the list entry for this manager
+ * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
+ * @drm_dev: pointer to the drm device
+ * @pipe: the pipe number for this crtc/manager
+ * @ops: pointer to callbacks for exynos drm specific functionality
  * @ctx: A pointer to the manager's implementation specific context
  */
 struct exynos_drm_manager {
-	struct device *dev;
+	struct list_head list;
+	enum exynos_drm_output_type type;
+	struct drm_device *drm_dev;
 	int pipe;
 	struct exynos_drm_manager_ops *ops;
-	struct exynos_drm_display_ops *display_ops;
 	void *ctx;
 };
 
@@ -267,14 +291,11 @@ struct exynos_drm_private {
  *	by probe callback.
  * @open: this would be called with drm device file open.
  * @close: this would be called with drm device file close.
- * @encoder: encoder object owned by this sub driver.
- * @connector: connector object owned by this sub driver.
  */
 struct exynos_drm_subdrv {
 	struct list_head list;
 	struct device *dev;
 	struct drm_device *drm_dev;
-	struct exynos_drm_manager *manager;
 
 	int (*probe)(struct drm_device *drm_dev, struct device *dev);
 	void (*remove)(struct drm_device *drm_dev, struct device *dev);
@@ -282,9 +303,6 @@ struct exynos_drm_subdrv {
 			struct drm_file *file);
 	void (*close)(struct drm_device *drm_dev, struct device *dev,
 			struct drm_file *file);
-
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
 };
 
 /*
@@ -299,6 +317,16 @@ int exynos_drm_device_register(struct drm_device *dev);
  */
 int exynos_drm_device_unregister(struct drm_device *dev);
 
+int exynos_drm_initialize_managers(struct drm_device *dev);
+void exynos_drm_remove_managers(struct drm_device *dev);
+int exynos_drm_initialize_displays(struct drm_device *dev);
+void exynos_drm_remove_displays(struct drm_device *dev);
+
+int exynos_drm_manager_register(struct exynos_drm_manager *manager);
+int exynos_drm_manager_unregister(struct exynos_drm_manager *manager);
+int exynos_drm_display_register(struct exynos_drm_display *display);
+int exynos_drm_display_unregister(struct exynos_drm_display *display);
+
 /*
  * this function would be called by sub drivers such as display controller
  * or hdmi driver to register this sub driver object to exynos drm driver
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index efe4e60..d4ae664 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -26,24 +26,23 @@
  * exynos specific encoder structure.
  *
  * @drm_encoder: encoder object.
- * @manager: specific encoder has its own manager to control a hardware
- *	appropriately and we can access a hardware drawing on this manager.
+ * @display: the display structure that maps to this encoder
  */
 struct exynos_drm_encoder {
 	struct drm_crtc			*old_crtc;
 	struct drm_encoder		drm_encoder;
-	struct exynos_drm_manager	*manager;
+	struct exynos_drm_display	*display;
 };
 
 static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
-	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
-	struct exynos_drm_display_ops *display_ops = manager->display_ops;
+	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+	struct exynos_drm_display *display = exynos_encoder->display;
 
 	DRM_DEBUG_KMS("encoder dpms: %d\n", mode);
 
-	if (display_ops && display_ops->dpms)
-		display_ops->dpms(manager->ctx, mode);
+	if (display->ops->dpms)
+		display->ops->dpms(display, mode);
 }
 
 static bool
@@ -52,15 +51,17 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
 			       struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = encoder->dev;
+	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+	struct exynos_drm_display *display = exynos_encoder->display;
 	struct drm_connector *connector;
-	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
-	struct exynos_drm_manager_ops *manager_ops = manager->ops;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder)
-			if (manager_ops && manager_ops->mode_fixup)
-				manager_ops->mode_fixup(manager, connector,
-							mode, adjusted_mode);
+		if (connector->encoder != encoder)
+			continue;
+
+		if (display->ops->mode_fixup)
+			display->ops->mode_fixup(display, connector, mode,
+					adjusted_mode);
 	}
 
 	return true;
@@ -102,8 +103,7 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_connector *connector;
-	struct exynos_drm_manager *manager;
-	struct exynos_drm_manager_ops *manager_ops;
+	struct exynos_drm_display *display;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		if (connector->encoder == encoder) {
@@ -123,11 +123,11 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
 						encoder->crtc);
 			}
 
-			manager = exynos_drm_get_manager(encoder);
-			manager_ops = manager->ops;
+			display = exynos_encoder->display;
 
-			if (manager_ops && manager_ops->mode_set)
-				manager_ops->mode_set(manager, adjusted_mode);
+			if (display->ops->mode_set)
+				display->ops->mode_set(display,
+							adjusted_mode);
 
 			exynos_encoder->old_crtc = encoder->crtc;
 		}
@@ -142,39 +142,15 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
 static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 {
 	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
-	struct exynos_drm_manager *manager = exynos_encoder->manager;
-	struct exynos_drm_manager_ops *manager_ops = manager->ops;
-
-	if (manager_ops && manager_ops->commit)
-		manager_ops->commit(manager);
-}
+	struct exynos_drm_display *display = exynos_encoder->display;
 
-void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb)
-{
-	struct exynos_drm_encoder *exynos_encoder;
-	struct exynos_drm_manager_ops *ops;
-	struct drm_device *dev = fb->dev;
-	struct drm_encoder *encoder;
+	if (display->ops->dpms)
+		display->ops->dpms(display, DRM_MODE_DPMS_ON);
 
-	/*
-	 * make sure that overlay data are updated to real hardware
-	 * for all encoders.
-	 */
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		exynos_encoder = to_exynos_encoder(encoder);
-		ops = exynos_encoder->manager->ops;
-
-		/*
-		 * wait for vblank interrupt
-		 * - this makes sure that overlay data are updated to
-		 *	real hardware.
-		 */
-		if (ops->wait_for_vblank)
-			ops->wait_for_vblank(exynos_encoder->manager);
-	}
+	if (display->ops->commit)
+		display->ops->commit(display);
 }
 
-
 static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
 {
 	struct drm_plane *plane;
@@ -200,10 +176,7 @@ static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
 
 static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
 {
-	struct exynos_drm_encoder *exynos_encoder =
-		to_exynos_encoder(encoder);
-
-	exynos_encoder->manager->pipe = -1;
+	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
 
 	drm_encoder_cleanup(encoder);
 	kfree(exynos_encoder);
@@ -218,13 +191,12 @@ static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder)
 	struct drm_encoder *clone;
 	struct drm_device *dev = encoder->dev;
 	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
-	struct exynos_drm_display_ops *display_ops =
-				exynos_encoder->manager->display_ops;
+	struct exynos_drm_display *display = exynos_encoder->display;
 	unsigned int clone_mask = 0;
 	int cnt = 0;
 
 	list_for_each_entry(clone, &dev->mode_config.encoder_list, head) {
-		switch (display_ops->type) {
+		switch (display->type) {
 		case EXYNOS_DISPLAY_TYPE_LCD:
 		case EXYNOS_DISPLAY_TYPE_HDMI:
 		case EXYNOS_DISPLAY_TYPE_VIDI:
@@ -248,24 +220,20 @@ void exynos_drm_encoder_setup(struct drm_device *dev)
 
 struct drm_encoder *
 exynos_drm_encoder_create(struct drm_device *dev,
-			   struct exynos_drm_manager *manager,
+			   struct exynos_drm_display *display,
 			   unsigned long possible_crtcs)
 {
 	struct drm_encoder *encoder;
 	struct exynos_drm_encoder *exynos_encoder;
-	int ret;
 
-	if (!manager || !possible_crtcs)
-		return NULL;
-
-	if (!manager->dev)
+	if (!possible_crtcs)
 		return NULL;
 
 	exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
 	if (!exynos_encoder)
 		return NULL;
 
-	exynos_encoder->manager = manager;
+	exynos_encoder->display = display;
 	encoder = &exynos_encoder->drm_encoder;
 	encoder->possible_crtcs = possible_crtcs;
 
@@ -276,174 +244,12 @@ exynos_drm_encoder_create(struct drm_device *dev,
 
 	drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs);
 
-	if (manager->ops && manager->ops->initialize) {
-		ret = manager->ops->initialize(manager, dev);
-		if (ret) {
-			DRM_ERROR("Manager initialize failed %d\n", ret);
-			goto error;
-		}
-	}
-
-	if (manager->display_ops && manager->display_ops->initialize) {
-		ret = manager->display_ops->initialize(manager->dev, dev);
-		if (ret) {
-			DRM_ERROR("Display initialize failed %d\n", ret);
-			goto error;
-		}
-	}
-
 	DRM_DEBUG_KMS("encoder has been created\n");
 
 	return encoder;
-
-error:
-	exynos_drm_encoder_destroy(&exynos_encoder->drm_encoder);
-	return NULL;
 }
 
-struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder)
+struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder)
 {
-	return to_exynos_encoder(encoder)->manager;
-}
-
-void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
-			    void (*fn)(struct drm_encoder *, void *))
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_encoder *encoder;
-	struct exynos_drm_private *private = dev->dev_private;
-	struct exynos_drm_manager *manager;
-
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		/*
-		 * if crtc is detached from encoder, check pipe,
-		 * otherwise check crtc attached to encoder
-		 */
-		if (!encoder->crtc) {
-			manager = to_exynos_encoder(encoder)->manager;
-			if (manager->pipe < 0 ||
-					private->crtc[manager->pipe] != crtc)
-				continue;
-		} else {
-			if (encoder->crtc != crtc)
-				continue;
-		}
-
-		fn(encoder, data);
-	}
-}
-
-void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data)
-{
-	struct exynos_drm_manager *manager =
-		to_exynos_encoder(encoder)->manager;
-	struct exynos_drm_manager_ops *manager_ops = manager->ops;
-	int crtc = *(int *)data;
-
-	if (manager->pipe != crtc)
-		return;
-
-	if (manager_ops->enable_vblank)
-		manager_ops->enable_vblank(manager);
-}
-
-void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
-{
-	struct exynos_drm_manager *manager =
-		to_exynos_encoder(encoder)->manager;
-	struct exynos_drm_manager_ops *manager_ops = manager->ops;
-	int crtc = *(int *)data;
-
-	if (manager->pipe != crtc)
-		return;
-
-	if (manager_ops->disable_vblank)
-		manager_ops->disable_vblank(manager);
-}
-
-void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
-{
-	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
-	struct exynos_drm_manager *manager = exynos_encoder->manager;
-	struct exynos_drm_manager_ops *manager_ops = manager->ops;
-	int mode = *(int *)data;
-
-	if (manager_ops && manager_ops->dpms)
-		manager_ops->dpms(manager, mode);
-
-	/*
-	 * if this condition is ok then it means that the crtc is already
-	 * detached from encoder and last function for detaching is properly
-	 * done, so clear pipe from manager to prevent repeated call.
-	 */
-	if (mode > DRM_MODE_DPMS_ON) {
-		if (!encoder->crtc)
-			manager->pipe = -1;
-	}
-}
-
-void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data)
-{
-	struct exynos_drm_manager *manager =
-		to_exynos_encoder(encoder)->manager;
-	int pipe = *(int *)data;
-
-	/*
-	 * when crtc is detached from encoder, this pipe is used
-	 * to select manager operation
-	 */
-	manager->pipe = pipe;
-}
-
-void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data)
-{
-	struct exynos_drm_manager *manager =
-		to_exynos_encoder(encoder)->manager;
-	struct exynos_drm_manager_ops *manager_ops = manager->ops;
-	struct exynos_drm_overlay *overlay = data;
-
-	if (manager_ops && manager_ops->win_mode_set)
-		manager_ops->win_mode_set(manager, overlay);
-}
-
-void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data)
-{
-	struct exynos_drm_manager *manager =
-		to_exynos_encoder(encoder)->manager;
-	struct exynos_drm_manager_ops *manager_ops = manager->ops;
-	int zpos = DEFAULT_ZPOS;
-
-	if (data)
-		zpos = *(int *)data;
-
-	if (manager_ops && manager_ops->win_commit)
-		manager_ops->win_commit(manager, zpos);
-}
-
-void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data)
-{
-	struct exynos_drm_manager *manager =
-		to_exynos_encoder(encoder)->manager;
-	struct exynos_drm_manager_ops *manager_ops = manager->ops;
-	int zpos = DEFAULT_ZPOS;
-
-	if (data)
-		zpos = *(int *)data;
-
-	if (manager_ops && manager_ops->win_enable)
-		manager_ops->win_enable(manager, zpos);
-}
-
-void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
-{
-	struct exynos_drm_manager *manager =
-		to_exynos_encoder(encoder)->manager;
-	struct exynos_drm_manager_ops *manager_ops = manager->ops;
-	int zpos = DEFAULT_ZPOS;
-
-	if (data)
-		zpos = *(int *)data;
-
-	if (manager_ops && manager_ops->win_disable)
-		manager_ops->win_disable(manager, zpos);
+	return to_exynos_encoder(encoder)->display;
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h
index 0f3e5e2..b7a1620 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.h
@@ -18,20 +18,8 @@ struct exynos_drm_manager;
 
 void exynos_drm_encoder_setup(struct drm_device *dev);
 struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev,
-					       struct exynos_drm_manager *mgr,
-					       unsigned long possible_crtcs);
-struct exynos_drm_manager *
-exynos_drm_get_manager(struct drm_encoder *encoder);
-void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
-			    void (*fn)(struct drm_encoder *, void *));
-void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data);
-void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb);
+			struct exynos_drm_display *mgr,
+			unsigned long possible_crtcs);
+struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder);
 
 #endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index ea39e0e..c7c08d0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -22,7 +22,7 @@
 #include "exynos_drm_fb.h"
 #include "exynos_drm_gem.h"
 #include "exynos_drm_iommu.h"
-#include "exynos_drm_encoder.h"
+#include "exynos_drm_crtc.h"
 
 #define to_exynos_fb(x)	container_of(x, struct exynos_drm_fb, fb)
 
@@ -71,7 +71,7 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
 	unsigned int i;
 
 	/* make sure that overlay data are updated before relesing fb. */
-	exynos_drm_encoder_complete_scanout(fb);
+	exynos_drm_crtc_complete_scanout(fb);
 
 	drm_framebuffer_cleanup(fb);
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index b980b05..d2b8ccb 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -105,7 +105,6 @@ struct fimd_win_data {
 };
 
 struct fimd_context {
-	struct exynos_drm_subdrv	subdrv;
 	struct device			*dev;
 	struct drm_device		*drm_dev;
 	int				irq;
@@ -120,6 +119,7 @@ struct fimd_context {
 	u32				vidcon0;
 	u32				vidcon1;
 	bool				suspended;
+	int				pipe;
 	struct mutex			lock;
 	wait_queue_head_t		wait_vsync_queue;
 	atomic_t			wait_vsync_event;
@@ -147,22 +147,22 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data(
 	return (struct fimd_driver_data *)of_id->data;
 }
 
-static bool fimd_display_is_connected(struct device *dev)
+static bool fimd_display_is_connected(struct exynos_drm_display *display)
 {
 	/* TODO. */
 
 	return true;
 }
 
-static void *fimd_get_panel(struct device *dev)
+static void *fimd_get_panel(struct exynos_drm_display *display)
 {
-	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
-	struct fimd_context *ctx = mgr->ctx;
+	struct fimd_context *ctx = display->ctx;
 
 	return &ctx->panel;
 }
 
-static int fimd_check_mode(struct device *dev, struct drm_display_mode *mode)
+static int fimd_check_mode(struct exynos_drm_display *display,
+			struct drm_display_mode *mode)
 {
 	/* TODO. */
 
@@ -170,12 +170,16 @@ static int fimd_check_mode(struct device *dev, struct drm_display_mode *mode)
 }
 
 static struct exynos_drm_display_ops fimd_display_ops = {
-	.type = EXYNOS_DISPLAY_TYPE_LCD,
 	.is_connected = fimd_display_is_connected,
 	.get_panel = fimd_get_panel,
 	.check_mode = fimd_check_mode,
 };
 
+static struct exynos_drm_display fimd_display = {
+	.type = EXYNOS_DISPLAY_TYPE_LCD,
+	.ops = &fimd_display_ops,
+};
+
 static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
 			struct exynos_drm_overlay *overlay)
 {
@@ -484,15 +488,45 @@ static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
 }
 
 static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,
-			struct drm_device *drm_dev)
+			struct drm_device *drm_dev, int pipe)
 {
 	struct fimd_context *ctx = mgr->ctx;
 
 	ctx->drm_dev = drm_dev;
+	ctx->pipe = pipe;
+
+	/*
+	 * enable drm irq mode.
+	 * - with irq_enabled = 1, we can use the vblank feature.
+	 *
+	 * P.S. note that we wouldn't use drm irq handler but
+	 *	just specific driver own one instead because
+	 *	drm framework supports only one irq handler.
+	 */
+	ctx->drm_dev->irq_enabled = 1;
+
+	/*
+	 * with vblank_disable_allowed = 1, vblank interrupt will be disabled
+	 * by drm timer once a current process gives up ownership of
+	 * vblank event.(after drm_vblank_put function is called)
+	 */
+	drm_dev->vblank_disable_allowed = 1;
+
+	/* attach this sub driver to iommu mapping if supported. */
+	if (is_drm_iommu_supported(ctx->drm_dev))
+		drm_iommu_attach_device(ctx->drm_dev, ctx->dev);
 
 	return 0;
 }
 
+static void fimd_mgr_remove(struct exynos_drm_manager *mgr)
+{
+	struct fimd_context *ctx = mgr->ctx;
+
+	if (is_drm_iommu_supported(ctx->drm_dev))
+		drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
+}
+
 static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
 {
 	struct fimd_context *ctx = mgr->ctx;
@@ -526,23 +560,6 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
 	mutex_unlock(&ctx->lock);
 }
 
-static void fimd_apply(struct exynos_drm_manager *mgr)
-{
-	struct fimd_context *ctx = mgr->ctx;
-	struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
-	struct fimd_win_data *win_data;
-	int i;
-
-	for (i = 0; i < WINDOWS_NR; i++) {
-		win_data = &ctx->win_data[i];
-		if (win_data->enabled && (mgr_ops && mgr_ops->win_commit))
-			mgr_ops->win_commit(mgr, i);
-	}
-
-	if (mgr_ops && mgr_ops->commit)
-		mgr_ops->commit(mgr);
-}
-
 static void fimd_commit(struct exynos_drm_manager *mgr)
 {
 	struct fimd_context *ctx = mgr->ctx;
@@ -599,6 +616,21 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
 	writel(val, ctx->regs + VIDCON0);
 }
 
+static void fimd_apply(struct exynos_drm_manager *mgr)
+{
+	struct fimd_context *ctx = mgr->ctx;
+	struct fimd_win_data *win_data;
+	int i;
+
+	for (i = 0; i < WINDOWS_NR; i++) {
+		win_data = &ctx->win_data[i];
+		if (win_data->enabled)
+			fimd_win_commit(mgr, i);
+	}
+
+	fimd_commit(mgr);
+}
+
 static int fimd_enable_vblank(struct exynos_drm_manager *mgr)
 {
 	struct fimd_context *ctx = mgr->ctx;
@@ -663,6 +695,7 @@ static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr)
 
 static struct exynos_drm_manager_ops fimd_manager_ops = {
 	.initialize = fimd_mgr_initialize,
+	.remove = fimd_mgr_remove,
 	.dpms = fimd_dpms,
 	.commit = fimd_commit,
 	.enable_vblank = fimd_enable_vblank,
@@ -674,16 +707,13 @@ static struct exynos_drm_manager_ops fimd_manager_ops = {
 };
 
 static struct exynos_drm_manager fimd_manager = {
-	.pipe		= -1,
-	.ops		= &fimd_manager_ops,
-	.display_ops	= &fimd_display_ops,
+	.type = EXYNOS_DISPLAY_TYPE_LCD,
+	.ops = &fimd_manager_ops,
 };
 
 static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
 {
 	struct fimd_context *ctx = (struct fimd_context *)dev_id;
-	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-	struct exynos_drm_manager *manager = subdrv->manager;
 	u32 val;
 
 	val = readl(ctx->regs + VIDINTCON1);
@@ -693,11 +723,11 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
 		writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
 
 	/* check the crtc is detached already from encoder */
-	if (manager->pipe < 0 || !ctx->drm_dev)
+	if (ctx->pipe < 0 || !ctx->drm_dev)
 		goto out;
 
-	drm_handle_vblank(ctx->drm_dev, manager->pipe);
-	exynos_drm_crtc_finish_pageflip(ctx->drm_dev, manager->pipe);
+	drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+	exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
 
 	/* set wait vsync event to zero and wake up queue. */
 	if (atomic_read(&ctx->wait_vsync_event)) {
@@ -708,39 +738,6 @@ out:
 	return IRQ_HANDLED;
 }
 
-static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
-{
-	/*
-	 * enable drm irq mode.
-	 * - with irq_enabled = 1, we can use the vblank feature.
-	 *
-	 * P.S. note that we wouldn't use drm irq handler but
-	 *	just specific driver own one instead because
-	 *	drm framework supports only one irq handler.
-	 */
-	drm_dev->irq_enabled = 1;
-
-	/*
-	 * with vblank_disable_allowed = 1, vblank interrupt will be disabled
-	 * by drm timer once a current process gives up ownership of
-	 * vblank event.(after drm_vblank_put function is called)
-	 */
-	drm_dev->vblank_disable_allowed = 1;
-
-	/* attach this sub driver to iommu mapping if supported. */
-	if (is_drm_iommu_supported(drm_dev))
-		drm_iommu_attach_device(drm_dev, dev);
-
-	return 0;
-}
-
-static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
-{
-	/* detach this sub driver from iommu mapping if supported. */
-	if (is_drm_iommu_supported(drm_dev))
-		drm_iommu_detach_device(drm_dev, dev);
-}
-
 static int fimd_configure_clocks(struct fimd_context *ctx, struct device *dev)
 {
 	struct videomode *vm = &ctx->panel.vm;
@@ -826,9 +823,8 @@ static int fimd_clock(struct fimd_context *ctx, bool enable)
 	return 0;
 }
 
-static void fimd_window_suspend(struct device *dev)
+static void fimd_window_suspend(struct exynos_drm_manager *mgr)
 {
-	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
 	struct fimd_context *ctx = mgr->ctx;
 	struct fimd_win_data *win_data;
 	int i;
@@ -841,9 +837,8 @@ static void fimd_window_suspend(struct device *dev)
 	fimd_wait_for_vblank(mgr);
 }
 
-static void fimd_window_resume(struct device *dev)
+static void fimd_window_resume(struct exynos_drm_manager *mgr)
 {
-	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
 	struct fimd_context *ctx = mgr->ctx;
 	struct fimd_win_data *win_data;
 	int i;
@@ -858,7 +853,6 @@ static void fimd_window_resume(struct device *dev)
 static int fimd_activate(struct exynos_drm_manager *mgr, bool enable)
 {
 	struct fimd_context *ctx = mgr->ctx;
-	struct device *dev = ctx->subdrv.dev;
 
 	if (enable) {
 		int ret;
@@ -873,11 +867,11 @@ static int fimd_activate(struct exynos_drm_manager *mgr, bool enable)
 		if (test_and_clear_bit(0, &ctx->irq_flags))
 			fimd_enable_vblank(mgr);
 
-		fimd_window_resume(dev);
+		fimd_window_resume(mgr);
 
 		fimd_apply(mgr);
 	} else {
-		fimd_window_suspend(dev);
+		fimd_window_suspend(mgr);
 
 		fimd_clock(ctx, false);
 		ctx->suspended = true;
@@ -914,7 +908,6 @@ static int fimd_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct fimd_context *ctx;
-	struct exynos_drm_subdrv *subdrv;
 	struct resource *res;
 	int win;
 	int ret = -EINVAL;
@@ -961,27 +954,22 @@ static int fimd_probe(struct platform_device *pdev)
 	DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
 	atomic_set(&ctx->wait_vsync_event, 0);
 
-	fimd_manager.ctx = ctx;
-
-	subdrv = &ctx->subdrv;
-
-	subdrv->dev = dev;
-	subdrv->manager = &fimd_manager;
-	subdrv->probe = fimd_subdrv_probe;
-	subdrv->remove = fimd_subdrv_remove;
-
 	mutex_init(&ctx->lock);
 
 	platform_set_drvdata(pdev, &fimd_manager);
 
+	fimd_manager.ctx = ctx;
+	exynos_drm_manager_register(&fimd_manager);
+
+	fimd_display.ctx = ctx;
+	exynos_drm_display_register(&fimd_display);
+
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
 
 	for (win = 0; win < WINDOWS_NR; win++)
 		fimd_clear_win(ctx, win);
 
-	exynos_drm_subdrv_register(subdrv);
-
 	return 0;
 }
 
@@ -991,7 +979,8 @@ static int fimd_remove(struct platform_device *pdev)
 	struct exynos_drm_manager *mgr = platform_get_drvdata(pdev);
 	struct fimd_context *ctx = mgr->ctx;
 
-	exynos_drm_subdrv_unregister(&ctx->subdrv);
+	exynos_drm_display_unregister(&fimd_display);
+	exynos_drm_manager_unregister(&fimd_manager);
 
 	if (ctx->suspended)
 		goto out;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index f9a9324..b0b09b2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -23,11 +23,6 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_hdmi.h"
 
-#define to_context(dev)		platform_get_drvdata(to_platform_device(dev))
-#define to_subdrv(dev)		to_context(dev)
-#define get_ctx_from_subdrv(subdrv)	container_of(subdrv,\
-					struct drm_hdmi_context, subdrv);
-
 /* platform device pointer for common drm hdmi device. */
 static struct platform_device *exynos_drm_hdmi_pdev;
 
@@ -41,7 +36,6 @@ static struct exynos_hdmi_ops *hdmi_ops;
 static struct exynos_mixer_ops *mixer_ops;
 
 struct drm_hdmi_context {
-	struct exynos_drm_subdrv	subdrv;
 	struct exynos_drm_hdmi_context	*hdmi_ctx;
 	struct exynos_drm_hdmi_context	*mixer_ctx;
 
@@ -97,10 +91,10 @@ void exynos_mixer_ops_register(struct exynos_mixer_ops *ops)
 		mixer_ops = ops;
 }
 
-static int drm_hdmi_display_initialize(struct device *dev,
+static int drm_hdmi_display_initialize(struct exynos_drm_display *display,
 		struct drm_device *drm_dev)
 {
-	struct drm_hdmi_context *ctx = to_context(dev);
+	struct drm_hdmi_context *ctx = display->ctx;
 
 	if (hdmi_ops && hdmi_ops->initialize)
 		return hdmi_ops->initialize(ctx->hdmi_ctx->ctx, drm_dev);
@@ -109,9 +103,9 @@ static int drm_hdmi_display_initialize(struct device *dev,
 }
 
 
-static bool drm_hdmi_is_connected(struct device *dev)
+static bool drm_hdmi_is_connected(struct exynos_drm_display *display)
 {
-	struct drm_hdmi_context *ctx = to_context(dev);
+	struct drm_hdmi_context *ctx = display->ctx;
 
 	if (hdmi_ops && hdmi_ops->is_connected)
 		return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx);
@@ -119,10 +113,10 @@ static bool drm_hdmi_is_connected(struct device *dev)
 	return false;
 }
 
-static struct edid *drm_hdmi_get_edid(struct device *dev,
+static struct edid *drm_hdmi_get_edid(struct exynos_drm_display *display,
 			struct drm_connector *connector)
 {
-	struct drm_hdmi_context *ctx = to_context(dev);
+	struct drm_hdmi_context *ctx = display->ctx;
 
 	if (hdmi_ops && hdmi_ops->get_edid)
 		return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
@@ -151,68 +145,28 @@ static int drm_hdmi_check_mode_ctx(struct drm_hdmi_context *ctx,
 	return 0;
 }
 
-static int drm_hdmi_check_mode(struct device *dev,
+static int drm_hdmi_check_mode(struct exynos_drm_display *display,
 		struct drm_display_mode *mode)
 {
-	struct drm_hdmi_context *ctx = to_context(dev);
+	struct drm_hdmi_context *ctx = display->ctx;
 
 	return drm_hdmi_check_mode_ctx(ctx, mode);
 }
 
-static int drm_hdmi_display_dpms(struct device *dev, int mode)
+static void drm_hdmi_display_dpms(struct exynos_drm_display *display, int mode)
 {
-	struct drm_hdmi_context *ctx = to_context(dev);
+	struct drm_hdmi_context *ctx = display->ctx;
 
 	if (hdmi_ops && hdmi_ops->dpms)
 		hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
-
-	return 0;
 }
 
-static struct exynos_drm_display_ops drm_hdmi_display_ops = {
-	.type = EXYNOS_DISPLAY_TYPE_HDMI,
-	.initialize = drm_hdmi_display_initialize,
-	.is_connected = drm_hdmi_is_connected,
-	.get_edid = drm_hdmi_get_edid,
-	.check_mode = drm_hdmi_check_mode,
-	.dpms = drm_hdmi_display_dpms,
-};
-
-static int drm_hdmi_enable_vblank(struct exynos_drm_manager *mgr)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-	struct exynos_drm_manager *manager = subdrv->manager;
-
-	if (mixer_ops && mixer_ops->enable_vblank)
-		return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx,
-						manager->pipe);
-
-	return 0;
-}
-
-static void drm_hdmi_disable_vblank(struct exynos_drm_manager *mgr)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-
-	if (mixer_ops && mixer_ops->disable_vblank)
-		return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
-}
-
-static void drm_hdmi_wait_for_vblank(struct exynos_drm_manager *mgr)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-
-	if (mixer_ops && mixer_ops->wait_for_vblank)
-		mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx);
-}
-
-static void drm_hdmi_mode_fixup(struct exynos_drm_manager *mgr,
+static void drm_hdmi_mode_fixup(struct exynos_drm_display *display,
 				struct drm_connector *connector,
 				const struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
 {
-	struct drm_hdmi_context *ctx = mgr->ctx;
+	struct drm_hdmi_context *ctx = display->ctx;
 	struct drm_display_mode *m;
 	int mode_ok;
 
@@ -252,23 +206,66 @@ static void drm_hdmi_mode_fixup(struct exynos_drm_manager *mgr,
 	}
 }
 
-static void drm_hdmi_mode_set(struct exynos_drm_manager *mgr, void *mode)
+static void drm_hdmi_mode_set(struct exynos_drm_display *display,
+			struct drm_display_mode *mode)
 {
-	struct drm_hdmi_context *ctx = mgr->ctx;
+	struct drm_hdmi_context *ctx = display->ctx;
 
 	if (hdmi_ops && hdmi_ops->mode_set)
 		hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
 }
 
-static void drm_hdmi_get_max_resol(struct exynos_drm_manager *mgr,
+static void drm_hdmi_get_max_resol(struct exynos_drm_display *display,
 				unsigned int *width, unsigned int *height)
 {
-	struct drm_hdmi_context *ctx = mgr->ctx;
+	struct drm_hdmi_context *ctx = display->ctx;
 
 	if (hdmi_ops && hdmi_ops->get_max_resol)
 		hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height);
 }
 
+static struct exynos_drm_display_ops drm_hdmi_display_ops = {
+	.initialize = drm_hdmi_display_initialize,
+	.is_connected = drm_hdmi_is_connected,
+	.get_edid = drm_hdmi_get_edid,
+	.check_mode = drm_hdmi_check_mode,
+	.dpms = drm_hdmi_display_dpms,
+	.mode_fixup = drm_hdmi_mode_fixup,
+	.mode_set = drm_hdmi_mode_set,
+	.get_max_resol = drm_hdmi_get_max_resol,
+};
+
+static struct exynos_drm_display hdmi_display = {
+	.type = EXYNOS_DISPLAY_TYPE_HDMI,
+	.ops = &drm_hdmi_display_ops,
+};
+
+static int drm_hdmi_enable_vblank(struct exynos_drm_manager *mgr)
+{
+	struct drm_hdmi_context *ctx = mgr->ctx;
+
+	if (mixer_ops && mixer_ops->enable_vblank)
+		return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx, mgr->pipe);
+
+	return 0;
+}
+
+static void drm_hdmi_disable_vblank(struct exynos_drm_manager *mgr)
+{
+	struct drm_hdmi_context *ctx = mgr->ctx;
+
+	if (mixer_ops && mixer_ops->disable_vblank)
+		return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
+}
+
+static void drm_hdmi_wait_for_vblank(struct exynos_drm_manager *mgr)
+{
+	struct drm_hdmi_context *ctx = mgr->ctx;
+
+	if (mixer_ops && mixer_ops->wait_for_vblank)
+		mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx);
+}
+
 static void drm_hdmi_commit(struct exynos_drm_manager *mgr)
 {
 	struct drm_hdmi_context *ctx = mgr->ctx;
@@ -277,11 +274,25 @@ static void drm_hdmi_commit(struct exynos_drm_manager *mgr)
 		hdmi_ops->commit(ctx->hdmi_ctx->ctx);
 }
 
-static int drm_hdmi_mgr_initialize(struct exynos_drm_manager *mgr, struct drm_device *drm_dev)
+static int drm_hdmi_mgr_initialize(struct exynos_drm_manager *mgr,
+			struct drm_device *drm_dev, int pipe)
 {
 	struct drm_hdmi_context *ctx = mgr->ctx;
 	int ret = 0;
 
+	if (!hdmi_ctx) {
+		DRM_ERROR("hdmi context not initialized.\n");
+		return -EFAULT;
+	}
+
+	if (!mixer_ctx) {
+		DRM_ERROR("mixer context not initialized.\n");
+		return -EFAULT;
+	}
+
+	ctx->hdmi_ctx = hdmi_ctx;
+	ctx->mixer_ctx = mixer_ctx;
+
 	if (mixer_ops && mixer_ops->initialize)
 		ret = mixer_ops->initialize(ctx->mixer_ctx->ctx, drm_dev);
 
@@ -291,6 +302,14 @@ static int drm_hdmi_mgr_initialize(struct exynos_drm_manager *mgr, struct drm_de
 	return ret;
 }
 
+static void drm_hdmi_mgr_remove(struct exynos_drm_manager *mgr)
+{
+	struct drm_hdmi_context *ctx = mgr->ctx;
+
+	if (mixer_ops->iommu_on)
+		mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false);
+}
+
 static void drm_hdmi_dpms(struct exynos_drm_manager *mgr, int mode)
 {
 	struct drm_hdmi_context *ctx = mgr->ctx;
@@ -345,13 +364,11 @@ static void drm_mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
 
 static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
 	.initialize = drm_hdmi_mgr_initialize,
+	.remove = drm_hdmi_mgr_remove,
 	.dpms = drm_hdmi_dpms,
 	.enable_vblank = drm_hdmi_enable_vblank,
 	.disable_vblank = drm_hdmi_disable_vblank,
 	.wait_for_vblank = drm_hdmi_wait_for_vblank,
-	.mode_fixup = drm_hdmi_mode_fixup,
-	.mode_set = drm_hdmi_mode_set,
-	.get_max_resol = drm_hdmi_get_max_resol,
 	.commit = drm_hdmi_commit,
 	.win_mode_set = drm_mixer_win_mode_set,
 	.win_commit = drm_mixer_win_commit,
@@ -359,55 +376,13 @@ static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
 };
 
 static struct exynos_drm_manager hdmi_manager = {
-	.pipe		= -1,
+	.type		= EXYNOS_DISPLAY_TYPE_HDMI,
 	.ops		= &drm_hdmi_manager_ops,
-	.display_ops	= &drm_hdmi_display_ops,
 };
 
-static int hdmi_subdrv_probe(struct drm_device *drm_dev,
-		struct device *dev)
-{
-	struct exynos_drm_subdrv *subdrv = to_subdrv(dev);
-	struct drm_hdmi_context *ctx;
-
-	if (!hdmi_ctx) {
-		DRM_ERROR("hdmi context not initialized.\n");
-		return -EFAULT;
-	}
-
-	if (!mixer_ctx) {
-		DRM_ERROR("mixer context not initialized.\n");
-		return -EFAULT;
-	}
-
-	ctx = get_ctx_from_subdrv(subdrv);
-
-	if (!ctx) {
-		DRM_ERROR("no drm hdmi context.\n");
-		return -EFAULT;
-	}
-
-	ctx->hdmi_ctx = hdmi_ctx;
-	ctx->mixer_ctx = mixer_ctx;
-
-	return 0;
-}
-
-static void hdmi_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
-{
-	struct drm_hdmi_context *ctx;
-	struct exynos_drm_subdrv *subdrv = to_subdrv(dev);
-
-	ctx = get_ctx_from_subdrv(subdrv);
-
-	if (mixer_ops->iommu_on)
-		mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false);
-}
-
 static int exynos_drm_hdmi_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct exynos_drm_subdrv *subdrv;
 	struct drm_hdmi_context *ctx;
 
 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
@@ -415,26 +390,18 @@ static int exynos_drm_hdmi_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	hdmi_manager.ctx = ctx;
+	hdmi_display.ctx = ctx;
 
-	subdrv = &ctx->subdrv;
-
-	subdrv->dev = dev;
-	subdrv->manager = &hdmi_manager;
-	subdrv->probe = hdmi_subdrv_probe;
-	subdrv->remove = hdmi_subdrv_remove;
-
-	platform_set_drvdata(pdev, subdrv);
-
-	exynos_drm_subdrv_register(subdrv);
+	exynos_drm_manager_register(&hdmi_manager);
+	exynos_drm_display_register(&hdmi_display);
 
 	return 0;
 }
 
 static int exynos_drm_hdmi_remove(struct platform_device *pdev)
 {
-	struct drm_hdmi_context *ctx = platform_get_drvdata(pdev);
-
-	exynos_drm_subdrv_unregister(&ctx->subdrv);
+	exynos_drm_display_unregister(&hdmi_display);
+	exynos_drm_manager_unregister(&hdmi_manager);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
index 923239b..37059ea 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
@@ -19,10 +19,12 @@
  * exynos hdmi common context structure.
  *
  * @drm_dev: pointer to drm_device.
+ * @pipe: pipe for mixer
  * @ctx: pointer to the context of specific device driver.
  *	this context should be hdmi_context or mixer_context.
  */
 struct exynos_drm_hdmi_context {
+	int			pipe;
 	void			*ctx;
 };
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index cff3aed..e0db2b3 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -13,7 +13,7 @@
 
 #include <drm/exynos_drm.h>
 #include "exynos_drm_drv.h"
-#include "exynos_drm_encoder.h"
+#include "exynos_drm_crtc.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_gem.h"
 #include "exynos_drm_plane.h"
@@ -139,7 +139,7 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
 			overlay->crtc_x, overlay->crtc_y,
 			overlay->crtc_width, overlay->crtc_height);
 
-	exynos_drm_fn_encoder(crtc, overlay, exynos_drm_encoder_plane_mode_set);
+	exynos_drm_crtc_plane_mode_set(crtc, overlay);
 
 	return 0;
 }
@@ -149,8 +149,7 @@ void exynos_plane_commit(struct drm_plane *plane)
 	struct exynos_plane *exynos_plane = to_exynos_plane(plane);
 	struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
 
-	exynos_drm_fn_encoder(plane->crtc, &overlay->zpos,
-			exynos_drm_encoder_plane_commit);
+	exynos_drm_crtc_plane_commit(plane->crtc, overlay->zpos);
 }
 
 void exynos_plane_dpms(struct drm_plane *plane, int mode)
@@ -162,17 +161,13 @@ void exynos_plane_dpms(struct drm_plane *plane, int mode)
 		if (exynos_plane->enabled)
 			return;
 
-		exynos_drm_fn_encoder(plane->crtc, &overlay->zpos,
-				exynos_drm_encoder_plane_enable);
-
+		exynos_drm_crtc_plane_enable(plane->crtc, overlay->zpos);
 		exynos_plane->enabled = true;
 	} else {
 		if (!exynos_plane->enabled)
 			return;
 
-		exynos_drm_fn_encoder(plane->crtc, &overlay->zpos,
-				exynos_drm_encoder_plane_disable);
-
+		exynos_drm_crtc_plane_disable(plane->crtc, overlay->zpos);
 		exynos_plane->enabled = false;
 	}
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index ce0e2ea..90dacaf 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -45,7 +45,7 @@ struct vidi_win_data {
 };
 
 struct vidi_context {
-	struct exynos_drm_subdrv	subdrv;
+	struct drm_device		*drm_dev;
 	struct drm_crtc			*crtc;
 	struct vidi_win_data		win_data[WINDOWS_NR];
 	struct edid			*raw_edid;
@@ -58,6 +58,7 @@ struct vidi_context {
 	bool				direct_vblank;
 	struct work_struct		work;
 	struct mutex			lock;
+	int				pipe;
 };
 
 static const char fake_edid_info[] = {
@@ -85,10 +86,9 @@ static const char fake_edid_info[] = {
 	0x00, 0x00, 0x00, 0x06
 };
 
-static bool vidi_display_is_connected(struct device *dev)
+static bool vidi_display_is_connected(struct exynos_drm_display *display)
 {
-	struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
-	struct vidi_context *ctx = mgr->ctx;
+	struct vidi_context *ctx = display->ctx;
 
 	/*
 	 * connection request would come from user side
@@ -97,11 +97,10 @@ static bool vidi_display_is_connected(struct device *dev)
 	return ctx->connected ? true : false;
 }
 
-static struct edid *vidi_get_edid(struct device *dev,
+static struct edid *vidi_get_edid(struct exynos_drm_display *display,
 			struct drm_connector *connector)
 {
-	struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
-	struct vidi_context *ctx = mgr->ctx;
+	struct vidi_context *ctx = display->ctx;
 	struct edid *edid;
 	int edid_len;
 
@@ -124,14 +123,8 @@ static struct edid *vidi_get_edid(struct device *dev,
 	return edid;
 }
 
-static void *vidi_get_panel(struct device *dev)
-{
-	/* TODO. */
-
-	return NULL;
-}
-
-static int vidi_check_mode(struct device *dev, struct drm_display_mode *mode)
+static int vidi_check_mode(struct exynos_drm_display *display,
+			struct drm_display_mode *mode)
 {
 	/* TODO. */
 
@@ -139,13 +132,16 @@ static int vidi_check_mode(struct device *dev, struct drm_display_mode *mode)
 }
 
 static struct exynos_drm_display_ops vidi_display_ops = {
-	.type = EXYNOS_DISPLAY_TYPE_VIDI,
 	.is_connected = vidi_display_is_connected,
 	.get_edid = vidi_get_edid,
-	.get_panel = vidi_get_panel,
 	.check_mode = vidi_check_mode,
 };
 
+static struct exynos_drm_display vidi_display = {
+	.type = EXYNOS_DISPLAY_TYPE_VIDI,
+	.ops = &vidi_display_ops,
+};
+
 static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
 {
 	struct vidi_context *ctx = mgr->ctx;
@@ -325,7 +321,38 @@ static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
 	/* TODO. */
 }
 
+static int vidi_mgr_initialize(struct exynos_drm_manager *mgr,
+			struct drm_device *drm_dev, int pipe)
+{
+	struct vidi_context *ctx = mgr->ctx;
+
+	DRM_ERROR("vidi initialize ct=%p dev=%p pipe=%d\n", ctx, drm_dev, pipe);
+
+	ctx->drm_dev = drm_dev;
+	ctx->pipe = pipe;
+
+	/*
+	 * enable drm irq mode.
+	 * - with irq_enabled = 1, we can use the vblank feature.
+	 *
+	 * P.S. note that we wouldn't use drm irq handler but
+	 *	just specific driver own one instead because
+	 *	drm framework supports only one irq handler.
+	 */
+	drm_dev->irq_enabled = 1;
+
+	/*
+	 * with vblank_disable_allowed = 1, vblank interrupt will be disabled
+	 * by drm timer once a current process gives up ownership of
+	 * vblank event.(after drm_vblank_put function is called)
+	 */
+	drm_dev->vblank_disable_allowed = 1;
+
+	return 0;
+}
+
 static struct exynos_drm_manager_ops vidi_manager_ops = {
+	.initialize = vidi_mgr_initialize,
 	.dpms = vidi_dpms,
 	.commit = vidi_commit,
 	.enable_vblank = vidi_enable_vblank,
@@ -336,19 +363,16 @@ static struct exynos_drm_manager_ops vidi_manager_ops = {
 };
 
 static struct exynos_drm_manager vidi_manager = {
-	.pipe		= -1,
-	.ops		= &vidi_manager_ops,
-	.display_ops	= &vidi_display_ops,
+	.type = EXYNOS_DISPLAY_TYPE_VIDI,
+	.ops = &vidi_manager_ops,
 };
 
 static void vidi_fake_vblank_handler(struct work_struct *work)
 {
 	struct vidi_context *ctx = container_of(work, struct vidi_context,
 					work);
-	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-	struct exynos_drm_manager *manager = subdrv->manager;
 
-	if (manager->pipe < 0)
+	if (ctx->pipe < 0)
 		return;
 
 	/* refresh rate is about 50Hz. */
@@ -357,7 +381,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
 	mutex_lock(&ctx->lock);
 
 	if (ctx->direct_vblank) {
-		drm_handle_vblank(subdrv->drm_dev, manager->pipe);
+		drm_handle_vblank(ctx->drm_dev, ctx->pipe);
 		ctx->direct_vblank = false;
 		mutex_unlock(&ctx->lock);
 		return;
@@ -365,34 +389,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
 
 	mutex_unlock(&ctx->lock);
 
-	exynos_drm_crtc_finish_pageflip(subdrv->drm_dev, manager->pipe);
-}
-
-static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
-{
-	/*
-	 * enable drm irq mode.
-	 * - with irq_enabled = 1, we can use the vblank feature.
-	 *
-	 * P.S. note that we wouldn't use drm irq handler but
-	 *	just specific driver own one instead because
-	 *	drm framework supports only one irq handler.
-	 */
-	drm_dev->irq_enabled = 1;
-
-	/*
-	 * with vblank_disable_allowed = 1, vblank interrupt will be disabled
-	 * by drm timer once a current process gives up ownership of
-	 * vblank event.(after drm_vblank_put function is called)
-	 */
-	drm_dev->vblank_disable_allowed = 1;
-
-	return 0;
-}
-
-static void vidi_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
-{
-	/* TODO. */
+	exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
 }
 
 static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
@@ -462,7 +459,7 @@ static int vidi_store_connection(struct device *dev,
 
 	DRM_DEBUG_KMS("requested connection.\n");
 
-	drm_helper_hpd_irq_event(ctx->subdrv.drm_dev);
+	drm_helper_hpd_irq_event(ctx->drm_dev);
 
 	return len;
 }
@@ -475,8 +472,7 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
 {
 	struct vidi_context *ctx = NULL;
 	struct drm_encoder *encoder;
-	struct exynos_drm_manager *manager;
-	struct exynos_drm_display_ops *display_ops;
+	struct exynos_drm_display *display;
 	struct drm_exynos_vidi_connection *vidi = data;
 	int edid_len;
 
@@ -492,11 +488,10 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
 
 	list_for_each_entry(encoder, &drm_dev->mode_config.encoder_list,
 								head) {
-		manager = exynos_drm_get_manager(encoder);
-		display_ops = manager->display_ops;
+		display = exynos_drm_get_display(encoder);
 
-		if (display_ops->type == EXYNOS_DISPLAY_TYPE_VIDI) {
-			ctx = manager->ctx;
+		if (display->type == EXYNOS_DISPLAY_TYPE_VIDI) {
+			ctx = display->ctx;
 			break;
 		}
 	}
@@ -536,7 +531,7 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
 	}
 
 	ctx->connected = vidi->connection;
-	drm_helper_hpd_irq_event(ctx->subdrv.drm_dev);
+	drm_helper_hpd_irq_event(ctx->drm_dev);
 
 	return 0;
 }
@@ -545,7 +540,6 @@ static int vidi_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct vidi_context *ctx;
-	struct exynos_drm_subdrv *subdrv;
 	int ret;
 
 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
@@ -557,12 +551,7 @@ static int vidi_probe(struct platform_device *pdev)
 	INIT_WORK(&ctx->work, vidi_fake_vblank_handler);
 
 	vidi_manager.ctx = ctx;
-
-	subdrv = &ctx->subdrv;
-	subdrv->dev = dev;
-	subdrv->manager = &vidi_manager;
-	subdrv->probe = vidi_subdrv_probe;
-	subdrv->remove = vidi_subdrv_remove;
+	vidi_display.ctx = ctx;
 
 	mutex_init(&ctx->lock);
 
@@ -572,7 +561,8 @@ static int vidi_probe(struct platform_device *pdev)
 	if (ret < 0)
 		DRM_INFO("failed to create connection sysfs.\n");
 
-	exynos_drm_subdrv_register(subdrv);
+	exynos_drm_manager_register(&vidi_manager);
+	exynos_drm_display_register(&vidi_display);
 
 	return 0;
 }
@@ -581,7 +571,8 @@ static int vidi_remove(struct platform_device *pdev)
 {
 	struct vidi_context *ctx = platform_get_drvdata(pdev);
 
-	exynos_drm_subdrv_unregister(&ctx->subdrv);
+	exynos_drm_display_unregister(&vidi_display);
+	exynos_drm_manager_unregister(&vidi_manager);
 
 	if (ctx->raw_edid != (struct edid *)fake_edid_info) {
 		kfree(ctx->raw_edid);
-- 
1.8.4

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

* [PATCH v3 13/32] drm/exynos: hdmi: remove the i2c drivers and use devtree
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (11 preceding siblings ...)
  2013-10-29 16:12 ` [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv Sean Paul
@ 2013-10-29 16:12 ` Sean Paul
  2013-11-10 20:46   ` Tomasz Figa
  2013-10-29 16:13 ` [PATCH v3 14/32] drm/exynos: Remove exynos_drm_hdmi shim Sean Paul
                   ` (19 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:12 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

From: Daniel Kurtz <djkurtz@chromium.org>

The i2c client was previously being passed into the hdmi driver via a
dedicated i2c driver, and then a global variable. This patch removes all
of that and just uses the device tree to get the i2c_client. This patch
also properly references the client so we don't lose it before we're
done with it.

Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2:
	- Change include to linux/i2c.h instead of linux/of_i2c.h
Changes in v3: None

 drivers/gpu/drm/exynos/Makefile         |  1 -
 drivers/gpu/drm/exynos/exynos_ddc.c     | 63 --------------------------------
 drivers/gpu/drm/exynos/exynos_hdmi.c    | 59 ++++++++++++++----------------
 drivers/gpu/drm/exynos/exynos_hdmi.h    | 23 ------------
 drivers/gpu/drm/exynos/exynos_hdmiphy.c | 65 ---------------------------------
 5 files changed, 27 insertions(+), 184 deletions(-)
 delete mode 100644 drivers/gpu/drm/exynos/exynos_ddc.c
 delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmi.h
 delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy.c

diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index 639b49e..819961a 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -12,7 +12,6 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)	+= exynos_drm_fimd.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)	+= exynos_hdmi.o exynos_mixer.o \
-					   exynos_ddc.o exynos_hdmiphy.o \
 					   exynos_drm_hdmi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)	+= exynos_drm_vidi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_G2D)	+= exynos_drm_g2d.o
diff --git a/drivers/gpu/drm/exynos/exynos_ddc.c b/drivers/gpu/drm/exynos/exynos_ddc.c
deleted file mode 100644
index 6a8c84e..0000000
--- a/drivers/gpu/drm/exynos/exynos_ddc.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors:
- *	Seung-Woo Kim <sw0312.kim@samsung.com>
- *	Inki Dae <inki.dae@samsung.com>
- *
- * 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 <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/of.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_hdmi.h"
-
-static int s5p_ddc_probe(struct i2c_client *client,
-			const struct i2c_device_id *dev_id)
-{
-	hdmi_attach_ddc_client(client);
-
-	dev_info(&client->adapter->dev,
-		"attached %s into i2c adapter successfully\n",
-		client->name);
-
-	return 0;
-}
-
-static int s5p_ddc_remove(struct i2c_client *client)
-{
-	dev_info(&client->adapter->dev,
-		"detached %s from i2c adapter successfully\n",
-		client->name);
-
-	return 0;
-}
-
-static struct of_device_id hdmiddc_match_types[] = {
-	{
-		.compatible = "samsung,exynos5-hdmiddc",
-	}, {
-		.compatible = "samsung,exynos4210-hdmiddc",
-	}, {
-		/* end node */
-	}
-};
-
-struct i2c_driver ddc_driver = {
-	.driver = {
-		.name = "exynos-hdmiddc",
-		.owner = THIS_MODULE,
-		.of_match_table = hdmiddc_match_types,
-	},
-	.probe		= s5p_ddc_probe,
-	.remove		= s5p_ddc_remove,
-	.command		= NULL,
-};
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index d35ab2a..e106309 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -33,6 +33,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/i2c.h>
 #include <linux/of_gpio.h>
 
 #include <drm/exynos_drm.h>
@@ -40,8 +41,6 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_hdmi.h"
 
-#include "exynos_hdmi.h"
-
 #include <linux/gpio.h>
 #include <media/s5p_hdmi.h>
 
@@ -1849,20 +1848,6 @@ fail:
 	return -ENODEV;
 }
 
-static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
-
-void hdmi_attach_ddc_client(struct i2c_client *ddc)
-{
-	if (ddc)
-		hdmi_ddc = ddc;
-}
-
-void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
-{
-	if (hdmiphy)
-		hdmi_hdmiphy = hdmiphy;
-}
-
 static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
 					(struct device *dev)
 {
@@ -1907,6 +1892,7 @@ static int hdmi_probe(struct platform_device *pdev)
 	struct s5p_hdmi_platform_data *pdata;
 	struct resource *res;
 	const struct of_device_id *match;
+	struct device_node *ddc_node, *phy_node;
 	int ret;
 
 	 if (!dev->of_node)
@@ -1957,21 +1943,30 @@ static int hdmi_probe(struct platform_device *pdev)
 	}
 
 	/* DDC i2c driver */
-	if (i2c_add_driver(&ddc_driver)) {
-		DRM_ERROR("failed to register ddc i2c driver\n");
-		return -ENOENT;
+	ddc_node = of_find_node_by_name(NULL, "hdmiddc");
+	if (!ddc_node) {
+		DRM_ERROR("Failed to find ddc node in device tree\n");
+		return -ENODEV;
+	}
+	hdata->ddc_port = of_find_i2c_device_by_node(ddc_node);
+	if (!hdata->ddc_port) {
+		DRM_ERROR("Failed to get ddc i2c client by node\n");
+		return -ENODEV;
 	}
-
-	hdata->ddc_port = hdmi_ddc;
 
 	/* hdmiphy i2c driver */
-	if (i2c_add_driver(&hdmiphy_driver)) {
-		DRM_ERROR("failed to register hdmiphy i2c driver\n");
-		ret = -ENOENT;
+	phy_node = of_find_node_by_name(NULL, "hdmiphy");
+	if (!phy_node) {
+		DRM_ERROR("Failed to find hdmiphy node in device tree\n");
+		ret = -ENODEV;
+		goto err_ddc;
+	}
+	hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
+	if (!hdata->hdmiphy_port) {
+		DRM_ERROR("Failed to get hdmi phy i2c client from node\n");
+		ret = -ENODEV;
 		goto err_ddc;
 	}
-
-	hdata->hdmiphy_port = hdmi_hdmiphy;
 
 	hdata->irq = gpio_to_irq(hdata->hpd_gpio);
 	if (hdata->irq < 0) {
@@ -2002,22 +1997,22 @@ static int hdmi_probe(struct platform_device *pdev)
 	return 0;
 
 err_hdmiphy:
-	i2c_del_driver(&hdmiphy_driver);
+	put_device(&hdata->hdmiphy_port->dev);
 err_ddc:
-	i2c_del_driver(&ddc_driver);
+	put_device(&hdata->ddc_port->dev);
 	return ret;
 }
 
 static int hdmi_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
+	struct hdmi_context *hdata = ctx->ctx;
 
 	pm_runtime_disable(dev);
 
-	/* hdmiphy i2c driver */
-	i2c_del_driver(&hdmiphy_driver);
-	/* DDC i2c driver */
-	i2c_del_driver(&ddc_driver);
+	put_device(&hdata->hdmiphy_port->dev);
+	put_device(&hdata->ddc_port->dev);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.h b/drivers/gpu/drm/exynos/exynos_hdmi.h
deleted file mode 100644
index 0ddf395..0000000
--- a/drivers/gpu/drm/exynos/exynos_hdmi.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- *	Inki Dae <inki.dae@samsung.com>
- *	Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * 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 _EXYNOS_HDMI_H_
-#define _EXYNOS_HDMI_H_
-
-void hdmi_attach_ddc_client(struct i2c_client *ddc);
-void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy);
-
-extern struct i2c_driver hdmiphy_driver;
-extern struct i2c_driver ddc_driver;
-
-#endif
diff --git a/drivers/gpu/drm/exynos/exynos_hdmiphy.c b/drivers/gpu/drm/exynos/exynos_hdmiphy.c
deleted file mode 100644
index 59abb14..0000000
--- a/drivers/gpu/drm/exynos/exynos_hdmiphy.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors:
- *	Seung-Woo Kim <sw0312.kim@samsung.com>
- *	Inki Dae <inki.dae@samsung.com>
- *
- * 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 <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/of.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_hdmi.h"
-
-
-static int hdmiphy_probe(struct i2c_client *client,
-	const struct i2c_device_id *id)
-{
-	hdmi_attach_hdmiphy_client(client);
-
-	dev_info(&client->adapter->dev, "attached s5p_hdmiphy "
-		"into i2c adapter successfully\n");
-
-	return 0;
-}
-
-static int hdmiphy_remove(struct i2c_client *client)
-{
-	dev_info(&client->adapter->dev, "detached s5p_hdmiphy "
-		"from i2c adapter successfully\n");
-
-	return 0;
-}
-
-static struct of_device_id hdmiphy_match_types[] = {
-	{
-		.compatible = "samsung,exynos5-hdmiphy",
-	}, {
-		.compatible = "samsung,exynos4210-hdmiphy",
-	}, {
-		.compatible = "samsung,exynos4212-hdmiphy",
-	}, {
-		/* end node */
-	}
-};
-
-struct i2c_driver hdmiphy_driver = {
-	.driver = {
-		.name	= "exynos-hdmiphy",
-		.owner	= THIS_MODULE,
-		.of_match_table = hdmiphy_match_types,
-	},
-	.probe		= hdmiphy_probe,
-	.remove		= hdmiphy_remove,
-	.command		= NULL,
-};
-EXPORT_SYMBOL(hdmiphy_driver);
-- 
1.8.4

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

* [PATCH v3 14/32] drm/exynos: Remove exynos_drm_hdmi shim
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (12 preceding siblings ...)
  2013-10-29 16:12 ` [PATCH v3 13/32] drm/exynos: hdmi: remove the i2c drivers and use devtree Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-10 21:24   ` Tomasz Figa
  2013-10-29 16:13 ` [PATCH v3 15/32] drm/exynos: Use drm_mode_copy to copy modes Sean Paul
                   ` (18 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch trims exynos_drm_hdmi out of the driver. The reason it
existed in the first place was to make up for the mixture of
display/overlay/manager ops being spread across hdmi and mixer. With
that code now rationalized, mixer and hdmi map directly to
exynos_drm_crtc and exynos_drm_encoder, respectively. Since there is a
1:1 mapping, we no longer need this layer.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2:
	- hdmi/mixer ops now take display/manager instead of context
Changes in v3:
	- Moved removal of exynos_drm_hdmi.c file here

 drivers/gpu/drm/exynos/Makefile          |   3 +-
 drivers/gpu/drm/exynos/exynos_drm_drv.c  |  13 -
 drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 416 -------------------------------
 drivers/gpu/drm/exynos/exynos_drm_hdmi.h |  69 -----
 drivers/gpu/drm/exynos/exynos_hdmi.c     | 162 +++++++-----
 drivers/gpu/drm/exynos/exynos_mixer.c    | 204 ++++++++-------
 drivers/gpu/drm/exynos/exynos_mixer.h    |  20 ++
 7 files changed, 222 insertions(+), 665 deletions(-)
 delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.c
 delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.h
 create mode 100644 drivers/gpu/drm/exynos/exynos_mixer.h

diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index 819961a..afbe499 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -11,8 +11,7 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
 exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)	+= exynos_drm_fimd.o
-exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)	+= exynos_hdmi.o exynos_mixer.o \
-					   exynos_drm_hdmi.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)	+= exynos_hdmi.o exynos_mixer.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)	+= exynos_drm_vidi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_G2D)	+= exynos_drm_g2d.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_IPP)	+= exynos_drm_ipp.o
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 250903c..4b265bf 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -329,13 +329,6 @@ static int __init exynos_drm_init(void)
 	ret = platform_driver_register(&mixer_driver);
 	if (ret < 0)
 		goto out_mixer;
-	ret = platform_driver_register(&exynos_drm_common_hdmi_driver);
-	if (ret < 0)
-		goto out_common_hdmi;
-
-	ret = exynos_platform_device_hdmi_register();
-	if (ret < 0)
-		goto out_common_hdmi_dev;
 #endif
 
 #ifdef CONFIG_DRM_EXYNOS_VIDI
@@ -428,10 +421,6 @@ out_vidi:
 #endif
 
 #ifdef CONFIG_DRM_EXYNOS_HDMI
-	exynos_platform_device_hdmi_unregister();
-out_common_hdmi_dev:
-	platform_driver_unregister(&exynos_drm_common_hdmi_driver);
-out_common_hdmi:
 	platform_driver_unregister(&mixer_driver);
 out_mixer:
 	platform_driver_unregister(&hdmi_driver);
@@ -473,8 +462,6 @@ static void __exit exynos_drm_exit(void)
 #endif
 
 #ifdef CONFIG_DRM_EXYNOS_HDMI
-	exynos_platform_device_hdmi_unregister();
-	platform_driver_unregister(&exynos_drm_common_hdmi_driver);
 	platform_driver_unregister(&mixer_driver);
 	platform_driver_unregister(&hdmi_driver);
 #endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
deleted file mode 100644
index b0b09b2..0000000
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Authors:
- *	Inki Dae <inki.dae@samsung.com>
- *	Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * 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 <linux/kernel.h>
-#include <linux/wait.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-
-#include <drm/exynos_drm.h>
-
-#include "exynos_drm_drv.h"
-#include "exynos_drm_hdmi.h"
-
-/* platform device pointer for common drm hdmi device. */
-static struct platform_device *exynos_drm_hdmi_pdev;
-
-/* Common hdmi subdrv needs to access the hdmi and mixer though context.
-* These should be initialied by the repective drivers */
-static struct exynos_drm_hdmi_context *hdmi_ctx;
-static struct exynos_drm_hdmi_context *mixer_ctx;
-
-/* these callback points shoud be set by specific drivers. */
-static struct exynos_hdmi_ops *hdmi_ops;
-static struct exynos_mixer_ops *mixer_ops;
-
-struct drm_hdmi_context {
-	struct exynos_drm_hdmi_context	*hdmi_ctx;
-	struct exynos_drm_hdmi_context	*mixer_ctx;
-
-	bool	enabled[MIXER_WIN_NR];
-};
-
-int exynos_platform_device_hdmi_register(void)
-{
-	struct platform_device *pdev;
-
-	if (exynos_drm_hdmi_pdev)
-		return -EEXIST;
-
-	pdev = platform_device_register_simple(
-			"exynos-drm-hdmi", -1, NULL, 0);
-	if (IS_ERR(pdev))
-		return PTR_ERR(pdev);
-
-	exynos_drm_hdmi_pdev = pdev;
-
-	return 0;
-}
-
-void exynos_platform_device_hdmi_unregister(void)
-{
-	if (exynos_drm_hdmi_pdev) {
-		platform_device_unregister(exynos_drm_hdmi_pdev);
-		exynos_drm_hdmi_pdev = NULL;
-	}
-}
-
-void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx)
-{
-	if (ctx)
-		hdmi_ctx = ctx;
-}
-
-void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx)
-{
-	if (ctx)
-		mixer_ctx = ctx;
-}
-
-void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)
-{
-	if (ops)
-		hdmi_ops = ops;
-}
-
-void exynos_mixer_ops_register(struct exynos_mixer_ops *ops)
-{
-	if (ops)
-		mixer_ops = ops;
-}
-
-static int drm_hdmi_display_initialize(struct exynos_drm_display *display,
-		struct drm_device *drm_dev)
-{
-	struct drm_hdmi_context *ctx = display->ctx;
-
-	if (hdmi_ops && hdmi_ops->initialize)
-		return hdmi_ops->initialize(ctx->hdmi_ctx->ctx, drm_dev);
-
-	return 0;
-}
-
-
-static bool drm_hdmi_is_connected(struct exynos_drm_display *display)
-{
-	struct drm_hdmi_context *ctx = display->ctx;
-
-	if (hdmi_ops && hdmi_ops->is_connected)
-		return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx);
-
-	return false;
-}
-
-static struct edid *drm_hdmi_get_edid(struct exynos_drm_display *display,
-			struct drm_connector *connector)
-{
-	struct drm_hdmi_context *ctx = display->ctx;
-
-	if (hdmi_ops && hdmi_ops->get_edid)
-		return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
-
-	return NULL;
-}
-static int drm_hdmi_check_mode_ctx(struct drm_hdmi_context *ctx,
-		struct drm_display_mode *mode)
-{
-	int ret = 0;
-
-	/*
-	* Both, mixer and hdmi should be able to handle the requested mode.
-	* If any of the two fails, return mode as BAD.
-	*/
-
-	if (mixer_ops && mixer_ops->check_mode)
-		ret = mixer_ops->check_mode(ctx->mixer_ctx->ctx, mode);
-
-	if (ret)
-		return ret;
-
-	if (hdmi_ops && hdmi_ops->check_mode)
-		return hdmi_ops->check_mode(ctx->hdmi_ctx->ctx, mode);
-
-	return 0;
-}
-
-static int drm_hdmi_check_mode(struct exynos_drm_display *display,
-		struct drm_display_mode *mode)
-{
-	struct drm_hdmi_context *ctx = display->ctx;
-
-	return drm_hdmi_check_mode_ctx(ctx, mode);
-}
-
-static void drm_hdmi_display_dpms(struct exynos_drm_display *display, int mode)
-{
-	struct drm_hdmi_context *ctx = display->ctx;
-
-	if (hdmi_ops && hdmi_ops->dpms)
-		hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
-}
-
-static void drm_hdmi_mode_fixup(struct exynos_drm_display *display,
-				struct drm_connector *connector,
-				const struct drm_display_mode *mode,
-				struct drm_display_mode *adjusted_mode)
-{
-	struct drm_hdmi_context *ctx = display->ctx;
-	struct drm_display_mode *m;
-	int mode_ok;
-
-	drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-	mode_ok = drm_hdmi_check_mode_ctx(ctx, adjusted_mode);
-
-	/* just return if user desired mode exists. */
-	if (mode_ok == 0)
-		return;
-
-	/*
-	 * otherwise, find the most suitable mode among modes and change it
-	 * to adjusted_mode.
-	 */
-	list_for_each_entry(m, &connector->modes, head) {
-		mode_ok = drm_hdmi_check_mode_ctx(ctx, m);
-
-		if (mode_ok == 0) {
-			struct drm_mode_object base;
-			struct list_head head;
-
-			DRM_INFO("desired mode doesn't exist so\n");
-			DRM_INFO("use the most suitable mode among modes.\n");
-
-			DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
-				m->hdisplay, m->vdisplay, m->vrefresh);
-
-			/* preserve display mode header while copying. */
-			head = adjusted_mode->head;
-			base = adjusted_mode->base;
-			memcpy(adjusted_mode, m, sizeof(*m));
-			adjusted_mode->head = head;
-			adjusted_mode->base = base;
-			break;
-		}
-	}
-}
-
-static void drm_hdmi_mode_set(struct exynos_drm_display *display,
-			struct drm_display_mode *mode)
-{
-	struct drm_hdmi_context *ctx = display->ctx;
-
-	if (hdmi_ops && hdmi_ops->mode_set)
-		hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
-}
-
-static void drm_hdmi_get_max_resol(struct exynos_drm_display *display,
-				unsigned int *width, unsigned int *height)
-{
-	struct drm_hdmi_context *ctx = display->ctx;
-
-	if (hdmi_ops && hdmi_ops->get_max_resol)
-		hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height);
-}
-
-static struct exynos_drm_display_ops drm_hdmi_display_ops = {
-	.initialize = drm_hdmi_display_initialize,
-	.is_connected = drm_hdmi_is_connected,
-	.get_edid = drm_hdmi_get_edid,
-	.check_mode = drm_hdmi_check_mode,
-	.dpms = drm_hdmi_display_dpms,
-	.mode_fixup = drm_hdmi_mode_fixup,
-	.mode_set = drm_hdmi_mode_set,
-	.get_max_resol = drm_hdmi_get_max_resol,
-};
-
-static struct exynos_drm_display hdmi_display = {
-	.type = EXYNOS_DISPLAY_TYPE_HDMI,
-	.ops = &drm_hdmi_display_ops,
-};
-
-static int drm_hdmi_enable_vblank(struct exynos_drm_manager *mgr)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-
-	if (mixer_ops && mixer_ops->enable_vblank)
-		return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx, mgr->pipe);
-
-	return 0;
-}
-
-static void drm_hdmi_disable_vblank(struct exynos_drm_manager *mgr)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-
-	if (mixer_ops && mixer_ops->disable_vblank)
-		return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
-}
-
-static void drm_hdmi_wait_for_vblank(struct exynos_drm_manager *mgr)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-
-	if (mixer_ops && mixer_ops->wait_for_vblank)
-		mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx);
-}
-
-static void drm_hdmi_commit(struct exynos_drm_manager *mgr)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-
-	if (hdmi_ops && hdmi_ops->commit)
-		hdmi_ops->commit(ctx->hdmi_ctx->ctx);
-}
-
-static int drm_hdmi_mgr_initialize(struct exynos_drm_manager *mgr,
-			struct drm_device *drm_dev, int pipe)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-	int ret = 0;
-
-	if (!hdmi_ctx) {
-		DRM_ERROR("hdmi context not initialized.\n");
-		return -EFAULT;
-	}
-
-	if (!mixer_ctx) {
-		DRM_ERROR("mixer context not initialized.\n");
-		return -EFAULT;
-	}
-
-	ctx->hdmi_ctx = hdmi_ctx;
-	ctx->mixer_ctx = mixer_ctx;
-
-	if (mixer_ops && mixer_ops->initialize)
-		ret = mixer_ops->initialize(ctx->mixer_ctx->ctx, drm_dev);
-
-	if (mixer_ops->iommu_on)
-		mixer_ops->iommu_on(ctx->mixer_ctx->ctx, true);
-
-	return ret;
-}
-
-static void drm_hdmi_mgr_remove(struct exynos_drm_manager *mgr)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-
-	if (mixer_ops->iommu_on)
-		mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false);
-}
-
-static void drm_hdmi_dpms(struct exynos_drm_manager *mgr, int mode)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-
-	if (mixer_ops && mixer_ops->dpms)
-		mixer_ops->dpms(ctx->mixer_ctx->ctx, mode);
-
-	if (hdmi_ops && hdmi_ops->dpms)
-		hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
-}
-
-static void drm_mixer_win_mode_set(struct exynos_drm_manager *mgr,
-				struct exynos_drm_overlay *overlay)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-
-	if (mixer_ops && mixer_ops->win_mode_set)
-		mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
-}
-
-static void drm_mixer_win_commit(struct exynos_drm_manager *mgr, int zpos)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-	int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
-
-	if (win < 0 || win >= MIXER_WIN_NR) {
-		DRM_ERROR("mixer window[%d] is wrong\n", win);
-		return;
-	}
-
-	if (mixer_ops && mixer_ops->win_commit)
-		mixer_ops->win_commit(ctx->mixer_ctx->ctx, win);
-
-	ctx->enabled[win] = true;
-}
-
-static void drm_mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
-{
-	struct drm_hdmi_context *ctx = mgr->ctx;
-	int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
-
-	if (win < 0 || win >= MIXER_WIN_NR) {
-		DRM_ERROR("mixer window[%d] is wrong\n", win);
-		return;
-	}
-
-	if (mixer_ops && mixer_ops->win_disable)
-		mixer_ops->win_disable(ctx->mixer_ctx->ctx, win);
-
-	ctx->enabled[win] = false;
-}
-
-static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
-	.initialize = drm_hdmi_mgr_initialize,
-	.remove = drm_hdmi_mgr_remove,
-	.dpms = drm_hdmi_dpms,
-	.enable_vblank = drm_hdmi_enable_vblank,
-	.disable_vblank = drm_hdmi_disable_vblank,
-	.wait_for_vblank = drm_hdmi_wait_for_vblank,
-	.commit = drm_hdmi_commit,
-	.win_mode_set = drm_mixer_win_mode_set,
-	.win_commit = drm_mixer_win_commit,
-	.win_disable = drm_mixer_win_disable,
-};
-
-static struct exynos_drm_manager hdmi_manager = {
-	.type		= EXYNOS_DISPLAY_TYPE_HDMI,
-	.ops		= &drm_hdmi_manager_ops,
-};
-
-static int exynos_drm_hdmi_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct drm_hdmi_context *ctx;
-
-	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
-	if (!ctx)
-		return -ENOMEM;
-
-	hdmi_manager.ctx = ctx;
-	hdmi_display.ctx = ctx;
-
-	exynos_drm_manager_register(&hdmi_manager);
-	exynos_drm_display_register(&hdmi_display);
-
-	return 0;
-}
-
-static int exynos_drm_hdmi_remove(struct platform_device *pdev)
-{
-	exynos_drm_display_unregister(&hdmi_display);
-	exynos_drm_manager_unregister(&hdmi_manager);
-
-	return 0;
-}
-
-struct platform_driver exynos_drm_common_hdmi_driver = {
-	.probe		= exynos_drm_hdmi_probe,
-	.remove		= exynos_drm_hdmi_remove,
-	.driver		= {
-		.name	= "exynos-drm-hdmi",
-		.owner	= THIS_MODULE,
-	},
-};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
deleted file mode 100644
index 37059ea..0000000
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* exynos_drm_hdmi.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authoer: Inki Dae <inki.dae@samsung.com>
- *
- * 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 _EXYNOS_DRM_HDMI_H_
-#define _EXYNOS_DRM_HDMI_H_
-
-#define MIXER_WIN_NR		3
-#define MIXER_DEFAULT_WIN	0
-
-/*
- * exynos hdmi common context structure.
- *
- * @drm_dev: pointer to drm_device.
- * @pipe: pipe for mixer
- * @ctx: pointer to the context of specific device driver.
- *	this context should be hdmi_context or mixer_context.
- */
-struct exynos_drm_hdmi_context {
-	int			pipe;
-	void			*ctx;
-};
-
-struct exynos_hdmi_ops {
-	/* display */
-	int (*initialize)(void *ctx, struct drm_device *drm_dev);
-	bool (*is_connected)(void *ctx);
-	struct edid *(*get_edid)(void *ctx,
-			struct drm_connector *connector);
-	int (*check_mode)(void *ctx, struct drm_display_mode *mode);
-	void (*dpms)(void *ctx, int mode);
-
-	/* manager */
-	void (*mode_set)(void *ctx, struct drm_display_mode *mode);
-	void (*get_max_resol)(void *ctx, unsigned int *width,
-				unsigned int *height);
-	void (*commit)(void *ctx);
-};
-
-struct exynos_mixer_ops {
-	/* manager */
-	int (*initialize)(void *ctx, struct drm_device *drm_dev);
-	int (*iommu_on)(void *ctx, bool enable);
-	int (*enable_vblank)(void *ctx, int pipe);
-	void (*disable_vblank)(void *ctx);
-	void (*wait_for_vblank)(void *ctx);
-	void (*dpms)(void *ctx, int mode);
-
-	/* overlay */
-	void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
-	void (*win_commit)(void *ctx, int zpos);
-	void (*win_disable)(void *ctx, int zpos);
-
-	/* display */
-	int (*check_mode)(void *ctx, struct drm_display_mode *mode);
-};
-
-void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx);
-void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx);
-void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops);
-void exynos_mixer_ops_register(struct exynos_mixer_ops *ops);
-#endif
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index e106309..9e12fb7 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -39,14 +39,14 @@
 #include <drm/exynos_drm.h>
 
 #include "exynos_drm_drv.h"
-#include "exynos_drm_hdmi.h"
+#include "exynos_mixer.h"
 
 #include <linux/gpio.h>
 #include <media/s5p_hdmi.h>
 
 #define MAX_WIDTH		1920
 #define MAX_HEIGHT		1080
-#define get_hdmi_context(dev)	platform_get_drvdata(to_platform_device(dev))
+#define get_hdmi_display(dev)	platform_get_drvdata(to_platform_device(dev))
 
 /* AVI header and aspect ratio */
 #define HDMI_AVI_VERSION		0x02
@@ -187,7 +187,6 @@ struct hdmi_context {
 	struct mutex			hdmi_mutex;
 
 	void __iomem			*regs;
-	void				*parent_ctx;
 	int				irq;
 
 	struct i2c_client		*ddc_port;
@@ -740,26 +739,28 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
 	}
 }
 
-static int hdmi_initialize(void *ctx, struct drm_device *drm_dev)
+static int hdmi_initialize(struct exynos_drm_display *display,
+			struct drm_device *drm_dev)
 {
-	struct hdmi_context *hdata = ctx;
+	struct hdmi_context *hdata = display->ctx;
 
 	hdata->drm_dev = drm_dev;
 
 	return 0;
 }
 
-static bool hdmi_is_connected(void *ctx)
+static bool hdmi_is_connected(struct exynos_drm_display *display)
 {
-	struct hdmi_context *hdata = ctx;
+	struct hdmi_context *hdata = display->ctx;
 
 	return hdata->hpd;
 }
 
-static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
+static struct edid *hdmi_get_edid(struct exynos_drm_display *display,
+			struct drm_connector *connector)
 {
 	struct edid *raw_edid;
-	struct hdmi_context *hdata = ctx;
+	struct hdmi_context *hdata = display->ctx;
 
 	if (!hdata->ddc_port)
 		return ERR_PTR(-ENODEV);
@@ -798,9 +799,10 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
 	return -EINVAL;
 }
 
-static int hdmi_check_mode(void *ctx, struct drm_display_mode *mode)
+static int hdmi_check_mode(struct exynos_drm_display *display,
+			struct drm_display_mode *mode)
 {
-	struct hdmi_context *hdata = ctx;
+	struct hdmi_context *hdata = display->ctx;
 	int ret;
 
 	DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
@@ -808,12 +810,62 @@ static int hdmi_check_mode(void *ctx, struct drm_display_mode *mode)
 		(mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
 		false, mode->clock * 1000);
 
+	ret = mixer_check_mode(mode);
+	if (ret)
+		return ret;
+
 	ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
 	if (ret < 0)
 		return ret;
 	return 0;
 }
 
+static void hdmi_mode_fixup(struct exynos_drm_display *display,
+				struct drm_connector *connector,
+				const struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	struct drm_display_mode *m;
+	int mode_ok;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+	mode_ok = hdmi_check_mode(display, adjusted_mode);
+
+	/* just return if user desired mode exists. */
+	if (mode_ok == 0)
+		return;
+
+	/*
+	 * otherwise, find the most suitable mode among modes and change it
+	 * to adjusted_mode.
+	 */
+	list_for_each_entry(m, &connector->modes, head) {
+		mode_ok = hdmi_check_mode(display, m);
+
+		if (mode_ok == 0) {
+			struct drm_mode_object base;
+			struct list_head head;
+
+			DRM_INFO("desired mode doesn't exist so\n");
+			DRM_INFO("use the most suitable mode among modes.\n");
+
+			DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
+				m->hdisplay, m->vdisplay, m->vrefresh);
+
+			/* preserve display mode header while copying. */
+			head = adjusted_mode->head;
+			base = adjusted_mode->base;
+			memcpy(adjusted_mode, m, sizeof(*m));
+			adjusted_mode->head = head;
+			adjusted_mode->base = base;
+			break;
+		}
+	}
+}
+
 static void hdmi_set_acr(u32 freq, u8 *acr)
 {
 	u32 n, cts;
@@ -1639,9 +1691,10 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
 	hdmi_set_reg(tg->tg_3d, 1, 0x0);
 }
 
-static void hdmi_mode_set(void *ctx, struct drm_display_mode *mode)
+static void hdmi_mode_set(struct exynos_drm_display *display,
+			struct drm_display_mode *mode)
 {
-	struct hdmi_context *hdata = ctx;
+	struct hdmi_context *hdata = display->ctx;
 	struct drm_display_mode *m = mode;
 
 	DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
@@ -1655,16 +1708,16 @@ static void hdmi_mode_set(void *ctx, struct drm_display_mode *mode)
 		hdmi_v14_mode_set(hdata, mode);
 }
 
-static void hdmi_get_max_resol(void *ctx, unsigned int *width,
-					unsigned int *height)
+static void hdmi_get_max_resol(struct exynos_drm_display *display,
+			unsigned int *width, unsigned int *height)
 {
 	*width = MAX_WIDTH;
 	*height = MAX_HEIGHT;
 }
 
-static void hdmi_commit(void *ctx)
+static void hdmi_commit(struct exynos_drm_display *display)
 {
-	struct hdmi_context *hdata = ctx;
+	struct hdmi_context *hdata = display->ctx;
 
 	mutex_lock(&hdata->hdmi_mutex);
 	if (!hdata->powered) {
@@ -1676,8 +1729,9 @@ static void hdmi_commit(void *ctx)
 	hdmi_conf_apply(hdata);
 }
 
-static void hdmi_poweron(struct hdmi_context *hdata)
+static void hdmi_poweron(struct exynos_drm_display *display)
 {
+	struct hdmi_context *hdata = display->ctx;
 	struct hdmi_resources *res = &hdata->res;
 
 	mutex_lock(&hdata->hdmi_mutex);
@@ -1698,11 +1752,12 @@ static void hdmi_poweron(struct hdmi_context *hdata)
 	clk_prepare_enable(res->sclk_hdmi);
 
 	hdmiphy_poweron(hdata);
-	hdmi_commit(hdata);
+	hdmi_commit(display);
 }
 
-static void hdmi_poweroff(struct hdmi_context *hdata)
+static void hdmi_poweroff(struct exynos_drm_display *display)
 {
+	struct hdmi_context *hdata = display->ctx;
 	struct hdmi_resources *res = &hdata->res;
 
 	mutex_lock(&hdata->hdmi_mutex);
@@ -1730,9 +1785,9 @@ out:
 	mutex_unlock(&hdata->hdmi_mutex);
 }
 
-static void hdmi_dpms(void *ctx, int mode)
+static void hdmi_dpms(struct exynos_drm_display *display, int mode)
 {
-	struct hdmi_context *hdata = ctx;
+	struct hdmi_context *hdata = display->ctx;
 
 	DRM_DEBUG_KMS("mode %d\n", mode);
 
@@ -1753,24 +1808,26 @@ static void hdmi_dpms(void *ctx, int mode)
 	}
 }
 
-static struct exynos_hdmi_ops hdmi_ops = {
-	/* display */
+static struct exynos_drm_display_ops hdmi_display_ops = {
 	.initialize	= hdmi_initialize,
 	.is_connected	= hdmi_is_connected,
+	.get_max_resol	= hdmi_get_max_resol,
 	.get_edid	= hdmi_get_edid,
 	.check_mode	= hdmi_check_mode,
-	.dpms		= hdmi_dpms,
-
-	/* manager */
+	.mode_fixup	= hdmi_mode_fixup,
 	.mode_set	= hdmi_mode_set,
-	.get_max_resol	= hdmi_get_max_resol,
+	.dpms		= hdmi_dpms,
 	.commit		= hdmi_commit,
 };
 
+static struct exynos_drm_display hdmi_display = {
+	.type = EXYNOS_DISPLAY_TYPE_HDMI,
+	.ops = &hdmi_display_ops,
+};
+
 static irqreturn_t hdmi_irq_thread(int irq, void *arg)
 {
-	struct exynos_drm_hdmi_context *ctx = arg;
-	struct hdmi_context *hdata = ctx->ctx;
+	struct hdmi_context *hdata = arg;
 
 	mutex_lock(&hdata->hdmi_mutex);
 	hdata->hpd = gpio_get_value(hdata->hpd_gpio);
@@ -1887,7 +1944,6 @@ static struct of_device_id hdmi_match_types[] = {
 static int hdmi_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct exynos_drm_hdmi_context *drm_hdmi_ctx;
 	struct hdmi_context *hdata;
 	struct s5p_hdmi_platform_data *pdata;
 	struct resource *res;
@@ -1902,20 +1958,13 @@ static int hdmi_probe(struct platform_device *pdev)
 	if (!pdata)
 		return -EINVAL;
 
-	drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx), GFP_KERNEL);
-	if (!drm_hdmi_ctx)
-		return -ENOMEM;
-
 	hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
 	if (!hdata)
 		return -ENOMEM;
 
 	mutex_init(&hdata->hdmi_mutex);
 
-	drm_hdmi_ctx->ctx = (void *)hdata;
-	hdata->parent_ctx = (void *)drm_hdmi_ctx;
-
-	platform_set_drvdata(pdev, drm_hdmi_ctx);
+	platform_set_drvdata(pdev, &hdmi_display);
 
 	match = of_match_node(hdmi_match_types, dev->of_node);
 	if (!match)
@@ -1980,17 +2029,14 @@ static int hdmi_probe(struct platform_device *pdev)
 	ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
 			hdmi_irq_thread, IRQF_TRIGGER_RISING |
 			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-			"hdmi", drm_hdmi_ctx);
+			"hdmi", hdata);
 	if (ret) {
 		DRM_ERROR("failed to register hdmi interrupt\n");
 		goto err_hdmiphy;
 	}
 
-	/* Attach HDMI Driver to common hdmi. */
-	exynos_hdmi_drv_attach(drm_hdmi_ctx);
-
-	/* register specific callbacks to common hdmi. */
-	exynos_hdmi_ops_register(&hdmi_ops);
+	hdmi_display.ctx = hdata;
+	exynos_drm_display_register(&hdmi_display);
 
 	pm_runtime_enable(dev);
 
@@ -2006,8 +2052,8 @@ err_ddc:
 static int hdmi_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
-	struct hdmi_context *hdata = ctx->ctx;
+	struct exynos_drm_display *display = get_hdmi_display(dev);
+	struct hdmi_context *hdata = display->ctx;
 
 	pm_runtime_disable(dev);
 
@@ -2020,8 +2066,8 @@ static int hdmi_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int hdmi_suspend(struct device *dev)
 {
-	struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
-	struct hdmi_context *hdata = ctx->ctx;
+	struct exynos_drm_display *display = get_hdmi_display(dev);
+	struct hdmi_context *hdata = display->ctx;
 
 	disable_irq(hdata->irq);
 
@@ -2034,15 +2080,15 @@ static int hdmi_suspend(struct device *dev)
 		return 0;
 	}
 
-	hdmi_poweroff(hdata);
+	hdmi_poweroff(display);
 
 	return 0;
 }
 
 static int hdmi_resume(struct device *dev)
 {
-	struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
-	struct hdmi_context *hdata = ctx->ctx;
+	struct exynos_drm_display *display = get_hdmi_display(dev);
+	struct hdmi_context *hdata = display->ctx;
 
 	hdata->hpd = gpio_get_value(hdata->hpd_gpio);
 
@@ -2053,7 +2099,7 @@ static int hdmi_resume(struct device *dev)
 		return 0;
 	}
 
-	hdmi_poweron(hdata);
+	hdmi_poweron(display);
 
 	return 0;
 }
@@ -2062,20 +2108,18 @@ static int hdmi_resume(struct device *dev)
 #ifdef CONFIG_PM_RUNTIME
 static int hdmi_runtime_suspend(struct device *dev)
 {
-	struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
-	struct hdmi_context *hdata = ctx->ctx;
+	struct exynos_drm_display *display = get_hdmi_display(dev);
 
-	hdmi_poweroff(hdata);
+	hdmi_poweroff(display);
 
 	return 0;
 }
 
 static int hdmi_runtime_resume(struct device *dev)
 {
-	struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
-	struct hdmi_context *hdata = ctx->ctx;
+	struct exynos_drm_display *display = get_hdmi_display(dev);
 
-	hdmi_poweron(hdata);
+	hdmi_poweron(display);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 60935c4..39aed3e 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -36,10 +36,13 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
-#include "exynos_drm_hdmi.h"
 #include "exynos_drm_iommu.h"
+#include "exynos_mixer.h"
 
-#define get_mixer_context(dev)	platform_get_drvdata(to_platform_device(dev))
+#define get_mixer_manager(dev)	platform_get_drvdata(to_platform_device(dev))
+
+#define MIXER_WIN_NR		3
+#define MIXER_DEFAULT_WIN	0
 
 struct hdmi_win_data {
 	dma_addr_t		dma_addr;
@@ -94,7 +97,6 @@ struct mixer_context {
 	struct mixer_resources	mixer_res;
 	struct hdmi_win_data	win_data[MIXER_WIN_NR];
 	enum mixer_version_id	mxr_ver;
-	void			*parent_ctx;
 	wait_queue_head_t	wait_vsync_queue;
 	atomic_t		wait_vsync_event;
 };
@@ -685,35 +687,37 @@ static void mixer_win_reset(struct mixer_context *ctx)
 	spin_unlock_irqrestore(&res->reg_slock, flags);
 }
 
-static int mixer_initialize(void *ctx, struct drm_device *drm_dev)
+static int mixer_initialize(struct exynos_drm_manager *mgr,
+			struct drm_device *drm_dev, int pipe)
 {
-	struct mixer_context *mixer_ctx = ctx;
+	struct mixer_context *mixer_ctx = mgr->ctx;
 
 	mixer_ctx->drm_dev = drm_dev;
+	mixer_ctx->pipe = pipe;
 
-	return 0;
+	if (!is_drm_iommu_supported(mixer_ctx->drm_dev))
+		return 0;
+
+	return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
 }
 
-static int mixer_iommu_on(void *ctx, bool enable)
+static void mixer_mgr_remove(struct exynos_drm_manager *mgr)
 {
-	struct mixer_context *mdata = ctx;
-
-	if (is_drm_iommu_supported(mdata->drm_dev)) {
-		if (enable)
-			return drm_iommu_attach_device(mdata->drm_dev,
-					mdata->dev);
+	struct mixer_context *mixer_ctx = mgr->ctx;
 
-		drm_iommu_detach_device(mdata->drm_dev, mdata->dev);
-	}
-	return 0;
+	if (is_drm_iommu_supported(mixer_ctx->drm_dev))
+		drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
 }
 
-static int mixer_enable_vblank(void *ctx, int pipe)
+static int mixer_enable_vblank(struct exynos_drm_manager *mgr)
 {
-	struct mixer_context *mixer_ctx = ctx;
+	struct mixer_context *mixer_ctx = mgr->ctx;
 	struct mixer_resources *res = &mixer_ctx->mixer_res;
 
-	mixer_ctx->pipe = pipe;
+	if (!mixer_ctx->powered) {
+		mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
+		return 0;
+	}
 
 	/* enable vsync interrupt */
 	mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
@@ -722,19 +726,19 @@ static int mixer_enable_vblank(void *ctx, int pipe)
 	return 0;
 }
 
-static void mixer_disable_vblank(void *ctx)
+static void mixer_disable_vblank(struct exynos_drm_manager *mgr)
 {
-	struct mixer_context *mixer_ctx = ctx;
+	struct mixer_context *mixer_ctx = mgr->ctx;
 	struct mixer_resources *res = &mixer_ctx->mixer_res;
 
 	/* disable vsync interrupt */
 	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 }
 
-static void mixer_win_mode_set(void *ctx,
-			      struct exynos_drm_overlay *overlay)
+static void mixer_win_mode_set(struct exynos_drm_manager *mgr,
+			struct exynos_drm_overlay *overlay)
 {
-	struct mixer_context *mixer_ctx = ctx;
+	struct mixer_context *mixer_ctx = mgr->ctx;
 	struct hdmi_win_data *win_data;
 	int win;
 
@@ -783,9 +787,10 @@ static void mixer_win_mode_set(void *ctx,
 	win_data->scan_flags = overlay->scan_flag;
 }
 
-static void mixer_win_commit(void *ctx, int win)
+static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos)
 {
-	struct mixer_context *mixer_ctx = ctx;
+	struct mixer_context *mixer_ctx = mgr->ctx;
+	int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
 
 	DRM_DEBUG_KMS("win: %d\n", win);
 
@@ -804,10 +809,11 @@ static void mixer_win_commit(void *ctx, int win)
 	mixer_ctx->win_data[win].enabled = true;
 }
 
-static void mixer_win_disable(void *ctx, int win)
+static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
 {
-	struct mixer_context *mixer_ctx = ctx;
+	struct mixer_context *mixer_ctx = mgr->ctx;
 	struct mixer_resources *res = &mixer_ctx->mixer_res;
+	int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
 	unsigned long flags;
 
 	DRM_DEBUG_KMS("win: %d\n", win);
@@ -831,32 +837,9 @@ static void mixer_win_disable(void *ctx, int win)
 	mixer_ctx->win_data[win].enabled = false;
 }
 
-static int mixer_check_mode(void *ctx, struct drm_display_mode *mode)
+static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
 {
-	struct mixer_context *mixer_ctx = ctx;
-	u32 w, h;
-
-	w = mode->hdisplay;
-	h = mode->vdisplay;
-
-	DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
-		mode->hdisplay, mode->vdisplay, mode->vrefresh,
-		(mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
-
-	if (mixer_ctx->mxr_ver == MXR_VER_0_0_0_16 ||
-		mixer_ctx->mxr_ver == MXR_VER_128_0_0_184)
-		return 0;
-
-	if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
-		(w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
-		(w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
-		return 0;
-
-	return -EINVAL;
-}
-static void mixer_wait_for_vblank(void *ctx)
-{
-	struct mixer_context *mixer_ctx = ctx;
+	struct mixer_context *mixer_ctx = mgr->ctx;
 
 	mutex_lock(&mixer_ctx->mixer_mutex);
 	if (!mixer_ctx->powered) {
@@ -877,21 +860,23 @@ static void mixer_wait_for_vblank(void *ctx)
 		DRM_DEBUG_KMS("vblank wait timed out.\n");
 }
 
-static void mixer_window_suspend(struct mixer_context *ctx)
+static void mixer_window_suspend(struct exynos_drm_manager *mgr)
 {
+	struct mixer_context *ctx = mgr->ctx;
 	struct hdmi_win_data *win_data;
 	int i;
 
 	for (i = 0; i < MIXER_WIN_NR; i++) {
 		win_data = &ctx->win_data[i];
 		win_data->resume = win_data->enabled;
-		mixer_win_disable(ctx, i);
+		mixer_win_disable(mgr, i);
 	}
-	mixer_wait_for_vblank(ctx);
+	mixer_wait_for_vblank(mgr);
 }
 
-static void mixer_window_resume(struct mixer_context *ctx)
+static void mixer_window_resume(struct exynos_drm_manager *mgr)
 {
+	struct mixer_context *ctx = mgr->ctx;
 	struct hdmi_win_data *win_data;
 	int i;
 
@@ -900,12 +885,13 @@ static void mixer_window_resume(struct mixer_context *ctx)
 		win_data->enabled = win_data->resume;
 		win_data->resume = false;
 		if (win_data->enabled)
-			mixer_win_commit(ctx, i);
+			mixer_win_commit(mgr, i);
 	}
 }
 
-static void mixer_poweron(struct mixer_context *ctx)
+static void mixer_poweron(struct exynos_drm_manager *mgr)
 {
+	struct mixer_context *ctx = mgr->ctx;
 	struct mixer_resources *res = &ctx->mixer_res;
 
 	mutex_lock(&ctx->mixer_mutex);
@@ -925,11 +911,12 @@ static void mixer_poweron(struct mixer_context *ctx)
 	mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
 	mixer_win_reset(ctx);
 
-	mixer_window_resume(ctx);
+	mixer_window_resume(mgr);
 }
 
-static void mixer_poweroff(struct mixer_context *ctx)
+static void mixer_poweroff(struct exynos_drm_manager *mgr)
 {
+	struct mixer_context *ctx = mgr->ctx;
 	struct mixer_resources *res = &ctx->mixer_res;
 
 	mutex_lock(&ctx->mixer_mutex);
@@ -937,7 +924,7 @@ static void mixer_poweroff(struct mixer_context *ctx)
 		goto out;
 	mutex_unlock(&ctx->mixer_mutex);
 
-	mixer_window_suspend(ctx);
+	mixer_window_suspend(mgr);
 
 	ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
 
@@ -954,9 +941,9 @@ out:
 	mutex_unlock(&ctx->mixer_mutex);
 }
 
-static void mixer_dpms(void *ctx, int mode)
+static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
 {
-	struct mixer_context *mixer_ctx = ctx;
+	struct mixer_context *mixer_ctx = mgr->ctx;
 
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
@@ -975,20 +962,41 @@ static void mixer_dpms(void *ctx, int mode)
 	}
 }
 
-static struct exynos_mixer_ops mixer_ops = {
-	/* manager */
+/* Only valid for Mixer version 16.0.33.0 */
+int mixer_check_mode(struct drm_display_mode *mode)
+{
+	u32 w, h;
+
+	w = mode->hdisplay;
+	h = mode->vdisplay;
+
+	DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
+		mode->hdisplay, mode->vdisplay, mode->vrefresh,
+		(mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
+
+	if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
+		(w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
+		(w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
+		return 0;
+
+	return -EINVAL;
+}
+
+static struct exynos_drm_manager_ops mixer_manager_ops = {
 	.initialize		= mixer_initialize,
-	.iommu_on		= mixer_iommu_on,
+	.remove			= mixer_mgr_remove,
+	.dpms			= mixer_dpms,
 	.enable_vblank		= mixer_enable_vblank,
 	.disable_vblank		= mixer_disable_vblank,
 	.wait_for_vblank	= mixer_wait_for_vblank,
-	.dpms			= mixer_dpms,
 	.win_mode_set		= mixer_win_mode_set,
 	.win_commit		= mixer_win_commit,
 	.win_disable		= mixer_win_disable,
+};
 
-	/* display */
-	.check_mode		= mixer_check_mode,
+static struct exynos_drm_manager mixer_manager = {
+	.type			= EXYNOS_DISPLAY_TYPE_HDMI,
+	.ops			= &mixer_manager_ops,
 };
 
 static irqreturn_t mixer_irq_handler(int irq, void *arg)
@@ -1044,10 +1052,9 @@ out:
 	return IRQ_HANDLED;
 }
 
-static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
+static int mixer_resources_init(struct mixer_context *mixer_ctx,
 				struct platform_device *pdev)
 {
-	struct mixer_context *mixer_ctx = ctx->ctx;
 	struct device *dev = &pdev->dev;
 	struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
 	struct resource *res;
@@ -1096,10 +1103,9 @@ static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
 	return 0;
 }
 
-static int vp_resources_init(struct exynos_drm_hdmi_context *ctx,
+static int vp_resources_init(struct mixer_context *mixer_ctx,
 			     struct platform_device *pdev)
 {
-	struct mixer_context *mixer_ctx = ctx->ctx;
 	struct device *dev = &pdev->dev;
 	struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
 	struct resource *res;
@@ -1184,21 +1190,17 @@ static struct of_device_id mixer_match_types[] = {
 static int mixer_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct exynos_drm_hdmi_context *drm_hdmi_ctx;
 	struct mixer_context *ctx;
 	struct mixer_drv_data *drv;
 	int ret;
 
 	dev_info(dev, "probe start\n");
 
-	drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx),
-								GFP_KERNEL);
-	if (!drm_hdmi_ctx)
-		return -ENOMEM;
-
-	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
-	if (!ctx)
+	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx) {
+		DRM_ERROR("failed to alloc mixer context.\n");
 		return -ENOMEM;
+	}
 
 	mutex_init(&ctx->mixer_mutex);
 
@@ -1211,18 +1213,14 @@ static int mixer_probe(struct platform_device *pdev)
 			platform_get_device_id(pdev)->driver_data;
 	}
 
-	ctx->dev = dev;
-	ctx->parent_ctx = (void *)drm_hdmi_ctx;
-	drm_hdmi_ctx->ctx = (void *)ctx;
+	ctx->dev = &pdev->dev;
 	ctx->vp_enabled = drv->is_vp_enabled;
 	ctx->mxr_ver = drv->version;
 	DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
 	atomic_set(&ctx->wait_vsync_event, 0);
 
-	platform_set_drvdata(pdev, drm_hdmi_ctx);
-
 	/* acquire resources: regs, irqs, clocks */
-	ret = mixer_resources_init(drm_hdmi_ctx, pdev);
+	ret = mixer_resources_init(ctx, pdev);
 	if (ret) {
 		DRM_ERROR("mixer_resources_init failed\n");
 		goto fail;
@@ -1230,18 +1228,16 @@ static int mixer_probe(struct platform_device *pdev)
 
 	if (ctx->vp_enabled) {
 		/* acquire vp resources: regs, irqs, clocks */
-		ret = vp_resources_init(drm_hdmi_ctx, pdev);
+		ret = vp_resources_init(ctx, pdev);
 		if (ret) {
 			DRM_ERROR("vp_resources_init failed\n");
 			goto fail;
 		}
 	}
 
-	/* attach mixer driver to common hdmi. */
-	exynos_mixer_drv_attach(drm_hdmi_ctx);
-
-	/* register specific callback point to common hdmi. */
-	exynos_mixer_ops_register(&mixer_ops);
+	mixer_manager.ctx = ctx;
+	platform_set_drvdata(pdev, &mixer_manager);
+	exynos_drm_manager_register(&mixer_manager);
 
 	pm_runtime_enable(dev);
 
@@ -1265,30 +1261,28 @@ static int mixer_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int mixer_suspend(struct device *dev)
 {
-	struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
-	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
+	struct exynos_drm_manager *mgr = get_mixer_manager(dev);
 
 	if (pm_runtime_suspended(dev)) {
 		DRM_DEBUG_KMS("Already suspended\n");
 		return 0;
 	}
 
-	mixer_poweroff(ctx);
+	mixer_poweroff(mgr);
 
 	return 0;
 }
 
 static int mixer_resume(struct device *dev)
 {
-	struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
-	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
+	struct exynos_drm_manager *mgr = get_mixer_manager(dev);
 
 	if (!pm_runtime_suspended(dev)) {
 		DRM_DEBUG_KMS("Already resumed\n");
 		return 0;
 	}
 
-	mixer_poweron(ctx);
+	mixer_poweron(mgr);
 
 	return 0;
 }
@@ -1297,20 +1291,18 @@ static int mixer_resume(struct device *dev)
 #ifdef CONFIG_PM_RUNTIME
 static int mixer_runtime_suspend(struct device *dev)
 {
-	struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
-	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
+	struct exynos_drm_manager *mgr = get_mixer_manager(dev);
 
-	mixer_poweroff(ctx);
+	mixer_poweroff(mgr);
 
 	return 0;
 }
 
 static int mixer_runtime_resume(struct device *dev)
 {
-	struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
-	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
+	struct exynos_drm_manager *mgr = get_mixer_manager(dev);
 
-	mixer_poweron(ctx);
+	mixer_poweron(mgr);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.h b/drivers/gpu/drm/exynos/exynos_mixer.h
new file mode 100644
index 0000000..3811e41
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_mixer.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _EXYNOS_MIXER_H_
+#define _EXYNOS_MIXER_H_
+
+/* This function returns 0 if the given timing is valid for the mixer */
+int mixer_check_mode(struct drm_display_mode *mode);
+
+#endif
-- 
1.8.4

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

* [PATCH v3 15/32] drm/exynos: Use drm_mode_copy to copy modes
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (13 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 14/32] drm/exynos: Remove exynos_drm_hdmi shim Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-10 21:27   ` Tomasz Figa
  2013-10-29 16:13 ` [PATCH v3 16/32] drm/exynos: Disable unused crtc planes from crtc Sean Paul
                   ` (17 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch changes the manual copying of mode to adjusted_mode in
mode_fixup to use drm_mode_copy instead of handling things manually.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_hdmi.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 9e12fb7..2c127b9 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -846,21 +846,13 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display,
 		mode_ok = hdmi_check_mode(display, m);
 
 		if (mode_ok == 0) {
-			struct drm_mode_object base;
-			struct list_head head;
-
 			DRM_INFO("desired mode doesn't exist so\n");
 			DRM_INFO("use the most suitable mode among modes.\n");
 
 			DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
 				m->hdisplay, m->vdisplay, m->vrefresh);
 
-			/* preserve display mode header while copying. */
-			head = adjusted_mode->head;
-			base = adjusted_mode->base;
-			memcpy(adjusted_mode, m, sizeof(*m));
-			adjusted_mode->head = head;
-			adjusted_mode->base = base;
+			drm_mode_copy(adjusted_mode, m);
 			break;
 		}
 	}
-- 
1.8.4

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

* [PATCH v3 16/32] drm/exynos: Disable unused crtc planes from crtc
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (14 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 15/32] drm/exynos: Use drm_mode_copy to copy modes Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-10 21:29   ` Tomasz Figa
  2013-10-29 16:13 ` [PATCH v3 17/32] drm/exynos: Add mode_set manager operation Sean Paul
                   ` (16 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch moves the code which disables unused crtc planes from the
encoder to the crtc. Since there is a 1:1 encoder/crtc mapping in
exynos, the only valid crtc change the pre-existing code could catch is
disconnecting an active crtc from the encoder. Thus it is functionally
equivalent to just disable all planes attached to a crtc when the crtc
is disabled.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_crtc.c    | 13 +++++-
 drivers/gpu/drm/exynos/exynos_drm_encoder.c | 65 ++---------------------------
 2 files changed, 15 insertions(+), 63 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 347d62d..d019385 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -176,10 +176,19 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 
 static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
 {
-	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct drm_plane *plane;
+	int ret;
 
-	exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_OFF);
 	exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+
+	list_for_each_entry(plane, &crtc->dev->mode_config.plane_list, head) {
+		if (plane->crtc != crtc)
+			continue;
+
+		ret = plane->funcs->disable_plane(plane);
+		if (ret)
+			DRM_ERROR("Failed to disable plane %d\n", ret);
+	}
 }
 
 static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index d4ae664..bfa2f17 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -29,7 +29,6 @@
  * @display: the display structure that maps to this encoder
  */
 struct exynos_drm_encoder {
-	struct drm_crtc			*old_crtc;
 	struct drm_encoder		drm_encoder;
 	struct exynos_drm_display	*display;
 };
@@ -67,71 +66,15 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
 	return true;
 }
 
-static void disable_plane_to_crtc(struct drm_device *dev,
-						struct drm_crtc *old_crtc,
-						struct drm_crtc *new_crtc)
-{
-	struct drm_plane *plane;
-
-	/*
-	 * if old_crtc isn't same as encoder->crtc then it means that
-	 * user changed crtc id to another one so the plane to old_crtc
-	 * should be disabled and plane->crtc should be set to new_crtc
-	 * (encoder->crtc)
-	 */
-	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
-		if (plane->crtc == old_crtc) {
-			/*
-			 * do not change below call order.
-			 *
-			 * plane->funcs->disable_plane call checks
-			 * if encoder->crtc is same as plane->crtc and if same
-			 * then manager_ops->win_disable callback will be called
-			 * to diasble current hw overlay so plane->crtc should
-			 * have new_crtc because new_crtc was set to
-			 * encoder->crtc in advance.
-			 */
-			plane->crtc = new_crtc;
-			plane->funcs->disable_plane(plane);
-		}
-	}
-}
-
 static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
 					 struct drm_display_mode *mode,
 					 struct drm_display_mode *adjusted_mode)
 {
-	struct drm_device *dev = encoder->dev;
-	struct drm_connector *connector;
-	struct exynos_drm_display *display;
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			struct exynos_drm_encoder *exynos_encoder;
-
-			exynos_encoder = to_exynos_encoder(encoder);
-
-			if (exynos_encoder->old_crtc != encoder->crtc &&
-					exynos_encoder->old_crtc) {
-
-				/*
-				 * disable a plane to old crtc and change
-				 * crtc of the plane to new one.
-				 */
-				disable_plane_to_crtc(dev,
-						exynos_encoder->old_crtc,
-						encoder->crtc);
-			}
-
-			display = exynos_encoder->display;
-
-			if (display->ops->mode_set)
-				display->ops->mode_set(display,
-							adjusted_mode);
+	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+	struct exynos_drm_display *display = exynos_encoder->display;
 
-			exynos_encoder->old_crtc = encoder->crtc;
-		}
-	}
+	if (display->ops->mode_set)
+		display->ops->mode_set(display, adjusted_mode);
 }
 
 static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
-- 
1.8.4

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

* [PATCH v3 17/32] drm/exynos: Add mode_set manager operation
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (15 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 16/32] drm/exynos: Disable unused crtc planes from crtc Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-10 21:31   ` Tomasz Figa
  2013-10-29 16:13 ` [PATCH v3 18/32] drm/exynos: Implement mode_fixup " Sean Paul
                   ` (15 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch adds a mode_set callback to the manager operations which
sets the crtc's current mode to the manager driver.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 ++++
 drivers/gpu/drm/exynos/exynos_drm_drv.h  | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index d019385..a5cb104 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -115,6 +115,7 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
 			  struct drm_framebuffer *old_fb)
 {
 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct exynos_drm_manager *manager = exynos_crtc->manager;
 	struct drm_plane *plane = exynos_crtc->plane;
 	unsigned int crtc_w;
 	unsigned int crtc_h;
@@ -129,6 +130,9 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	crtc_w = crtc->fb->width - x;
 	crtc_h = crtc->fb->height - y;
 
+	if (manager->ops->mode_set)
+		manager->ops->mode_set(manager, &crtc->mode);
+
 	ret = exynos_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h,
 				    x, y, crtc_w, crtc_h);
 	if (ret)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index dc730e5..c58a4c7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -184,6 +184,7 @@ struct exynos_drm_display {
  * @initialize: initializes the manager with drm_dev
  * @remove: cleans up the manager for removal
  * @dpms: control device power.
+ * @mode_set: set the given mode to the manager
  * @commit: set current hw specific display mode to hw.
  * @enable_vblank: specific driver callback for enabling vblank interrupt.
  * @disable_vblank: specific driver callback for disabling vblank interrupt.
@@ -200,6 +201,8 @@ struct exynos_drm_manager_ops {
 				struct drm_device *drm_dev, int pipe);
 	void (*remove)(struct exynos_drm_manager *mgr);
 	void (*dpms)(struct exynos_drm_manager *mgr, int mode);
+	void (*mode_set)(struct exynos_drm_manager *mgr,
+				const struct drm_display_mode *mode);
 	void (*commit)(struct exynos_drm_manager *mgr);
 	int (*enable_vblank)(struct exynos_drm_manager *mgr);
 	void (*disable_vblank)(struct exynos_drm_manager *mgr);
-- 
1.8.4

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

* [PATCH v3 18/32] drm/exynos: Implement mode_fixup manager operation
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (16 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 17/32] drm/exynos: Add mode_set manager operation Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-10 21:33   ` Tomasz Figa
  2013-10-29 16:13 ` [PATCH v3 19/32] drm/exynos: Use mode_set to configure fimd Sean Paul
                   ` (14 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch adds a new manager callback for mode_fixup and pipes it
through exynos_drm_crtc.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_crtc.c | 7 ++++++-
 drivers/gpu/drm/exynos/exynos_drm_drv.h  | 4 ++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index a5cb104..100a561 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -105,7 +105,12 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
 			    const struct drm_display_mode *mode,
 			    struct drm_display_mode *adjusted_mode)
 {
-	/* drm framework doesn't check NULL */
+	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+	struct exynos_drm_manager *manager = exynos_crtc->manager;
+
+	if (manager->ops->mode_fixup)
+		return manager->ops->mode_fixup(manager, mode, adjusted_mode);
+
 	return true;
 }
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index c58a4c7..97bdfcc 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -184,6 +184,7 @@ struct exynos_drm_display {
  * @initialize: initializes the manager with drm_dev
  * @remove: cleans up the manager for removal
  * @dpms: control device power.
+ * @mode_fixup: fix mode data before applying it
  * @mode_set: set the given mode to the manager
  * @commit: set current hw specific display mode to hw.
  * @enable_vblank: specific driver callback for enabling vblank interrupt.
@@ -201,6 +202,9 @@ struct exynos_drm_manager_ops {
 				struct drm_device *drm_dev, int pipe);
 	void (*remove)(struct exynos_drm_manager *mgr);
 	void (*dpms)(struct exynos_drm_manager *mgr, int mode);
+	bool (*mode_fixup)(struct exynos_drm_manager *mgr,
+				const struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode);
 	void (*mode_set)(struct exynos_drm_manager *mgr,
 				const struct drm_display_mode *mode);
 	void (*commit)(struct exynos_drm_manager *mgr);
-- 
1.8.4

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

* [PATCH v3 19/32] drm/exynos: Use mode_set to configure fimd
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (17 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 18/32] drm/exynos: Implement mode_fixup " Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-10 22:03   ` Tomasz Figa
  2013-10-29 16:13 ` [PATCH v3 20/32] drm/exynos: Remove unused/useless fimd_context members Sean Paul
                   ` (13 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch uses the mode passed into mode_set to configure fimd instead
of directly using the panel from context. This will allow us to move
the exynos_drm_display implementation from fimd into the DP driver
where it belongs.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_fimd.c | 159 ++++++++++++++++++-------------
 1 file changed, 91 insertions(+), 68 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index d2b8ccb..f69d6e5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -104,6 +104,20 @@ struct fimd_win_data {
 	bool			resume;
 };
 
+struct fimd_mode_data {
+	unsigned		vtotal;
+	unsigned		vdisplay;
+	unsigned		vsync_len;
+	unsigned		vbpd;
+	unsigned		vfpd;
+	unsigned		htotal;
+	unsigned		hdisplay;
+	unsigned		hsync_len;
+	unsigned		hbpd;
+	unsigned		hfpd;
+	u32			clkdiv;
+};
+
 struct fimd_context {
 	struct device			*dev;
 	struct drm_device		*drm_dev;
@@ -112,8 +126,8 @@ struct fimd_context {
 	struct clk			*bus_clk;
 	struct clk			*lcd_clk;
 	void __iomem			*regs;
+	struct fimd_mode_data		mode;
 	struct fimd_win_data		win_data[WINDOWS_NR];
-	unsigned int			clkdiv;
 	unsigned int			default_win;
 	unsigned long			irq_flags;
 	u32				vidcon0;
@@ -560,11 +574,56 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
 	mutex_unlock(&ctx->lock);
 }
 
+static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
+		const struct drm_display_mode *mode)
+{
+	unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
+	u32 clkdiv;
+
+	/* Find the clock divider value that gets us closest to ideal_clk */
+	clkdiv = DIV_ROUND_CLOSEST(clk_get_rate(ctx->lcd_clk), ideal_clk);
+
+	return (clkdiv < 0x100) ? clkdiv : 0xff;
+}
+
+static bool fimd_mode_fixup(struct exynos_drm_manager *mgr,
+		const struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	if (adjusted_mode->vrefresh == 0)
+		adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE;
+
+	return true;
+}
+
+static void fimd_mode_set(struct exynos_drm_manager *mgr,
+		const struct drm_display_mode *in_mode)
+{
+	struct fimd_context *ctx = mgr->ctx;
+	struct fimd_mode_data *mode = &ctx->mode;
+	int hblank, vblank;
+
+	vblank = in_mode->crtc_vblank_end - in_mode->crtc_vblank_start;
+	mode->vtotal = in_mode->crtc_vtotal;
+	mode->vdisplay = in_mode->crtc_vdisplay;
+	mode->vsync_len = in_mode->crtc_vsync_end - in_mode->crtc_vsync_start;
+	mode->vbpd = (vblank - mode->vsync_len) / 2;
+	mode->vfpd = vblank - mode->vsync_len - mode->vbpd;
+
+	hblank = in_mode->crtc_hblank_end - in_mode->crtc_hblank_start;
+	mode->htotal = in_mode->crtc_htotal;
+	mode->hdisplay = in_mode->crtc_hdisplay;
+	mode->hsync_len = in_mode->crtc_hsync_end - in_mode->crtc_hsync_start;
+	mode->hbpd = (hblank - mode->hsync_len) / 2;
+	mode->hfpd = hblank - mode->hsync_len - mode->hbpd;
+
+	mode->clkdiv = fimd_calc_clkdiv(ctx, in_mode);
+}
+
 static void fimd_commit(struct exynos_drm_manager *mgr)
 {
 	struct fimd_context *ctx = mgr->ctx;
-	struct exynos_drm_panel_info *panel = &ctx->panel;
-	struct videomode *vm = &panel->vm;
+	struct fimd_mode_data *mode = &ctx->mode;
 	struct fimd_driver_data *driver_data;
 	u32 val;
 
@@ -572,26 +631,30 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
 	if (ctx->suspended)
 		return;
 
+	/* nothing to do if we haven't set the mode yet */
+	if (mode->htotal == 0 || mode->vtotal == 0)
+		return;
+
 	/* setup polarity values from machine code. */
 	writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
 
 	/* setup vertical timing values. */
-	val = VIDTCON0_VBPD(vm->vback_porch - 1) |
-	       VIDTCON0_VFPD(vm->vfront_porch - 1) |
-	       VIDTCON0_VSPW(vm->vsync_len - 1);
+	val = VIDTCON0_VBPD(mode->vbpd - 1) |
+		VIDTCON0_VFPD(mode->vfpd - 1) |
+		VIDTCON0_VSPW(mode->vsync_len - 1);
 	writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
 
 	/* setup horizontal timing values.  */
-	val = VIDTCON1_HBPD(vm->hback_porch - 1) |
-	       VIDTCON1_HFPD(vm->hfront_porch - 1) |
-	       VIDTCON1_HSPW(vm->hsync_len - 1);
+	val = VIDTCON1_HBPD(mode->hbpd - 1) |
+		VIDTCON1_HFPD(mode->hfpd - 1) |
+		VIDTCON1_HSPW(mode->hsync_len - 1);
 	writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
 
 	/* setup horizontal and vertical display size. */
-	val = VIDTCON2_LINEVAL(vm->vactive - 1) |
-	       VIDTCON2_HOZVAL(vm->hactive - 1) |
-	       VIDTCON2_LINEVAL_E(vm->vactive - 1) |
-	       VIDTCON2_HOZVAL_E(vm->hactive - 1);
+	val = VIDTCON2_LINEVAL(mode->vdisplay - 1) |
+	       VIDTCON2_HOZVAL(mode->hdisplay - 1) |
+	       VIDTCON2_LINEVAL_E(mode->vdisplay - 1) |
+	       VIDTCON2_HOZVAL_E(mode->hdisplay - 1);
 	writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
 
 	/* setup clock source, clock divider, enable dma. */
@@ -603,8 +666,8 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
 		val |= VIDCON0_CLKSEL_LCD;
 	}
 
-	if (ctx->clkdiv > 1)
-		val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
+	if (mode->clkdiv > 1)
+		val |= VIDCON0_CLKVAL_F(mode->clkdiv - 1) | VIDCON0_CLKDIR;
 	else
 		val &= ~VIDCON0_CLKDIR;	/* 1:1 clock */
 
@@ -697,6 +760,8 @@ static struct exynos_drm_manager_ops fimd_manager_ops = {
 	.initialize = fimd_mgr_initialize,
 	.remove = fimd_mgr_remove,
 	.dpms = fimd_dpms,
+	.mode_fixup = fimd_mode_fixup,
+	.mode_set = fimd_mode_set,
 	.commit = fimd_commit,
 	.enable_vblank = fimd_enable_vblank,
 	.disable_vblank = fimd_disable_vblank,
@@ -738,56 +803,6 @@ out:
 	return IRQ_HANDLED;
 }
 
-static int fimd_configure_clocks(struct fimd_context *ctx, struct device *dev)
-{
-	struct videomode *vm = &ctx->panel.vm;
-	unsigned long clk;
-
-	ctx->bus_clk = devm_clk_get(dev, "fimd");
-	if (IS_ERR(ctx->bus_clk)) {
-		dev_err(dev, "failed to get bus clock\n");
-		return PTR_ERR(ctx->bus_clk);
-	}
-
-	ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
-	if (IS_ERR(ctx->lcd_clk)) {
-		dev_err(dev, "failed to get lcd clock\n");
-		return PTR_ERR(ctx->lcd_clk);
-	}
-
-	clk = clk_get_rate(ctx->lcd_clk);
-	if (clk == 0) {
-		dev_err(dev, "error getting sclk_fimd clock rate\n");
-		return -EINVAL;
-	}
-
-	if (vm->pixelclock == 0) {
-		unsigned long c;
-		c = vm->hactive + vm->hback_porch + vm->hfront_porch +
-		    vm->hsync_len;
-		c *= vm->vactive + vm->vback_porch + vm->vfront_porch +
-		     vm->vsync_len;
-		vm->pixelclock = c * FIMD_DEFAULT_FRAMERATE;
-		if (vm->pixelclock == 0) {
-			dev_err(dev, "incorrect display timings\n");
-			return -EINVAL;
-		}
-		dev_warn(dev, "pixel clock recalculated to %luHz (%dHz frame rate)\n",
-			 vm->pixelclock, FIMD_DEFAULT_FRAMERATE);
-	}
-	ctx->clkdiv = DIV_ROUND_UP(clk, vm->pixelclock);
-	if (ctx->clkdiv > 256) {
-		dev_warn(dev, "calculated pixel clock divider too high (%u), lowered to 256\n",
-			 ctx->clkdiv);
-		ctx->clkdiv = 256;
-	}
-	vm->pixelclock = clk / ctx->clkdiv;
-	DRM_DEBUG_KMS("pixel clock = %lu, clkdiv = %d\n", vm->pixelclock,
-		      ctx->clkdiv);
-
-	return 0;
-}
-
 static void fimd_clear_win(struct fimd_context *ctx, int win)
 {
 	writel(0, ctx->regs + WINCON(win));
@@ -925,9 +940,17 @@ static int fimd_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	ret = fimd_configure_clocks(ctx, dev);
-	if (ret)
-		return ret;
+	ctx->bus_clk = devm_clk_get(dev, "fimd");
+	if (IS_ERR(ctx->bus_clk)) {
+		dev_err(dev, "failed to get bus clock\n");
+		return PTR_ERR(ctx->bus_clk);
+	}
+
+	ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd");
+	if (IS_ERR(ctx->lcd_clk)) {
+		dev_err(dev, "failed to get lcd clock\n");
+		return PTR_ERR(ctx->lcd_clk);
+	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-- 
1.8.4

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

* [PATCH v3 20/32] drm/exynos: Remove unused/useless fimd_context members
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (18 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 19/32] drm/exynos: Use mode_set to configure fimd Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-11  1:19   ` Tomasz Figa
  2013-10-29 16:13 ` [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/ Sean Paul
                   ` (12 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch removes a few fimd_context members which are either entirely
unused or unneeded.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_fimd.c | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index f69d6e5..61124ca 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -121,8 +121,6 @@ struct fimd_mode_data {
 struct fimd_context {
 	struct device			*dev;
 	struct drm_device		*drm_dev;
-	int				irq;
-	struct drm_crtc			*crtc;
 	struct clk			*bus_clk;
 	struct clk			*lcd_clk;
 	void __iomem			*regs;
@@ -134,7 +132,6 @@ struct fimd_context {
 	u32				vidcon1;
 	bool				suspended;
 	int				pipe;
-	struct mutex			lock;
 	wait_queue_head_t		wait_vsync_queue;
 	atomic_t			wait_vsync_event;
 
@@ -547,8 +544,6 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
 
 	DRM_DEBUG_KMS("%d\n", mode);
 
-	mutex_lock(&ctx->lock);
-
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		/*
@@ -570,8 +565,6 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
 		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
 		break;
 	}
-
-	mutex_unlock(&ctx->lock);
 }
 
 static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
@@ -964,9 +957,7 @@ static int fimd_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
-	ctx->irq = res->start;
-
-	ret = devm_request_irq(dev, ctx->irq, fimd_irq_handler,
+	ret = devm_request_irq(dev, res->start, fimd_irq_handler,
 							0, "drm_fimd", ctx);
 	if (ret) {
 		dev_err(dev, "irq request failed.\n");
@@ -977,8 +968,6 @@ static int fimd_probe(struct platform_device *pdev)
 	DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
 	atomic_set(&ctx->wait_vsync_event, 0);
 
-	mutex_init(&ctx->lock);
-
 	platform_set_drvdata(pdev, &fimd_manager);
 
 	fimd_manager.ctx = ctx;
-- 
1.8.4

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

* [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (19 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 20/32] drm/exynos: Remove unused/useless fimd_context members Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-10-31 10:46   ` Inki Dae
       [not found]   ` <3513711.0qTZKxmOZX@flatron>
  2013-10-29 16:13 ` [PATCH v3 22/32] drm/exynos: Move display implementation into dp Sean Paul
                   ` (11 subsequent siblings)
  32 siblings, 2 replies; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch moves the code from video/ to drm/

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 drivers/gpu/drm/exynos/Kconfig          |    7 +
 drivers/gpu/drm/exynos/Makefile         |    1 +
 drivers/gpu/drm/exynos/exynos_dp_core.c | 1213 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_dp_core.h |  210 ++++++
 drivers/gpu/drm/exynos/exynos_dp_reg.c  | 1245 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_dp_reg.h  |  366 +++++++++
 drivers/video/exynos/Kconfig            |    7 -
 drivers/video/exynos/Makefile           |    1 -
 drivers/video/exynos/exynos_dp_core.c   | 1213 ------------------------------
 drivers/video/exynos/exynos_dp_core.h   |  210 ------
 drivers/video/exynos/exynos_dp_reg.c    | 1245 -------------------------------
 drivers/video/exynos/exynos_dp_reg.h    |  366 ---------
 12 files changed, 3042 insertions(+), 3042 deletions(-)
 create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h
 create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.h
 delete mode 100644 drivers/video/exynos/exynos_dp_core.c
 delete mode 100644 drivers/video/exynos/exynos_dp_core.h
 delete mode 100644 drivers/video/exynos/exynos_dp_reg.c
 delete mode 100644 drivers/video/exynos/exynos_dp_reg.h

diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 45b6ef5..3ace74f 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -30,6 +30,13 @@ config DRM_EXYNOS_FIMD
 	help
 	  Choose this option if you want to use Exynos FIMD for DRM.
 
+config DRM_EXYNOS_DP
+	bool "EXYNOS DRM DP driver support"
+	depends on ARCH_EXYNOS
+	default n
+	help
+	  This enables support for DP device.
+
 config DRM_EXYNOS_HDMI
 	bool "Exynos DRM HDMI"
 	depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index afbe499..fc8555c 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -11,6 +11,7 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
 exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)	+= exynos_drm_fimd.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_DP)	+= exynos_dp_core.o exynos_dp_reg.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)	+= exynos_hdmi.o exynos_mixer.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)	+= exynos_drm_vidi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_G2D)	+= exynos_drm_g2d.o
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
new file mode 100644
index 0000000..089ae22
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -0,0 +1,1213 @@
+/*
+ * Samsung SoC DP (Display Port) interface driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#include <video/exynos_dp.h>
+
+#include "exynos_dp_core.h"
+
+static int exynos_dp_init_dp(struct exynos_dp_device *dp)
+{
+	exynos_dp_reset(dp);
+
+	exynos_dp_swreset(dp);
+
+	exynos_dp_init_analog_param(dp);
+	exynos_dp_init_interrupt(dp);
+
+	/* SW defined function Normal operation */
+	exynos_dp_enable_sw_function(dp);
+
+	exynos_dp_config_interrupt(dp);
+	exynos_dp_init_analog_func(dp);
+
+	exynos_dp_init_hpd(dp);
+	exynos_dp_init_aux(dp);
+
+	return 0;
+}
+
+static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
+{
+	int timeout_loop = 0;
+
+	while (exynos_dp_get_plug_in_status(dp) != 0) {
+		timeout_loop++;
+		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+			dev_err(dp->dev, "failed to get hpd plug status\n");
+			return -ETIMEDOUT;
+		}
+		usleep_range(10, 11);
+	}
+
+	return 0;
+}
+
+static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
+{
+	int i;
+	unsigned char sum = 0;
+
+	for (i = 0; i < EDID_BLOCK_LENGTH; i++)
+		sum = sum + edid_data[i];
+
+	return sum;
+}
+
+static int exynos_dp_read_edid(struct exynos_dp_device *dp)
+{
+	unsigned char edid[EDID_BLOCK_LENGTH * 2];
+	unsigned int extend_block = 0;
+	unsigned char sum;
+	unsigned char test_vector;
+	int retval;
+
+	/*
+	 * EDID device address is 0x50.
+	 * However, if necessary, you must have set upper address
+	 * into E-EDID in I2C device, 0x30.
+	 */
+
+	/* Read Extension Flag, Number of 128-byte EDID extension blocks */
+	retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
+				EDID_EXTENSION_FLAG,
+				&extend_block);
+	if (retval)
+		return retval;
+
+	if (extend_block > 0) {
+		dev_dbg(dp->dev, "EDID data includes a single extension!\n");
+
+		/* Read EDID data */
+		retval = exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
+						EDID_HEADER_PATTERN,
+						EDID_BLOCK_LENGTH,
+						&edid[EDID_HEADER_PATTERN]);
+		if (retval != 0) {
+			dev_err(dp->dev, "EDID Read failed!\n");
+			return -EIO;
+		}
+		sum = exynos_dp_calc_edid_check_sum(edid);
+		if (sum != 0) {
+			dev_err(dp->dev, "EDID bad checksum!\n");
+			return -EIO;
+		}
+
+		/* Read additional EDID data */
+		retval = exynos_dp_read_bytes_from_i2c(dp,
+				I2C_EDID_DEVICE_ADDR,
+				EDID_BLOCK_LENGTH,
+				EDID_BLOCK_LENGTH,
+				&edid[EDID_BLOCK_LENGTH]);
+		if (retval != 0) {
+			dev_err(dp->dev, "EDID Read failed!\n");
+			return -EIO;
+		}
+		sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
+		if (sum != 0) {
+			dev_err(dp->dev, "EDID bad checksum!\n");
+			return -EIO;
+		}
+
+		exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
+					&test_vector);
+		if (test_vector & DPCD_TEST_EDID_READ) {
+			exynos_dp_write_byte_to_dpcd(dp,
+				DPCD_ADDR_TEST_EDID_CHECKSUM,
+				edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
+			exynos_dp_write_byte_to_dpcd(dp,
+				DPCD_ADDR_TEST_RESPONSE,
+				DPCD_TEST_EDID_CHECKSUM_WRITE);
+		}
+	} else {
+		dev_info(dp->dev, "EDID data does not include any extensions.\n");
+
+		/* Read EDID data */
+		retval = exynos_dp_read_bytes_from_i2c(dp,
+				I2C_EDID_DEVICE_ADDR,
+				EDID_HEADER_PATTERN,
+				EDID_BLOCK_LENGTH,
+				&edid[EDID_HEADER_PATTERN]);
+		if (retval != 0) {
+			dev_err(dp->dev, "EDID Read failed!\n");
+			return -EIO;
+		}
+		sum = exynos_dp_calc_edid_check_sum(edid);
+		if (sum != 0) {
+			dev_err(dp->dev, "EDID bad checksum!\n");
+			return -EIO;
+		}
+
+		exynos_dp_read_byte_from_dpcd(dp,
+			DPCD_ADDR_TEST_REQUEST,
+			&test_vector);
+		if (test_vector & DPCD_TEST_EDID_READ) {
+			exynos_dp_write_byte_to_dpcd(dp,
+				DPCD_ADDR_TEST_EDID_CHECKSUM,
+				edid[EDID_CHECKSUM]);
+			exynos_dp_write_byte_to_dpcd(dp,
+				DPCD_ADDR_TEST_RESPONSE,
+				DPCD_TEST_EDID_CHECKSUM_WRITE);
+		}
+	}
+
+	dev_err(dp->dev, "EDID Read success!\n");
+	return 0;
+}
+
+static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
+{
+	u8 buf[12];
+	int i;
+	int retval;
+
+	/* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
+	retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
+				12, buf);
+	if (retval)
+		return retval;
+
+	/* Read EDID */
+	for (i = 0; i < 3; i++) {
+		retval = exynos_dp_read_edid(dp);
+		if (!retval)
+			break;
+	}
+
+	return retval;
+}
+
+static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp,
+						bool enable)
+{
+	u8 data;
+
+	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
+
+	if (enable)
+		exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
+			DPCD_ENHANCED_FRAME_EN |
+			DPCD_LANE_COUNT_SET(data));
+	else
+		exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
+			DPCD_LANE_COUNT_SET(data));
+}
+
+static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp)
+{
+	u8 data;
+	int retval;
+
+	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
+	retval = DPCD_ENHANCED_FRAME_CAP(data);
+
+	return retval;
+}
+
+static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
+{
+	u8 data;
+
+	data = exynos_dp_is_enhanced_mode_available(dp);
+	exynos_dp_enable_rx_to_enhanced_mode(dp, data);
+	exynos_dp_enable_enhanced_mode(dp, data);
+}
+
+static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
+{
+	exynos_dp_set_training_pattern(dp, DP_NONE);
+
+	exynos_dp_write_byte_to_dpcd(dp,
+		DPCD_ADDR_TRAINING_PATTERN_SET,
+		DPCD_TRAINING_PATTERN_DISABLED);
+}
+
+static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
+					int pre_emphasis, int lane)
+{
+	switch (lane) {
+	case 0:
+		exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
+		break;
+	case 1:
+		exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
+		break;
+
+	case 2:
+		exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
+		break;
+
+	case 3:
+		exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
+		break;
+	}
+}
+
+static int exynos_dp_link_start(struct exynos_dp_device *dp)
+{
+	u8 buf[4];
+	int lane, lane_count, pll_tries, retval;
+
+	lane_count = dp->link_train.lane_count;
+
+	dp->link_train.lt_state = CLOCK_RECOVERY;
+	dp->link_train.eq_loop = 0;
+
+	for (lane = 0; lane < lane_count; lane++)
+		dp->link_train.cr_loop[lane] = 0;
+
+	/* Set link rate and count as you want to establish*/
+	exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
+	exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
+
+	/* Setup RX configuration */
+	buf[0] = dp->link_train.link_rate;
+	buf[1] = dp->link_train.lane_count;
+	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
+				2, buf);
+	if (retval)
+		return retval;
+
+	/* Set TX pre-emphasis to minimum */
+	for (lane = 0; lane < lane_count; lane++)
+		exynos_dp_set_lane_lane_pre_emphasis(dp,
+			PRE_EMPHASIS_LEVEL_0, lane);
+
+	/* Wait for PLL lock */
+	pll_tries = 0;
+	while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+		if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
+			dev_err(dp->dev, "Wait for PLL lock timed out\n");
+			return -ETIMEDOUT;
+		}
+
+		pll_tries++;
+		usleep_range(90, 120);
+	}
+
+	/* Set training pattern 1 */
+	exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
+
+	/* Set RX training pattern */
+	retval = exynos_dp_write_byte_to_dpcd(dp,
+			DPCD_ADDR_TRAINING_PATTERN_SET,
+			DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
+	if (retval)
+		return retval;
+
+	for (lane = 0; lane < lane_count; lane++)
+		buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
+			    DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
+
+	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
+			lane_count, buf);
+
+	return retval;
+}
+
+static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
+{
+	int shift = (lane & 1) * 4;
+	u8 link_value = link_status[lane>>1];
+
+	return (link_value >> shift) & 0xf;
+}
+
+static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
+{
+	int lane;
+	u8 lane_status;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = exynos_dp_get_lane_status(link_status, lane);
+		if ((lane_status & DPCD_LANE_CR_DONE) == 0)
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
+				int lane_count)
+{
+	int lane;
+	u8 lane_status;
+
+	if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
+		return -EINVAL;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = exynos_dp_get_lane_status(link_status, lane);
+		lane_status &= DPCD_CHANNEL_EQ_BITS;
+		if (lane_status != DPCD_CHANNEL_EQ_BITS)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2],
+							int lane)
+{
+	int shift = (lane & 1) * 4;
+	u8 link_value = adjust_request[lane>>1];
+
+	return (link_value >> shift) & 0x3;
+}
+
+static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
+					u8 adjust_request[2],
+					int lane)
+{
+	int shift = (lane & 1) * 4;
+	u8 link_value = adjust_request[lane>>1];
+
+	return ((link_value >> shift) & 0xc) >> 2;
+}
+
+static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
+					u8 training_lane_set, int lane)
+{
+	switch (lane) {
+	case 0:
+		exynos_dp_set_lane0_link_training(dp, training_lane_set);
+		break;
+	case 1:
+		exynos_dp_set_lane1_link_training(dp, training_lane_set);
+		break;
+
+	case 2:
+		exynos_dp_set_lane2_link_training(dp, training_lane_set);
+		break;
+
+	case 3:
+		exynos_dp_set_lane3_link_training(dp, training_lane_set);
+		break;
+	}
+}
+
+static unsigned int exynos_dp_get_lane_link_training(
+				struct exynos_dp_device *dp,
+				int lane)
+{
+	u32 reg;
+
+	switch (lane) {
+	case 0:
+		reg = exynos_dp_get_lane0_link_training(dp);
+		break;
+	case 1:
+		reg = exynos_dp_get_lane1_link_training(dp);
+		break;
+	case 2:
+		reg = exynos_dp_get_lane2_link_training(dp);
+		break;
+	case 3:
+		reg = exynos_dp_get_lane3_link_training(dp);
+		break;
+	default:
+		WARN_ON(1);
+		return 0;
+	}
+
+	return reg;
+}
+
+static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
+{
+	exynos_dp_training_pattern_dis(dp);
+	exynos_dp_set_enhanced_mode(dp);
+
+	dp->link_train.lt_state = FAILED;
+}
+
+static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp,
+					u8 adjust_request[2])
+{
+	int lane, lane_count;
+	u8 voltage_swing, pre_emphasis, training_lane;
+
+	lane_count = dp->link_train.lane_count;
+	for (lane = 0; lane < lane_count; lane++) {
+		voltage_swing = exynos_dp_get_adjust_request_voltage(
+						adjust_request, lane);
+		pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
+						adjust_request, lane);
+		training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
+				DPCD_PRE_EMPHASIS_SET(pre_emphasis);
+
+		if (voltage_swing == VOLTAGE_LEVEL_3)
+			training_lane |= DPCD_MAX_SWING_REACHED;
+		if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
+			training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
+
+		dp->link_train.training_lane[lane] = training_lane;
+	}
+}
+
+static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
+{
+	int lane, lane_count, retval;
+	u8 voltage_swing, pre_emphasis, training_lane;
+	u8 link_status[2], adjust_request[2];
+
+	usleep_range(100, 101);
+
+	lane_count = dp->link_train.lane_count;
+
+	retval =  exynos_dp_read_bytes_from_dpcd(dp,
+			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
+	if (retval)
+		return retval;
+
+	retval =  exynos_dp_read_bytes_from_dpcd(dp,
+			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+	if (retval)
+		return retval;
+
+	if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
+		/* set training pattern 2 for EQ */
+		exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
+
+		retval = exynos_dp_write_byte_to_dpcd(dp,
+				DPCD_ADDR_TRAINING_PATTERN_SET,
+				DPCD_SCRAMBLING_DISABLED |
+				DPCD_TRAINING_PATTERN_2);
+		if (retval)
+			return retval;
+
+		dev_info(dp->dev, "Link Training Clock Recovery success\n");
+		dp->link_train.lt_state = EQUALIZER_TRAINING;
+	} else {
+		for (lane = 0; lane < lane_count; lane++) {
+			training_lane = exynos_dp_get_lane_link_training(
+							dp, lane);
+			voltage_swing = exynos_dp_get_adjust_request_voltage(
+							adjust_request, lane);
+			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
+							adjust_request, lane);
+
+			if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
+					voltage_swing &&
+			    DPCD_PRE_EMPHASIS_GET(training_lane) ==
+					pre_emphasis)
+				dp->link_train.cr_loop[lane]++;
+
+			if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
+			    voltage_swing == VOLTAGE_LEVEL_3 ||
+			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
+				dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
+					dp->link_train.cr_loop[lane],
+					voltage_swing, pre_emphasis);
+				exynos_dp_reduce_link_rate(dp);
+				return -EIO;
+			}
+		}
+	}
+
+	exynos_dp_get_adjust_training_lane(dp, adjust_request);
+
+	for (lane = 0; lane < lane_count; lane++)
+		exynos_dp_set_lane_link_training(dp,
+			dp->link_train.training_lane[lane], lane);
+
+	retval = exynos_dp_write_bytes_to_dpcd(dp,
+			DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
+			dp->link_train.training_lane);
+	if (retval)
+		return retval;
+
+	return retval;
+}
+
+static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
+{
+	int lane, lane_count, retval;
+	u32 reg;
+	u8 link_align, link_status[2], adjust_request[2];
+
+	usleep_range(400, 401);
+
+	lane_count = dp->link_train.lane_count;
+
+	retval = exynos_dp_read_bytes_from_dpcd(dp,
+			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
+	if (retval)
+		return retval;
+
+	if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
+		exynos_dp_reduce_link_rate(dp);
+		return -EIO;
+	}
+
+	retval = exynos_dp_read_bytes_from_dpcd(dp,
+			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+	if (retval)
+		return retval;
+
+	retval = exynos_dp_read_byte_from_dpcd(dp,
+			DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
+	if (retval)
+		return retval;
+
+	exynos_dp_get_adjust_training_lane(dp, adjust_request);
+
+	if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) {
+		/* traing pattern Set to Normal */
+		exynos_dp_training_pattern_dis(dp);
+
+		dev_info(dp->dev, "Link Training success!\n");
+
+		exynos_dp_get_link_bandwidth(dp, &reg);
+		dp->link_train.link_rate = reg;
+		dev_dbg(dp->dev, "final bandwidth = %.2x\n",
+			dp->link_train.link_rate);
+
+		exynos_dp_get_lane_count(dp, &reg);
+		dp->link_train.lane_count = reg;
+		dev_dbg(dp->dev, "final lane count = %.2x\n",
+			dp->link_train.lane_count);
+
+		/* set enhanced mode if available */
+		exynos_dp_set_enhanced_mode(dp);
+		dp->link_train.lt_state = FINISHED;
+
+		return 0;
+	}
+
+	/* not all locked */
+	dp->link_train.eq_loop++;
+
+	if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
+		dev_err(dp->dev, "EQ Max loop\n");
+		exynos_dp_reduce_link_rate(dp);
+		return -EIO;
+	}
+
+	for (lane = 0; lane < lane_count; lane++)
+		exynos_dp_set_lane_link_training(dp,
+			dp->link_train.training_lane[lane], lane);
+
+	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
+			lane_count, dp->link_train.training_lane);
+
+	return retval;
+}
+
+static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
+					u8 *bandwidth)
+{
+	u8 data;
+
+	/*
+	 * For DP rev.1.1, Maximum link rate of Main Link lanes
+	 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
+	 */
+	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
+	*bandwidth = data;
+}
+
+static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
+					u8 *lane_count)
+{
+	u8 data;
+
+	/*
+	 * For DP rev.1.1, Maximum number of Main Link lanes
+	 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
+	 */
+	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
+	*lane_count = DPCD_MAX_LANE_COUNT(data);
+}
+
+static void exynos_dp_init_training(struct exynos_dp_device *dp,
+			enum link_lane_count_type max_lane,
+			enum link_rate_type max_rate)
+{
+	/*
+	 * MACRO_RST must be applied after the PLL_LOCK to avoid
+	 * the DP inter pair skew issue for at least 10 us
+	 */
+	exynos_dp_reset_macro(dp);
+
+	/* Initialize by reading RX's DPCD */
+	exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
+	exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
+
+	if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
+	   (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
+		dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
+			dp->link_train.link_rate);
+		dp->link_train.link_rate = LINK_RATE_1_62GBPS;
+	}
+
+	if (dp->link_train.lane_count == 0) {
+		dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
+			dp->link_train.lane_count);
+		dp->link_train.lane_count = (u8)LANE_COUNT1;
+	}
+
+	/* Setup TX lane count & rate */
+	if (dp->link_train.lane_count > max_lane)
+		dp->link_train.lane_count = max_lane;
+	if (dp->link_train.link_rate > max_rate)
+		dp->link_train.link_rate = max_rate;
+
+	/* All DP analog module power up */
+	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
+}
+
+static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
+{
+	int retval = 0, training_finished = 0;
+
+	dp->link_train.lt_state = START;
+
+	/* Process here */
+	while (!retval && !training_finished) {
+		switch (dp->link_train.lt_state) {
+		case START:
+			retval = exynos_dp_link_start(dp);
+			if (retval)
+				dev_err(dp->dev, "LT link start failed!\n");
+			break;
+		case CLOCK_RECOVERY:
+			retval = exynos_dp_process_clock_recovery(dp);
+			if (retval)
+				dev_err(dp->dev, "LT CR failed!\n");
+			break;
+		case EQUALIZER_TRAINING:
+			retval = exynos_dp_process_equalizer_training(dp);
+			if (retval)
+				dev_err(dp->dev, "LT EQ failed!\n");
+			break;
+		case FINISHED:
+			training_finished = 1;
+			break;
+		case FAILED:
+			return -EREMOTEIO;
+		}
+	}
+	if (retval)
+		dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
+
+	return retval;
+}
+
+static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
+				u32 count,
+				u32 bwtype)
+{
+	int i;
+	int retval;
+
+	for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
+		exynos_dp_init_training(dp, count, bwtype);
+		retval = exynos_dp_sw_link_training(dp);
+		if (retval == 0)
+			break;
+
+		usleep_range(100, 110);
+	}
+
+	return retval;
+}
+
+static int exynos_dp_config_video(struct exynos_dp_device *dp)
+{
+	int retval = 0;
+	int timeout_loop = 0;
+	int done_count = 0;
+
+	exynos_dp_config_video_slave_mode(dp);
+
+	exynos_dp_set_video_color_format(dp);
+
+	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+		dev_err(dp->dev, "PLL is not locked yet.\n");
+		return -EINVAL;
+	}
+
+	for (;;) {
+		timeout_loop++;
+		if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
+			break;
+		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+			dev_err(dp->dev, "Timeout of video streamclk ok\n");
+			return -ETIMEDOUT;
+		}
+
+		usleep_range(1, 2);
+	}
+
+	/* Set to use the register calculated M/N video */
+	exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
+
+	/* For video bist, Video timing must be generated by register */
+	exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
+
+	/* Disable video mute */
+	exynos_dp_enable_video_mute(dp, 0);
+
+	/* Configure video slave mode */
+	exynos_dp_enable_video_master(dp, 0);
+
+	/* Enable video */
+	exynos_dp_start_video(dp);
+
+	timeout_loop = 0;
+
+	for (;;) {
+		timeout_loop++;
+		if (exynos_dp_is_video_stream_on(dp) == 0) {
+			done_count++;
+			if (done_count > 10)
+				break;
+		} else if (done_count) {
+			done_count = 0;
+		}
+		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+			dev_err(dp->dev, "Timeout of video streamclk ok\n");
+			return -ETIMEDOUT;
+		}
+
+		usleep_range(1000, 1001);
+	}
+
+	if (retval != 0)
+		dev_err(dp->dev, "Video stream is not detected!\n");
+
+	return retval;
+}
+
+static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable)
+{
+	u8 data;
+
+	if (enable) {
+		exynos_dp_enable_scrambling(dp);
+
+		exynos_dp_read_byte_from_dpcd(dp,
+			DPCD_ADDR_TRAINING_PATTERN_SET,
+			&data);
+		exynos_dp_write_byte_to_dpcd(dp,
+			DPCD_ADDR_TRAINING_PATTERN_SET,
+			(u8)(data & ~DPCD_SCRAMBLING_DISABLED));
+	} else {
+		exynos_dp_disable_scrambling(dp);
+
+		exynos_dp_read_byte_from_dpcd(dp,
+			DPCD_ADDR_TRAINING_PATTERN_SET,
+			&data);
+		exynos_dp_write_byte_to_dpcd(dp,
+			DPCD_ADDR_TRAINING_PATTERN_SET,
+			(u8)(data | DPCD_SCRAMBLING_DISABLED));
+	}
+}
+
+static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
+{
+	struct exynos_dp_device *dp = arg;
+
+	enum dp_irq_type irq_type;
+
+	irq_type = exynos_dp_get_irq_type(dp);
+	switch (irq_type) {
+	case DP_IRQ_TYPE_HP_CABLE_IN:
+		dev_dbg(dp->dev, "Received irq - cable in\n");
+		schedule_work(&dp->hotplug_work);
+		exynos_dp_clear_hotplug_interrupts(dp);
+		break;
+	case DP_IRQ_TYPE_HP_CABLE_OUT:
+		dev_dbg(dp->dev, "Received irq - cable out\n");
+		exynos_dp_clear_hotplug_interrupts(dp);
+		break;
+	case DP_IRQ_TYPE_HP_CHANGE:
+		/*
+		 * We get these change notifications once in a while, but there
+		 * is nothing we can do with them. Just ignore it for now and
+		 * only handle cable changes.
+		 */
+		dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
+		exynos_dp_clear_hotplug_interrupts(dp);
+		break;
+	default:
+		dev_err(dp->dev, "Received irq - unknown type!\n");
+		break;
+	}
+	return IRQ_HANDLED;
+}
+
+static void exynos_dp_hotplug(struct work_struct *work)
+{
+	struct exynos_dp_device *dp;
+	int ret;
+
+	dp = container_of(work, struct exynos_dp_device, hotplug_work);
+
+	ret = exynos_dp_detect_hpd(dp);
+	if (ret) {
+		/* Cable has been disconnected, we're done */
+		return;
+	}
+
+	ret = exynos_dp_handle_edid(dp);
+	if (ret) {
+		dev_err(dp->dev, "unable to handle edid\n");
+		return;
+	}
+
+	ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
+					dp->video_info->link_rate);
+	if (ret) {
+		dev_err(dp->dev, "unable to do link train\n");
+		return;
+	}
+
+	exynos_dp_enable_scramble(dp, 1);
+	exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
+	exynos_dp_enable_enhanced_mode(dp, 1);
+
+	exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
+	exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
+
+	exynos_dp_init_video(dp);
+	ret = exynos_dp_config_video(dp);
+	if (ret)
+		dev_err(dp->dev, "unable to config video\n");
+}
+
+#ifdef CONFIG_OF
+static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+	struct device_node *dp_node = dev->of_node;
+	struct exynos_dp_platdata *pd;
+	struct video_info *dp_video_config;
+
+	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+	if (!pd) {
+		dev_err(dev, "memory allocation for pdata failed\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	dp_video_config = devm_kzalloc(dev,
+				sizeof(*dp_video_config), GFP_KERNEL);
+
+	if (!dp_video_config) {
+		dev_err(dev, "memory allocation for video config failed\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	pd->video_info = dp_video_config;
+
+	dp_video_config->h_sync_polarity =
+		of_property_read_bool(dp_node, "hsync-active-high");
+
+	dp_video_config->v_sync_polarity =
+		of_property_read_bool(dp_node, "vsync-active-high");
+
+	dp_video_config->interlaced =
+		of_property_read_bool(dp_node, "interlaced");
+
+	if (of_property_read_u32(dp_node, "samsung,color-space",
+				&dp_video_config->color_space)) {
+		dev_err(dev, "failed to get color-space\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,dynamic-range",
+				&dp_video_config->dynamic_range)) {
+		dev_err(dev, "failed to get dynamic-range\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
+				&dp_video_config->ycbcr_coeff)) {
+		dev_err(dev, "failed to get ycbcr-coeff\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,color-depth",
+				&dp_video_config->color_depth)) {
+		dev_err(dev, "failed to get color-depth\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,link-rate",
+				&dp_video_config->link_rate)) {
+		dev_err(dev, "failed to get link-rate\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,lane-count",
+				&dp_video_config->lane_count)) {
+		dev_err(dev, "failed to get lane-count\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	return pd;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+	struct device_node *dp_phy_node = of_node_get(dp->dev->of_node);
+	u32 phy_base;
+	int ret = 0;
+
+	dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
+	if (!dp_phy_node) {
+		dev_err(dp->dev, "could not find dptx-phy node\n");
+		return -ENODEV;
+	}
+
+	if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
+		dev_err(dp->dev, "failed to get reg for dptx-phy\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
+				&dp->enable_mask)) {
+		dev_err(dp->dev, "failed to get enable-mask for dptx-phy\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	dp->phy_addr = ioremap(phy_base, SZ_4);
+	if (!dp->phy_addr) {
+		dev_err(dp->dev, "failed to ioremap dp-phy\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+err:
+	of_node_put(dp_phy_node);
+
+	return ret;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = __raw_readl(dp->phy_addr);
+	reg |= dp->enable_mask;
+	__raw_writel(reg, dp->phy_addr);
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = __raw_readl(dp->phy_addr);
+	reg &= ~(dp->enable_mask);
+	__raw_writel(reg, dp->phy_addr);
+}
+#else
+static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+	return NULL;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+	return -EINVAL;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+	return;
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+	return;
+}
+#endif /* CONFIG_OF */
+
+static int exynos_dp_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct exynos_dp_device *dp;
+	struct exynos_dp_platdata *pdata;
+
+	int ret = 0;
+
+	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
+				GFP_KERNEL);
+	if (!dp) {
+		dev_err(&pdev->dev, "no memory for device data\n");
+		return -ENOMEM;
+	}
+
+	dp->dev = &pdev->dev;
+
+	if (pdev->dev.of_node) {
+		pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+
+		ret = exynos_dp_dt_parse_phydata(dp);
+		if (ret)
+			return ret;
+	} else {
+		pdata = pdev->dev.platform_data;
+		if (!pdata) {
+			dev_err(&pdev->dev, "no platform data\n");
+			return -EINVAL;
+		}
+	}
+
+	dp->clock = devm_clk_get(&pdev->dev, "dp");
+	if (IS_ERR(dp->clock)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		return PTR_ERR(dp->clock);
+	}
+
+	clk_prepare_enable(dp->clock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dp->reg_base))
+		return PTR_ERR(dp->reg_base);
+
+	dp->irq = platform_get_irq(pdev, 0);
+	if (dp->irq == -ENXIO) {
+		dev_err(&pdev->dev, "failed to get irq\n");
+		return -ENODEV;
+	}
+
+	INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
+
+	dp->video_info = pdata->video_info;
+
+	if (pdev->dev.of_node) {
+		if (dp->phy_addr)
+			exynos_dp_phy_init(dp);
+	} else {
+		if (pdata->phy_init)
+			pdata->phy_init();
+	}
+
+	exynos_dp_init_dp(dp);
+
+	ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
+				"exynos-dp", dp);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request irq\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, dp);
+
+	return 0;
+}
+
+static int exynos_dp_remove(struct platform_device *pdev)
+{
+	struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
+	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
+
+	flush_work(&dp->hotplug_work);
+
+	if (pdev->dev.of_node) {
+		if (dp->phy_addr)
+			exynos_dp_phy_exit(dp);
+	} else {
+		if (pdata->phy_exit)
+			pdata->phy_exit();
+	}
+
+	clk_disable_unprepare(dp->clock);
+
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos_dp_suspend(struct device *dev)
+{
+	struct exynos_dp_platdata *pdata = dev->platform_data;
+	struct exynos_dp_device *dp = dev_get_drvdata(dev);
+
+	disable_irq(dp->irq);
+
+	flush_work(&dp->hotplug_work);
+
+	if (dev->of_node) {
+		if (dp->phy_addr)
+			exynos_dp_phy_exit(dp);
+	} else {
+		if (pdata->phy_exit)
+			pdata->phy_exit();
+	}
+
+	clk_disable_unprepare(dp->clock);
+
+	return 0;
+}
+
+static int exynos_dp_resume(struct device *dev)
+{
+	struct exynos_dp_platdata *pdata = dev->platform_data;
+	struct exynos_dp_device *dp = dev_get_drvdata(dev);
+
+	if (dev->of_node) {
+		if (dp->phy_addr)
+			exynos_dp_phy_init(dp);
+	} else {
+		if (pdata->phy_init)
+			pdata->phy_init();
+	}
+
+	clk_prepare_enable(dp->clock);
+
+	exynos_dp_init_dp(dp);
+
+	enable_irq(dp->irq);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops exynos_dp_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
+};
+
+static const struct of_device_id exynos_dp_match[] = {
+	{ .compatible = "samsung,exynos5-dp" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_match);
+
+static struct platform_driver exynos_dp_driver = {
+	.probe		= exynos_dp_probe,
+	.remove		= exynos_dp_remove,
+	.driver		= {
+		.name	= "exynos-dp",
+		.owner	= THIS_MODULE,
+		.pm	= &exynos_dp_pm_ops,
+		.of_match_table = of_match_ptr(exynos_dp_match),
+	},
+};
+
+module_platform_driver(exynos_dp_driver);
+
+MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung SoC DP Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h
new file mode 100644
index 0000000..6c567bbf
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
@@ -0,0 +1,210 @@
+/*
+ * Header file for Samsung DP (Display Port) interface driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * 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 _EXYNOS_DP_CORE_H
+#define _EXYNOS_DP_CORE_H
+
+enum dp_irq_type {
+	DP_IRQ_TYPE_HP_CABLE_IN,
+	DP_IRQ_TYPE_HP_CABLE_OUT,
+	DP_IRQ_TYPE_HP_CHANGE,
+	DP_IRQ_TYPE_UNKNOWN,
+};
+
+struct link_train {
+	int eq_loop;
+	int cr_loop[4];
+
+	u8 link_rate;
+	u8 lane_count;
+	u8 training_lane[4];
+
+	enum link_training_state lt_state;
+};
+
+struct exynos_dp_device {
+	struct device		*dev;
+	struct clk		*clock;
+	unsigned int		irq;
+	void __iomem		*reg_base;
+	void __iomem		*phy_addr;
+	unsigned int		enable_mask;
+
+	struct video_info	*video_info;
+	struct link_train	link_train;
+	struct work_struct	hotplug_work;
+};
+
+/* exynos_dp_reg.c */
+void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_stop_video(struct exynos_dp_device *dp);
+void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
+void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
+void exynos_dp_reset(struct exynos_dp_device *dp);
+void exynos_dp_swreset(struct exynos_dp_device *dp);
+void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
+enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
+void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
+				enum analog_power_block block,
+				bool enable);
+void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
+void exynos_dp_init_hpd(struct exynos_dp_device *dp);
+enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
+void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
+void exynos_dp_reset_aux(struct exynos_dp_device *dp);
+void exynos_dp_init_aux(struct exynos_dp_device *dp);
+int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
+void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
+int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
+int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned char data);
+int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned char *data);
+int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned int count,
+				unsigned char data[]);
+int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned int count,
+				unsigned char data[]);
+int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
+				unsigned int device_addr,
+				unsigned int reg_addr);
+int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
+				unsigned int device_addr,
+				unsigned int reg_addr,
+				unsigned int *data);
+int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
+				unsigned int device_addr,
+				unsigned int reg_addr,
+				unsigned int count,
+				unsigned char edid[]);
+void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
+void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
+void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
+void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
+void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
+				 enum pattern_set pattern);
+void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level);
+void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level);
+void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level);
+void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level);
+void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
+				u32 training_lane);
+void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
+				u32 training_lane);
+void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
+				u32 training_lane);
+void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
+				u32 training_lane);
+u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
+u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
+u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
+u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
+void exynos_dp_reset_macro(struct exynos_dp_device *dp);
+void exynos_dp_init_video(struct exynos_dp_device *dp);
+
+void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
+int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
+void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
+			enum clock_recovery_m_value_type type,
+			u32 m_value,
+			u32 n_value);
+void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
+void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
+void exynos_dp_start_video(struct exynos_dp_device *dp);
+int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
+void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
+void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
+void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
+
+/* I2C EDID Chip ID, Slave Address */
+#define I2C_EDID_DEVICE_ADDR			0x50
+#define I2C_E_EDID_DEVICE_ADDR			0x30
+
+#define EDID_BLOCK_LENGTH			0x80
+#define EDID_HEADER_PATTERN			0x00
+#define EDID_EXTENSION_FLAG			0x7e
+#define EDID_CHECKSUM				0x7f
+
+/* Definition for DPCD Register */
+#define DPCD_ADDR_DPCD_REV			0x0000
+#define DPCD_ADDR_MAX_LINK_RATE			0x0001
+#define DPCD_ADDR_MAX_LANE_COUNT		0x0002
+#define DPCD_ADDR_LINK_BW_SET			0x0100
+#define DPCD_ADDR_LANE_COUNT_SET		0x0101
+#define DPCD_ADDR_TRAINING_PATTERN_SET		0x0102
+#define DPCD_ADDR_TRAINING_LANE0_SET		0x0103
+#define DPCD_ADDR_LANE0_1_STATUS		0x0202
+#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED	0x0204
+#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1	0x0206
+#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3	0x0207
+#define DPCD_ADDR_TEST_REQUEST			0x0218
+#define DPCD_ADDR_TEST_RESPONSE			0x0260
+#define DPCD_ADDR_TEST_EDID_CHECKSUM		0x0261
+#define DPCD_ADDR_SINK_POWER_STATE		0x0600
+
+/* DPCD_ADDR_MAX_LANE_COUNT */
+#define DPCD_ENHANCED_FRAME_CAP(x)		(((x) >> 7) & 0x1)
+#define DPCD_MAX_LANE_COUNT(x)			((x) & 0x1f)
+
+/* DPCD_ADDR_LANE_COUNT_SET */
+#define DPCD_ENHANCED_FRAME_EN			(0x1 << 7)
+#define DPCD_LANE_COUNT_SET(x)			((x) & 0x1f)
+
+/* DPCD_ADDR_TRAINING_PATTERN_SET */
+#define DPCD_SCRAMBLING_DISABLED		(0x1 << 5)
+#define DPCD_SCRAMBLING_ENABLED			(0x0 << 5)
+#define DPCD_TRAINING_PATTERN_2			(0x2 << 0)
+#define DPCD_TRAINING_PATTERN_1			(0x1 << 0)
+#define DPCD_TRAINING_PATTERN_DISABLED		(0x0 << 0)
+
+/* DPCD_ADDR_TRAINING_LANE0_SET */
+#define DPCD_MAX_PRE_EMPHASIS_REACHED		(0x1 << 5)
+#define DPCD_PRE_EMPHASIS_SET(x)		(((x) & 0x3) << 3)
+#define DPCD_PRE_EMPHASIS_GET(x)		(((x) >> 3) & 0x3)
+#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0	(0x0 << 3)
+#define DPCD_MAX_SWING_REACHED			(0x1 << 2)
+#define DPCD_VOLTAGE_SWING_SET(x)		(((x) & 0x3) << 0)
+#define DPCD_VOLTAGE_SWING_GET(x)		(((x) >> 0) & 0x3)
+#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0	(0x0 << 0)
+
+/* DPCD_ADDR_LANE0_1_STATUS */
+#define DPCD_LANE_SYMBOL_LOCKED			(0x1 << 2)
+#define DPCD_LANE_CHANNEL_EQ_DONE		(0x1 << 1)
+#define DPCD_LANE_CR_DONE			(0x1 << 0)
+#define DPCD_CHANNEL_EQ_BITS			(DPCD_LANE_CR_DONE|	\
+						 DPCD_LANE_CHANNEL_EQ_DONE|\
+						 DPCD_LANE_SYMBOL_LOCKED)
+
+/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
+#define DPCD_LINK_STATUS_UPDATED		(0x1 << 7)
+#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED	(0x1 << 6)
+#define DPCD_INTERLANE_ALIGN_DONE		(0x1 << 0)
+
+/* DPCD_ADDR_TEST_REQUEST */
+#define DPCD_TEST_EDID_READ			(0x1 << 2)
+
+/* DPCD_ADDR_TEST_RESPONSE */
+#define DPCD_TEST_EDID_CHECKSUM_WRITE		(0x1 << 2)
+
+/* DPCD_ADDR_SINK_POWER_STATE */
+#define DPCD_SET_POWER_STATE_D0			(0x1 << 0)
+#define DPCD_SET_POWER_STATE_D4			(0x2 << 0)
+
+#endif /* _EXYNOS_DP_CORE_H */
diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.c b/drivers/gpu/drm/exynos/exynos_dp_reg.c
new file mode 100644
index 0000000..29d9d03
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_dp_reg.c
@@ -0,0 +1,1245 @@
+/*
+ * Samsung DP (Display port) register interface driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * 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/device.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include <video/exynos_dp.h>
+
+#include "exynos_dp_core.h"
+#include "exynos_dp_reg.h"
+
+#define COMMON_INT_MASK_1	0
+#define COMMON_INT_MASK_2	0
+#define COMMON_INT_MASK_3	0
+#define COMMON_INT_MASK_4	(HOTPLUG_CHG | HPD_LOST | PLUG)
+#define INT_STA_MASK		INT_HPD
+
+void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable) {
+		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+		reg |= HDCP_VIDEO_MUTE;
+		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+	} else {
+		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+		reg &= ~HDCP_VIDEO_MUTE;
+		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+	}
+}
+
+void exynos_dp_stop_video(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+	reg &= ~VIDEO_EN;
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+}
+
+void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable)
+		reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
+			LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
+	else
+		reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
+			LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
+
+	writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
+}
+
+void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = TX_TERMINAL_CTRL_50_OHM;
+	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
+
+	reg = SEL_24M | TX_DVDD_BIT_1_0625V;
+	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
+
+	reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
+	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
+
+	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
+		TX_CUR1_2X | TX_CUR_16_MA;
+	writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
+
+	reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
+		CH1_AMP_400_MV | CH0_AMP_400_MV;
+	writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
+}
+
+void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
+{
+	/* Set interrupt pin assertion polarity as high */
+	writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
+
+	/* Clear pending regisers */
+	writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
+	writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
+	writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
+	writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
+	writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
+
+	/* 0:mask,1: unmask */
+	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
+	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
+	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
+	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
+	writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
+}
+
+void exynos_dp_reset(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	exynos_dp_stop_video(dp);
+	exynos_dp_enable_video_mute(dp, 0);
+
+	reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
+		AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
+		HDCP_FUNC_EN_N | SW_FUNC_EN_N;
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+
+	reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
+		SERDES_FIFO_FUNC_EN_N |
+		LS_CLK_DOMAIN_FUNC_EN_N;
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+
+	usleep_range(20, 30);
+
+	exynos_dp_lane_swap(dp, 0);
+
+	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+	writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+
+	writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
+	writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
+
+	writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
+	writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
+
+	writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
+
+	writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
+
+	writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
+	writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
+
+	writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
+	writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
+
+	writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+}
+
+void exynos_dp_swreset(struct exynos_dp_device *dp)
+{
+	writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
+}
+
+void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	/* 0: mask, 1: unmask */
+	reg = COMMON_INT_MASK_1;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
+
+	reg = COMMON_INT_MASK_2;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
+
+	reg = COMMON_INT_MASK_3;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
+
+	reg = COMMON_INT_MASK_4;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
+
+	reg = INT_STA_MASK;
+	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
+}
+
+enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
+	if (reg & PLL_LOCK)
+		return PLL_LOCKED;
+	else
+		return PLL_UNLOCKED;
+}
+
+void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable) {
+		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
+		reg |= DP_PLL_PD;
+		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
+	} else {
+		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
+		reg &= ~DP_PLL_PD;
+		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
+	}
+}
+
+void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
+				enum analog_power_block block,
+				bool enable)
+{
+	u32 reg;
+
+	switch (block) {
+	case AUX_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg |= AUX_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg &= ~AUX_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	case CH0_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg |= CH0_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg &= ~CH0_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	case CH1_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg |= CH1_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg &= ~CH1_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	case CH2_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg |= CH2_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg &= ~CH2_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	case CH3_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg |= CH3_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg &= ~CH3_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	case ANALOG_TOTAL:
+		if (enable) {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg |= DP_PHY_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
+			reg &= ~DP_PHY_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	case POWER_ALL:
+		if (enable) {
+			reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
+				CH1_PD | CH0_PD;
+			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
+		} else {
+			writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
+{
+	u32 reg;
+	int timeout_loop = 0;
+
+	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
+
+	reg = PLL_LOCK_CHG;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
+	reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
+	writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
+
+	/* Power up PLL */
+	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+		exynos_dp_set_pll_power_down(dp, 0);
+
+		while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+			timeout_loop++;
+			if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+				dev_err(dp->dev, "failed to get pll lock status\n");
+				return;
+			}
+			usleep_range(10, 20);
+		}
+	}
+
+	/* Enable Serdes FIFO function and Link symbol clock domain module */
+	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+	reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
+		| AUX_FUNC_EN_N);
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+}
+
+void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = HOTPLUG_CHG | HPD_LOST | PLUG;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
+
+	reg = INT_HPD;
+	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
+}
+
+void exynos_dp_init_hpd(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	exynos_dp_clear_hotplug_interrupts(dp);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+	reg &= ~(F_HPD | HPD_CTRL);
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+}
+
+enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	/* Parse hotplug interrupt status register */
+	reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
+
+	if (reg & PLUG)
+		return DP_IRQ_TYPE_HP_CABLE_IN;
+
+	if (reg & HPD_LOST)
+		return DP_IRQ_TYPE_HP_CABLE_OUT;
+
+	if (reg & HOTPLUG_CHG)
+		return DP_IRQ_TYPE_HP_CHANGE;
+
+	return DP_IRQ_TYPE_UNKNOWN;
+}
+
+void exynos_dp_reset_aux(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	/* Disable AUX channel module */
+	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+	reg |= AUX_FUNC_EN_N;
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+}
+
+void exynos_dp_init_aux(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	/* Clear inerrupts related to AUX channel */
+	reg = RPLY_RECEIV | AUX_ERR;
+	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
+
+	exynos_dp_reset_aux(dp);
+
+	/* Disable AUX transaction H/W retry */
+	reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
+		AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
+	writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
+
+	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
+	reg = DEFER_CTRL_EN | DEFER_COUNT(1);
+	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
+
+	/* Enable AUX channel module */
+	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+	reg &= ~AUX_FUNC_EN_N;
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
+}
+
+int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+	if (reg & HPD_STATUS)
+		return 0;
+
+	return -EINVAL;
+}
+
+void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+	reg &= ~SW_FUNC_EN_N;
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+}
+
+int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
+{
+	int reg;
+	int retval = 0;
+	int timeout_loop = 0;
+
+	/* Enable AUX CH operation */
+	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
+	reg |= AUX_EN;
+	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
+
+	/* Is AUX CH command reply received? */
+	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
+	while (!(reg & RPLY_RECEIV)) {
+		timeout_loop++;
+		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+			dev_err(dp->dev, "AUX CH command reply failed!\n");
+			return -ETIMEDOUT;
+		}
+		reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
+		usleep_range(10, 11);
+	}
+
+	/* Clear interrupt source for AUX CH command reply */
+	writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
+
+	/* Clear interrupt source for AUX CH access error */
+	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
+	if (reg & AUX_ERR) {
+		writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
+		return -EREMOTEIO;
+	}
+
+	/* Check AUX CH error access status */
+	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
+	if ((reg & AUX_STATUS_MASK) != 0) {
+		dev_err(dp->dev, "AUX CH error happens: %d\n\n",
+			reg & AUX_STATUS_MASK);
+		return -EREMOTEIO;
+	}
+
+	return retval;
+}
+
+int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned char data)
+{
+	u32 reg;
+	int i;
+	int retval;
+
+	for (i = 0; i < 3; i++) {
+		/* Clear AUX CH data buffer */
+		reg = BUF_CLR;
+		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+		/* Select DPCD device address */
+		reg = AUX_ADDR_7_0(reg_addr);
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+		reg = AUX_ADDR_15_8(reg_addr);
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+		reg = AUX_ADDR_19_16(reg_addr);
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+		/* Write data buffer */
+		reg = (unsigned int)data;
+		writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
+
+		/*
+		 * Set DisplayPort transaction and write 1 byte
+		 * If bit 3 is 1, DisplayPort transaction.
+		 * If Bit 3 is 0, I2C transaction.
+		 */
+		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+		/* Start AUX transaction */
+		retval = exynos_dp_start_aux_transaction(dp);
+		if (retval == 0)
+			break;
+		else
+			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+				__func__);
+	}
+
+	return retval;
+}
+
+int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned char *data)
+{
+	u32 reg;
+	int i;
+	int retval;
+
+	for (i = 0; i < 3; i++) {
+		/* Clear AUX CH data buffer */
+		reg = BUF_CLR;
+		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+		/* Select DPCD device address */
+		reg = AUX_ADDR_7_0(reg_addr);
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+		reg = AUX_ADDR_15_8(reg_addr);
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+		reg = AUX_ADDR_19_16(reg_addr);
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+		/*
+		 * Set DisplayPort transaction and read 1 byte
+		 * If bit 3 is 1, DisplayPort transaction.
+		 * If Bit 3 is 0, I2C transaction.
+		 */
+		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+		/* Start AUX transaction */
+		retval = exynos_dp_start_aux_transaction(dp);
+		if (retval == 0)
+			break;
+		else
+			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+				__func__);
+	}
+
+	/* Read data buffer */
+	reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
+	*data = (unsigned char)(reg & 0xff);
+
+	return retval;
+}
+
+int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned int count,
+				unsigned char data[])
+{
+	u32 reg;
+	unsigned int start_offset;
+	unsigned int cur_data_count;
+	unsigned int cur_data_idx;
+	int i;
+	int retval = 0;
+
+	/* Clear AUX CH data buffer */
+	reg = BUF_CLR;
+	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+	start_offset = 0;
+	while (start_offset < count) {
+		/* Buffer size of AUX CH is 16 * 4bytes */
+		if ((count - start_offset) > 16)
+			cur_data_count = 16;
+		else
+			cur_data_count = count - start_offset;
+
+		for (i = 0; i < 3; i++) {
+			/* Select DPCD device address */
+			reg = AUX_ADDR_7_0(reg_addr + start_offset);
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+			reg = AUX_ADDR_15_8(reg_addr + start_offset);
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+			reg = AUX_ADDR_19_16(reg_addr + start_offset);
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+			for (cur_data_idx = 0; cur_data_idx < cur_data_count;
+			     cur_data_idx++) {
+				reg = data[start_offset + cur_data_idx];
+				writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0
+							  + 4 * cur_data_idx);
+			}
+
+			/*
+			 * Set DisplayPort transaction and write
+			 * If bit 3 is 1, DisplayPort transaction.
+			 * If Bit 3 is 0, I2C transaction.
+			 */
+			reg = AUX_LENGTH(cur_data_count) |
+				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+			/* Start AUX transaction */
+			retval = exynos_dp_start_aux_transaction(dp);
+			if (retval == 0)
+				break;
+			else
+				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+					__func__);
+		}
+
+		start_offset += cur_data_count;
+	}
+
+	return retval;
+}
+
+int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
+				unsigned int reg_addr,
+				unsigned int count,
+				unsigned char data[])
+{
+	u32 reg;
+	unsigned int start_offset;
+	unsigned int cur_data_count;
+	unsigned int cur_data_idx;
+	int i;
+	int retval = 0;
+
+	/* Clear AUX CH data buffer */
+	reg = BUF_CLR;
+	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+	start_offset = 0;
+	while (start_offset < count) {
+		/* Buffer size of AUX CH is 16 * 4bytes */
+		if ((count - start_offset) > 16)
+			cur_data_count = 16;
+		else
+			cur_data_count = count - start_offset;
+
+		/* AUX CH Request Transaction process */
+		for (i = 0; i < 3; i++) {
+			/* Select DPCD device address */
+			reg = AUX_ADDR_7_0(reg_addr + start_offset);
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+			reg = AUX_ADDR_15_8(reg_addr + start_offset);
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+			reg = AUX_ADDR_19_16(reg_addr + start_offset);
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+			/*
+			 * Set DisplayPort transaction and read
+			 * If bit 3 is 1, DisplayPort transaction.
+			 * If Bit 3 is 0, I2C transaction.
+			 */
+			reg = AUX_LENGTH(cur_data_count) |
+				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+			/* Start AUX transaction */
+			retval = exynos_dp_start_aux_transaction(dp);
+			if (retval == 0)
+				break;
+			else
+				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+					__func__);
+		}
+
+		for (cur_data_idx = 0; cur_data_idx < cur_data_count;
+		    cur_data_idx++) {
+			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
+						 + 4 * cur_data_idx);
+			data[start_offset + cur_data_idx] =
+				(unsigned char)reg;
+		}
+
+		start_offset += cur_data_count;
+	}
+
+	return retval;
+}
+
+int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
+				unsigned int device_addr,
+				unsigned int reg_addr)
+{
+	u32 reg;
+	int retval;
+
+	/* Set EDID device address */
+	reg = device_addr;
+	writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
+	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
+	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
+
+	/* Set offset from base address of EDID device */
+	writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
+
+	/*
+	 * Set I2C transaction and write address
+	 * If bit 3 is 1, DisplayPort transaction.
+	 * If Bit 3 is 0, I2C transaction.
+	 */
+	reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
+		AUX_TX_COMM_WRITE;
+	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+	/* Start AUX transaction */
+	retval = exynos_dp_start_aux_transaction(dp);
+	if (retval != 0)
+		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
+
+	return retval;
+}
+
+int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
+				unsigned int device_addr,
+				unsigned int reg_addr,
+				unsigned int *data)
+{
+	u32 reg;
+	int i;
+	int retval;
+
+	for (i = 0; i < 3; i++) {
+		/* Clear AUX CH data buffer */
+		reg = BUF_CLR;
+		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+		/* Select EDID device */
+		retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
+		if (retval != 0)
+			continue;
+
+		/*
+		 * Set I2C transaction and read data
+		 * If bit 3 is 1, DisplayPort transaction.
+		 * If Bit 3 is 0, I2C transaction.
+		 */
+		reg = AUX_TX_COMM_I2C_TRANSACTION |
+			AUX_TX_COMM_READ;
+		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
+
+		/* Start AUX transaction */
+		retval = exynos_dp_start_aux_transaction(dp);
+		if (retval == 0)
+			break;
+		else
+			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+				__func__);
+	}
+
+	/* Read data */
+	if (retval == 0)
+		*data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
+
+	return retval;
+}
+
+int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
+				unsigned int device_addr,
+				unsigned int reg_addr,
+				unsigned int count,
+				unsigned char edid[])
+{
+	u32 reg;
+	unsigned int i, j;
+	unsigned int cur_data_idx;
+	unsigned int defer = 0;
+	int retval = 0;
+
+	for (i = 0; i < count; i += 16) {
+		for (j = 0; j < 3; j++) {
+			/* Clear AUX CH data buffer */
+			reg = BUF_CLR;
+			writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
+
+			/* Set normal AUX CH command */
+			reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
+			reg &= ~ADDR_ONLY;
+			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
+
+			/*
+			 * If Rx sends defer, Tx sends only reads
+			 * request without sending address
+			 */
+			if (!defer)
+				retval = exynos_dp_select_i2c_device(dp,
+						device_addr, reg_addr + i);
+			else
+				defer = 0;
+
+			if (retval == 0) {
+				/*
+				 * Set I2C transaction and write data
+				 * If bit 3 is 1, DisplayPort transaction.
+				 * If Bit 3 is 0, I2C transaction.
+				 */
+				reg = AUX_LENGTH(16) |
+					AUX_TX_COMM_I2C_TRANSACTION |
+					AUX_TX_COMM_READ;
+				writel(reg, dp->reg_base +
+					EXYNOS_DP_AUX_CH_CTL_1);
+
+				/* Start AUX transaction */
+				retval = exynos_dp_start_aux_transaction(dp);
+				if (retval == 0)
+					break;
+				else
+					dev_dbg(dp->dev,
+						"%s: Aux Transaction fail!\n",
+						__func__);
+			}
+			/* Check if Rx sends defer */
+			reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
+			if (reg == AUX_RX_COMM_AUX_DEFER ||
+				reg == AUX_RX_COMM_I2C_DEFER) {
+				dev_err(dp->dev, "Defer: %d\n\n", reg);
+				defer = 1;
+			}
+		}
+
+		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
+			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
+						 + 4 * cur_data_idx);
+			edid[i + cur_data_idx] = (unsigned char)reg;
+		}
+	}
+
+	return retval;
+}
+
+void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype)
+{
+	u32 reg;
+
+	reg = bwtype;
+	if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS))
+		writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
+}
+
+void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
+	*bwtype = reg;
+}
+
+void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
+{
+	u32 reg;
+
+	reg = count;
+	writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
+}
+
+void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
+	*count = reg;
+}
+
+void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable) {
+		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+		reg |= ENHANCED;
+		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+	} else {
+		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+		reg &= ~ENHANCED;
+		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+	}
+}
+
+void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
+				 enum pattern_set pattern)
+{
+	u32 reg;
+
+	switch (pattern) {
+	case PRBS7:
+		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
+		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+		break;
+	case D10_2:
+		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
+		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+		break;
+	case TRAINING_PTN1:
+		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
+		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+		break;
+	case TRAINING_PTN2:
+		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
+		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+		break;
+	case DP_NONE:
+		reg = SCRAMBLING_ENABLE |
+			LINK_QUAL_PATTERN_SET_DISABLE |
+			SW_TRAINING_PATTERN_SET_NORMAL;
+		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+		break;
+	default:
+		break;
+	}
+}
+
+void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+	reg &= ~PRE_EMPHASIS_SET_MASK;
+	reg |= level << PRE_EMPHASIS_SET_SHIFT;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+	reg &= ~PRE_EMPHASIS_SET_MASK;
+	reg |= level << PRE_EMPHASIS_SET_SHIFT;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+	reg &= ~PRE_EMPHASIS_SET_MASK;
+	reg |= level << PRE_EMPHASIS_SET_SHIFT;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+	reg &= ~PRE_EMPHASIS_SET_MASK;
+	reg |= level << PRE_EMPHASIS_SET_SHIFT;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
+					u32 training_lane)
+{
+	u32 reg;
+
+	reg = training_lane;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
+					u32 training_lane)
+{
+	u32 reg;
+
+	reg = training_lane;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
+					u32 training_lane)
+{
+	u32 reg;
+
+	reg = training_lane;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+}
+
+void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
+					u32 training_lane)
+{
+	u32 reg;
+
+	reg = training_lane;
+	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+}
+
+u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
+	return reg;
+}
+
+u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
+	return reg;
+}
+
+u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
+	return reg;
+}
+
+u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
+	return reg;
+}
+
+void exynos_dp_reset_macro(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
+	reg |= MACRO_RST;
+	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
+
+	/* 10 us is the minimum reset time. */
+	usleep_range(10, 20);
+
+	reg &= ~MACRO_RST;
+	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
+}
+
+void exynos_dp_init_video(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
+	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
+
+	reg = 0x0;
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+
+	reg = CHA_CRI(4) | CHA_CTRL;
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+
+	reg = 0x0;
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+
+	reg = VID_HRES_TH(2) | VID_VRES_TH(0);
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
+}
+
+void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	/* Configure the input color depth, color space, dynamic range */
+	reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
+		(dp->video_info->color_depth << IN_BPC_SHIFT) |
+		(dp->video_info->color_space << IN_COLOR_F_SHIFT);
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
+
+	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
+	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
+	reg &= ~IN_YC_COEFFI_MASK;
+	if (dp->video_info->ycbcr_coeff)
+		reg |= IN_YC_COEFFI_ITU709;
+	else
+		reg |= IN_YC_COEFFI_ITU601;
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
+}
+
+int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
+
+	if (!(reg & DET_STA)) {
+		dev_dbg(dp->dev, "Input stream clock not detected.\n");
+		return -EINVAL;
+	}
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
+	dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
+
+	if (reg & CHA_STA) {
+		dev_dbg(dp->dev, "Input stream clk is changing\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
+		enum clock_recovery_m_value_type type,
+		u32 m_value,
+		u32 n_value)
+{
+	u32 reg;
+
+	if (type == REGISTER_M) {
+		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+		reg |= FIX_M_VID;
+		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+		reg = m_value & 0xff;
+		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
+		reg = (m_value >> 8) & 0xff;
+		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
+		reg = (m_value >> 16) & 0xff;
+		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
+
+		reg = n_value & 0xff;
+		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
+		reg = (n_value >> 8) & 0xff;
+		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
+		reg = (n_value >> 16) & 0xff;
+		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
+	} else  {
+		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+		reg &= ~FIX_M_VID;
+		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
+
+		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
+		writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
+		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
+	}
+}
+
+void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type)
+{
+	u32 reg;
+
+	if (type == VIDEO_TIMING_FROM_CAPTURE) {
+		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+		reg &= ~FORMAT_SEL;
+		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+	} else {
+		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+		reg |= FORMAT_SEL;
+		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+	}
+}
+
+void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable) {
+		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+		reg &= ~VIDEO_MODE_MASK;
+		reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
+		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+	} else {
+		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+		reg &= ~VIDEO_MODE_MASK;
+		reg |= VIDEO_MODE_SLAVE_MODE;
+		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+	}
+}
+
+void exynos_dp_start_video(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+	reg |= VIDEO_EN;
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
+}
+
+int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
+	if (!(reg & STRM_VALID)) {
+		dev_dbg(dp->dev, "Input video stream is not detected.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+	reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
+	reg |= MASTER_VID_FUNC_EN_N;
+	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+	reg &= ~INTERACE_SCAN_CFG;
+	reg |= (dp->video_info->interlaced << 2);
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+	reg &= ~VSYNC_POLARITY_CFG;
+	reg |= (dp->video_info->v_sync_polarity << 1);
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+
+	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+	reg &= ~HSYNC_POLARITY_CFG;
+	reg |= (dp->video_info->h_sync_polarity << 0);
+	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
+
+	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
+	writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
+}
+
+void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+	reg &= ~SCRAMBLING_DISABLE;
+	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+}
+
+void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+	reg |= SCRAMBLING_DISABLE;
+	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
+}
diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.h b/drivers/gpu/drm/exynos/exynos_dp_reg.h
new file mode 100644
index 0000000..2e9bd0e
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_dp_reg.h
@@ -0,0 +1,366 @@
+/*
+ * Register definition file for Samsung DP driver
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _EXYNOS_DP_REG_H
+#define _EXYNOS_DP_REG_H
+
+#define EXYNOS_DP_TX_SW_RESET			0x14
+#define EXYNOS_DP_FUNC_EN_1			0x18
+#define EXYNOS_DP_FUNC_EN_2			0x1C
+#define EXYNOS_DP_VIDEO_CTL_1			0x20
+#define EXYNOS_DP_VIDEO_CTL_2			0x24
+#define EXYNOS_DP_VIDEO_CTL_3			0x28
+
+#define EXYNOS_DP_VIDEO_CTL_8			0x3C
+#define EXYNOS_DP_VIDEO_CTL_10			0x44
+
+#define EXYNOS_DP_LANE_MAP			0x35C
+
+#define EXYNOS_DP_ANALOG_CTL_1			0x370
+#define EXYNOS_DP_ANALOG_CTL_2			0x374
+#define EXYNOS_DP_ANALOG_CTL_3			0x378
+#define EXYNOS_DP_PLL_FILTER_CTL_1		0x37C
+#define EXYNOS_DP_TX_AMP_TUNING_CTL		0x380
+
+#define EXYNOS_DP_AUX_HW_RETRY_CTL		0x390
+
+#define EXYNOS_DP_COMMON_INT_STA_1		0x3C4
+#define EXYNOS_DP_COMMON_INT_STA_2		0x3C8
+#define EXYNOS_DP_COMMON_INT_STA_3		0x3CC
+#define EXYNOS_DP_COMMON_INT_STA_4		0x3D0
+#define EXYNOS_DP_INT_STA			0x3DC
+#define EXYNOS_DP_COMMON_INT_MASK_1		0x3E0
+#define EXYNOS_DP_COMMON_INT_MASK_2		0x3E4
+#define EXYNOS_DP_COMMON_INT_MASK_3		0x3E8
+#define EXYNOS_DP_COMMON_INT_MASK_4		0x3EC
+#define EXYNOS_DP_INT_STA_MASK			0x3F8
+#define EXYNOS_DP_INT_CTL			0x3FC
+
+#define EXYNOS_DP_SYS_CTL_1			0x600
+#define EXYNOS_DP_SYS_CTL_2			0x604
+#define EXYNOS_DP_SYS_CTL_3			0x608
+#define EXYNOS_DP_SYS_CTL_4			0x60C
+
+#define EXYNOS_DP_PKT_SEND_CTL			0x640
+#define EXYNOS_DP_HDCP_CTL			0x648
+
+#define EXYNOS_DP_LINK_BW_SET			0x680
+#define EXYNOS_DP_LANE_COUNT_SET		0x684
+#define EXYNOS_DP_TRAINING_PTN_SET		0x688
+#define EXYNOS_DP_LN0_LINK_TRAINING_CTL		0x68C
+#define EXYNOS_DP_LN1_LINK_TRAINING_CTL		0x690
+#define EXYNOS_DP_LN2_LINK_TRAINING_CTL		0x694
+#define EXYNOS_DP_LN3_LINK_TRAINING_CTL		0x698
+
+#define EXYNOS_DP_DEBUG_CTL			0x6C0
+#define EXYNOS_DP_HPD_DEGLITCH_L		0x6C4
+#define EXYNOS_DP_HPD_DEGLITCH_H		0x6C8
+#define EXYNOS_DP_LINK_DEBUG_CTL		0x6E0
+
+#define EXYNOS_DP_M_VID_0			0x700
+#define EXYNOS_DP_M_VID_1			0x704
+#define EXYNOS_DP_M_VID_2			0x708
+#define EXYNOS_DP_N_VID_0			0x70C
+#define EXYNOS_DP_N_VID_1			0x710
+#define EXYNOS_DP_N_VID_2			0x714
+
+#define EXYNOS_DP_PLL_CTL			0x71C
+#define EXYNOS_DP_PHY_PD			0x720
+#define EXYNOS_DP_PHY_TEST			0x724
+
+#define EXYNOS_DP_VIDEO_FIFO_THRD		0x730
+#define EXYNOS_DP_AUDIO_MARGIN			0x73C
+
+#define EXYNOS_DP_M_VID_GEN_FILTER_TH		0x764
+#define EXYNOS_DP_M_AUD_GEN_FILTER_TH		0x778
+#define EXYNOS_DP_AUX_CH_STA			0x780
+#define EXYNOS_DP_AUX_CH_DEFER_CTL		0x788
+#define EXYNOS_DP_AUX_RX_COMM			0x78C
+#define EXYNOS_DP_BUFFER_DATA_CTL		0x790
+#define EXYNOS_DP_AUX_CH_CTL_1			0x794
+#define EXYNOS_DP_AUX_ADDR_7_0			0x798
+#define EXYNOS_DP_AUX_ADDR_15_8			0x79C
+#define EXYNOS_DP_AUX_ADDR_19_16		0x7A0
+#define EXYNOS_DP_AUX_CH_CTL_2			0x7A4
+
+#define EXYNOS_DP_BUF_DATA_0			0x7C0
+
+#define EXYNOS_DP_SOC_GENERAL_CTL		0x800
+
+/* EXYNOS_DP_TX_SW_RESET */
+#define RESET_DP_TX				(0x1 << 0)
+
+/* EXYNOS_DP_FUNC_EN_1 */
+#define MASTER_VID_FUNC_EN_N			(0x1 << 7)
+#define SLAVE_VID_FUNC_EN_N			(0x1 << 5)
+#define AUD_FIFO_FUNC_EN_N			(0x1 << 4)
+#define AUD_FUNC_EN_N				(0x1 << 3)
+#define HDCP_FUNC_EN_N				(0x1 << 2)
+#define CRC_FUNC_EN_N				(0x1 << 1)
+#define SW_FUNC_EN_N				(0x1 << 0)
+
+/* EXYNOS_DP_FUNC_EN_2 */
+#define SSC_FUNC_EN_N				(0x1 << 7)
+#define AUX_FUNC_EN_N				(0x1 << 2)
+#define SERDES_FIFO_FUNC_EN_N			(0x1 << 1)
+#define LS_CLK_DOMAIN_FUNC_EN_N			(0x1 << 0)
+
+/* EXYNOS_DP_VIDEO_CTL_1 */
+#define VIDEO_EN				(0x1 << 7)
+#define HDCP_VIDEO_MUTE				(0x1 << 6)
+
+/* EXYNOS_DP_VIDEO_CTL_1 */
+#define IN_D_RANGE_MASK				(0x1 << 7)
+#define IN_D_RANGE_SHIFT			(7)
+#define IN_D_RANGE_CEA				(0x1 << 7)
+#define IN_D_RANGE_VESA				(0x0 << 7)
+#define IN_BPC_MASK				(0x7 << 4)
+#define IN_BPC_SHIFT				(4)
+#define IN_BPC_12_BITS				(0x3 << 4)
+#define IN_BPC_10_BITS				(0x2 << 4)
+#define IN_BPC_8_BITS				(0x1 << 4)
+#define IN_BPC_6_BITS				(0x0 << 4)
+#define IN_COLOR_F_MASK				(0x3 << 0)
+#define IN_COLOR_F_SHIFT			(0)
+#define IN_COLOR_F_YCBCR444			(0x2 << 0)
+#define IN_COLOR_F_YCBCR422			(0x1 << 0)
+#define IN_COLOR_F_RGB				(0x0 << 0)
+
+/* EXYNOS_DP_VIDEO_CTL_3 */
+#define IN_YC_COEFFI_MASK			(0x1 << 7)
+#define IN_YC_COEFFI_SHIFT			(7)
+#define IN_YC_COEFFI_ITU709			(0x1 << 7)
+#define IN_YC_COEFFI_ITU601			(0x0 << 7)
+#define VID_CHK_UPDATE_TYPE_MASK		(0x1 << 4)
+#define VID_CHK_UPDATE_TYPE_SHIFT		(4)
+#define VID_CHK_UPDATE_TYPE_1			(0x1 << 4)
+#define VID_CHK_UPDATE_TYPE_0			(0x0 << 4)
+
+/* EXYNOS_DP_VIDEO_CTL_8 */
+#define VID_HRES_TH(x)				(((x) & 0xf) << 4)
+#define VID_VRES_TH(x)				(((x) & 0xf) << 0)
+
+/* EXYNOS_DP_VIDEO_CTL_10 */
+#define FORMAT_SEL				(0x1 << 4)
+#define INTERACE_SCAN_CFG			(0x1 << 2)
+#define VSYNC_POLARITY_CFG			(0x1 << 1)
+#define HSYNC_POLARITY_CFG			(0x1 << 0)
+
+/* EXYNOS_DP_LANE_MAP */
+#define LANE3_MAP_LOGIC_LANE_0			(0x0 << 6)
+#define LANE3_MAP_LOGIC_LANE_1			(0x1 << 6)
+#define LANE3_MAP_LOGIC_LANE_2			(0x2 << 6)
+#define LANE3_MAP_LOGIC_LANE_3			(0x3 << 6)
+#define LANE2_MAP_LOGIC_LANE_0			(0x0 << 4)
+#define LANE2_MAP_LOGIC_LANE_1			(0x1 << 4)
+#define LANE2_MAP_LOGIC_LANE_2			(0x2 << 4)
+#define LANE2_MAP_LOGIC_LANE_3			(0x3 << 4)
+#define LANE1_MAP_LOGIC_LANE_0			(0x0 << 2)
+#define LANE1_MAP_LOGIC_LANE_1			(0x1 << 2)
+#define LANE1_MAP_LOGIC_LANE_2			(0x2 << 2)
+#define LANE1_MAP_LOGIC_LANE_3			(0x3 << 2)
+#define LANE0_MAP_LOGIC_LANE_0			(0x0 << 0)
+#define LANE0_MAP_LOGIC_LANE_1			(0x1 << 0)
+#define LANE0_MAP_LOGIC_LANE_2			(0x2 << 0)
+#define LANE0_MAP_LOGIC_LANE_3			(0x3 << 0)
+
+/* EXYNOS_DP_ANALOG_CTL_1 */
+#define TX_TERMINAL_CTRL_50_OHM			(0x1 << 4)
+
+/* EXYNOS_DP_ANALOG_CTL_2 */
+#define SEL_24M					(0x1 << 3)
+#define TX_DVDD_BIT_1_0625V			(0x4 << 0)
+
+/* EXYNOS_DP_ANALOG_CTL_3 */
+#define DRIVE_DVDD_BIT_1_0625V			(0x4 << 5)
+#define VCO_BIT_600_MICRO			(0x5 << 0)
+
+/* EXYNOS_DP_PLL_FILTER_CTL_1 */
+#define PD_RING_OSC				(0x1 << 6)
+#define AUX_TERMINAL_CTRL_50_OHM		(0x2 << 4)
+#define TX_CUR1_2X				(0x1 << 2)
+#define TX_CUR_16_MA				(0x3 << 0)
+
+/* EXYNOS_DP_TX_AMP_TUNING_CTL */
+#define CH3_AMP_400_MV				(0x0 << 24)
+#define CH2_AMP_400_MV				(0x0 << 16)
+#define CH1_AMP_400_MV				(0x0 << 8)
+#define CH0_AMP_400_MV				(0x0 << 0)
+
+/* EXYNOS_DP_AUX_HW_RETRY_CTL */
+#define AUX_BIT_PERIOD_EXPECTED_DELAY(x)	(((x) & 0x7) << 8)
+#define AUX_HW_RETRY_INTERVAL_MASK		(0x3 << 3)
+#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS	(0x0 << 3)
+#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS	(0x1 << 3)
+#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS	(0x2 << 3)
+#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS	(0x3 << 3)
+#define AUX_HW_RETRY_COUNT_SEL(x)		(((x) & 0x7) << 0)
+
+/* EXYNOS_DP_COMMON_INT_STA_1 */
+#define VSYNC_DET				(0x1 << 7)
+#define PLL_LOCK_CHG				(0x1 << 6)
+#define SPDIF_ERR				(0x1 << 5)
+#define SPDIF_UNSTBL				(0x1 << 4)
+#define VID_FORMAT_CHG				(0x1 << 3)
+#define AUD_CLK_CHG				(0x1 << 2)
+#define VID_CLK_CHG				(0x1 << 1)
+#define SW_INT					(0x1 << 0)
+
+/* EXYNOS_DP_COMMON_INT_STA_2 */
+#define ENC_EN_CHG				(0x1 << 6)
+#define HW_BKSV_RDY				(0x1 << 3)
+#define HW_SHA_DONE				(0x1 << 2)
+#define HW_AUTH_STATE_CHG			(0x1 << 1)
+#define HW_AUTH_DONE				(0x1 << 0)
+
+/* EXYNOS_DP_COMMON_INT_STA_3 */
+#define AFIFO_UNDER				(0x1 << 7)
+#define AFIFO_OVER				(0x1 << 6)
+#define R0_CHK_FLAG				(0x1 << 5)
+
+/* EXYNOS_DP_COMMON_INT_STA_4 */
+#define PSR_ACTIVE				(0x1 << 7)
+#define PSR_INACTIVE				(0x1 << 6)
+#define SPDIF_BI_PHASE_ERR			(0x1 << 5)
+#define HOTPLUG_CHG				(0x1 << 2)
+#define HPD_LOST				(0x1 << 1)
+#define PLUG					(0x1 << 0)
+
+/* EXYNOS_DP_INT_STA */
+#define INT_HPD					(0x1 << 6)
+#define HW_TRAINING_FINISH			(0x1 << 5)
+#define RPLY_RECEIV				(0x1 << 1)
+#define AUX_ERR					(0x1 << 0)
+
+/* EXYNOS_DP_INT_CTL */
+#define SOFT_INT_CTRL				(0x1 << 2)
+#define INT_POL1				(0x1 << 1)
+#define INT_POL0				(0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_1 */
+#define DET_STA					(0x1 << 2)
+#define FORCE_DET				(0x1 << 1)
+#define DET_CTRL				(0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_2 */
+#define CHA_CRI(x)				(((x) & 0xf) << 4)
+#define CHA_STA					(0x1 << 2)
+#define FORCE_CHA				(0x1 << 1)
+#define CHA_CTRL				(0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_3 */
+#define HPD_STATUS				(0x1 << 6)
+#define F_HPD					(0x1 << 5)
+#define HPD_CTRL				(0x1 << 4)
+#define HDCP_RDY				(0x1 << 3)
+#define STRM_VALID				(0x1 << 2)
+#define F_VALID					(0x1 << 1)
+#define VALID_CTRL				(0x1 << 0)
+
+/* EXYNOS_DP_SYS_CTL_4 */
+#define FIX_M_AUD				(0x1 << 4)
+#define ENHANCED				(0x1 << 3)
+#define FIX_M_VID				(0x1 << 2)
+#define M_VID_UPDATE_CTRL			(0x3 << 0)
+
+/* EXYNOS_DP_TRAINING_PTN_SET */
+#define SCRAMBLER_TYPE				(0x1 << 9)
+#define HW_LINK_TRAINING_PATTERN		(0x1 << 8)
+#define SCRAMBLING_DISABLE			(0x1 << 5)
+#define SCRAMBLING_ENABLE			(0x0 << 5)
+#define LINK_QUAL_PATTERN_SET_MASK		(0x3 << 2)
+#define LINK_QUAL_PATTERN_SET_PRBS7		(0x3 << 2)
+#define LINK_QUAL_PATTERN_SET_D10_2		(0x1 << 2)
+#define LINK_QUAL_PATTERN_SET_DISABLE		(0x0 << 2)
+#define SW_TRAINING_PATTERN_SET_MASK		(0x3 << 0)
+#define SW_TRAINING_PATTERN_SET_PTN2		(0x2 << 0)
+#define SW_TRAINING_PATTERN_SET_PTN1		(0x1 << 0)
+#define SW_TRAINING_PATTERN_SET_NORMAL		(0x0 << 0)
+
+/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
+#define PRE_EMPHASIS_SET_MASK			(0x3 << 3)
+#define PRE_EMPHASIS_SET_SHIFT			(3)
+
+/* EXYNOS_DP_DEBUG_CTL */
+#define PLL_LOCK				(0x1 << 4)
+#define F_PLL_LOCK				(0x1 << 3)
+#define PLL_LOCK_CTRL				(0x1 << 2)
+#define PN_INV					(0x1 << 0)
+
+/* EXYNOS_DP_PLL_CTL */
+#define DP_PLL_PD				(0x1 << 7)
+#define DP_PLL_RESET				(0x1 << 6)
+#define DP_PLL_LOOP_BIT_DEFAULT			(0x1 << 4)
+#define DP_PLL_REF_BIT_1_1250V			(0x5 << 0)
+#define DP_PLL_REF_BIT_1_2500V			(0x7 << 0)
+
+/* EXYNOS_DP_PHY_PD */
+#define DP_PHY_PD				(0x1 << 5)
+#define AUX_PD					(0x1 << 4)
+#define CH3_PD					(0x1 << 3)
+#define CH2_PD					(0x1 << 2)
+#define CH1_PD					(0x1 << 1)
+#define CH0_PD					(0x1 << 0)
+
+/* EXYNOS_DP_PHY_TEST */
+#define MACRO_RST				(0x1 << 5)
+#define CH1_TEST				(0x1 << 1)
+#define CH0_TEST				(0x1 << 0)
+
+/* EXYNOS_DP_AUX_CH_STA */
+#define AUX_BUSY				(0x1 << 4)
+#define AUX_STATUS_MASK				(0xf << 0)
+
+/* EXYNOS_DP_AUX_CH_DEFER_CTL */
+#define DEFER_CTRL_EN				(0x1 << 7)
+#define DEFER_COUNT(x)				(((x) & 0x7f) << 0)
+
+/* EXYNOS_DP_AUX_RX_COMM */
+#define AUX_RX_COMM_I2C_DEFER			(0x2 << 2)
+#define AUX_RX_COMM_AUX_DEFER			(0x2 << 0)
+
+/* EXYNOS_DP_BUFFER_DATA_CTL */
+#define BUF_CLR					(0x1 << 7)
+#define BUF_DATA_COUNT(x)			(((x) & 0x1f) << 0)
+
+/* EXYNOS_DP_AUX_CH_CTL_1 */
+#define AUX_LENGTH(x)				(((x - 1) & 0xf) << 4)
+#define AUX_TX_COMM_MASK			(0xf << 0)
+#define AUX_TX_COMM_DP_TRANSACTION		(0x1 << 3)
+#define AUX_TX_COMM_I2C_TRANSACTION		(0x0 << 3)
+#define AUX_TX_COMM_MOT				(0x1 << 2)
+#define AUX_TX_COMM_WRITE			(0x0 << 0)
+#define AUX_TX_COMM_READ			(0x1 << 0)
+
+/* EXYNOS_DP_AUX_ADDR_7_0 */
+#define AUX_ADDR_7_0(x)				(((x) >> 0) & 0xff)
+
+/* EXYNOS_DP_AUX_ADDR_15_8 */
+#define AUX_ADDR_15_8(x)			(((x) >> 8) & 0xff)
+
+/* EXYNOS_DP_AUX_ADDR_19_16 */
+#define AUX_ADDR_19_16(x)			(((x) >> 16) & 0x0f)
+
+/* EXYNOS_DP_AUX_CH_CTL_2 */
+#define ADDR_ONLY				(0x1 << 1)
+#define AUX_EN					(0x1 << 0)
+
+/* EXYNOS_DP_SOC_GENERAL_CTL */
+#define AUDIO_MODE_SPDIF_MODE			(0x1 << 8)
+#define AUDIO_MODE_MASTER_MODE			(0x0 << 8)
+#define MASTER_VIDEO_INTERLACE_EN		(0x1 << 4)
+#define VIDEO_MASTER_CLK_SEL			(0x1 << 2)
+#define VIDEO_MASTER_MODE_EN			(0x1 << 1)
+#define VIDEO_MODE_MASK				(0x1 << 0)
+#define VIDEO_MODE_SLAVE_MODE			(0x1 << 0)
+#define VIDEO_MODE_MASTER_MODE			(0x0 << 0)
+
+#endif /* _EXYNOS_DP_REG_H */
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
index 1b035b2..7032ad9 100644
--- a/drivers/video/exynos/Kconfig
+++ b/drivers/video/exynos/Kconfig
@@ -27,11 +27,4 @@ config EXYNOS_LCD_S6E8AX0
 	  If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
 	  LCD control driver.
 
-config EXYNOS_DP
-	bool "EXYNOS DP driver support"
-	depends on ARCH_EXYNOS
-	default n
-	help
-	  This enables support for DP device.
-
 endif # EXYNOS_VIDEO
diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile
index ec7772e..b5b1bd2 100644
--- a/drivers/video/exynos/Makefile
+++ b/drivers/video/exynos/Makefile
@@ -5,4 +5,3 @@
 obj-$(CONFIG_EXYNOS_MIPI_DSI)		+= exynos_mipi_dsi.o exynos_mipi_dsi_common.o \
 				     	exynos_mipi_dsi_lowlevel.o
 obj-$(CONFIG_EXYNOS_LCD_S6E8AX0)	+= s6e8ax0.o
-obj-$(CONFIG_EXYNOS_DP)			+= exynos_dp_core.o exynos_dp_reg.o
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
deleted file mode 100644
index 089ae22..0000000
--- a/drivers/video/exynos/exynos_dp_core.c
+++ /dev/null
@@ -1,1213 +0,0 @@
-/*
- * Samsung SoC DP (Display Port) interface driver.
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * 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/module.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-
-#include <video/exynos_dp.h>
-
-#include "exynos_dp_core.h"
-
-static int exynos_dp_init_dp(struct exynos_dp_device *dp)
-{
-	exynos_dp_reset(dp);
-
-	exynos_dp_swreset(dp);
-
-	exynos_dp_init_analog_param(dp);
-	exynos_dp_init_interrupt(dp);
-
-	/* SW defined function Normal operation */
-	exynos_dp_enable_sw_function(dp);
-
-	exynos_dp_config_interrupt(dp);
-	exynos_dp_init_analog_func(dp);
-
-	exynos_dp_init_hpd(dp);
-	exynos_dp_init_aux(dp);
-
-	return 0;
-}
-
-static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
-{
-	int timeout_loop = 0;
-
-	while (exynos_dp_get_plug_in_status(dp) != 0) {
-		timeout_loop++;
-		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-			dev_err(dp->dev, "failed to get hpd plug status\n");
-			return -ETIMEDOUT;
-		}
-		usleep_range(10, 11);
-	}
-
-	return 0;
-}
-
-static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
-{
-	int i;
-	unsigned char sum = 0;
-
-	for (i = 0; i < EDID_BLOCK_LENGTH; i++)
-		sum = sum + edid_data[i];
-
-	return sum;
-}
-
-static int exynos_dp_read_edid(struct exynos_dp_device *dp)
-{
-	unsigned char edid[EDID_BLOCK_LENGTH * 2];
-	unsigned int extend_block = 0;
-	unsigned char sum;
-	unsigned char test_vector;
-	int retval;
-
-	/*
-	 * EDID device address is 0x50.
-	 * However, if necessary, you must have set upper address
-	 * into E-EDID in I2C device, 0x30.
-	 */
-
-	/* Read Extension Flag, Number of 128-byte EDID extension blocks */
-	retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
-				EDID_EXTENSION_FLAG,
-				&extend_block);
-	if (retval)
-		return retval;
-
-	if (extend_block > 0) {
-		dev_dbg(dp->dev, "EDID data includes a single extension!\n");
-
-		/* Read EDID data */
-		retval = exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
-						EDID_HEADER_PATTERN,
-						EDID_BLOCK_LENGTH,
-						&edid[EDID_HEADER_PATTERN]);
-		if (retval != 0) {
-			dev_err(dp->dev, "EDID Read failed!\n");
-			return -EIO;
-		}
-		sum = exynos_dp_calc_edid_check_sum(edid);
-		if (sum != 0) {
-			dev_err(dp->dev, "EDID bad checksum!\n");
-			return -EIO;
-		}
-
-		/* Read additional EDID data */
-		retval = exynos_dp_read_bytes_from_i2c(dp,
-				I2C_EDID_DEVICE_ADDR,
-				EDID_BLOCK_LENGTH,
-				EDID_BLOCK_LENGTH,
-				&edid[EDID_BLOCK_LENGTH]);
-		if (retval != 0) {
-			dev_err(dp->dev, "EDID Read failed!\n");
-			return -EIO;
-		}
-		sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
-		if (sum != 0) {
-			dev_err(dp->dev, "EDID bad checksum!\n");
-			return -EIO;
-		}
-
-		exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
-					&test_vector);
-		if (test_vector & DPCD_TEST_EDID_READ) {
-			exynos_dp_write_byte_to_dpcd(dp,
-				DPCD_ADDR_TEST_EDID_CHECKSUM,
-				edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
-			exynos_dp_write_byte_to_dpcd(dp,
-				DPCD_ADDR_TEST_RESPONSE,
-				DPCD_TEST_EDID_CHECKSUM_WRITE);
-		}
-	} else {
-		dev_info(dp->dev, "EDID data does not include any extensions.\n");
-
-		/* Read EDID data */
-		retval = exynos_dp_read_bytes_from_i2c(dp,
-				I2C_EDID_DEVICE_ADDR,
-				EDID_HEADER_PATTERN,
-				EDID_BLOCK_LENGTH,
-				&edid[EDID_HEADER_PATTERN]);
-		if (retval != 0) {
-			dev_err(dp->dev, "EDID Read failed!\n");
-			return -EIO;
-		}
-		sum = exynos_dp_calc_edid_check_sum(edid);
-		if (sum != 0) {
-			dev_err(dp->dev, "EDID bad checksum!\n");
-			return -EIO;
-		}
-
-		exynos_dp_read_byte_from_dpcd(dp,
-			DPCD_ADDR_TEST_REQUEST,
-			&test_vector);
-		if (test_vector & DPCD_TEST_EDID_READ) {
-			exynos_dp_write_byte_to_dpcd(dp,
-				DPCD_ADDR_TEST_EDID_CHECKSUM,
-				edid[EDID_CHECKSUM]);
-			exynos_dp_write_byte_to_dpcd(dp,
-				DPCD_ADDR_TEST_RESPONSE,
-				DPCD_TEST_EDID_CHECKSUM_WRITE);
-		}
-	}
-
-	dev_err(dp->dev, "EDID Read success!\n");
-	return 0;
-}
-
-static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
-{
-	u8 buf[12];
-	int i;
-	int retval;
-
-	/* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
-	retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
-				12, buf);
-	if (retval)
-		return retval;
-
-	/* Read EDID */
-	for (i = 0; i < 3; i++) {
-		retval = exynos_dp_read_edid(dp);
-		if (!retval)
-			break;
-	}
-
-	return retval;
-}
-
-static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp,
-						bool enable)
-{
-	u8 data;
-
-	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
-
-	if (enable)
-		exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
-			DPCD_ENHANCED_FRAME_EN |
-			DPCD_LANE_COUNT_SET(data));
-	else
-		exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
-			DPCD_LANE_COUNT_SET(data));
-}
-
-static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp)
-{
-	u8 data;
-	int retval;
-
-	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
-	retval = DPCD_ENHANCED_FRAME_CAP(data);
-
-	return retval;
-}
-
-static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
-{
-	u8 data;
-
-	data = exynos_dp_is_enhanced_mode_available(dp);
-	exynos_dp_enable_rx_to_enhanced_mode(dp, data);
-	exynos_dp_enable_enhanced_mode(dp, data);
-}
-
-static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
-{
-	exynos_dp_set_training_pattern(dp, DP_NONE);
-
-	exynos_dp_write_byte_to_dpcd(dp,
-		DPCD_ADDR_TRAINING_PATTERN_SET,
-		DPCD_TRAINING_PATTERN_DISABLED);
-}
-
-static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
-					int pre_emphasis, int lane)
-{
-	switch (lane) {
-	case 0:
-		exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
-		break;
-	case 1:
-		exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
-		break;
-
-	case 2:
-		exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
-		break;
-
-	case 3:
-		exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
-		break;
-	}
-}
-
-static int exynos_dp_link_start(struct exynos_dp_device *dp)
-{
-	u8 buf[4];
-	int lane, lane_count, pll_tries, retval;
-
-	lane_count = dp->link_train.lane_count;
-
-	dp->link_train.lt_state = CLOCK_RECOVERY;
-	dp->link_train.eq_loop = 0;
-
-	for (lane = 0; lane < lane_count; lane++)
-		dp->link_train.cr_loop[lane] = 0;
-
-	/* Set link rate and count as you want to establish*/
-	exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
-	exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
-
-	/* Setup RX configuration */
-	buf[0] = dp->link_train.link_rate;
-	buf[1] = dp->link_train.lane_count;
-	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
-				2, buf);
-	if (retval)
-		return retval;
-
-	/* Set TX pre-emphasis to minimum */
-	for (lane = 0; lane < lane_count; lane++)
-		exynos_dp_set_lane_lane_pre_emphasis(dp,
-			PRE_EMPHASIS_LEVEL_0, lane);
-
-	/* Wait for PLL lock */
-	pll_tries = 0;
-	while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-		if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
-			dev_err(dp->dev, "Wait for PLL lock timed out\n");
-			return -ETIMEDOUT;
-		}
-
-		pll_tries++;
-		usleep_range(90, 120);
-	}
-
-	/* Set training pattern 1 */
-	exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
-
-	/* Set RX training pattern */
-	retval = exynos_dp_write_byte_to_dpcd(dp,
-			DPCD_ADDR_TRAINING_PATTERN_SET,
-			DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
-	if (retval)
-		return retval;
-
-	for (lane = 0; lane < lane_count; lane++)
-		buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
-			    DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
-
-	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
-			lane_count, buf);
-
-	return retval;
-}
-
-static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
-{
-	int shift = (lane & 1) * 4;
-	u8 link_value = link_status[lane>>1];
-
-	return (link_value >> shift) & 0xf;
-}
-
-static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
-{
-	int lane;
-	u8 lane_status;
-
-	for (lane = 0; lane < lane_count; lane++) {
-		lane_status = exynos_dp_get_lane_status(link_status, lane);
-		if ((lane_status & DPCD_LANE_CR_DONE) == 0)
-			return -EINVAL;
-	}
-	return 0;
-}
-
-static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
-				int lane_count)
-{
-	int lane;
-	u8 lane_status;
-
-	if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
-		return -EINVAL;
-
-	for (lane = 0; lane < lane_count; lane++) {
-		lane_status = exynos_dp_get_lane_status(link_status, lane);
-		lane_status &= DPCD_CHANNEL_EQ_BITS;
-		if (lane_status != DPCD_CHANNEL_EQ_BITS)
-			return -EINVAL;
-	}
-
-	return 0;
-}
-
-static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2],
-							int lane)
-{
-	int shift = (lane & 1) * 4;
-	u8 link_value = adjust_request[lane>>1];
-
-	return (link_value >> shift) & 0x3;
-}
-
-static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
-					u8 adjust_request[2],
-					int lane)
-{
-	int shift = (lane & 1) * 4;
-	u8 link_value = adjust_request[lane>>1];
-
-	return ((link_value >> shift) & 0xc) >> 2;
-}
-
-static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
-					u8 training_lane_set, int lane)
-{
-	switch (lane) {
-	case 0:
-		exynos_dp_set_lane0_link_training(dp, training_lane_set);
-		break;
-	case 1:
-		exynos_dp_set_lane1_link_training(dp, training_lane_set);
-		break;
-
-	case 2:
-		exynos_dp_set_lane2_link_training(dp, training_lane_set);
-		break;
-
-	case 3:
-		exynos_dp_set_lane3_link_training(dp, training_lane_set);
-		break;
-	}
-}
-
-static unsigned int exynos_dp_get_lane_link_training(
-				struct exynos_dp_device *dp,
-				int lane)
-{
-	u32 reg;
-
-	switch (lane) {
-	case 0:
-		reg = exynos_dp_get_lane0_link_training(dp);
-		break;
-	case 1:
-		reg = exynos_dp_get_lane1_link_training(dp);
-		break;
-	case 2:
-		reg = exynos_dp_get_lane2_link_training(dp);
-		break;
-	case 3:
-		reg = exynos_dp_get_lane3_link_training(dp);
-		break;
-	default:
-		WARN_ON(1);
-		return 0;
-	}
-
-	return reg;
-}
-
-static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
-{
-	exynos_dp_training_pattern_dis(dp);
-	exynos_dp_set_enhanced_mode(dp);
-
-	dp->link_train.lt_state = FAILED;
-}
-
-static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp,
-					u8 adjust_request[2])
-{
-	int lane, lane_count;
-	u8 voltage_swing, pre_emphasis, training_lane;
-
-	lane_count = dp->link_train.lane_count;
-	for (lane = 0; lane < lane_count; lane++) {
-		voltage_swing = exynos_dp_get_adjust_request_voltage(
-						adjust_request, lane);
-		pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
-						adjust_request, lane);
-		training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
-				DPCD_PRE_EMPHASIS_SET(pre_emphasis);
-
-		if (voltage_swing == VOLTAGE_LEVEL_3)
-			training_lane |= DPCD_MAX_SWING_REACHED;
-		if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
-			training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
-
-		dp->link_train.training_lane[lane] = training_lane;
-	}
-}
-
-static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
-{
-	int lane, lane_count, retval;
-	u8 voltage_swing, pre_emphasis, training_lane;
-	u8 link_status[2], adjust_request[2];
-
-	usleep_range(100, 101);
-
-	lane_count = dp->link_train.lane_count;
-
-	retval =  exynos_dp_read_bytes_from_dpcd(dp,
-			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
-	if (retval)
-		return retval;
-
-	retval =  exynos_dp_read_bytes_from_dpcd(dp,
-			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
-	if (retval)
-		return retval;
-
-	if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
-		/* set training pattern 2 for EQ */
-		exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
-
-		retval = exynos_dp_write_byte_to_dpcd(dp,
-				DPCD_ADDR_TRAINING_PATTERN_SET,
-				DPCD_SCRAMBLING_DISABLED |
-				DPCD_TRAINING_PATTERN_2);
-		if (retval)
-			return retval;
-
-		dev_info(dp->dev, "Link Training Clock Recovery success\n");
-		dp->link_train.lt_state = EQUALIZER_TRAINING;
-	} else {
-		for (lane = 0; lane < lane_count; lane++) {
-			training_lane = exynos_dp_get_lane_link_training(
-							dp, lane);
-			voltage_swing = exynos_dp_get_adjust_request_voltage(
-							adjust_request, lane);
-			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
-							adjust_request, lane);
-
-			if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
-					voltage_swing &&
-			    DPCD_PRE_EMPHASIS_GET(training_lane) ==
-					pre_emphasis)
-				dp->link_train.cr_loop[lane]++;
-
-			if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
-			    voltage_swing == VOLTAGE_LEVEL_3 ||
-			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
-				dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
-					dp->link_train.cr_loop[lane],
-					voltage_swing, pre_emphasis);
-				exynos_dp_reduce_link_rate(dp);
-				return -EIO;
-			}
-		}
-	}
-
-	exynos_dp_get_adjust_training_lane(dp, adjust_request);
-
-	for (lane = 0; lane < lane_count; lane++)
-		exynos_dp_set_lane_link_training(dp,
-			dp->link_train.training_lane[lane], lane);
-
-	retval = exynos_dp_write_bytes_to_dpcd(dp,
-			DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
-			dp->link_train.training_lane);
-	if (retval)
-		return retval;
-
-	return retval;
-}
-
-static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
-{
-	int lane, lane_count, retval;
-	u32 reg;
-	u8 link_align, link_status[2], adjust_request[2];
-
-	usleep_range(400, 401);
-
-	lane_count = dp->link_train.lane_count;
-
-	retval = exynos_dp_read_bytes_from_dpcd(dp,
-			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
-	if (retval)
-		return retval;
-
-	if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
-		exynos_dp_reduce_link_rate(dp);
-		return -EIO;
-	}
-
-	retval = exynos_dp_read_bytes_from_dpcd(dp,
-			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
-	if (retval)
-		return retval;
-
-	retval = exynos_dp_read_byte_from_dpcd(dp,
-			DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
-	if (retval)
-		return retval;
-
-	exynos_dp_get_adjust_training_lane(dp, adjust_request);
-
-	if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) {
-		/* traing pattern Set to Normal */
-		exynos_dp_training_pattern_dis(dp);
-
-		dev_info(dp->dev, "Link Training success!\n");
-
-		exynos_dp_get_link_bandwidth(dp, &reg);
-		dp->link_train.link_rate = reg;
-		dev_dbg(dp->dev, "final bandwidth = %.2x\n",
-			dp->link_train.link_rate);
-
-		exynos_dp_get_lane_count(dp, &reg);
-		dp->link_train.lane_count = reg;
-		dev_dbg(dp->dev, "final lane count = %.2x\n",
-			dp->link_train.lane_count);
-
-		/* set enhanced mode if available */
-		exynos_dp_set_enhanced_mode(dp);
-		dp->link_train.lt_state = FINISHED;
-
-		return 0;
-	}
-
-	/* not all locked */
-	dp->link_train.eq_loop++;
-
-	if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
-		dev_err(dp->dev, "EQ Max loop\n");
-		exynos_dp_reduce_link_rate(dp);
-		return -EIO;
-	}
-
-	for (lane = 0; lane < lane_count; lane++)
-		exynos_dp_set_lane_link_training(dp,
-			dp->link_train.training_lane[lane], lane);
-
-	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
-			lane_count, dp->link_train.training_lane);
-
-	return retval;
-}
-
-static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
-					u8 *bandwidth)
-{
-	u8 data;
-
-	/*
-	 * For DP rev.1.1, Maximum link rate of Main Link lanes
-	 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
-	 */
-	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
-	*bandwidth = data;
-}
-
-static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
-					u8 *lane_count)
-{
-	u8 data;
-
-	/*
-	 * For DP rev.1.1, Maximum number of Main Link lanes
-	 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
-	 */
-	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
-	*lane_count = DPCD_MAX_LANE_COUNT(data);
-}
-
-static void exynos_dp_init_training(struct exynos_dp_device *dp,
-			enum link_lane_count_type max_lane,
-			enum link_rate_type max_rate)
-{
-	/*
-	 * MACRO_RST must be applied after the PLL_LOCK to avoid
-	 * the DP inter pair skew issue for at least 10 us
-	 */
-	exynos_dp_reset_macro(dp);
-
-	/* Initialize by reading RX's DPCD */
-	exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
-	exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
-
-	if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
-	   (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
-		dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
-			dp->link_train.link_rate);
-		dp->link_train.link_rate = LINK_RATE_1_62GBPS;
-	}
-
-	if (dp->link_train.lane_count == 0) {
-		dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
-			dp->link_train.lane_count);
-		dp->link_train.lane_count = (u8)LANE_COUNT1;
-	}
-
-	/* Setup TX lane count & rate */
-	if (dp->link_train.lane_count > max_lane)
-		dp->link_train.lane_count = max_lane;
-	if (dp->link_train.link_rate > max_rate)
-		dp->link_train.link_rate = max_rate;
-
-	/* All DP analog module power up */
-	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
-}
-
-static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
-{
-	int retval = 0, training_finished = 0;
-
-	dp->link_train.lt_state = START;
-
-	/* Process here */
-	while (!retval && !training_finished) {
-		switch (dp->link_train.lt_state) {
-		case START:
-			retval = exynos_dp_link_start(dp);
-			if (retval)
-				dev_err(dp->dev, "LT link start failed!\n");
-			break;
-		case CLOCK_RECOVERY:
-			retval = exynos_dp_process_clock_recovery(dp);
-			if (retval)
-				dev_err(dp->dev, "LT CR failed!\n");
-			break;
-		case EQUALIZER_TRAINING:
-			retval = exynos_dp_process_equalizer_training(dp);
-			if (retval)
-				dev_err(dp->dev, "LT EQ failed!\n");
-			break;
-		case FINISHED:
-			training_finished = 1;
-			break;
-		case FAILED:
-			return -EREMOTEIO;
-		}
-	}
-	if (retval)
-		dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
-
-	return retval;
-}
-
-static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
-				u32 count,
-				u32 bwtype)
-{
-	int i;
-	int retval;
-
-	for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
-		exynos_dp_init_training(dp, count, bwtype);
-		retval = exynos_dp_sw_link_training(dp);
-		if (retval == 0)
-			break;
-
-		usleep_range(100, 110);
-	}
-
-	return retval;
-}
-
-static int exynos_dp_config_video(struct exynos_dp_device *dp)
-{
-	int retval = 0;
-	int timeout_loop = 0;
-	int done_count = 0;
-
-	exynos_dp_config_video_slave_mode(dp);
-
-	exynos_dp_set_video_color_format(dp);
-
-	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-		dev_err(dp->dev, "PLL is not locked yet.\n");
-		return -EINVAL;
-	}
-
-	for (;;) {
-		timeout_loop++;
-		if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
-			break;
-		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-			dev_err(dp->dev, "Timeout of video streamclk ok\n");
-			return -ETIMEDOUT;
-		}
-
-		usleep_range(1, 2);
-	}
-
-	/* Set to use the register calculated M/N video */
-	exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
-
-	/* For video bist, Video timing must be generated by register */
-	exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
-
-	/* Disable video mute */
-	exynos_dp_enable_video_mute(dp, 0);
-
-	/* Configure video slave mode */
-	exynos_dp_enable_video_master(dp, 0);
-
-	/* Enable video */
-	exynos_dp_start_video(dp);
-
-	timeout_loop = 0;
-
-	for (;;) {
-		timeout_loop++;
-		if (exynos_dp_is_video_stream_on(dp) == 0) {
-			done_count++;
-			if (done_count > 10)
-				break;
-		} else if (done_count) {
-			done_count = 0;
-		}
-		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-			dev_err(dp->dev, "Timeout of video streamclk ok\n");
-			return -ETIMEDOUT;
-		}
-
-		usleep_range(1000, 1001);
-	}
-
-	if (retval != 0)
-		dev_err(dp->dev, "Video stream is not detected!\n");
-
-	return retval;
-}
-
-static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable)
-{
-	u8 data;
-
-	if (enable) {
-		exynos_dp_enable_scrambling(dp);
-
-		exynos_dp_read_byte_from_dpcd(dp,
-			DPCD_ADDR_TRAINING_PATTERN_SET,
-			&data);
-		exynos_dp_write_byte_to_dpcd(dp,
-			DPCD_ADDR_TRAINING_PATTERN_SET,
-			(u8)(data & ~DPCD_SCRAMBLING_DISABLED));
-	} else {
-		exynos_dp_disable_scrambling(dp);
-
-		exynos_dp_read_byte_from_dpcd(dp,
-			DPCD_ADDR_TRAINING_PATTERN_SET,
-			&data);
-		exynos_dp_write_byte_to_dpcd(dp,
-			DPCD_ADDR_TRAINING_PATTERN_SET,
-			(u8)(data | DPCD_SCRAMBLING_DISABLED));
-	}
-}
-
-static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
-{
-	struct exynos_dp_device *dp = arg;
-
-	enum dp_irq_type irq_type;
-
-	irq_type = exynos_dp_get_irq_type(dp);
-	switch (irq_type) {
-	case DP_IRQ_TYPE_HP_CABLE_IN:
-		dev_dbg(dp->dev, "Received irq - cable in\n");
-		schedule_work(&dp->hotplug_work);
-		exynos_dp_clear_hotplug_interrupts(dp);
-		break;
-	case DP_IRQ_TYPE_HP_CABLE_OUT:
-		dev_dbg(dp->dev, "Received irq - cable out\n");
-		exynos_dp_clear_hotplug_interrupts(dp);
-		break;
-	case DP_IRQ_TYPE_HP_CHANGE:
-		/*
-		 * We get these change notifications once in a while, but there
-		 * is nothing we can do with them. Just ignore it for now and
-		 * only handle cable changes.
-		 */
-		dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
-		exynos_dp_clear_hotplug_interrupts(dp);
-		break;
-	default:
-		dev_err(dp->dev, "Received irq - unknown type!\n");
-		break;
-	}
-	return IRQ_HANDLED;
-}
-
-static void exynos_dp_hotplug(struct work_struct *work)
-{
-	struct exynos_dp_device *dp;
-	int ret;
-
-	dp = container_of(work, struct exynos_dp_device, hotplug_work);
-
-	ret = exynos_dp_detect_hpd(dp);
-	if (ret) {
-		/* Cable has been disconnected, we're done */
-		return;
-	}
-
-	ret = exynos_dp_handle_edid(dp);
-	if (ret) {
-		dev_err(dp->dev, "unable to handle edid\n");
-		return;
-	}
-
-	ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
-					dp->video_info->link_rate);
-	if (ret) {
-		dev_err(dp->dev, "unable to do link train\n");
-		return;
-	}
-
-	exynos_dp_enable_scramble(dp, 1);
-	exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
-	exynos_dp_enable_enhanced_mode(dp, 1);
-
-	exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
-	exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
-
-	exynos_dp_init_video(dp);
-	ret = exynos_dp_config_video(dp);
-	if (ret)
-		dev_err(dp->dev, "unable to config video\n");
-}
-
-#ifdef CONFIG_OF
-static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
-{
-	struct device_node *dp_node = dev->of_node;
-	struct exynos_dp_platdata *pd;
-	struct video_info *dp_video_config;
-
-	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-	if (!pd) {
-		dev_err(dev, "memory allocation for pdata failed\n");
-		return ERR_PTR(-ENOMEM);
-	}
-	dp_video_config = devm_kzalloc(dev,
-				sizeof(*dp_video_config), GFP_KERNEL);
-
-	if (!dp_video_config) {
-		dev_err(dev, "memory allocation for video config failed\n");
-		return ERR_PTR(-ENOMEM);
-	}
-	pd->video_info = dp_video_config;
-
-	dp_video_config->h_sync_polarity =
-		of_property_read_bool(dp_node, "hsync-active-high");
-
-	dp_video_config->v_sync_polarity =
-		of_property_read_bool(dp_node, "vsync-active-high");
-
-	dp_video_config->interlaced =
-		of_property_read_bool(dp_node, "interlaced");
-
-	if (of_property_read_u32(dp_node, "samsung,color-space",
-				&dp_video_config->color_space)) {
-		dev_err(dev, "failed to get color-space\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,dynamic-range",
-				&dp_video_config->dynamic_range)) {
-		dev_err(dev, "failed to get dynamic-range\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
-				&dp_video_config->ycbcr_coeff)) {
-		dev_err(dev, "failed to get ycbcr-coeff\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,color-depth",
-				&dp_video_config->color_depth)) {
-		dev_err(dev, "failed to get color-depth\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,link-rate",
-				&dp_video_config->link_rate)) {
-		dev_err(dev, "failed to get link-rate\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,lane-count",
-				&dp_video_config->lane_count)) {
-		dev_err(dev, "failed to get lane-count\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	return pd;
-}
-
-static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
-{
-	struct device_node *dp_phy_node = of_node_get(dp->dev->of_node);
-	u32 phy_base;
-	int ret = 0;
-
-	dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
-	if (!dp_phy_node) {
-		dev_err(dp->dev, "could not find dptx-phy node\n");
-		return -ENODEV;
-	}
-
-	if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
-		dev_err(dp->dev, "failed to get reg for dptx-phy\n");
-		ret = -EINVAL;
-		goto err;
-	}
-
-	if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
-				&dp->enable_mask)) {
-		dev_err(dp->dev, "failed to get enable-mask for dptx-phy\n");
-		ret = -EINVAL;
-		goto err;
-	}
-
-	dp->phy_addr = ioremap(phy_base, SZ_4);
-	if (!dp->phy_addr) {
-		dev_err(dp->dev, "failed to ioremap dp-phy\n");
-		ret = -ENOMEM;
-		goto err;
-	}
-
-err:
-	of_node_put(dp_phy_node);
-
-	return ret;
-}
-
-static void exynos_dp_phy_init(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = __raw_readl(dp->phy_addr);
-	reg |= dp->enable_mask;
-	__raw_writel(reg, dp->phy_addr);
-}
-
-static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = __raw_readl(dp->phy_addr);
-	reg &= ~(dp->enable_mask);
-	__raw_writel(reg, dp->phy_addr);
-}
-#else
-static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
-{
-	return NULL;
-}
-
-static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
-{
-	return -EINVAL;
-}
-
-static void exynos_dp_phy_init(struct exynos_dp_device *dp)
-{
-	return;
-}
-
-static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
-{
-	return;
-}
-#endif /* CONFIG_OF */
-
-static int exynos_dp_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	struct exynos_dp_device *dp;
-	struct exynos_dp_platdata *pdata;
-
-	int ret = 0;
-
-	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
-				GFP_KERNEL);
-	if (!dp) {
-		dev_err(&pdev->dev, "no memory for device data\n");
-		return -ENOMEM;
-	}
-
-	dp->dev = &pdev->dev;
-
-	if (pdev->dev.of_node) {
-		pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
-		if (IS_ERR(pdata))
-			return PTR_ERR(pdata);
-
-		ret = exynos_dp_dt_parse_phydata(dp);
-		if (ret)
-			return ret;
-	} else {
-		pdata = pdev->dev.platform_data;
-		if (!pdata) {
-			dev_err(&pdev->dev, "no platform data\n");
-			return -EINVAL;
-		}
-	}
-
-	dp->clock = devm_clk_get(&pdev->dev, "dp");
-	if (IS_ERR(dp->clock)) {
-		dev_err(&pdev->dev, "failed to get clock\n");
-		return PTR_ERR(dp->clock);
-	}
-
-	clk_prepare_enable(dp->clock);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dp->reg_base))
-		return PTR_ERR(dp->reg_base);
-
-	dp->irq = platform_get_irq(pdev, 0);
-	if (dp->irq == -ENXIO) {
-		dev_err(&pdev->dev, "failed to get irq\n");
-		return -ENODEV;
-	}
-
-	INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
-
-	dp->video_info = pdata->video_info;
-
-	if (pdev->dev.of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_init(dp);
-	} else {
-		if (pdata->phy_init)
-			pdata->phy_init();
-	}
-
-	exynos_dp_init_dp(dp);
-
-	ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
-				"exynos-dp", dp);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to request irq\n");
-		return ret;
-	}
-
-	platform_set_drvdata(pdev, dp);
-
-	return 0;
-}
-
-static int exynos_dp_remove(struct platform_device *pdev)
-{
-	struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
-	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
-
-	flush_work(&dp->hotplug_work);
-
-	if (pdev->dev.of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_exit(dp);
-	} else {
-		if (pdata->phy_exit)
-			pdata->phy_exit();
-	}
-
-	clk_disable_unprepare(dp->clock);
-
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos_dp_suspend(struct device *dev)
-{
-	struct exynos_dp_platdata *pdata = dev->platform_data;
-	struct exynos_dp_device *dp = dev_get_drvdata(dev);
-
-	disable_irq(dp->irq);
-
-	flush_work(&dp->hotplug_work);
-
-	if (dev->of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_exit(dp);
-	} else {
-		if (pdata->phy_exit)
-			pdata->phy_exit();
-	}
-
-	clk_disable_unprepare(dp->clock);
-
-	return 0;
-}
-
-static int exynos_dp_resume(struct device *dev)
-{
-	struct exynos_dp_platdata *pdata = dev->platform_data;
-	struct exynos_dp_device *dp = dev_get_drvdata(dev);
-
-	if (dev->of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_init(dp);
-	} else {
-		if (pdata->phy_init)
-			pdata->phy_init();
-	}
-
-	clk_prepare_enable(dp->clock);
-
-	exynos_dp_init_dp(dp);
-
-	enable_irq(dp->irq);
-
-	return 0;
-}
-#endif
-
-static const struct dev_pm_ops exynos_dp_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
-};
-
-static const struct of_device_id exynos_dp_match[] = {
-	{ .compatible = "samsung,exynos5-dp" },
-	{},
-};
-MODULE_DEVICE_TABLE(of, exynos_dp_match);
-
-static struct platform_driver exynos_dp_driver = {
-	.probe		= exynos_dp_probe,
-	.remove		= exynos_dp_remove,
-	.driver		= {
-		.name	= "exynos-dp",
-		.owner	= THIS_MODULE,
-		.pm	= &exynos_dp_pm_ops,
-		.of_match_table = of_match_ptr(exynos_dp_match),
-	},
-};
-
-module_platform_driver(exynos_dp_driver);
-
-MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
-MODULE_DESCRIPTION("Samsung SoC DP Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
deleted file mode 100644
index 6c567bbf..0000000
--- a/drivers/video/exynos/exynos_dp_core.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Header file for Samsung DP (Display Port) interface driver.
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * 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 _EXYNOS_DP_CORE_H
-#define _EXYNOS_DP_CORE_H
-
-enum dp_irq_type {
-	DP_IRQ_TYPE_HP_CABLE_IN,
-	DP_IRQ_TYPE_HP_CABLE_OUT,
-	DP_IRQ_TYPE_HP_CHANGE,
-	DP_IRQ_TYPE_UNKNOWN,
-};
-
-struct link_train {
-	int eq_loop;
-	int cr_loop[4];
-
-	u8 link_rate;
-	u8 lane_count;
-	u8 training_lane[4];
-
-	enum link_training_state lt_state;
-};
-
-struct exynos_dp_device {
-	struct device		*dev;
-	struct clk		*clock;
-	unsigned int		irq;
-	void __iomem		*reg_base;
-	void __iomem		*phy_addr;
-	unsigned int		enable_mask;
-
-	struct video_info	*video_info;
-	struct link_train	link_train;
-	struct work_struct	hotplug_work;
-};
-
-/* exynos_dp_reg.c */
-void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_stop_video(struct exynos_dp_device *dp);
-void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
-void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
-void exynos_dp_reset(struct exynos_dp_device *dp);
-void exynos_dp_swreset(struct exynos_dp_device *dp);
-void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
-enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
-void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
-				enum analog_power_block block,
-				bool enable);
-void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
-void exynos_dp_init_hpd(struct exynos_dp_device *dp);
-enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
-void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
-void exynos_dp_reset_aux(struct exynos_dp_device *dp);
-void exynos_dp_init_aux(struct exynos_dp_device *dp);
-int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
-void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
-int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
-int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned char data);
-int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned char *data);
-int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char data[]);
-int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char data[]);
-int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr);
-int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr,
-				unsigned int *data);
-int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char edid[]);
-void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
-void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
-void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
-void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
-void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
-				 enum pattern_set pattern);
-void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
-				u32 training_lane);
-void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
-				u32 training_lane);
-void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
-				u32 training_lane);
-void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
-				u32 training_lane);
-u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
-u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
-u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
-u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
-void exynos_dp_reset_macro(struct exynos_dp_device *dp);
-void exynos_dp_init_video(struct exynos_dp_device *dp);
-
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
-int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
-void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
-			enum clock_recovery_m_value_type type,
-			u32 m_value,
-			u32 n_value);
-void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
-void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_start_video(struct exynos_dp_device *dp);
-int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
-void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
-void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
-
-/* I2C EDID Chip ID, Slave Address */
-#define I2C_EDID_DEVICE_ADDR			0x50
-#define I2C_E_EDID_DEVICE_ADDR			0x30
-
-#define EDID_BLOCK_LENGTH			0x80
-#define EDID_HEADER_PATTERN			0x00
-#define EDID_EXTENSION_FLAG			0x7e
-#define EDID_CHECKSUM				0x7f
-
-/* Definition for DPCD Register */
-#define DPCD_ADDR_DPCD_REV			0x0000
-#define DPCD_ADDR_MAX_LINK_RATE			0x0001
-#define DPCD_ADDR_MAX_LANE_COUNT		0x0002
-#define DPCD_ADDR_LINK_BW_SET			0x0100
-#define DPCD_ADDR_LANE_COUNT_SET		0x0101
-#define DPCD_ADDR_TRAINING_PATTERN_SET		0x0102
-#define DPCD_ADDR_TRAINING_LANE0_SET		0x0103
-#define DPCD_ADDR_LANE0_1_STATUS		0x0202
-#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED	0x0204
-#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1	0x0206
-#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3	0x0207
-#define DPCD_ADDR_TEST_REQUEST			0x0218
-#define DPCD_ADDR_TEST_RESPONSE			0x0260
-#define DPCD_ADDR_TEST_EDID_CHECKSUM		0x0261
-#define DPCD_ADDR_SINK_POWER_STATE		0x0600
-
-/* DPCD_ADDR_MAX_LANE_COUNT */
-#define DPCD_ENHANCED_FRAME_CAP(x)		(((x) >> 7) & 0x1)
-#define DPCD_MAX_LANE_COUNT(x)			((x) & 0x1f)
-
-/* DPCD_ADDR_LANE_COUNT_SET */
-#define DPCD_ENHANCED_FRAME_EN			(0x1 << 7)
-#define DPCD_LANE_COUNT_SET(x)			((x) & 0x1f)
-
-/* DPCD_ADDR_TRAINING_PATTERN_SET */
-#define DPCD_SCRAMBLING_DISABLED		(0x1 << 5)
-#define DPCD_SCRAMBLING_ENABLED			(0x0 << 5)
-#define DPCD_TRAINING_PATTERN_2			(0x2 << 0)
-#define DPCD_TRAINING_PATTERN_1			(0x1 << 0)
-#define DPCD_TRAINING_PATTERN_DISABLED		(0x0 << 0)
-
-/* DPCD_ADDR_TRAINING_LANE0_SET */
-#define DPCD_MAX_PRE_EMPHASIS_REACHED		(0x1 << 5)
-#define DPCD_PRE_EMPHASIS_SET(x)		(((x) & 0x3) << 3)
-#define DPCD_PRE_EMPHASIS_GET(x)		(((x) >> 3) & 0x3)
-#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0	(0x0 << 3)
-#define DPCD_MAX_SWING_REACHED			(0x1 << 2)
-#define DPCD_VOLTAGE_SWING_SET(x)		(((x) & 0x3) << 0)
-#define DPCD_VOLTAGE_SWING_GET(x)		(((x) >> 0) & 0x3)
-#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0	(0x0 << 0)
-
-/* DPCD_ADDR_LANE0_1_STATUS */
-#define DPCD_LANE_SYMBOL_LOCKED			(0x1 << 2)
-#define DPCD_LANE_CHANNEL_EQ_DONE		(0x1 << 1)
-#define DPCD_LANE_CR_DONE			(0x1 << 0)
-#define DPCD_CHANNEL_EQ_BITS			(DPCD_LANE_CR_DONE|	\
-						 DPCD_LANE_CHANNEL_EQ_DONE|\
-						 DPCD_LANE_SYMBOL_LOCKED)
-
-/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
-#define DPCD_LINK_STATUS_UPDATED		(0x1 << 7)
-#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED	(0x1 << 6)
-#define DPCD_INTERLANE_ALIGN_DONE		(0x1 << 0)
-
-/* DPCD_ADDR_TEST_REQUEST */
-#define DPCD_TEST_EDID_READ			(0x1 << 2)
-
-/* DPCD_ADDR_TEST_RESPONSE */
-#define DPCD_TEST_EDID_CHECKSUM_WRITE		(0x1 << 2)
-
-/* DPCD_ADDR_SINK_POWER_STATE */
-#define DPCD_SET_POWER_STATE_D0			(0x1 << 0)
-#define DPCD_SET_POWER_STATE_D4			(0x2 << 0)
-
-#endif /* _EXYNOS_DP_CORE_H */
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c
deleted file mode 100644
index 29d9d03..0000000
--- a/drivers/video/exynos/exynos_dp_reg.c
+++ /dev/null
@@ -1,1245 +0,0 @@
-/*
- * Samsung DP (Display port) register interface driver.
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * 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/device.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#include <video/exynos_dp.h>
-
-#include "exynos_dp_core.h"
-#include "exynos_dp_reg.h"
-
-#define COMMON_INT_MASK_1	0
-#define COMMON_INT_MASK_2	0
-#define COMMON_INT_MASK_3	0
-#define COMMON_INT_MASK_4	(HOTPLUG_CHG | HPD_LOST | PLUG)
-#define INT_STA_MASK		INT_HPD
-
-void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable) {
-		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-		reg |= HDCP_VIDEO_MUTE;
-		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-		reg &= ~HDCP_VIDEO_MUTE;
-		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-	}
-}
-
-void exynos_dp_stop_video(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-	reg &= ~VIDEO_EN;
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-}
-
-void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable)
-		reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
-			LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
-	else
-		reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
-			LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
-
-	writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
-}
-
-void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = TX_TERMINAL_CTRL_50_OHM;
-	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
-
-	reg = SEL_24M | TX_DVDD_BIT_1_0625V;
-	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
-
-	reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
-	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
-
-	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
-		TX_CUR1_2X | TX_CUR_16_MA;
-	writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
-
-	reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
-		CH1_AMP_400_MV | CH0_AMP_400_MV;
-	writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
-}
-
-void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
-{
-	/* Set interrupt pin assertion polarity as high */
-	writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
-
-	/* Clear pending regisers */
-	writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
-	writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
-	writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
-	writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
-	writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
-
-	/* 0:mask,1: unmask */
-	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
-	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
-	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
-	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
-	writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
-}
-
-void exynos_dp_reset(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	exynos_dp_stop_video(dp);
-	exynos_dp_enable_video_mute(dp, 0);
-
-	reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
-		AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
-		HDCP_FUNC_EN_N | SW_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-
-	reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
-		SERDES_FIFO_FUNC_EN_N |
-		LS_CLK_DOMAIN_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-
-	usleep_range(20, 30);
-
-	exynos_dp_lane_swap(dp, 0);
-
-	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-	writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-
-	writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
-	writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
-
-	writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
-	writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
-
-	writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
-
-	writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
-
-	writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
-	writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
-
-	writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
-	writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
-
-	writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-}
-
-void exynos_dp_swreset(struct exynos_dp_device *dp)
-{
-	writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
-}
-
-void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* 0: mask, 1: unmask */
-	reg = COMMON_INT_MASK_1;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
-
-	reg = COMMON_INT_MASK_2;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
-
-	reg = COMMON_INT_MASK_3;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
-
-	reg = COMMON_INT_MASK_4;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
-
-	reg = INT_STA_MASK;
-	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
-}
-
-enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
-	if (reg & PLL_LOCK)
-		return PLL_LOCKED;
-	else
-		return PLL_UNLOCKED;
-}
-
-void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable) {
-		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
-		reg |= DP_PLL_PD;
-		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
-		reg &= ~DP_PLL_PD;
-		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
-	}
-}
-
-void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
-				enum analog_power_block block,
-				bool enable)
-{
-	u32 reg;
-
-	switch (block) {
-	case AUX_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= AUX_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~AUX_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case CH0_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= CH0_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~CH0_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case CH1_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= CH1_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~CH1_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case CH2_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= CH2_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~CH2_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case CH3_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= CH3_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~CH3_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case ANALOG_TOTAL:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= DP_PHY_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~DP_PHY_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case POWER_ALL:
-		if (enable) {
-			reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
-				CH1_PD | CH0_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
-{
-	u32 reg;
-	int timeout_loop = 0;
-
-	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
-
-	reg = PLL_LOCK_CHG;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
-	reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
-	writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
-
-	/* Power up PLL */
-	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-		exynos_dp_set_pll_power_down(dp, 0);
-
-		while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-			timeout_loop++;
-			if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-				dev_err(dp->dev, "failed to get pll lock status\n");
-				return;
-			}
-			usleep_range(10, 20);
-		}
-	}
-
-	/* Enable Serdes FIFO function and Link symbol clock domain module */
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-	reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
-		| AUX_FUNC_EN_N);
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-}
-
-void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = HOTPLUG_CHG | HPD_LOST | PLUG;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
-
-	reg = INT_HPD;
-	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
-}
-
-void exynos_dp_init_hpd(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	exynos_dp_clear_hotplug_interrupts(dp);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	reg &= ~(F_HPD | HPD_CTRL);
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-}
-
-enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* Parse hotplug interrupt status register */
-	reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
-
-	if (reg & PLUG)
-		return DP_IRQ_TYPE_HP_CABLE_IN;
-
-	if (reg & HPD_LOST)
-		return DP_IRQ_TYPE_HP_CABLE_OUT;
-
-	if (reg & HOTPLUG_CHG)
-		return DP_IRQ_TYPE_HP_CHANGE;
-
-	return DP_IRQ_TYPE_UNKNOWN;
-}
-
-void exynos_dp_reset_aux(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* Disable AUX channel module */
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-	reg |= AUX_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-}
-
-void exynos_dp_init_aux(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* Clear inerrupts related to AUX channel */
-	reg = RPLY_RECEIV | AUX_ERR;
-	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
-
-	exynos_dp_reset_aux(dp);
-
-	/* Disable AUX transaction H/W retry */
-	reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
-		AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
-
-	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
-	reg = DEFER_CTRL_EN | DEFER_COUNT(1);
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
-
-	/* Enable AUX channel module */
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-	reg &= ~AUX_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-}
-
-int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	if (reg & HPD_STATUS)
-		return 0;
-
-	return -EINVAL;
-}
-
-void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-	reg &= ~SW_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-}
-
-int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
-{
-	int reg;
-	int retval = 0;
-	int timeout_loop = 0;
-
-	/* Enable AUX CH operation */
-	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-	reg |= AUX_EN;
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-
-	/* Is AUX CH command reply received? */
-	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-	while (!(reg & RPLY_RECEIV)) {
-		timeout_loop++;
-		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-			dev_err(dp->dev, "AUX CH command reply failed!\n");
-			return -ETIMEDOUT;
-		}
-		reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-		usleep_range(10, 11);
-	}
-
-	/* Clear interrupt source for AUX CH command reply */
-	writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
-
-	/* Clear interrupt source for AUX CH access error */
-	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-	if (reg & AUX_ERR) {
-		writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
-		return -EREMOTEIO;
-	}
-
-	/* Check AUX CH error access status */
-	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
-	if ((reg & AUX_STATUS_MASK) != 0) {
-		dev_err(dp->dev, "AUX CH error happens: %d\n\n",
-			reg & AUX_STATUS_MASK);
-		return -EREMOTEIO;
-	}
-
-	return retval;
-}
-
-int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned char data)
-{
-	u32 reg;
-	int i;
-	int retval;
-
-	for (i = 0; i < 3; i++) {
-		/* Clear AUX CH data buffer */
-		reg = BUF_CLR;
-		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-		/* Select DPCD device address */
-		reg = AUX_ADDR_7_0(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-		reg = AUX_ADDR_15_8(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-		reg = AUX_ADDR_19_16(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-		/* Write data buffer */
-		reg = (unsigned int)data;
-		writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-
-		/*
-		 * Set DisplayPort transaction and write 1 byte
-		 * If bit 3 is 1, DisplayPort transaction.
-		 * If Bit 3 is 0, I2C transaction.
-		 */
-		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-		/* Start AUX transaction */
-		retval = exynos_dp_start_aux_transaction(dp);
-		if (retval == 0)
-			break;
-		else
-			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-				__func__);
-	}
-
-	return retval;
-}
-
-int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned char *data)
-{
-	u32 reg;
-	int i;
-	int retval;
-
-	for (i = 0; i < 3; i++) {
-		/* Clear AUX CH data buffer */
-		reg = BUF_CLR;
-		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-		/* Select DPCD device address */
-		reg = AUX_ADDR_7_0(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-		reg = AUX_ADDR_15_8(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-		reg = AUX_ADDR_19_16(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-		/*
-		 * Set DisplayPort transaction and read 1 byte
-		 * If bit 3 is 1, DisplayPort transaction.
-		 * If Bit 3 is 0, I2C transaction.
-		 */
-		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-		/* Start AUX transaction */
-		retval = exynos_dp_start_aux_transaction(dp);
-		if (retval == 0)
-			break;
-		else
-			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-				__func__);
-	}
-
-	/* Read data buffer */
-	reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-	*data = (unsigned char)(reg & 0xff);
-
-	return retval;
-}
-
-int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char data[])
-{
-	u32 reg;
-	unsigned int start_offset;
-	unsigned int cur_data_count;
-	unsigned int cur_data_idx;
-	int i;
-	int retval = 0;
-
-	/* Clear AUX CH data buffer */
-	reg = BUF_CLR;
-	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-	start_offset = 0;
-	while (start_offset < count) {
-		/* Buffer size of AUX CH is 16 * 4bytes */
-		if ((count - start_offset) > 16)
-			cur_data_count = 16;
-		else
-			cur_data_count = count - start_offset;
-
-		for (i = 0; i < 3; i++) {
-			/* Select DPCD device address */
-			reg = AUX_ADDR_7_0(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-			reg = AUX_ADDR_15_8(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-			reg = AUX_ADDR_19_16(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-			for (cur_data_idx = 0; cur_data_idx < cur_data_count;
-			     cur_data_idx++) {
-				reg = data[start_offset + cur_data_idx];
-				writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0
-							  + 4 * cur_data_idx);
-			}
-
-			/*
-			 * Set DisplayPort transaction and write
-			 * If bit 3 is 1, DisplayPort transaction.
-			 * If Bit 3 is 0, I2C transaction.
-			 */
-			reg = AUX_LENGTH(cur_data_count) |
-				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-			/* Start AUX transaction */
-			retval = exynos_dp_start_aux_transaction(dp);
-			if (retval == 0)
-				break;
-			else
-				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-					__func__);
-		}
-
-		start_offset += cur_data_count;
-	}
-
-	return retval;
-}
-
-int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char data[])
-{
-	u32 reg;
-	unsigned int start_offset;
-	unsigned int cur_data_count;
-	unsigned int cur_data_idx;
-	int i;
-	int retval = 0;
-
-	/* Clear AUX CH data buffer */
-	reg = BUF_CLR;
-	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-	start_offset = 0;
-	while (start_offset < count) {
-		/* Buffer size of AUX CH is 16 * 4bytes */
-		if ((count - start_offset) > 16)
-			cur_data_count = 16;
-		else
-			cur_data_count = count - start_offset;
-
-		/* AUX CH Request Transaction process */
-		for (i = 0; i < 3; i++) {
-			/* Select DPCD device address */
-			reg = AUX_ADDR_7_0(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-			reg = AUX_ADDR_15_8(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-			reg = AUX_ADDR_19_16(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-			/*
-			 * Set DisplayPort transaction and read
-			 * If bit 3 is 1, DisplayPort transaction.
-			 * If Bit 3 is 0, I2C transaction.
-			 */
-			reg = AUX_LENGTH(cur_data_count) |
-				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-			/* Start AUX transaction */
-			retval = exynos_dp_start_aux_transaction(dp);
-			if (retval == 0)
-				break;
-			else
-				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-					__func__);
-		}
-
-		for (cur_data_idx = 0; cur_data_idx < cur_data_count;
-		    cur_data_idx++) {
-			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
-						 + 4 * cur_data_idx);
-			data[start_offset + cur_data_idx] =
-				(unsigned char)reg;
-		}
-
-		start_offset += cur_data_count;
-	}
-
-	return retval;
-}
-
-int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr)
-{
-	u32 reg;
-	int retval;
-
-	/* Set EDID device address */
-	reg = device_addr;
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-	/* Set offset from base address of EDID device */
-	writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-
-	/*
-	 * Set I2C transaction and write address
-	 * If bit 3 is 1, DisplayPort transaction.
-	 * If Bit 3 is 0, I2C transaction.
-	 */
-	reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
-		AUX_TX_COMM_WRITE;
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-	/* Start AUX transaction */
-	retval = exynos_dp_start_aux_transaction(dp);
-	if (retval != 0)
-		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
-
-	return retval;
-}
-
-int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr,
-				unsigned int *data)
-{
-	u32 reg;
-	int i;
-	int retval;
-
-	for (i = 0; i < 3; i++) {
-		/* Clear AUX CH data buffer */
-		reg = BUF_CLR;
-		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-		/* Select EDID device */
-		retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
-		if (retval != 0)
-			continue;
-
-		/*
-		 * Set I2C transaction and read data
-		 * If bit 3 is 1, DisplayPort transaction.
-		 * If Bit 3 is 0, I2C transaction.
-		 */
-		reg = AUX_TX_COMM_I2C_TRANSACTION |
-			AUX_TX_COMM_READ;
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-		/* Start AUX transaction */
-		retval = exynos_dp_start_aux_transaction(dp);
-		if (retval == 0)
-			break;
-		else
-			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-				__func__);
-	}
-
-	/* Read data */
-	if (retval == 0)
-		*data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-
-	return retval;
-}
-
-int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char edid[])
-{
-	u32 reg;
-	unsigned int i, j;
-	unsigned int cur_data_idx;
-	unsigned int defer = 0;
-	int retval = 0;
-
-	for (i = 0; i < count; i += 16) {
-		for (j = 0; j < 3; j++) {
-			/* Clear AUX CH data buffer */
-			reg = BUF_CLR;
-			writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-			/* Set normal AUX CH command */
-			reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-			reg &= ~ADDR_ONLY;
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-
-			/*
-			 * If Rx sends defer, Tx sends only reads
-			 * request without sending address
-			 */
-			if (!defer)
-				retval = exynos_dp_select_i2c_device(dp,
-						device_addr, reg_addr + i);
-			else
-				defer = 0;
-
-			if (retval == 0) {
-				/*
-				 * Set I2C transaction and write data
-				 * If bit 3 is 1, DisplayPort transaction.
-				 * If Bit 3 is 0, I2C transaction.
-				 */
-				reg = AUX_LENGTH(16) |
-					AUX_TX_COMM_I2C_TRANSACTION |
-					AUX_TX_COMM_READ;
-				writel(reg, dp->reg_base +
-					EXYNOS_DP_AUX_CH_CTL_1);
-
-				/* Start AUX transaction */
-				retval = exynos_dp_start_aux_transaction(dp);
-				if (retval == 0)
-					break;
-				else
-					dev_dbg(dp->dev,
-						"%s: Aux Transaction fail!\n",
-						__func__);
-			}
-			/* Check if Rx sends defer */
-			reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
-			if (reg == AUX_RX_COMM_AUX_DEFER ||
-				reg == AUX_RX_COMM_I2C_DEFER) {
-				dev_err(dp->dev, "Defer: %d\n\n", reg);
-				defer = 1;
-			}
-		}
-
-		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
-			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
-						 + 4 * cur_data_idx);
-			edid[i + cur_data_idx] = (unsigned char)reg;
-		}
-	}
-
-	return retval;
-}
-
-void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype)
-{
-	u32 reg;
-
-	reg = bwtype;
-	if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS))
-		writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
-}
-
-void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
-	*bwtype = reg;
-}
-
-void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
-{
-	u32 reg;
-
-	reg = count;
-	writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
-}
-
-void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
-	*count = reg;
-}
-
-void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable) {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg |= ENHANCED;
-		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg &= ~ENHANCED;
-		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-	}
-}
-
-void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
-				 enum pattern_set pattern)
-{
-	u32 reg;
-
-	switch (pattern) {
-	case PRBS7:
-		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	case D10_2:
-		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	case TRAINING_PTN1:
-		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	case TRAINING_PTN2:
-		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	case DP_NONE:
-		reg = SCRAMBLING_ENABLE |
-			LINK_QUAL_PATTERN_SET_DISABLE |
-			SW_TRAINING_PATTERN_SET_NORMAL;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	default:
-		break;
-	}
-}
-
-void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-	reg &= ~PRE_EMPHASIS_SET_MASK;
-	reg |= level << PRE_EMPHASIS_SET_SHIFT;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-	reg &= ~PRE_EMPHASIS_SET_MASK;
-	reg |= level << PRE_EMPHASIS_SET_SHIFT;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-	reg &= ~PRE_EMPHASIS_SET_MASK;
-	reg |= level << PRE_EMPHASIS_SET_SHIFT;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-	reg &= ~PRE_EMPHASIS_SET_MASK;
-	reg |= level << PRE_EMPHASIS_SET_SHIFT;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
-					u32 training_lane)
-{
-	u32 reg;
-
-	reg = training_lane;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
-					u32 training_lane)
-{
-	u32 reg;
-
-	reg = training_lane;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
-					u32 training_lane)
-{
-	u32 reg;
-
-	reg = training_lane;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
-					u32 training_lane)
-{
-	u32 reg;
-
-	reg = training_lane;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-}
-
-u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-	return reg;
-}
-
-u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-	return reg;
-}
-
-u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-	return reg;
-}
-
-u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-	return reg;
-}
-
-void exynos_dp_reset_macro(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
-	reg |= MACRO_RST;
-	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
-
-	/* 10 us is the minimum reset time. */
-	usleep_range(10, 20);
-
-	reg &= ~MACRO_RST;
-	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
-}
-
-void exynos_dp_init_video(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
-
-	reg = 0x0;
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-
-	reg = CHA_CRI(4) | CHA_CTRL;
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-
-	reg = 0x0;
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-
-	reg = VID_HRES_TH(2) | VID_VRES_TH(0);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
-}
-
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* Configure the input color depth, color space, dynamic range */
-	reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
-		(dp->video_info->color_depth << IN_BPC_SHIFT) |
-		(dp->video_info->color_space << IN_COLOR_F_SHIFT);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
-
-	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
-	reg &= ~IN_YC_COEFFI_MASK;
-	if (dp->video_info->ycbcr_coeff)
-		reg |= IN_YC_COEFFI_ITU709;
-	else
-		reg |= IN_YC_COEFFI_ITU601;
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
-}
-
-int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-
-	if (!(reg & DET_STA)) {
-		dev_dbg(dp->dev, "Input stream clock not detected.\n");
-		return -EINVAL;
-	}
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-	dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
-
-	if (reg & CHA_STA) {
-		dev_dbg(dp->dev, "Input stream clk is changing\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
-		enum clock_recovery_m_value_type type,
-		u32 m_value,
-		u32 n_value)
-{
-	u32 reg;
-
-	if (type == REGISTER_M) {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg |= FIX_M_VID;
-		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg = m_value & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
-		reg = (m_value >> 8) & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
-		reg = (m_value >> 16) & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
-
-		reg = n_value & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
-		reg = (n_value >> 8) & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
-		reg = (n_value >> 16) & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
-	} else  {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg &= ~FIX_M_VID;
-		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-
-		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
-		writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
-		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
-	}
-}
-
-void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type)
-{
-	u32 reg;
-
-	if (type == VIDEO_TIMING_FROM_CAPTURE) {
-		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-		reg &= ~FORMAT_SEL;
-		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-		reg |= FORMAT_SEL;
-		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	}
-}
-
-void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable) {
-		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-		reg &= ~VIDEO_MODE_MASK;
-		reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
-		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-		reg &= ~VIDEO_MODE_MASK;
-		reg |= VIDEO_MODE_SLAVE_MODE;
-		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-	}
-}
-
-void exynos_dp_start_video(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-	reg |= VIDEO_EN;
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-}
-
-int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	if (!(reg & STRM_VALID)) {
-		dev_dbg(dp->dev, "Input video stream is not detected.\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-	reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
-	reg |= MASTER_VID_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	reg &= ~INTERACE_SCAN_CFG;
-	reg |= (dp->video_info->interlaced << 2);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	reg &= ~VSYNC_POLARITY_CFG;
-	reg |= (dp->video_info->v_sync_polarity << 1);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	reg &= ~HSYNC_POLARITY_CFG;
-	reg |= (dp->video_info->h_sync_polarity << 0);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-
-	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
-	writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-}
-
-void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-	reg &= ~SCRAMBLING_DISABLE;
-	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-}
-
-void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-	reg |= SCRAMBLING_DISABLE;
-	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-}
diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/video/exynos/exynos_dp_reg.h
deleted file mode 100644
index 2e9bd0e..0000000
--- a/drivers/video/exynos/exynos_dp_reg.h
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Register definition file for Samsung DP driver
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _EXYNOS_DP_REG_H
-#define _EXYNOS_DP_REG_H
-
-#define EXYNOS_DP_TX_SW_RESET			0x14
-#define EXYNOS_DP_FUNC_EN_1			0x18
-#define EXYNOS_DP_FUNC_EN_2			0x1C
-#define EXYNOS_DP_VIDEO_CTL_1			0x20
-#define EXYNOS_DP_VIDEO_CTL_2			0x24
-#define EXYNOS_DP_VIDEO_CTL_3			0x28
-
-#define EXYNOS_DP_VIDEO_CTL_8			0x3C
-#define EXYNOS_DP_VIDEO_CTL_10			0x44
-
-#define EXYNOS_DP_LANE_MAP			0x35C
-
-#define EXYNOS_DP_ANALOG_CTL_1			0x370
-#define EXYNOS_DP_ANALOG_CTL_2			0x374
-#define EXYNOS_DP_ANALOG_CTL_3			0x378
-#define EXYNOS_DP_PLL_FILTER_CTL_1		0x37C
-#define EXYNOS_DP_TX_AMP_TUNING_CTL		0x380
-
-#define EXYNOS_DP_AUX_HW_RETRY_CTL		0x390
-
-#define EXYNOS_DP_COMMON_INT_STA_1		0x3C4
-#define EXYNOS_DP_COMMON_INT_STA_2		0x3C8
-#define EXYNOS_DP_COMMON_INT_STA_3		0x3CC
-#define EXYNOS_DP_COMMON_INT_STA_4		0x3D0
-#define EXYNOS_DP_INT_STA			0x3DC
-#define EXYNOS_DP_COMMON_INT_MASK_1		0x3E0
-#define EXYNOS_DP_COMMON_INT_MASK_2		0x3E4
-#define EXYNOS_DP_COMMON_INT_MASK_3		0x3E8
-#define EXYNOS_DP_COMMON_INT_MASK_4		0x3EC
-#define EXYNOS_DP_INT_STA_MASK			0x3F8
-#define EXYNOS_DP_INT_CTL			0x3FC
-
-#define EXYNOS_DP_SYS_CTL_1			0x600
-#define EXYNOS_DP_SYS_CTL_2			0x604
-#define EXYNOS_DP_SYS_CTL_3			0x608
-#define EXYNOS_DP_SYS_CTL_4			0x60C
-
-#define EXYNOS_DP_PKT_SEND_CTL			0x640
-#define EXYNOS_DP_HDCP_CTL			0x648
-
-#define EXYNOS_DP_LINK_BW_SET			0x680
-#define EXYNOS_DP_LANE_COUNT_SET		0x684
-#define EXYNOS_DP_TRAINING_PTN_SET		0x688
-#define EXYNOS_DP_LN0_LINK_TRAINING_CTL		0x68C
-#define EXYNOS_DP_LN1_LINK_TRAINING_CTL		0x690
-#define EXYNOS_DP_LN2_LINK_TRAINING_CTL		0x694
-#define EXYNOS_DP_LN3_LINK_TRAINING_CTL		0x698
-
-#define EXYNOS_DP_DEBUG_CTL			0x6C0
-#define EXYNOS_DP_HPD_DEGLITCH_L		0x6C4
-#define EXYNOS_DP_HPD_DEGLITCH_H		0x6C8
-#define EXYNOS_DP_LINK_DEBUG_CTL		0x6E0
-
-#define EXYNOS_DP_M_VID_0			0x700
-#define EXYNOS_DP_M_VID_1			0x704
-#define EXYNOS_DP_M_VID_2			0x708
-#define EXYNOS_DP_N_VID_0			0x70C
-#define EXYNOS_DP_N_VID_1			0x710
-#define EXYNOS_DP_N_VID_2			0x714
-
-#define EXYNOS_DP_PLL_CTL			0x71C
-#define EXYNOS_DP_PHY_PD			0x720
-#define EXYNOS_DP_PHY_TEST			0x724
-
-#define EXYNOS_DP_VIDEO_FIFO_THRD		0x730
-#define EXYNOS_DP_AUDIO_MARGIN			0x73C
-
-#define EXYNOS_DP_M_VID_GEN_FILTER_TH		0x764
-#define EXYNOS_DP_M_AUD_GEN_FILTER_TH		0x778
-#define EXYNOS_DP_AUX_CH_STA			0x780
-#define EXYNOS_DP_AUX_CH_DEFER_CTL		0x788
-#define EXYNOS_DP_AUX_RX_COMM			0x78C
-#define EXYNOS_DP_BUFFER_DATA_CTL		0x790
-#define EXYNOS_DP_AUX_CH_CTL_1			0x794
-#define EXYNOS_DP_AUX_ADDR_7_0			0x798
-#define EXYNOS_DP_AUX_ADDR_15_8			0x79C
-#define EXYNOS_DP_AUX_ADDR_19_16		0x7A0
-#define EXYNOS_DP_AUX_CH_CTL_2			0x7A4
-
-#define EXYNOS_DP_BUF_DATA_0			0x7C0
-
-#define EXYNOS_DP_SOC_GENERAL_CTL		0x800
-
-/* EXYNOS_DP_TX_SW_RESET */
-#define RESET_DP_TX				(0x1 << 0)
-
-/* EXYNOS_DP_FUNC_EN_1 */
-#define MASTER_VID_FUNC_EN_N			(0x1 << 7)
-#define SLAVE_VID_FUNC_EN_N			(0x1 << 5)
-#define AUD_FIFO_FUNC_EN_N			(0x1 << 4)
-#define AUD_FUNC_EN_N				(0x1 << 3)
-#define HDCP_FUNC_EN_N				(0x1 << 2)
-#define CRC_FUNC_EN_N				(0x1 << 1)
-#define SW_FUNC_EN_N				(0x1 << 0)
-
-/* EXYNOS_DP_FUNC_EN_2 */
-#define SSC_FUNC_EN_N				(0x1 << 7)
-#define AUX_FUNC_EN_N				(0x1 << 2)
-#define SERDES_FIFO_FUNC_EN_N			(0x1 << 1)
-#define LS_CLK_DOMAIN_FUNC_EN_N			(0x1 << 0)
-
-/* EXYNOS_DP_VIDEO_CTL_1 */
-#define VIDEO_EN				(0x1 << 7)
-#define HDCP_VIDEO_MUTE				(0x1 << 6)
-
-/* EXYNOS_DP_VIDEO_CTL_1 */
-#define IN_D_RANGE_MASK				(0x1 << 7)
-#define IN_D_RANGE_SHIFT			(7)
-#define IN_D_RANGE_CEA				(0x1 << 7)
-#define IN_D_RANGE_VESA				(0x0 << 7)
-#define IN_BPC_MASK				(0x7 << 4)
-#define IN_BPC_SHIFT				(4)
-#define IN_BPC_12_BITS				(0x3 << 4)
-#define IN_BPC_10_BITS				(0x2 << 4)
-#define IN_BPC_8_BITS				(0x1 << 4)
-#define IN_BPC_6_BITS				(0x0 << 4)
-#define IN_COLOR_F_MASK				(0x3 << 0)
-#define IN_COLOR_F_SHIFT			(0)
-#define IN_COLOR_F_YCBCR444			(0x2 << 0)
-#define IN_COLOR_F_YCBCR422			(0x1 << 0)
-#define IN_COLOR_F_RGB				(0x0 << 0)
-
-/* EXYNOS_DP_VIDEO_CTL_3 */
-#define IN_YC_COEFFI_MASK			(0x1 << 7)
-#define IN_YC_COEFFI_SHIFT			(7)
-#define IN_YC_COEFFI_ITU709			(0x1 << 7)
-#define IN_YC_COEFFI_ITU601			(0x0 << 7)
-#define VID_CHK_UPDATE_TYPE_MASK		(0x1 << 4)
-#define VID_CHK_UPDATE_TYPE_SHIFT		(4)
-#define VID_CHK_UPDATE_TYPE_1			(0x1 << 4)
-#define VID_CHK_UPDATE_TYPE_0			(0x0 << 4)
-
-/* EXYNOS_DP_VIDEO_CTL_8 */
-#define VID_HRES_TH(x)				(((x) & 0xf) << 4)
-#define VID_VRES_TH(x)				(((x) & 0xf) << 0)
-
-/* EXYNOS_DP_VIDEO_CTL_10 */
-#define FORMAT_SEL				(0x1 << 4)
-#define INTERACE_SCAN_CFG			(0x1 << 2)
-#define VSYNC_POLARITY_CFG			(0x1 << 1)
-#define HSYNC_POLARITY_CFG			(0x1 << 0)
-
-/* EXYNOS_DP_LANE_MAP */
-#define LANE3_MAP_LOGIC_LANE_0			(0x0 << 6)
-#define LANE3_MAP_LOGIC_LANE_1			(0x1 << 6)
-#define LANE3_MAP_LOGIC_LANE_2			(0x2 << 6)
-#define LANE3_MAP_LOGIC_LANE_3			(0x3 << 6)
-#define LANE2_MAP_LOGIC_LANE_0			(0x0 << 4)
-#define LANE2_MAP_LOGIC_LANE_1			(0x1 << 4)
-#define LANE2_MAP_LOGIC_LANE_2			(0x2 << 4)
-#define LANE2_MAP_LOGIC_LANE_3			(0x3 << 4)
-#define LANE1_MAP_LOGIC_LANE_0			(0x0 << 2)
-#define LANE1_MAP_LOGIC_LANE_1			(0x1 << 2)
-#define LANE1_MAP_LOGIC_LANE_2			(0x2 << 2)
-#define LANE1_MAP_LOGIC_LANE_3			(0x3 << 2)
-#define LANE0_MAP_LOGIC_LANE_0			(0x0 << 0)
-#define LANE0_MAP_LOGIC_LANE_1			(0x1 << 0)
-#define LANE0_MAP_LOGIC_LANE_2			(0x2 << 0)
-#define LANE0_MAP_LOGIC_LANE_3			(0x3 << 0)
-
-/* EXYNOS_DP_ANALOG_CTL_1 */
-#define TX_TERMINAL_CTRL_50_OHM			(0x1 << 4)
-
-/* EXYNOS_DP_ANALOG_CTL_2 */
-#define SEL_24M					(0x1 << 3)
-#define TX_DVDD_BIT_1_0625V			(0x4 << 0)
-
-/* EXYNOS_DP_ANALOG_CTL_3 */
-#define DRIVE_DVDD_BIT_1_0625V			(0x4 << 5)
-#define VCO_BIT_600_MICRO			(0x5 << 0)
-
-/* EXYNOS_DP_PLL_FILTER_CTL_1 */
-#define PD_RING_OSC				(0x1 << 6)
-#define AUX_TERMINAL_CTRL_50_OHM		(0x2 << 4)
-#define TX_CUR1_2X				(0x1 << 2)
-#define TX_CUR_16_MA				(0x3 << 0)
-
-/* EXYNOS_DP_TX_AMP_TUNING_CTL */
-#define CH3_AMP_400_MV				(0x0 << 24)
-#define CH2_AMP_400_MV				(0x0 << 16)
-#define CH1_AMP_400_MV				(0x0 << 8)
-#define CH0_AMP_400_MV				(0x0 << 0)
-
-/* EXYNOS_DP_AUX_HW_RETRY_CTL */
-#define AUX_BIT_PERIOD_EXPECTED_DELAY(x)	(((x) & 0x7) << 8)
-#define AUX_HW_RETRY_INTERVAL_MASK		(0x3 << 3)
-#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS	(0x0 << 3)
-#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS	(0x1 << 3)
-#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS	(0x2 << 3)
-#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS	(0x3 << 3)
-#define AUX_HW_RETRY_COUNT_SEL(x)		(((x) & 0x7) << 0)
-
-/* EXYNOS_DP_COMMON_INT_STA_1 */
-#define VSYNC_DET				(0x1 << 7)
-#define PLL_LOCK_CHG				(0x1 << 6)
-#define SPDIF_ERR				(0x1 << 5)
-#define SPDIF_UNSTBL				(0x1 << 4)
-#define VID_FORMAT_CHG				(0x1 << 3)
-#define AUD_CLK_CHG				(0x1 << 2)
-#define VID_CLK_CHG				(0x1 << 1)
-#define SW_INT					(0x1 << 0)
-
-/* EXYNOS_DP_COMMON_INT_STA_2 */
-#define ENC_EN_CHG				(0x1 << 6)
-#define HW_BKSV_RDY				(0x1 << 3)
-#define HW_SHA_DONE				(0x1 << 2)
-#define HW_AUTH_STATE_CHG			(0x1 << 1)
-#define HW_AUTH_DONE				(0x1 << 0)
-
-/* EXYNOS_DP_COMMON_INT_STA_3 */
-#define AFIFO_UNDER				(0x1 << 7)
-#define AFIFO_OVER				(0x1 << 6)
-#define R0_CHK_FLAG				(0x1 << 5)
-
-/* EXYNOS_DP_COMMON_INT_STA_4 */
-#define PSR_ACTIVE				(0x1 << 7)
-#define PSR_INACTIVE				(0x1 << 6)
-#define SPDIF_BI_PHASE_ERR			(0x1 << 5)
-#define HOTPLUG_CHG				(0x1 << 2)
-#define HPD_LOST				(0x1 << 1)
-#define PLUG					(0x1 << 0)
-
-/* EXYNOS_DP_INT_STA */
-#define INT_HPD					(0x1 << 6)
-#define HW_TRAINING_FINISH			(0x1 << 5)
-#define RPLY_RECEIV				(0x1 << 1)
-#define AUX_ERR					(0x1 << 0)
-
-/* EXYNOS_DP_INT_CTL */
-#define SOFT_INT_CTRL				(0x1 << 2)
-#define INT_POL1				(0x1 << 1)
-#define INT_POL0				(0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_1 */
-#define DET_STA					(0x1 << 2)
-#define FORCE_DET				(0x1 << 1)
-#define DET_CTRL				(0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_2 */
-#define CHA_CRI(x)				(((x) & 0xf) << 4)
-#define CHA_STA					(0x1 << 2)
-#define FORCE_CHA				(0x1 << 1)
-#define CHA_CTRL				(0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_3 */
-#define HPD_STATUS				(0x1 << 6)
-#define F_HPD					(0x1 << 5)
-#define HPD_CTRL				(0x1 << 4)
-#define HDCP_RDY				(0x1 << 3)
-#define STRM_VALID				(0x1 << 2)
-#define F_VALID					(0x1 << 1)
-#define VALID_CTRL				(0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_4 */
-#define FIX_M_AUD				(0x1 << 4)
-#define ENHANCED				(0x1 << 3)
-#define FIX_M_VID				(0x1 << 2)
-#define M_VID_UPDATE_CTRL			(0x3 << 0)
-
-/* EXYNOS_DP_TRAINING_PTN_SET */
-#define SCRAMBLER_TYPE				(0x1 << 9)
-#define HW_LINK_TRAINING_PATTERN		(0x1 << 8)
-#define SCRAMBLING_DISABLE			(0x1 << 5)
-#define SCRAMBLING_ENABLE			(0x0 << 5)
-#define LINK_QUAL_PATTERN_SET_MASK		(0x3 << 2)
-#define LINK_QUAL_PATTERN_SET_PRBS7		(0x3 << 2)
-#define LINK_QUAL_PATTERN_SET_D10_2		(0x1 << 2)
-#define LINK_QUAL_PATTERN_SET_DISABLE		(0x0 << 2)
-#define SW_TRAINING_PATTERN_SET_MASK		(0x3 << 0)
-#define SW_TRAINING_PATTERN_SET_PTN2		(0x2 << 0)
-#define SW_TRAINING_PATTERN_SET_PTN1		(0x1 << 0)
-#define SW_TRAINING_PATTERN_SET_NORMAL		(0x0 << 0)
-
-/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
-#define PRE_EMPHASIS_SET_MASK			(0x3 << 3)
-#define PRE_EMPHASIS_SET_SHIFT			(3)
-
-/* EXYNOS_DP_DEBUG_CTL */
-#define PLL_LOCK				(0x1 << 4)
-#define F_PLL_LOCK				(0x1 << 3)
-#define PLL_LOCK_CTRL				(0x1 << 2)
-#define PN_INV					(0x1 << 0)
-
-/* EXYNOS_DP_PLL_CTL */
-#define DP_PLL_PD				(0x1 << 7)
-#define DP_PLL_RESET				(0x1 << 6)
-#define DP_PLL_LOOP_BIT_DEFAULT			(0x1 << 4)
-#define DP_PLL_REF_BIT_1_1250V			(0x5 << 0)
-#define DP_PLL_REF_BIT_1_2500V			(0x7 << 0)
-
-/* EXYNOS_DP_PHY_PD */
-#define DP_PHY_PD				(0x1 << 5)
-#define AUX_PD					(0x1 << 4)
-#define CH3_PD					(0x1 << 3)
-#define CH2_PD					(0x1 << 2)
-#define CH1_PD					(0x1 << 1)
-#define CH0_PD					(0x1 << 0)
-
-/* EXYNOS_DP_PHY_TEST */
-#define MACRO_RST				(0x1 << 5)
-#define CH1_TEST				(0x1 << 1)
-#define CH0_TEST				(0x1 << 0)
-
-/* EXYNOS_DP_AUX_CH_STA */
-#define AUX_BUSY				(0x1 << 4)
-#define AUX_STATUS_MASK				(0xf << 0)
-
-/* EXYNOS_DP_AUX_CH_DEFER_CTL */
-#define DEFER_CTRL_EN				(0x1 << 7)
-#define DEFER_COUNT(x)				(((x) & 0x7f) << 0)
-
-/* EXYNOS_DP_AUX_RX_COMM */
-#define AUX_RX_COMM_I2C_DEFER			(0x2 << 2)
-#define AUX_RX_COMM_AUX_DEFER			(0x2 << 0)
-
-/* EXYNOS_DP_BUFFER_DATA_CTL */
-#define BUF_CLR					(0x1 << 7)
-#define BUF_DATA_COUNT(x)			(((x) & 0x1f) << 0)
-
-/* EXYNOS_DP_AUX_CH_CTL_1 */
-#define AUX_LENGTH(x)				(((x - 1) & 0xf) << 4)
-#define AUX_TX_COMM_MASK			(0xf << 0)
-#define AUX_TX_COMM_DP_TRANSACTION		(0x1 << 3)
-#define AUX_TX_COMM_I2C_TRANSACTION		(0x0 << 3)
-#define AUX_TX_COMM_MOT				(0x1 << 2)
-#define AUX_TX_COMM_WRITE			(0x0 << 0)
-#define AUX_TX_COMM_READ			(0x1 << 0)
-
-/* EXYNOS_DP_AUX_ADDR_7_0 */
-#define AUX_ADDR_7_0(x)				(((x) >> 0) & 0xff)
-
-/* EXYNOS_DP_AUX_ADDR_15_8 */
-#define AUX_ADDR_15_8(x)			(((x) >> 8) & 0xff)
-
-/* EXYNOS_DP_AUX_ADDR_19_16 */
-#define AUX_ADDR_19_16(x)			(((x) >> 16) & 0x0f)
-
-/* EXYNOS_DP_AUX_CH_CTL_2 */
-#define ADDR_ONLY				(0x1 << 1)
-#define AUX_EN					(0x1 << 0)
-
-/* EXYNOS_DP_SOC_GENERAL_CTL */
-#define AUDIO_MODE_SPDIF_MODE			(0x1 << 8)
-#define AUDIO_MODE_MASTER_MODE			(0x0 << 8)
-#define MASTER_VIDEO_INTERLACE_EN		(0x1 << 4)
-#define VIDEO_MASTER_CLK_SEL			(0x1 << 2)
-#define VIDEO_MASTER_MODE_EN			(0x1 << 1)
-#define VIDEO_MODE_MASK				(0x1 << 0)
-#define VIDEO_MODE_SLAVE_MODE			(0x1 << 0)
-#define VIDEO_MODE_MASTER_MODE			(0x0 << 0)
-
-#endif /* _EXYNOS_DP_REG_H */
-- 
1.8.4

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

* [PATCH v3 22/32] drm/exynos: Move display implementation into dp
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (20 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/ Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
       [not found]   ` <1383063198-10526-23-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2013-10-29 16:13 ` [PATCH v3 23/32] ARM: dts: Move display-timings node from fimd to dp Sean Paul
                   ` (10 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch moves the exynos_drm_display implementation from fimd into
the dp driver. This will allow for tighter integration of the dp driver
into the exynos drm driver.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 .../devicetree/bindings/video/exynos_dp.txt        |  17 +++
 .../devicetree/bindings/video/samsung-fimd.txt     |   2 +
 drivers/gpu/drm/exynos/exynos_dp_core.c            | 137 ++++++++++++++++-----
 drivers/gpu/drm/exynos/exynos_dp_core.h            |   5 +
 drivers/gpu/drm/exynos/exynos_drm_drv.c            |  14 +++
 drivers/gpu/drm/exynos/exynos_drm_drv.h            |   1 +
 drivers/gpu/drm/exynos/exynos_drm_fimd.c           |  78 +++---------
 7 files changed, 156 insertions(+), 98 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt
index 84f10c1..a073e15 100644
--- a/Documentation/devicetree/bindings/video/exynos_dp.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dp.txt
@@ -45,6 +45,8 @@ Required properties for dp-controller:
 	-samsung,lane-count:
 		number of lanes supported by the panel.
 			LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
+	- display-timings: timings for the connected panel as described by
+		Documentation/devicetree/bindings/video/display-timing.txt
 
 Optional properties for dp-controller:
 	-interlaced:
@@ -83,4 +85,19 @@ Board Specific portion:
 		samsung,color-depth = <1>;
 		samsung,link-rate = <0x0a>;
 		samsung,lane-count = <4>;
+
+		display-timings {
+			native-mode = <&lcd_timing>;
+			lcd_timing: 1366x768 {
+				clock-frequency = <70589280>;
+				hactive = <1366>;
+				vactive = <768>;
+				hfront-porch = <40>;
+				hback-porch = <40>;
+				hsync-len = <32>;
+				vback-porch = <10>;
+				vfront-porch = <12>;
+				vsync-len = <6>;
+			};
+		};
 	};
diff --git a/Documentation/devicetree/bindings/video/samsung-fimd.txt b/Documentation/devicetree/bindings/video/samsung-fimd.txt
index 778838a..fa465c3 100644
--- a/Documentation/devicetree/bindings/video/samsung-fimd.txt
+++ b/Documentation/devicetree/bindings/video/samsung-fimd.txt
@@ -39,6 +39,8 @@ Required properties:
 
 Optional Properties:
 - samsung,power-domain: a phandle to FIMD power domain node.
+- samsung,invert-vden: video enable signal is inverted
+- samsung,invert_vclk: video clock signal is inverted
 
 Example:
 
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
index 089ae22..13ea8b7 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -18,9 +18,12 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/of.h>
+#include <video/of_display_timing.h>
+#include <video/of_videomode.h>
 
-#include <video/exynos_dp.h>
+#include <drm/drmP.h>
 
+#include "exynos_drm_drv.h"
 #include "exynos_dp_core.h"
 
 static int exynos_dp_init_dp(struct exynos_dp_device *dp)
@@ -893,6 +896,35 @@ static void exynos_dp_hotplug(struct work_struct *work)
 		dev_err(dp->dev, "unable to config video\n");
 }
 
+static bool exynos_dp_display_is_connected(struct exynos_drm_display *display)
+{
+	return true;
+}
+
+static void *exynos_dp_get_panel(struct exynos_drm_display *display)
+{
+	struct exynos_dp_device *dp = display->ctx;
+
+	return &dp->panel;
+}
+
+static int exynos_dp_check_mode(struct exynos_drm_display *display,
+			struct drm_display_mode *mode)
+{
+	return 0;
+}
+
+static struct exynos_drm_display_ops exynos_dp_display_ops = {
+	.is_connected = exynos_dp_display_is_connected,
+	.get_panel = exynos_dp_get_panel,
+	.check_mode = exynos_dp_check_mode,
+};
+
+static struct exynos_drm_display exynos_dp_display = {
+	.type = EXYNOS_DISPLAY_TYPE_LCD,
+	.ops = &exynos_dp_display_ops,
+};
+
 #ifdef CONFIG_OF
 static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
 {
@@ -1000,6 +1032,19 @@ err:
 	return ret;
 }
 
+static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)
+{
+	int ret;
+
+	ret = of_get_videomode(dp->dev->of_node, &dp->panel.vm,
+			OF_USE_NATIVE_MODE);
+	if (ret) {
+		DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
 static void exynos_dp_phy_init(struct exynos_dp_device *dp)
 {
 	u32 reg;
@@ -1028,6 +1073,11 @@ static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
 	return -EINVAL;
 }
 
+static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)
+{
+	return -EINVAL;
+}
+
 static void exynos_dp_phy_init(struct exynos_dp_device *dp)
 {
 	return;
@@ -1039,6 +1089,46 @@ static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
 }
 #endif /* CONFIG_OF */
 
+void exynos_dp_poweron(struct exynos_dp_device *dp)
+{
+	struct device *dev = dp->dev;
+	struct exynos_dp_platdata *pdata = dev->platform_data;
+
+	if (dev->of_node) {
+		if (dp->phy_addr)
+			exynos_dp_phy_init(dp);
+	} else {
+		if (pdata->phy_init)
+			pdata->phy_init();
+	}
+
+	clk_prepare_enable(dp->clock);
+
+	exynos_dp_init_dp(dp);
+
+	enable_irq(dp->irq);
+}
+
+void exynos_dp_poweroff(struct exynos_dp_device *dp)
+{
+	struct device *dev = dp->dev;
+	struct exynos_dp_platdata *pdata = dev->platform_data;
+
+	disable_irq(dp->irq);
+
+	flush_work(&dp->hotplug_work);
+
+	if (dev->of_node) {
+		if (dp->phy_addr)
+			exynos_dp_phy_exit(dp);
+	} else {
+		if (pdata->phy_exit)
+			pdata->phy_exit();
+	}
+
+	clk_disable_unprepare(dp->clock);
+}
+
 static int exynos_dp_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -1064,6 +1154,10 @@ static int exynos_dp_probe(struct platform_device *pdev)
 		ret = exynos_dp_dt_parse_phydata(dp);
 		if (ret)
 			return ret;
+
+		ret = exynos_dp_dt_parse_panel(dp);
+		if (ret)
+			return ret;
 	} else {
 		pdata = pdev->dev.platform_data;
 		if (!pdata) {
@@ -1115,6 +1209,9 @@ static int exynos_dp_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, dp);
 
+	exynos_dp_display.ctx = dp;
+	exynos_drm_display_register(&exynos_dp_display);
+
 	return 0;
 }
 
@@ -1123,6 +1220,8 @@ static int exynos_dp_remove(struct platform_device *pdev)
 	struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
 	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
 
+	exynos_drm_display_unregister(&exynos_dp_display);
+
 	flush_work(&dp->hotplug_work);
 
 	if (pdev->dev.of_node) {
@@ -1142,45 +1241,17 @@ static int exynos_dp_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int exynos_dp_suspend(struct device *dev)
 {
-	struct exynos_dp_platdata *pdata = dev->platform_data;
 	struct exynos_dp_device *dp = dev_get_drvdata(dev);
 
-	disable_irq(dp->irq);
-
-	flush_work(&dp->hotplug_work);
-
-	if (dev->of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_exit(dp);
-	} else {
-		if (pdata->phy_exit)
-			pdata->phy_exit();
-	}
-
-	clk_disable_unprepare(dp->clock);
-
+	exynos_dp_poweroff(dp);
 	return 0;
 }
 
 static int exynos_dp_resume(struct device *dev)
 {
-	struct exynos_dp_platdata *pdata = dev->platform_data;
 	struct exynos_dp_device *dp = dev_get_drvdata(dev);
 
-	if (dev->of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_init(dp);
-	} else {
-		if (pdata->phy_init)
-			pdata->phy_init();
-	}
-
-	clk_prepare_enable(dp->clock);
-
-	exynos_dp_init_dp(dp);
-
-	enable_irq(dp->irq);
-
+	exynos_dp_poweron(dp);
 	return 0;
 }
 #endif
@@ -1195,7 +1266,7 @@ static const struct of_device_id exynos_dp_match[] = {
 };
 MODULE_DEVICE_TABLE(of, exynos_dp_match);
 
-static struct platform_driver exynos_dp_driver = {
+struct platform_driver dp_driver = {
 	.probe		= exynos_dp_probe,
 	.remove		= exynos_dp_remove,
 	.driver		= {
@@ -1206,8 +1277,6 @@ static struct platform_driver exynos_dp_driver = {
 	},
 };
 
-module_platform_driver(exynos_dp_driver);
-
 MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
 MODULE_DESCRIPTION("Samsung SoC DP Driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h
index 6c567bbf..a5e9145 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.h
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
@@ -13,6 +13,9 @@
 #ifndef _EXYNOS_DP_CORE_H
 #define _EXYNOS_DP_CORE_H
 
+#include <drm/exynos_drm.h>
+#include <video/exynos_dp.h>
+
 enum dp_irq_type {
 	DP_IRQ_TYPE_HP_CABLE_IN,
 	DP_IRQ_TYPE_HP_CABLE_OUT,
@@ -42,6 +45,8 @@ struct exynos_dp_device {
 	struct video_info	*video_info;
 	struct link_train	link_train;
 	struct work_struct	hotplug_work;
+
+	struct exynos_drm_panel_info panel;
 };
 
 /* exynos_dp_reg.c */
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 4b265bf..03caa3a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -316,6 +316,12 @@ static int __init exynos_drm_init(void)
 {
 	int ret;
 
+#ifdef CONFIG_DRM_EXYNOS_DP
+	ret = platform_driver_register(&dp_driver);
+	if (ret < 0)
+		goto out_dp;
+#endif
+
 #ifdef CONFIG_DRM_EXYNOS_FIMD
 	ret = platform_driver_register(&fimd_driver);
 	if (ret < 0)
@@ -431,6 +437,10 @@ out_hdmi:
 	platform_driver_unregister(&fimd_driver);
 out_fimd:
 #endif
+#ifdef CONFIG_DRM_EXYNOS_DP
+	platform_driver_unregister(&dp_driver);
+out_dp:
+#endif
 	return ret;
 }
 
@@ -473,6 +483,10 @@ static void __exit exynos_drm_exit(void)
 #ifdef CONFIG_DRM_EXYNOS_FIMD
 	platform_driver_unregister(&fimd_driver);
 #endif
+
+#ifdef CONFIG_DRM_EXYNOS_DP
+	platform_driver_unregister(&dp_driver);
+#endif
 }
 
 module_init(exynos_drm_init);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 97bdfcc..f3e18d1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -369,6 +369,7 @@ int exynos_platform_device_ipp_register(void);
  */
 void exynos_platform_device_ipp_unregister(void);
 
+extern struct platform_driver dp_driver;
 extern struct platform_driver fimd_driver;
 extern struct platform_driver hdmi_driver;
 extern struct platform_driver mixer_driver;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 61124ca..c6a05f6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -158,39 +158,6 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data(
 	return (struct fimd_driver_data *)of_id->data;
 }
 
-static bool fimd_display_is_connected(struct exynos_drm_display *display)
-{
-	/* TODO. */
-
-	return true;
-}
-
-static void *fimd_get_panel(struct exynos_drm_display *display)
-{
-	struct fimd_context *ctx = display->ctx;
-
-	return &ctx->panel;
-}
-
-static int fimd_check_mode(struct exynos_drm_display *display,
-			struct drm_display_mode *mode)
-{
-	/* TODO. */
-
-	return 0;
-}
-
-static struct exynos_drm_display_ops fimd_display_ops = {
-	.is_connected = fimd_display_is_connected,
-	.get_panel = fimd_get_panel,
-	.check_mode = fimd_check_mode,
-};
-
-static struct exynos_drm_display fimd_display = {
-	.type = EXYNOS_DISPLAY_TYPE_LCD,
-	.ops = &fimd_display_ops,
-};
-
 static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
 			struct exynos_drm_overlay *overlay)
 {
@@ -611,6 +578,16 @@ static void fimd_mode_set(struct exynos_drm_manager *mgr,
 	mode->hfpd = hblank - mode->hsync_len - mode->hbpd;
 
 	mode->clkdiv = fimd_calc_clkdiv(ctx, in_mode);
+
+	if (in_mode->flags & DRM_MODE_FLAG_NVSYNC)
+		ctx->vidcon1 |= VIDCON1_INV_VSYNC;
+	else
+		ctx->vidcon1 &= ~VIDCON1_INV_VSYNC;
+
+	if (in_mode->flags & DRM_MODE_FLAG_NHSYNC)
+		ctx->vidcon1 |= VIDCON1_INV_HSYNC;
+	else
+		ctx->vidcon1 &= ~VIDCON1_INV_HSYNC;
 }
 
 static void fimd_commit(struct exynos_drm_manager *mgr)
@@ -888,30 +865,6 @@ static int fimd_activate(struct exynos_drm_manager *mgr, bool enable)
 	return 0;
 }
 
-static int fimd_get_platform_data(struct fimd_context *ctx, struct device *dev)
-{
-	struct videomode *vm;
-	int ret;
-
-	vm = &ctx->panel.vm;
-	ret = of_get_videomode(dev->of_node, vm, OF_USE_NATIVE_MODE);
-	if (ret) {
-		DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
-		return ret;
-	}
-
-	if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW)
-		ctx->vidcon1 |= VIDCON1_INV_VSYNC;
-	if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW)
-		ctx->vidcon1 |= VIDCON1_INV_HSYNC;
-	if (vm->flags & DISPLAY_FLAGS_DE_LOW)
-		ctx->vidcon1 |= VIDCON1_INV_VDEN;
-	if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
-		ctx->vidcon1 |= VIDCON1_INV_VCLK;
-
-	return 0;
-}
-
 static int fimd_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -929,9 +882,10 @@ static int fimd_probe(struct platform_device *pdev)
 
 	ctx->dev = dev;
 
-	ret = fimd_get_platform_data(ctx, dev);
-	if (ret)
-		return ret;
+	if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
+		ctx->vidcon1 |= VIDCON1_INV_VDEN;
+	if (of_property_read_bool(dev->of_node, "samsung,invert-vclk"))
+		ctx->vidcon1 |= VIDCON1_INV_VCLK;
 
 	ctx->bus_clk = devm_clk_get(dev, "fimd");
 	if (IS_ERR(ctx->bus_clk)) {
@@ -973,9 +927,6 @@ static int fimd_probe(struct platform_device *pdev)
 	fimd_manager.ctx = ctx;
 	exynos_drm_manager_register(&fimd_manager);
 
-	fimd_display.ctx = ctx;
-	exynos_drm_display_register(&fimd_display);
-
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
 
@@ -991,7 +942,6 @@ static int fimd_remove(struct platform_device *pdev)
 	struct exynos_drm_manager *mgr = platform_get_drvdata(pdev);
 	struct fimd_context *ctx = mgr->ctx;
 
-	exynos_drm_display_unregister(&fimd_display);
 	exynos_drm_manager_unregister(&fimd_manager);
 
 	if (ctx->suspended)
-- 
1.8.4

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

* [PATCH v3 23/32] ARM: dts: Move display-timings node from fimd to dp
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (21 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 22/32] drm/exynos: Move display implementation into dp Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-10-29 16:13 ` [PATCH v3 24/32] drm/exynos: Implement dpms display callback in DP Sean Paul
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch moves the display-timings node from fimd to dp to reflect the
device tree bindings change.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3: None

 arch/arm/boot/dts/exynos5250-arndale.dts  | 7 ++++---
 arch/arm/boot/dts/exynos5250-smdk5250.dts | 7 ++++---
 arch/arm/boot/dts/exynos5250-snow.dts     | 7 ++++---
 arch/arm/boot/dts/exynos5420-smdk5420.dts | 7 ++++---
 4 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts
index cee55fa..4583de4 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -517,10 +517,7 @@
 		samsung,link-rate = <0x0a>;
 		samsung,lane-count = <4>;
 		status = "okay";
-	};
 
-	fimd: fimd@14400000 {
-		status = "okay";
 		display-timings {
 			native-mode = <&timing0>;
 			timing0: timing@0 {
@@ -538,6 +535,10 @@
 		};
 	};
 
+	fimd: fimd@14400000 {
+		status = "okay";
+	};
+
 	usb_hub_bus {
 		compatible = "simple-bus";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index 2538b32..df1001d 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -261,10 +261,7 @@
 		pinctrl-names = "default";
 		pinctrl-0 = <&dp_hpd>;
 		status = "okay";
-	};
 
-	fimd@14400000 {
-		status = "okay";
 		display-timings {
 			native-mode = <&timing0>;
 			timing0: timing@0 {
@@ -282,6 +279,10 @@
 		};
 	};
 
+	fimd@14400000 {
+		status = "okay";
+	};
+
 	fixed-rate-clocks {
 		xxti {
 			compatible = "samsung,clock-xxti";
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts
index 86e8db5..395dbf7 100644
--- a/arch/arm/boot/dts/exynos5250-snow.dts
+++ b/arch/arm/boot/dts/exynos5250-snow.dts
@@ -223,10 +223,7 @@
 		pinctrl-names = "default";
 		pinctrl-0 = <&dp_hpd>;
 		status = "okay";
-	};
 
-	fimd: fimd@14400000 {
-		status = "okay";
 		display-timings {
 			native-mode = <&lcd_timing>;
 			lcd_timing: 1366x768 {
@@ -243,6 +240,10 @@
 		};
 	};
 
+	fimd: fimd@14400000 {
+		status = "okay";
+	};
+
 	fixed-rate-clocks {
 		xxti {
 			compatible = "samsung,clock-xxti";
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
index bafba25..763797c 100644
--- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
+++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
@@ -41,10 +41,7 @@
 		samsung,link-rate = <0x0a>;
 		samsung,lane-count = <4>;
 		status = "okay";
-	};
 
-	fimd@14400000 {
-		status = "okay";
 		display-timings {
 			native-mode = <&timing0>;
 			timing0: timing@0 {
@@ -61,4 +58,8 @@
 		};
 	};
 
+	fimd@14400000 {
+		status = "okay";
+	};
+
 };
-- 
1.8.4

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

* [PATCH v3 24/32] drm/exynos: Implement dpms display callback in DP
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (22 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 23/32] ARM: dts: Move display-timings node from fimd to dp Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-11  2:04   ` Tomasz Figa
  2013-10-29 16:13 ` [PATCH v3 25/32] drm/exynos: Clean up FIMD power on/off routines Sean Paul
                   ` (8 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch implements the dpms display callback for the DP driver.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2:
	- Added to the patchset
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_dp_core.c | 173 ++++++++++++++++----------------
 drivers/gpu/drm/exynos/exynos_dp_core.h |   1 +
 2 files changed, 85 insertions(+), 89 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
index 13ea8b7..476d3b0 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -914,10 +914,82 @@ static int exynos_dp_check_mode(struct exynos_drm_display *display,
 	return 0;
 }
 
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+	struct exynos_dp_platdata *pdata = dp->dev->platform_data;
+	u32 reg;
+
+	if (dp->phy_addr) {
+		reg = readl(dp->phy_addr);
+		reg |= dp->enable_mask;
+		writel(reg, dp->phy_addr);
+	}
+
+	if (pdata && pdata->phy_init)
+		pdata->phy_init();
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+	struct exynos_dp_platdata *pdata = dp->dev->platform_data;
+	u32 reg;
+
+	if (dp->phy_addr) {
+		reg = readl(dp->phy_addr);
+		reg &= ~(dp->enable_mask);
+		writel(reg, dp->phy_addr);
+	}
+
+	if (pdata && pdata->phy_exit)
+		pdata->phy_exit();
+}
+
+static void exynos_dp_poweron(struct exynos_dp_device *dp)
+{
+	if (dp->dpms_mode == DRM_MODE_DPMS_ON)
+		return;
+
+	clk_prepare_enable(dp->clock);
+	exynos_dp_phy_init(dp);
+	exynos_dp_init_dp(dp);
+	enable_irq(dp->irq);
+}
+
+static void exynos_dp_poweroff(struct exynos_dp_device *dp)
+{
+	if (dp->dpms_mode != DRM_MODE_DPMS_ON)
+		return;
+
+	disable_irq(dp->irq);
+	flush_work(&dp->hotplug_work);
+	exynos_dp_phy_exit(dp);
+	clk_disable_unprepare(dp->clock);
+}
+
+static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
+{
+	struct exynos_dp_device *dp = display->ctx;
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		exynos_dp_poweron(dp);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		exynos_dp_poweroff(dp);
+		break;
+	default:
+		break;
+	};
+	dp->dpms_mode = mode;
+}
+
 static struct exynos_drm_display_ops exynos_dp_display_ops = {
 	.is_connected = exynos_dp_display_is_connected,
 	.get_panel = exynos_dp_get_panel,
 	.check_mode = exynos_dp_check_mode,
+	.dpms = exynos_dp_dpms,
 };
 
 static struct exynos_drm_display exynos_dp_display = {
@@ -1044,24 +1116,6 @@ static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)
 	}
 	return 0;
 }
-
-static void exynos_dp_phy_init(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = __raw_readl(dp->phy_addr);
-	reg |= dp->enable_mask;
-	__raw_writel(reg, dp->phy_addr);
-}
-
-static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = __raw_readl(dp->phy_addr);
-	reg &= ~(dp->enable_mask);
-	__raw_writel(reg, dp->phy_addr);
-}
 #else
 static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
 {
@@ -1089,46 +1143,6 @@ static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
 }
 #endif /* CONFIG_OF */
 
-void exynos_dp_poweron(struct exynos_dp_device *dp)
-{
-	struct device *dev = dp->dev;
-	struct exynos_dp_platdata *pdata = dev->platform_data;
-
-	if (dev->of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_init(dp);
-	} else {
-		if (pdata->phy_init)
-			pdata->phy_init();
-	}
-
-	clk_prepare_enable(dp->clock);
-
-	exynos_dp_init_dp(dp);
-
-	enable_irq(dp->irq);
-}
-
-void exynos_dp_poweroff(struct exynos_dp_device *dp)
-{
-	struct device *dev = dp->dev;
-	struct exynos_dp_platdata *pdata = dev->platform_data;
-
-	disable_irq(dp->irq);
-
-	flush_work(&dp->hotplug_work);
-
-	if (dev->of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_exit(dp);
-	} else {
-		if (pdata->phy_exit)
-			pdata->phy_exit();
-	}
-
-	clk_disable_unprepare(dp->clock);
-}
-
 static int exynos_dp_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -1145,6 +1159,7 @@ static int exynos_dp_probe(struct platform_device *pdev)
 	}
 
 	dp->dev = &pdev->dev;
+	dp->dpms_mode = DRM_MODE_DPMS_OFF;
 
 	if (pdev->dev.of_node) {
 		pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
@@ -1190,26 +1205,17 @@ static int exynos_dp_probe(struct platform_device *pdev)
 
 	dp->video_info = pdata->video_info;
 
-	if (pdev->dev.of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_init(dp);
-	} else {
-		if (pdata->phy_init)
-			pdata->phy_init();
-	}
-
-	exynos_dp_init_dp(dp);
-
 	ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
 				"exynos-dp", dp);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to request irq\n");
 		return ret;
 	}
-
-	platform_set_drvdata(pdev, dp);
+	disable_irq(dp->irq);
 
 	exynos_dp_display.ctx = dp;
+
+	platform_set_drvdata(pdev, &exynos_dp_display);
 	exynos_drm_display_register(&exynos_dp_display);
 
 	return 0;
@@ -1217,41 +1223,30 @@ static int exynos_dp_probe(struct platform_device *pdev)
 
 static int exynos_dp_remove(struct platform_device *pdev)
 {
-	struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
-	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
+	struct exynos_drm_display *display = platform_get_drvdata(pdev);
 
+	exynos_dp_dpms(display, DRM_MODE_DPMS_OFF);
 	exynos_drm_display_unregister(&exynos_dp_display);
 
-	flush_work(&dp->hotplug_work);
-
-	if (pdev->dev.of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_exit(dp);
-	} else {
-		if (pdata->phy_exit)
-			pdata->phy_exit();
-	}
-
-	clk_disable_unprepare(dp->clock);
-
-
 	return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
 static int exynos_dp_suspend(struct device *dev)
 {
-	struct exynos_dp_device *dp = dev_get_drvdata(dev);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct exynos_drm_display *display = platform_get_drvdata(pdev);
 
-	exynos_dp_poweroff(dp);
+	exynos_dp_dpms(display, DRM_MODE_DPMS_OFF);
 	return 0;
 }
 
 static int exynos_dp_resume(struct device *dev)
 {
-	struct exynos_dp_device *dp = dev_get_drvdata(dev);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct exynos_drm_display *display = platform_get_drvdata(pdev);
 
-	exynos_dp_poweron(dp);
+	exynos_dp_dpms(display, DRM_MODE_DPMS_ON);
 	return 0;
 }
 #endif
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h
index a5e9145..0c67c19 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.h
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
@@ -45,6 +45,7 @@ struct exynos_dp_device {
 	struct video_info	*video_info;
 	struct link_train	link_train;
 	struct work_struct	hotplug_work;
+	int			dpms_mode;
 
 	struct exynos_drm_panel_info panel;
 };
-- 
1.8.4

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

* [PATCH v3 25/32] drm/exynos: Clean up FIMD power on/off routines
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (23 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 24/32] drm/exynos: Implement dpms display callback in DP Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-10-31 10:54   ` Inki Dae
  2013-11-11  2:09   ` Tomasz Figa
  2013-10-29 16:13 ` [PATCH v3 26/32] drm/exynos: Consolidate suspend/resume in drm_drv Sean Paul
                   ` (7 subsequent siblings)
  32 siblings, 2 replies; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch separates the fimd_activate function into poweron/poweroff
functions to be more consistent with the other drivers in exynos drm. It
also properly cleans up after failures in poweron. The functions have
also been shuffled around such that they are all in the same
spot in the file and poweron/poweroff can be called from the dpms function.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2:
	- Added to the patchset
Changes in v3: None

 drivers/gpu/drm/exynos/exynos_drm_fimd.c | 247 +++++++++++++++++--------------
 1 file changed, 135 insertions(+), 112 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index c6a05f6..ba12916 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -324,6 +324,12 @@ static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
 
 	win_data = &ctx->win_data[win];
 
+	/* If suspended, enable this on resume */
+	if (ctx->suspended) {
+		win_data->resume = true;
+		return;
+	}
+
 	/*
 	 * SHADOWCON/PRTCON register is used for enabling timing.
 	 *
@@ -505,35 +511,6 @@ static void fimd_mgr_remove(struct exynos_drm_manager *mgr)
 		drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
 }
 
-static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
-{
-	struct fimd_context *ctx = mgr->ctx;
-
-	DRM_DEBUG_KMS("%d\n", mode);
-
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		/*
-		 * enable fimd hardware only if suspended status.
-		 *
-		 * P.S. fimd_dpms function would be called at booting time so
-		 * clk_enable could be called double time.
-		 */
-		if (ctx->suspended)
-			pm_runtime_get_sync(ctx->dev);
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-	case DRM_MODE_DPMS_OFF:
-		if (!ctx->suspended)
-			pm_runtime_put_sync(ctx->dev);
-		break;
-	default:
-		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
-		break;
-	}
-}
-
 static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
 		const struct drm_display_mode *mode)
 {
@@ -726,6 +703,130 @@ static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr)
 		DRM_DEBUG_KMS("vblank wait timed out.\n");
 }
 
+static void fimd_window_suspend(struct exynos_drm_manager *mgr)
+{
+	struct fimd_context *ctx = mgr->ctx;
+	struct fimd_win_data *win_data;
+	int i;
+
+	for (i = 0; i < WINDOWS_NR; i++) {
+		win_data = &ctx->win_data[i];
+		win_data->resume = win_data->enabled;
+		if (win_data->enabled)
+			fimd_win_disable(mgr, i);
+	}
+	fimd_wait_for_vblank(mgr);
+}
+
+static void fimd_window_resume(struct exynos_drm_manager *mgr)
+{
+	struct fimd_context *ctx = mgr->ctx;
+	struct fimd_win_data *win_data;
+	int i;
+
+	for (i = 0; i < WINDOWS_NR; i++) {
+		win_data = &ctx->win_data[i];
+		win_data->enabled = win_data->resume;
+		win_data->resume = false;
+	}
+}
+
+static int fimd_poweron(struct exynos_drm_manager *mgr)
+{
+	struct fimd_context *ctx = mgr->ctx;
+	int ret;
+
+	if (!ctx->suspended)
+		return 0;
+
+	ctx->suspended = false;
+
+	ret = clk_prepare_enable(ctx->bus_clk);
+	if (ret < 0) {
+		DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
+		goto bus_clk_err;
+	}
+
+	ret = clk_prepare_enable(ctx->lcd_clk);
+	if  (ret < 0) {
+		DRM_ERROR("Failed to prepare_enable the lcd clk [%d]\n", ret);
+		goto lcd_clk_err;
+	}
+
+	/* if vblank was enabled status, enable it again. */
+	if (test_and_clear_bit(0, &ctx->irq_flags)) {
+		ret = fimd_enable_vblank(mgr);
+		if (ret) {
+			DRM_ERROR("Failed to re-enable vblank [%d]\n", ret);
+			goto enable_vblank_err;
+		}
+	}
+
+	fimd_window_resume(mgr);
+
+	fimd_apply(mgr);
+
+	return 0;
+
+enable_vblank_err:
+	clk_disable_unprepare(ctx->lcd_clk);
+lcd_clk_err:
+	clk_disable_unprepare(ctx->bus_clk);
+bus_clk_err:
+	ctx->suspended = true;
+	return ret;
+}
+
+static int fimd_poweroff(struct exynos_drm_manager *mgr)
+{
+	struct fimd_context *ctx = mgr->ctx;
+
+	if (ctx->suspended)
+		return 0;
+
+	/*
+	 * We need to make sure that all windows are disabled before we
+	 * suspend that connector. Otherwise we might try to scan from
+	 * a destroyed buffer later.
+	 */
+	fimd_window_suspend(mgr);
+
+	clk_disable_unprepare(ctx->lcd_clk);
+	clk_disable_unprepare(ctx->bus_clk);
+
+	ctx->suspended = true;
+	return 0;
+}
+
+static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
+{
+	struct fimd_context *ctx = mgr->ctx;
+
+	DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		/*
+		 * enable fimd hardware only if suspended status.
+		 *
+		 * P.S. fimd_dpms function would be called at booting time so
+		 * clk_enable could be called double time.
+		 */
+		if (ctx->suspended)
+			pm_runtime_get_sync(ctx->dev);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		if (!ctx->suspended)
+			pm_runtime_put_sync(ctx->dev);
+		break;
+	default:
+		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
+		break;
+	}
+}
+
 static struct exynos_drm_manager_ops fimd_manager_ops = {
 	.initialize = fimd_mgr_initialize,
 	.remove = fimd_mgr_remove,
@@ -786,85 +887,6 @@ static void fimd_clear_win(struct fimd_context *ctx, int win)
 	fimd_shadow_protect_win(ctx, win, false);
 }
 
-static int fimd_clock(struct fimd_context *ctx, bool enable)
-{
-	if (enable) {
-		int ret;
-
-		ret = clk_prepare_enable(ctx->bus_clk);
-		if (ret < 0)
-			return ret;
-
-		ret = clk_prepare_enable(ctx->lcd_clk);
-		if  (ret < 0) {
-			clk_disable_unprepare(ctx->bus_clk);
-			return ret;
-		}
-	} else {
-		clk_disable_unprepare(ctx->lcd_clk);
-		clk_disable_unprepare(ctx->bus_clk);
-	}
-
-	return 0;
-}
-
-static void fimd_window_suspend(struct exynos_drm_manager *mgr)
-{
-	struct fimd_context *ctx = mgr->ctx;
-	struct fimd_win_data *win_data;
-	int i;
-
-	for (i = 0; i < WINDOWS_NR; i++) {
-		win_data = &ctx->win_data[i];
-		win_data->resume = win_data->enabled;
-		fimd_win_disable(mgr, i);
-	}
-	fimd_wait_for_vblank(mgr);
-}
-
-static void fimd_window_resume(struct exynos_drm_manager *mgr)
-{
-	struct fimd_context *ctx = mgr->ctx;
-	struct fimd_win_data *win_data;
-	int i;
-
-	for (i = 0; i < WINDOWS_NR; i++) {
-		win_data = &ctx->win_data[i];
-		win_data->enabled = win_data->resume;
-		win_data->resume = false;
-	}
-}
-
-static int fimd_activate(struct exynos_drm_manager *mgr, bool enable)
-{
-	struct fimd_context *ctx = mgr->ctx;
-
-	if (enable) {
-		int ret;
-
-		ret = fimd_clock(ctx, true);
-		if (ret < 0)
-			return ret;
-
-		ctx->suspended = false;
-
-		/* if vblank was enabled status, enable it again. */
-		if (test_and_clear_bit(0, &ctx->irq_flags))
-			fimd_enable_vblank(mgr);
-
-		fimd_window_resume(mgr);
-
-		fimd_apply(mgr);
-	} else {
-		fimd_window_suspend(mgr);
-
-		fimd_clock(ctx, false);
-		ctx->suspended = true;
-	}
-
-	return 0;
-}
-
 static int fimd_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -881,6 +903,7 @@ static int fimd_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	ctx->dev = dev;
+	ctx->suspended = true;
 
 	if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
 		ctx->vidcon1 |= VIDCON1_INV_VDEN;
@@ -967,7 +990,7 @@ static int fimd_suspend(struct device *dev)
 	 * because the usage_count of pm runtime is more than 1.
 	 */
 	if (!pm_runtime_suspended(dev))
-		return fimd_activate(mgr, false);
+		return fimd_poweroff(mgr);
 
 	return 0;
 }
@@ -984,7 +1007,7 @@ static int fimd_resume(struct device *dev)
 	if (pm_runtime_suspended(dev))
 		return 0;
 
-	return fimd_activate(mgr, true);
+	return fimd_poweron(mgr);
 }
 #endif
 
@@ -993,14 +1016,14 @@ static int fimd_runtime_suspend(struct device *dev)
 {
 	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
 
-	return fimd_activate(mgr, false);
+	return fimd_poweroff(mgr);
 }
 
 static int fimd_runtime_resume(struct device *dev)
 {
 	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
 
-	return fimd_activate(mgr, true);
+	return fimd_poweron(mgr);
 }
 #endif
 
-- 
1.8.4

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

* [PATCH v3 26/32] drm/exynos: Consolidate suspend/resume in drm_drv
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (24 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 25/32] drm/exynos: Clean up FIMD power on/off routines Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-29 14:58   ` Tomasz Figa
  2013-12-19 16:48   ` Inki Dae
  2013-10-29 16:13 ` [PATCH v3 27/32] drm/exynos: Add create_connector callback Sean Paul
                   ` (6 subsequent siblings)
  32 siblings, 2 replies; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch removes all of the suspend/resume logic from the individual
drivers and consolidates it in drm_drv. This consolidation reduces the
number of functions which enable/disable the hardware to just one -- the
dpms callback. This ensures that we always power up/down in a consistent
manner.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2:
	- Added to the patchset
Changes in v3:
	- Made appropriate changes to vidi as well (removed pm_ops)

 drivers/gpu/drm/exynos/exynos_drm_drv.c  |  97 +++++++++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_drm_fimd.c |  91 ++++-------------------
 drivers/gpu/drm/exynos/exynos_drm_vidi.c | 119 +++++++++++++------------------
 drivers/gpu/drm/exynos/exynos_hdmi.c     |  82 +--------------------
 drivers/gpu/drm/exynos/exynos_mixer.c    |  75 ++++---------------
 5 files changed, 176 insertions(+), 288 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 03caa3a..91d6863 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -11,6 +11,7 @@
  * option) any later version.
  */
 
+#include <linux/pm_runtime.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
@@ -51,6 +52,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 		return -ENOMEM;
 
 	INIT_LIST_HEAD(&private->pageflip_event_list);
+	dev_set_drvdata(dev->dev, dev);
 	dev->dev_private = (void *)private;
 
 	/*
@@ -155,6 +157,41 @@ static int exynos_drm_unload(struct drm_device *dev)
 	return 0;
 }
 
+static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state)
+{
+	struct drm_connector *connector;
+
+	drm_modeset_lock_all(dev);
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		int old_dpms = connector->dpms;
+
+		if (connector->funcs->dpms)
+			connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
+
+		/* Set the old mode back to the connector for resume */
+		connector->dpms = old_dpms;
+	}
+	drm_modeset_unlock_all(dev);
+
+	return 0;
+}
+
+static int exynos_drm_resume(struct drm_device *dev)
+{
+	struct drm_connector *connector;
+
+	drm_modeset_lock_all(dev);
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->funcs->dpms)
+			connector->funcs->dpms(connector, connector->dpms);
+	}
+
+	drm_helper_resume_force_mode(dev);
+	drm_modeset_unlock_all(dev);
+
+	return 0;
+}
+
 static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 {
 	struct drm_exynos_file_private *file_priv;
@@ -262,6 +299,8 @@ static struct drm_driver exynos_drm_driver = {
 					DRIVER_GEM | DRIVER_PRIME,
 	.load			= exynos_drm_load,
 	.unload			= exynos_drm_unload,
+	.suspend		= exynos_drm_suspend,
+	.resume			= exynos_drm_resume,
 	.open			= exynos_drm_open,
 	.preclose		= exynos_drm_preclose,
 	.lastclose		= exynos_drm_lastclose,
@@ -293,6 +332,9 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
 {
 	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_sync(&pdev->dev);
+
 	return drm_platform_init(&exynos_drm_driver, pdev);
 }
 
@@ -303,12 +345,67 @@ static int exynos_drm_platform_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int exynos_drm_sys_suspend(struct device *dev)
+{
+	struct drm_device *drm_dev = dev_get_drvdata(dev);
+	pm_message_t message;
+
+	if (pm_runtime_suspended(dev))
+		return 0;
+
+	message.event = PM_EVENT_SUSPEND;
+	return exynos_drm_suspend(drm_dev, message);
+}
+
+static int exynos_drm_sys_resume(struct device *dev)
+{
+	struct drm_device *drm_dev = dev_get_drvdata(dev);
+
+	if (pm_runtime_suspended(dev))
+		return 0;
+
+	return exynos_drm_resume(drm_dev);
+}
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int exynos_drm_runtime_suspend(struct device *dev)
+{
+	struct drm_device *drm_dev = dev_get_drvdata(dev);
+	pm_message_t message;
+
+	if (pm_runtime_suspended(dev))
+		return 0;
+
+	message.event = PM_EVENT_SUSPEND;
+	return exynos_drm_suspend(drm_dev, message);
+}
+
+static int exynos_drm_runtime_resume(struct device *dev)
+{
+	struct drm_device *drm_dev = dev_get_drvdata(dev);
+
+	if (!pm_runtime_suspended(dev))
+		return 0;
+
+	return exynos_drm_resume(drm_dev);
+}
+#endif
+
+static const struct dev_pm_ops exynos_drm_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_sys_suspend, exynos_drm_sys_resume)
+	SET_RUNTIME_PM_OPS(exynos_drm_runtime_suspend,
+			exynos_drm_runtime_resume, NULL)
+};
+
 static struct platform_driver exynos_drm_platform_driver = {
 	.probe		= exynos_drm_platform_probe,
 	.remove		= exynos_drm_platform_remove,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "exynos-drm",
+		.pm	= &exynos_drm_pm_ops,
 	},
 };
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index ba12916..208e013 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -741,6 +741,8 @@ static int fimd_poweron(struct exynos_drm_manager *mgr)
 
 	ctx->suspended = false;
 
+	pm_runtime_get_sync(ctx->dev);
+
 	ret = clk_prepare_enable(ctx->bus_clk);
 	if (ret < 0) {
 		DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
@@ -794,32 +796,24 @@ static int fimd_poweroff(struct exynos_drm_manager *mgr)
 	clk_disable_unprepare(ctx->lcd_clk);
 	clk_disable_unprepare(ctx->bus_clk);
 
+	pm_runtime_put_sync(ctx->dev);
+
 	ctx->suspended = true;
 	return 0;
 }
 
 static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
 {
-	struct fimd_context *ctx = mgr->ctx;
-
 	DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
 
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
-		/*
-		 * enable fimd hardware only if suspended status.
-		 *
-		 * P.S. fimd_dpms function would be called at booting time so
-		 * clk_enable could be called double time.
-		 */
-		if (ctx->suspended)
-			pm_runtime_get_sync(ctx->dev);
+		fimd_poweron(mgr);
 		break;
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
-		if (!ctx->suspended)
-			pm_runtime_put_sync(ctx->dev);
+		fimd_poweroff(mgr);
 		break;
 	default:
 		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
@@ -950,8 +944,14 @@ static int fimd_probe(struct platform_device *pdev)
 	fimd_manager.ctx = ctx;
 	exynos_drm_manager_register(&fimd_manager);
 
+	/*
+	 * We need to runtime pm to enable/disable sysmmu since it is a child of
+	 * this driver. Ideally, this would hang off the drm driver's runtime
+	 * operations, but we're not quite there yet.
+	 *
+	 * Tracked in crbug.com/264312
+	 */
 	pm_runtime_enable(dev);
-	pm_runtime_get_sync(dev);
 
 	for (win = 0; win < WINDOWS_NR; win++)
 		fimd_clear_win(ctx, win);
@@ -961,84 +961,23 @@ static int fimd_probe(struct platform_device *pdev)
 
 static int fimd_remove(struct platform_device *pdev)
 {
-	struct device *dev = &pdev->dev;
 	struct exynos_drm_manager *mgr = platform_get_drvdata(pdev);
-	struct fimd_context *ctx = mgr->ctx;
 
 	exynos_drm_manager_unregister(&fimd_manager);
 
-	if (ctx->suspended)
-		goto out;
-
-	pm_runtime_set_suspended(dev);
-	pm_runtime_put_sync(dev);
+	fimd_dpms(mgr, DRM_MODE_DPMS_OFF);
 
-out:
-	pm_runtime_disable(dev);
+	pm_runtime_disable(&pdev->dev);
 
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int fimd_suspend(struct device *dev)
-{
-	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
-
-	/*
-	 * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
-	 * called here, an error would be returned by that interface
-	 * because the usage_count of pm runtime is more than 1.
-	 */
-	if (!pm_runtime_suspended(dev))
-		return fimd_poweroff(mgr);
-
-	return 0;
-}
-
-static int fimd_resume(struct device *dev)
-{
-	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
-
-	/*
-	 * if entered to sleep when lcd panel was on, the usage_count
-	 * of pm runtime would still be 1 so in this case, fimd driver
-	 * should be on directly not drawing on pm runtime interface.
-	 */
-	if (pm_runtime_suspended(dev))
-		return 0;
-
-	return fimd_poweron(mgr);
-}
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
-static int fimd_runtime_suspend(struct device *dev)
-{
-	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
-
-	return fimd_poweroff(mgr);
-}
-
-static int fimd_runtime_resume(struct device *dev)
-{
-	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
-
-	return fimd_poweron(mgr);
-}
-#endif
-
-static const struct dev_pm_ops fimd_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
-	SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
-};
-
 struct platform_driver fimd_driver = {
 	.probe		= fimd_probe,
 	.remove		= fimd_remove,
 	.driver		= {
 		.name	= "exynos4-fb",
 		.owner	= THIS_MODULE,
-		.pm	= &fimd_pm_ops,
 		.of_match_table = fimd_driver_dt_match,
 	},
 };
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 90dacaf..7d79b6c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -142,31 +142,6 @@ static struct exynos_drm_display vidi_display = {
 	.ops = &vidi_display_ops,
 };
 
-static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
-{
-	struct vidi_context *ctx = mgr->ctx;
-
-	DRM_DEBUG_KMS("%d\n", mode);
-
-	mutex_lock(&ctx->lock);
-
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		/* TODO. */
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-	case DRM_MODE_DPMS_OFF:
-		/* TODO. */
-		break;
-	default:
-		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
-		break;
-	}
-
-	mutex_unlock(&ctx->lock);
-}
-
 static void vidi_apply(struct exynos_drm_manager *mgr)
 {
 	struct vidi_context *ctx = mgr->ctx;
@@ -321,6 +296,55 @@ static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
 	/* TODO. */
 }
 
+static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
+{
+	struct vidi_context *ctx = mgr->ctx;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (enable != false && enable != true)
+		return -EINVAL;
+
+	if (enable) {
+		ctx->suspended = false;
+
+		/* if vblank was enabled status, enable it again. */
+		if (test_and_clear_bit(0, &ctx->irq_flags))
+			vidi_enable_vblank(mgr);
+
+		vidi_apply(mgr);
+	} else {
+		ctx->suspended = true;
+	}
+
+	return 0;
+}
+
+static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
+{
+	struct vidi_context *ctx = mgr->ctx;
+
+	DRM_DEBUG_KMS("%d\n", mode);
+
+	mutex_lock(&ctx->lock);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		vidi_power_on(mgr, true);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		vidi_power_on(mgr, false);
+		break;
+	default:
+		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
+		break;
+	}
+
+	mutex_unlock(&ctx->lock);
+}
+
 static int vidi_mgr_initialize(struct exynos_drm_manager *mgr,
 			struct drm_device *drm_dev, int pipe)
 {
@@ -392,30 +416,6 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
 	exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
 }
 
-static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
-{
-	struct vidi_context *ctx = mgr->ctx;
-
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
-	if (enable != false && enable != true)
-		return -EINVAL;
-
-	if (enable) {
-		ctx->suspended = false;
-
-		/* if vblank was enabled status, enable it again. */
-		if (test_and_clear_bit(0, &ctx->irq_flags))
-			vidi_enable_vblank(mgr);
-
-		vidi_apply(mgr);
-	} else {
-		ctx->suspended = true;
-	}
-
-	return 0;
-}
-
 static int vidi_show_connection(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -582,32 +582,11 @@ static int vidi_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int vidi_suspend(struct device *dev)
-{
-	struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
-
-	return vidi_power_on(mgr, false);
-}
-
-static int vidi_resume(struct device *dev)
-{
-	struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
-
-	return vidi_power_on(mgr, true);
-}
-#endif
-
-static const struct dev_pm_ops vidi_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(vidi_suspend, vidi_resume)
-};
-
 struct platform_driver vidi_driver = {
 	.probe		= vidi_probe,
 	.remove		= vidi_remove,
 	.driver		= {
 		.name	= "exynos-drm-vidi",
 		.owner	= THIS_MODULE,
-		.pm	= &vidi_pm_ops,
 	},
 };
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 2c127b9..c6561fe 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -28,7 +28,6 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
-#include <linux/pm_runtime.h>
 #include <linux/clk.h>
 #include <linux/regulator/consumer.h>
 #include <linux/io.h>
@@ -1770,7 +1769,6 @@ static void hdmi_poweroff(struct exynos_drm_display *display)
 	regulator_bulk_disable(res->regul_count, res->regul_bulk);
 
 	mutex_lock(&hdata->hdmi_mutex);
-
 	hdata->powered = false;
 
 out:
@@ -1779,20 +1777,16 @@ out:
 
 static void hdmi_dpms(struct exynos_drm_display *display, int mode)
 {
-	struct hdmi_context *hdata = display->ctx;
-
 	DRM_DEBUG_KMS("mode %d\n", mode);
 
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
-		if (pm_runtime_suspended(hdata->dev))
-			pm_runtime_get_sync(hdata->dev);
+		hdmi_poweron(display);
 		break;
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
-		if (!pm_runtime_suspended(hdata->dev))
-			pm_runtime_put_sync(hdata->dev);
+		hdmi_poweroff(display);
 		break;
 	default:
 		DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
@@ -2030,8 +2024,6 @@ static int hdmi_probe(struct platform_device *pdev)
 	hdmi_display.ctx = hdata;
 	exynos_drm_display_register(&hdmi_display);
 
-	pm_runtime_enable(dev);
-
 	return 0;
 
 err_hdmiphy:
@@ -2047,88 +2039,18 @@ static int hdmi_remove(struct platform_device *pdev)
 	struct exynos_drm_display *display = get_hdmi_display(dev);
 	struct hdmi_context *hdata = display->ctx;
 
-	pm_runtime_disable(dev);
-
 	put_device(&hdata->hdmiphy_port->dev);
 	put_device(&hdata->ddc_port->dev);
 
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int hdmi_suspend(struct device *dev)
-{
-	struct exynos_drm_display *display = get_hdmi_display(dev);
-	struct hdmi_context *hdata = display->ctx;
-
-	disable_irq(hdata->irq);
-
-	hdata->hpd = false;
-	if (hdata->drm_dev)
-		drm_helper_hpd_irq_event(hdata->drm_dev);
-
-	if (pm_runtime_suspended(dev)) {
-		DRM_DEBUG_KMS("Already suspended\n");
-		return 0;
-	}
-
-	hdmi_poweroff(display);
-
-	return 0;
-}
-
-static int hdmi_resume(struct device *dev)
-{
-	struct exynos_drm_display *display = get_hdmi_display(dev);
-	struct hdmi_context *hdata = display->ctx;
-
-	hdata->hpd = gpio_get_value(hdata->hpd_gpio);
-
-	enable_irq(hdata->irq);
-
-	if (!pm_runtime_suspended(dev)) {
-		DRM_DEBUG_KMS("Already resumed\n");
-		return 0;
-	}
-
-	hdmi_poweron(display);
-
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
-static int hdmi_runtime_suspend(struct device *dev)
-{
-	struct exynos_drm_display *display = get_hdmi_display(dev);
-
-	hdmi_poweroff(display);
-
-	return 0;
-}
-
-static int hdmi_runtime_resume(struct device *dev)
-{
-	struct exynos_drm_display *display = get_hdmi_display(dev);
-
-	hdmi_poweron(display);
-
-	return 0;
-}
-#endif
-
-static const struct dev_pm_ops hdmi_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(hdmi_suspend, hdmi_resume)
-	SET_RUNTIME_PM_OPS(hdmi_runtime_suspend, hdmi_runtime_resume, NULL)
-};
-
 struct platform_driver hdmi_driver = {
 	.probe		= hdmi_probe,
 	.remove		= hdmi_remove,
 	.driver		= {
 		.name	= "exynos-hdmi",
 		.owner	= THIS_MODULE,
-		.pm	= &hdmi_pm_ops,
 		.of_match_table = hdmi_match_types,
 	},
 };
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 39aed3e..985391d 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -902,6 +902,8 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
 	ctx->powered = true;
 	mutex_unlock(&ctx->mixer_mutex);
 
+	pm_runtime_get_sync(ctx->dev);
+
 	clk_prepare_enable(res->mixer);
 	if (ctx->vp_enabled) {
 		clk_prepare_enable(res->vp);
@@ -934,6 +936,8 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
 		clk_disable_unprepare(res->sclk_mixer);
 	}
 
+	pm_runtime_put_sync(ctx->dev);
+
 	mutex_lock(&ctx->mixer_mutex);
 	ctx->powered = false;
 
@@ -943,18 +947,14 @@ out:
 
 static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
 {
-	struct mixer_context *mixer_ctx = mgr->ctx;
-
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
-		if (pm_runtime_suspended(mixer_ctx->dev))
-			pm_runtime_get_sync(mixer_ctx->dev);
+		mixer_poweron(mgr);
 		break;
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
-		if (!pm_runtime_suspended(mixer_ctx->dev))
-			pm_runtime_put_sync(mixer_ctx->dev);
+		mixer_poweroff(mgr);
 		break;
 	default:
 		DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
@@ -1239,6 +1239,13 @@ static int mixer_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, &mixer_manager);
 	exynos_drm_manager_register(&mixer_manager);
 
+	/*
+	 * We need to runtime pm to enable/disable sysmmu since it is a child of
+	 * this driver. Ideally, this would hang off the drm driver's runtime
+	 * operations, but we're not quite there yet.
+	 *
+	 * Tracked in crbug.com/264312
+	 */
 	pm_runtime_enable(dev);
 
 	return 0;
@@ -1258,66 +1265,10 @@ static int mixer_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int mixer_suspend(struct device *dev)
-{
-	struct exynos_drm_manager *mgr = get_mixer_manager(dev);
-
-	if (pm_runtime_suspended(dev)) {
-		DRM_DEBUG_KMS("Already suspended\n");
-		return 0;
-	}
-
-	mixer_poweroff(mgr);
-
-	return 0;
-}
-
-static int mixer_resume(struct device *dev)
-{
-	struct exynos_drm_manager *mgr = get_mixer_manager(dev);
-
-	if (!pm_runtime_suspended(dev)) {
-		DRM_DEBUG_KMS("Already resumed\n");
-		return 0;
-	}
-
-	mixer_poweron(mgr);
-
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_PM_RUNTIME
-static int mixer_runtime_suspend(struct device *dev)
-{
-	struct exynos_drm_manager *mgr = get_mixer_manager(dev);
-
-	mixer_poweroff(mgr);
-
-	return 0;
-}
-
-static int mixer_runtime_resume(struct device *dev)
-{
-	struct exynos_drm_manager *mgr = get_mixer_manager(dev);
-
-	mixer_poweron(mgr);
-
-	return 0;
-}
-#endif
-
-static const struct dev_pm_ops mixer_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(mixer_suspend, mixer_resume)
-	SET_RUNTIME_PM_OPS(mixer_runtime_suspend, mixer_runtime_resume, NULL)
-};
-
 struct platform_driver mixer_driver = {
 	.driver = {
 		.name = "exynos-mixer",
 		.owner = THIS_MODULE,
-		.pm = &mixer_pm_ops,
 		.of_match_table = mixer_match_types,
 	},
 	.probe = mixer_probe,
-- 
1.8.4

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

* [PATCH v3 27/32] drm/exynos: Add create_connector callback
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (25 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 26/32] drm/exynos: Consolidate suspend/resume in drm_drv Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-11  2:19   ` Tomasz Figa
  2013-12-03  5:01   ` Inki Dae
  2013-10-29 16:13 ` [PATCH v3 28/32] drm/exynos: Implement drm_connector in hdmi directly Sean Paul
                   ` (5 subsequent siblings)
  32 siblings, 2 replies; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This creates a new display hook called create_connector. The purpose is
to allow the display driver to create its own drm_connector instead of
using the exynos_drm_connector. This moves things closer to completely
removing the exynos_drm_connector abstraction.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v2: None
Changes in v3:
	- Added to the patchset

 drivers/gpu/drm/exynos/exynos_drm_core.c | 3 +++
 drivers/gpu/drm/exynos/exynos_drm_drv.h  | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
index e76098d..1a60f5a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_core.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
@@ -87,6 +87,9 @@ static int exynos_drm_create_enc_conn(struct drm_device *dev,
 			return 0;
 	}
 
+	if (display->ops->create_connector)
+		return display->ops->create_connector(display, encoder);
+
 	/*
 	 * create and initialize a connector for this sub driver and
 	 * attach the encoder created above to the connector.
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index f3e18d1..db6a3b2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -139,6 +139,8 @@ struct exynos_drm_display;
 struct exynos_drm_display_ops {
 	int (*initialize)(struct exynos_drm_display *display,
 				struct drm_device *drm_dev);
+	int (*create_connector)(struct exynos_drm_display *display,
+				struct drm_encoder *encoder);
 	void (*remove)(struct exynos_drm_display *display);
 	bool (*is_connected)(struct exynos_drm_display *display);
 	void (*get_max_resol)(struct exynos_drm_display *display,
-- 
1.8.4

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

* [PATCH v3 28/32] drm/exynos: Implement drm_connector in hdmi directly
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (26 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 27/32] drm/exynos: Add create_connector callback Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-29 15:58   ` Tomasz Figa
  2013-10-29 16:13 ` [PATCH v3 29/32] drm/exynos: Implement drm_connector directly in dp driver Sean Paul
                   ` (4 subsequent siblings)
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch implements drm_connector in the hdmi driver directly, instead
of using exynos_drm_connector.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v3:
	- Added to the patchset

 drivers/gpu/drm/exynos/exynos_hdmi.c | 126 +++++++++++++++++++++++------------
 1 file changed, 85 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index c6561fe..b063610 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -43,9 +43,8 @@
 #include <linux/gpio.h>
 #include <media/s5p_hdmi.h>
 
-#define MAX_WIDTH		1920
-#define MAX_HEIGHT		1080
 #define get_hdmi_display(dev)	platform_get_drvdata(to_platform_device(dev))
+#define ctx_from_connector(c)	container_of(c, struct hdmi_context, connector)
 
 /* AVI header and aspect ratio */
 #define HDMI_AVI_VERSION		0x02
@@ -180,6 +179,8 @@ struct hdmi_conf_regs {
 struct hdmi_context {
 	struct device			*dev;
 	struct drm_device		*drm_dev;
+	struct drm_connector		connector;
+	struct drm_encoder		*encoder;
 	bool				hpd;
 	bool				powered;
 	bool				dvi_mode;
@@ -738,42 +739,46 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
 	}
 }
 
-static int hdmi_initialize(struct exynos_drm_display *display,
-			struct drm_device *drm_dev)
+static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
+				bool force)
 {
-	struct hdmi_context *hdata = display->ctx;
+	struct hdmi_context *hdata = ctx_from_connector(connector);
 
-	hdata->drm_dev = drm_dev;
-
-	return 0;
+	return hdata->hpd ? connector_status_connected :
+			connector_status_disconnected;
 }
 
-static bool hdmi_is_connected(struct exynos_drm_display *display)
+static void hdmi_connector_destroy(struct drm_connector *connector)
 {
-	struct hdmi_context *hdata = display->ctx;
-
-	return hdata->hpd;
 }
 
-static struct edid *hdmi_get_edid(struct exynos_drm_display *display,
-			struct drm_connector *connector)
+static struct drm_connector_funcs hdmi_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = hdmi_detect,
+	.destroy = hdmi_connector_destroy,
+};
+
+static int hdmi_get_modes(struct drm_connector *connector)
 {
-	struct edid *raw_edid;
-	struct hdmi_context *hdata = display->ctx;
+	struct hdmi_context *hdata = ctx_from_connector(connector);
+	struct edid *edid;
 
 	if (!hdata->ddc_port)
-		return ERR_PTR(-ENODEV);
+		return -ENODEV;
 
-	raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
-	if (!raw_edid)
-		return ERR_PTR(-ENODEV);
+	edid = drm_get_edid(connector, hdata->ddc_port->adapter);
+	if (!edid)
+		return -ENODEV;
 
-	hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
+	hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
 	DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
 		(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
-		raw_edid->width_cm, raw_edid->height_cm);
+		edid->width_cm, edid->height_cm);
+
+	drm_mode_connector_update_edid_property(connector, edid);
 
-	return raw_edid;
+	return drm_add_edid_modes(connector, edid);
 }
 
 static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
@@ -798,10 +803,10 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
 	return -EINVAL;
 }
 
-static int hdmi_check_mode(struct exynos_drm_display *display,
+static int hdmi_mode_valid(struct drm_connector *connector,
 			struct drm_display_mode *mode)
 {
-	struct hdmi_context *hdata = display->ctx;
+	struct hdmi_context *hdata = ctx_from_connector(connector);
 	int ret;
 
 	DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
@@ -811,11 +816,60 @@ static int hdmi_check_mode(struct exynos_drm_display *display,
 
 	ret = mixer_check_mode(mode);
 	if (ret)
-		return ret;
+		return MODE_BAD;
 
 	ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
 	if (ret < 0)
+		return MODE_BAD;
+
+	return MODE_OK;
+}
+
+static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
+{
+	struct hdmi_context *hdata = ctx_from_connector(connector);
+
+	return hdata->encoder;
+}
+
+static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
+	.get_modes = hdmi_get_modes,
+	.mode_valid = hdmi_mode_valid,
+	.best_encoder = hdmi_best_encoder,
+};
+
+static int hdmi_create_connector(struct exynos_drm_display *display,
+			struct drm_encoder *encoder)
+{
+	struct hdmi_context *hdata = display->ctx;
+	struct drm_connector *connector = &hdata->connector;
+	int ret;
+
+	hdata->encoder = encoder;
+	connector->interlace_allowed = true;
+	connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+	ret = drm_connector_init(hdata->drm_dev, connector,
+			&hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector with drm\n");
 		return ret;
+	}
+
+	drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
+	drm_sysfs_connector_add(connector);
+	drm_mode_connector_attach_encoder(connector, encoder);
+
+	return 0;
+}
+
+static int hdmi_initialize(struct exynos_drm_display *display,
+			struct drm_device *drm_dev)
+{
+	struct hdmi_context *hdata = display->ctx;
+
+	hdata->drm_dev = drm_dev;
+
 	return 0;
 }
 
@@ -831,10 +885,10 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display,
 
 	drm_mode_set_crtcinfo(adjusted_mode, 0);
 
-	mode_ok = hdmi_check_mode(display, adjusted_mode);
+	mode_ok = hdmi_mode_valid(connector, adjusted_mode);
 
 	/* just return if user desired mode exists. */
-	if (mode_ok == 0)
+	if (mode_ok == MODE_OK)
 		return;
 
 	/*
@@ -842,9 +896,9 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display,
 	 * to adjusted_mode.
 	 */
 	list_for_each_entry(m, &connector->modes, head) {
-		mode_ok = hdmi_check_mode(display, m);
+		mode_ok = hdmi_mode_valid(connector, m);
 
-		if (mode_ok == 0) {
+		if (mode_ok == MODE_OK) {
 			DRM_INFO("desired mode doesn't exist so\n");
 			DRM_INFO("use the most suitable mode among modes.\n");
 
@@ -1699,13 +1753,6 @@ static void hdmi_mode_set(struct exynos_drm_display *display,
 		hdmi_v14_mode_set(hdata, mode);
 }
 
-static void hdmi_get_max_resol(struct exynos_drm_display *display,
-			unsigned int *width, unsigned int *height)
-{
-	*width = MAX_WIDTH;
-	*height = MAX_HEIGHT;
-}
-
 static void hdmi_commit(struct exynos_drm_display *display)
 {
 	struct hdmi_context *hdata = display->ctx;
@@ -1796,10 +1843,7 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode)
 
 static struct exynos_drm_display_ops hdmi_display_ops = {
 	.initialize	= hdmi_initialize,
-	.is_connected	= hdmi_is_connected,
-	.get_max_resol	= hdmi_get_max_resol,
-	.get_edid	= hdmi_get_edid,
-	.check_mode	= hdmi_check_mode,
+	.create_connector = hdmi_create_connector,
 	.mode_fixup	= hdmi_mode_fixup,
 	.mode_set	= hdmi_mode_set,
 	.dpms		= hdmi_dpms,
-- 
1.8.4

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

* [PATCH v3 29/32] drm/exynos: Implement drm_connector directly in dp driver
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (27 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 28/32] drm/exynos: Implement drm_connector in hdmi directly Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-29 16:04   ` Tomasz Figa
  2013-12-03  4:45   ` Inki Dae
  2013-10-29 16:13 ` [PATCH v3 30/32] drm/exynos: Implement drm_connector directly in vidi driver Sean Paul
                   ` (3 subsequent siblings)
  32 siblings, 2 replies; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch implements drm_connector directly in the dp driver, this will
allow us to move away from the exynos_drm_connector layer.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v3:
	- Added to the patchset

 drivers/gpu/drm/exynos/exynos_dp_core.c | 99 ++++++++++++++++++++++++++++++---
 drivers/gpu/drm/exynos/exynos_dp_core.h |  4 ++
 2 files changed, 94 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
index 476d3b0..139ea15 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -22,10 +22,15 @@
 #include <video/of_videomode.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
 
 #include "exynos_drm_drv.h"
 #include "exynos_dp_core.h"
 
+#define ctx_from_connector(c)	container_of(c, struct exynos_dp_device, \
+					connector)
+
 static int exynos_dp_init_dp(struct exynos_dp_device *dp)
 {
 	exynos_dp_reset(dp);
@@ -896,21 +901,98 @@ static void exynos_dp_hotplug(struct work_struct *work)
 		dev_err(dp->dev, "unable to config video\n");
 }
 
-static bool exynos_dp_display_is_connected(struct exynos_drm_display *display)
+static enum drm_connector_status exynos_dp_detect(
+				struct drm_connector *connector, bool force)
 {
-	return true;
+	return connector_status_connected;
 }
 
-static void *exynos_dp_get_panel(struct exynos_drm_display *display)
+static void exynos_dp_connector_destroy(struct drm_connector *connector)
 {
-	struct exynos_dp_device *dp = display->ctx;
+}
+
+static struct drm_connector_funcs exynos_dp_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = exynos_dp_detect,
+	.destroy = exynos_dp_connector_destroy,
+};
+
+static int exynos_dp_get_modes(struct drm_connector *connector)
+{
+	struct exynos_dp_device *dp = ctx_from_connector(connector);
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_create(connector->dev);
+	if (!mode) {
+		DRM_ERROR("failed to create a new display mode.\n");
+		return 0;
+	}
 
-	return &dp->panel;
+	drm_display_mode_from_videomode(&dp->panel.vm, mode);
+	mode->width_mm = dp->panel.width_mm;
+	mode->height_mm = dp->panel.height_mm;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	drm_mode_set_name(mode);
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
 }
 
-static int exynos_dp_check_mode(struct exynos_drm_display *display,
+static int exynos_dp_mode_valid(struct drm_connector *connector,
 			struct drm_display_mode *mode)
 {
+	return MODE_OK;
+}
+
+static struct drm_encoder *exynos_dp_best_encoder(
+			struct drm_connector *connector)
+{
+	struct exynos_dp_device *dp = ctx_from_connector(connector);
+
+	return dp->encoder;
+}
+
+static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = {
+	.get_modes = exynos_dp_get_modes,
+	.mode_valid = exynos_dp_mode_valid,
+	.best_encoder = exynos_dp_best_encoder,
+};
+
+static int exynos_dp_initialize(struct exynos_drm_display *display,
+				struct drm_device *drm_dev)
+{
+	struct exynos_dp_device *dp = display->ctx;
+
+	dp->drm_dev = drm_dev;
+
+	return 0;
+}
+
+static int exynos_dp_create_connector(struct exynos_drm_display *display,
+				struct drm_encoder *encoder)
+{
+	struct exynos_dp_device *dp = display->ctx;
+	struct drm_connector *connector = &dp->connector;
+	int ret;
+
+	dp->encoder = encoder;
+	connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+	ret = drm_connector_init(dp->drm_dev, connector,
+			&exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector with drm\n");
+		return ret;
+	}
+
+	drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs);
+	drm_sysfs_connector_add(connector);
+	drm_mode_connector_attach_encoder(connector, encoder);
+
 	return 0;
 }
 
@@ -986,9 +1068,8 @@ static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
 }
 
 static struct exynos_drm_display_ops exynos_dp_display_ops = {
-	.is_connected = exynos_dp_display_is_connected,
-	.get_panel = exynos_dp_get_panel,
-	.check_mode = exynos_dp_check_mode,
+	.initialize = exynos_dp_initialize,
+	.create_connector = exynos_dp_create_connector,
 	.dpms = exynos_dp_dpms,
 };
 
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h
index 0c67c19..da3fa7e 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.h
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
@@ -13,6 +13,7 @@
 #ifndef _EXYNOS_DP_CORE_H
 #define _EXYNOS_DP_CORE_H
 
+#include <drm/drm_crtc.h>
 #include <drm/exynos_drm.h>
 #include <video/exynos_dp.h>
 
@@ -36,6 +37,9 @@ struct link_train {
 
 struct exynos_dp_device {
 	struct device		*dev;
+	struct drm_device	*drm_dev;
+	struct drm_connector	connector;
+	struct drm_encoder	*encoder;
 	struct clk		*clock;
 	unsigned int		irq;
 	void __iomem		*reg_base;
-- 
1.8.4

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

* [PATCH v3 30/32] drm/exynos: Implement drm_connector directly in vidi driver
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (28 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 29/32] drm/exynos: Implement drm_connector directly in dp driver Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-29 16:13   ` Tomasz Figa
  2013-12-03  4:47   ` Inki Dae
  2013-10-29 16:13 ` [PATCH v3 31/32] drm/exynos: Move lvds bridge discovery into DP driver Sean Paul
                   ` (2 subsequent siblings)
  32 siblings, 2 replies; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch implements drm_connector directly in the vidi
driver, this will allow us to move away from the exynos_drm_connector
layer.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v3:
	- Added to the patchset

 drivers/gpu/drm/exynos/exynos_drm_vidi.c | 163 ++++++++++++++++++++-----------
 1 file changed, 107 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 7d79b6c..5104431 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -29,6 +29,8 @@
 #define WINDOWS_NR		3
 
 #define get_vidi_mgr(dev)	platform_get_drvdata(to_platform_device(dev))
+#define ctx_from_connector(c)	container_of(c, struct vidi_context, \
+					connector)
 
 struct vidi_win_data {
 	unsigned int		offset_x;
@@ -47,6 +49,8 @@ struct vidi_win_data {
 struct vidi_context {
 	struct drm_device		*drm_dev;
 	struct drm_crtc			*crtc;
+	struct drm_encoder		*encoder;
+	struct drm_connector		connector;
 	struct vidi_win_data		win_data[WINDOWS_NR];
 	struct edid			*raw_edid;
 	unsigned int			clkdiv;
@@ -86,62 +90,6 @@ static const char fake_edid_info[] = {
 	0x00, 0x00, 0x00, 0x06
 };
 
-static bool vidi_display_is_connected(struct exynos_drm_display *display)
-{
-	struct vidi_context *ctx = display->ctx;
-
-	/*
-	 * connection request would come from user side
-	 * to do hotplug through specific ioctl.
-	 */
-	return ctx->connected ? true : false;
-}
-
-static struct edid *vidi_get_edid(struct exynos_drm_display *display,
-			struct drm_connector *connector)
-{
-	struct vidi_context *ctx = display->ctx;
-	struct edid *edid;
-	int edid_len;
-
-	/*
-	 * the edid data comes from user side and it would be set
-	 * to ctx->raw_edid through specific ioctl.
-	 */
-	if (!ctx->raw_edid) {
-		DRM_DEBUG_KMS("raw_edid is null.\n");
-		return ERR_PTR(-EFAULT);
-	}
-
-	edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
-	edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
-	if (!edid) {
-		DRM_DEBUG_KMS("failed to allocate edid\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	return edid;
-}
-
-static int vidi_check_mode(struct exynos_drm_display *display,
-			struct drm_display_mode *mode)
-{
-	/* TODO. */
-
-	return 0;
-}
-
-static struct exynos_drm_display_ops vidi_display_ops = {
-	.is_connected = vidi_display_is_connected,
-	.get_edid = vidi_get_edid,
-	.check_mode = vidi_check_mode,
-};
-
-static struct exynos_drm_display vidi_display = {
-	.type = EXYNOS_DISPLAY_TYPE_VIDI,
-	.ops = &vidi_display_ops,
-};
-
 static void vidi_apply(struct exynos_drm_manager *mgr)
 {
 	struct vidi_context *ctx = mgr->ctx;
@@ -536,6 +484,109 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
 	return 0;
 }
 
+static enum drm_connector_status vidi_detect(struct drm_connector *connector,
+			bool force)
+{
+	struct vidi_context *ctx = ctx_from_connector(connector);
+
+	/*
+	 * connection request would come from user side
+	 * to do hotplug through specific ioctl.
+	 */
+	return ctx->connected ? connector_status_connected :
+			connector_status_disconnected;
+}
+
+static void vidi_connector_destroy(struct drm_connector *connector)
+{
+}
+
+static struct drm_connector_funcs vidi_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = vidi_detect,
+	.destroy = vidi_connector_destroy,
+};
+
+static int vidi_get_modes(struct drm_connector *connector)
+{
+	struct vidi_context *ctx = ctx_from_connector(connector);
+	struct edid *edid;
+	int edid_len;
+
+	/*
+	 * the edid data comes from user side and it would be set
+	 * to ctx->raw_edid through specific ioctl.
+	 */
+	if (!ctx->raw_edid) {
+		DRM_DEBUG_KMS("raw_edid is null.\n");
+		return -EFAULT;
+	}
+
+	edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
+	edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
+	if (!edid) {
+		DRM_DEBUG_KMS("failed to allocate edid\n");
+		return -ENOMEM;
+	}
+
+	drm_mode_connector_update_edid_property(connector, edid);
+
+	return drm_add_edid_modes(connector, edid);
+}
+
+static int vidi_mode_valid(struct drm_connector *connector,
+			struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static struct drm_encoder *vidi_best_encoder(struct drm_connector *connector)
+{
+	struct vidi_context *ctx = ctx_from_connector(connector);
+
+	return ctx->encoder;
+}
+
+static struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
+	.get_modes = vidi_get_modes,
+	.mode_valid = vidi_mode_valid,
+	.best_encoder = vidi_best_encoder,
+};
+
+static int vidi_create_connector(struct exynos_drm_display *display,
+				struct drm_encoder *encoder)
+{
+	struct vidi_context *ctx = display->ctx;
+	struct drm_connector *connector = &ctx->connector;
+	int ret;
+
+	ctx->encoder = encoder;
+	connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+	ret = drm_connector_init(ctx->drm_dev, connector,
+			&vidi_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector with drm\n");
+		return ret;
+	}
+
+	drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
+	drm_sysfs_connector_add(connector);
+	drm_mode_connector_attach_encoder(connector, encoder);
+
+	return 0;
+}
+
+static struct exynos_drm_display_ops vidi_display_ops = {
+	.create_connector = vidi_create_connector,
+};
+
+static struct exynos_drm_display vidi_display = {
+	.type = EXYNOS_DISPLAY_TYPE_VIDI,
+	.ops = &vidi_display_ops,
+};
+
 static int vidi_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-- 
1.8.4

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

* [PATCH v3 31/32] drm/exynos: Move lvds bridge discovery into DP driver
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (29 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 30/32] drm/exynos: Implement drm_connector directly in vidi driver Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-29 16:55   ` Tomasz Figa
  2013-10-29 16:13 ` [PATCH v3 32/32] drm/exynos: Remove the exynos_drm_connector shim Sean Paul
  2013-11-07  5:48 ` [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Inki Dae
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This patch moves the lvds bridge discovery and connector pre-emption
code from exynos common code into the dp driver (since the bridge is
only applicable for dp).

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v3:
	- Added to the patchset

 drivers/gpu/drm/exynos/exynos_dp_core.c  | 41 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_drm_core.c | 41 --------------------------------
 2 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
index 139ea15..32ba791 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -24,6 +24,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/bridge/ptn3460.h>
 
 #include "exynos_drm_drv.h"
 #include "exynos_dp_core.h"
@@ -31,6 +32,11 @@
 #define ctx_from_connector(c)	container_of(c, struct exynos_dp_device, \
 					connector)
 
+struct bridge_init {
+	struct i2c_client *client;
+	struct device_node *node;
+};
+
 static int exynos_dp_init_dp(struct exynos_dp_device *dp)
 {
 	exynos_dp_reset(dp);
@@ -972,6 +978,35 @@ static int exynos_dp_initialize(struct exynos_drm_display *display,
 	return 0;
 }
 
+static bool find_bridge(const char *compat, struct bridge_init *bridge)
+{
+	bridge->client = NULL;
+	bridge->node = of_find_compatible_node(NULL, NULL, compat);
+	if (!bridge->node)
+		return false;
+
+	bridge->client = of_find_i2c_device_by_node(bridge->node);
+	if (!bridge->client)
+		return false;
+
+	return true;
+}
+
+/* returns the number of bridges attached */
+static int exynos_drm_attach_lcd_bridge(struct drm_device *dev,
+		struct drm_encoder *encoder)
+{
+	struct bridge_init bridge;
+	int ret;
+
+	if (find_bridge("nxp,ptn3460", &bridge)) {
+		ret = ptn3460_init(dev, encoder, bridge.client, bridge.node);
+		if (!ret)
+			return 1;
+	}
+	return 0;
+}
+
 static int exynos_dp_create_connector(struct exynos_drm_display *display,
 				struct drm_encoder *encoder)
 {
@@ -980,6 +1015,12 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display,
 	int ret;
 
 	dp->encoder = encoder;
+
+	/* Pre-empt DP connector creation if there's a bridge */
+	ret = exynos_drm_attach_lcd_bridge(dp->drm_dev, encoder);
+	if (ret)
+		return 0;
+
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
 
 	ret = drm_connector_init(dp->drm_dev, connector,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
index 1a60f5a..2446352 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_core.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
@@ -14,7 +14,6 @@
 
 #include <linux/i2c.h>
 #include <drm/drmP.h>
-#include <drm/bridge/ptn3460.h>
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_encoder.h"
@@ -25,40 +24,6 @@ static LIST_HEAD(exynos_drm_subdrv_list);
 static LIST_HEAD(exynos_drm_manager_list);
 static LIST_HEAD(exynos_drm_display_list);
 
-struct bridge_init {
-	struct i2c_client *client;
-	struct device_node *node;
-};
-
-static bool find_bridge(const char *compat, struct bridge_init *bridge)
-{
-	bridge->client = NULL;
-	bridge->node = of_find_compatible_node(NULL, NULL, compat);
-	if (!bridge->node)
-		return false;
-
-	bridge->client = of_find_i2c_device_by_node(bridge->node);
-	if (!bridge->client)
-		return false;
-
-	return true;
-}
-
-/* returns the number of bridges attached */
-static int exynos_drm_attach_lcd_bridge(struct drm_device *dev,
-		struct drm_encoder *encoder)
-{
-	struct bridge_init bridge;
-	int ret;
-
-	if (find_bridge("nxp,ptn3460", &bridge)) {
-		ret = ptn3460_init(dev, encoder, bridge.client, bridge.node);
-		if (!ret)
-			return 1;
-	}
-	return 0;
-}
-
 static int exynos_drm_create_enc_conn(struct drm_device *dev,
 					struct exynos_drm_display *display)
 {
@@ -81,12 +46,6 @@ static int exynos_drm_create_enc_conn(struct drm_device *dev,
 	}
 	display->encoder = encoder;
 
-	if (display->type == EXYNOS_DISPLAY_TYPE_LCD) {
-		ret = exynos_drm_attach_lcd_bridge(dev, encoder);
-		if (ret)
-			return 0;
-	}
-
 	if (display->ops->create_connector)
 		return display->ops->create_connector(display, encoder);
 
-- 
1.8.4

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

* [PATCH v3 32/32] drm/exynos: Remove the exynos_drm_connector shim
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (30 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 31/32] drm/exynos: Move lvds bridge discovery into DP driver Sean Paul
@ 2013-10-29 16:13 ` Sean Paul
  2013-11-29 16:14   ` Tomasz Figa
  2013-11-07  5:48 ` [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Inki Dae
  32 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-29 16:13 UTC (permalink / raw)
  To: dri-devel, inki.dae; +Cc: marcheu

This path removes the exynos_drm_connector code since it was just
passing hooks through display_ops. The individual device drivers are now
responsible for implementing drm_connector directly.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---

Changes in v3:
	- Added to the patchset

 drivers/gpu/drm/exynos/Makefile               |   2 +-
 drivers/gpu/drm/exynos/exynos_drm_connector.c | 258 --------------------------
 drivers/gpu/drm/exynos/exynos_drm_connector.h |  20 --
 drivers/gpu/drm/exynos/exynos_drm_core.c      |  18 +-
 drivers/gpu/drm/exynos/exynos_drm_drv.h       |  11 --
 drivers/gpu/drm/exynos/exynos_drm_encoder.c   |   1 -
 6 files changed, 4 insertions(+), 306 deletions(-)
 delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.c
 delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.h

diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index fc8555c..b1839e8 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -3,7 +3,7 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos
-exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \
+exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o \
 		exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \
 		exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \
 		exynos_drm_plane.o
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
deleted file mode 100644
index 9a16dbe..0000000
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- *	Inki Dae <inki.dae@samsung.com>
- *	Joonyoung Shim <jy0922.shim@samsung.com>
- *	Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * 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_helper.h>
-
-#include <drm/exynos_drm.h>
-#include "exynos_drm_drv.h"
-#include "exynos_drm_encoder.h"
-#include "exynos_drm_connector.h"
-
-#define to_exynos_connector(x)	container_of(x, struct exynos_drm_connector,\
-				drm_connector)
-
-struct exynos_drm_connector {
-	struct drm_connector		drm_connector;
-	uint32_t			encoder_id;
-	struct exynos_drm_display	*display;
-};
-
-static int exynos_drm_connector_get_modes(struct drm_connector *connector)
-{
-	struct exynos_drm_connector *exynos_connector =
-					to_exynos_connector(connector);
-	struct exynos_drm_display *display = exynos_connector->display;
-	struct edid *edid = NULL;
-	unsigned int count = 0;
-	int ret;
-
-	/*
-	 * if get_edid() exists then get_edid() callback of hdmi side
-	 * is called to get edid data through i2c interface else
-	 * get timing from the FIMD driver(display controller).
-	 *
-	 * P.S. in case of lcd panel, count is always 1 if success
-	 * because lcd panel has only one mode.
-	 */
-	if (display->ops->get_edid) {
-		edid = display->ops->get_edid(display, connector);
-		if (IS_ERR_OR_NULL(edid)) {
-			ret = PTR_ERR(edid);
-			edid = NULL;
-			DRM_ERROR("Panel operation get_edid failed %d\n", ret);
-			goto out;
-		}
-
-		count = drm_add_edid_modes(connector, edid);
-		if (!count) {
-			DRM_ERROR("Add edid modes failed %d\n", count);
-			goto out;
-		}
-
-		drm_mode_connector_update_edid_property(connector, edid);
-	} else {
-		struct exynos_drm_panel_info *panel;
-		struct drm_display_mode *mode = drm_mode_create(connector->dev);
-		if (!mode) {
-			DRM_ERROR("failed to create a new display mode.\n");
-			return 0;
-		}
-
-		if (display->ops->get_panel)
-			panel = display->ops->get_panel(display);
-		else {
-			drm_mode_destroy(connector->dev, mode);
-			return 0;
-		}
-
-		drm_display_mode_from_videomode(&panel->vm, mode);
-		mode->width_mm = panel->width_mm;
-		mode->height_mm = panel->height_mm;
-		connector->display_info.width_mm = mode->width_mm;
-		connector->display_info.height_mm = mode->height_mm;
-
-		mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-		drm_mode_set_name(mode);
-		drm_mode_probed_add(connector, mode);
-
-		count = 1;
-	}
-
-out:
-	kfree(edid);
-	return count;
-}
-
-static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
-					    struct drm_display_mode *mode)
-{
-	struct exynos_drm_connector *exynos_connector =
-					to_exynos_connector(connector);
-	struct exynos_drm_display *display = exynos_connector->display;
-	int ret = MODE_BAD;
-
-	DRM_DEBUG_KMS("%s\n", __FILE__);
-
-	if (display->ops->check_mode)
-		if (!display->ops->check_mode(display, mode))
-			ret = MODE_OK;
-
-	return ret;
-}
-
-static struct drm_encoder *exynos_drm_best_encoder(
-		struct drm_connector *connector)
-{
-	struct drm_device *dev = connector->dev;
-	struct exynos_drm_connector *exynos_connector =
-					to_exynos_connector(connector);
-	struct drm_mode_object *obj;
-	struct drm_encoder *encoder;
-
-	obj = drm_mode_object_find(dev, exynos_connector->encoder_id,
-				   DRM_MODE_OBJECT_ENCODER);
-	if (!obj) {
-		DRM_DEBUG_KMS("Unknown ENCODER ID %d\n",
-				exynos_connector->encoder_id);
-		return NULL;
-	}
-
-	encoder = obj_to_encoder(obj);
-
-	return encoder;
-}
-
-static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
-	.get_modes	= exynos_drm_connector_get_modes,
-	.mode_valid	= exynos_drm_connector_mode_valid,
-	.best_encoder	= exynos_drm_best_encoder,
-};
-
-static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
-				unsigned int max_width, unsigned int max_height)
-{
-	struct exynos_drm_connector *exynos_connector =
-					to_exynos_connector(connector);
-	struct exynos_drm_display *display = exynos_connector->display;
-	unsigned int width, height;
-
-	width = max_width;
-	height = max_height;
-
-	/*
-	 * if specific driver want to find desired_mode using maxmum
-	 * resolution then get max width and height from that driver.
-	 */
-	if (display->ops->get_max_resol)
-		display->ops->get_max_resol(display, &width, &height);
-
-	return drm_helper_probe_single_connector_modes(connector, width,
-							height);
-}
-
-/* get detection status of display device. */
-static enum drm_connector_status
-exynos_drm_connector_detect(struct drm_connector *connector, bool force)
-{
-	struct exynos_drm_connector *exynos_connector =
-					to_exynos_connector(connector);
-	struct exynos_drm_display *display = exynos_connector->display;
-	enum drm_connector_status status = connector_status_disconnected;
-
-	if (display->ops->is_connected) {
-		if (display->ops->is_connected(display))
-			status = connector_status_connected;
-		else
-			status = connector_status_disconnected;
-	}
-
-	return status;
-}
-
-static void exynos_drm_connector_destroy(struct drm_connector *connector)
-{
-	struct exynos_drm_connector *exynos_connector =
-		to_exynos_connector(connector);
-
-	drm_sysfs_connector_remove(connector);
-	drm_connector_cleanup(connector);
-	kfree(exynos_connector);
-}
-
-static struct drm_connector_funcs exynos_connector_funcs = {
-	.dpms		= drm_helper_connector_dpms,
-	.fill_modes	= exynos_drm_connector_fill_modes,
-	.detect		= exynos_drm_connector_detect,
-	.destroy	= exynos_drm_connector_destroy,
-};
-
-struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
-						   struct drm_encoder *encoder)
-{
-	struct exynos_drm_connector *exynos_connector;
-	struct exynos_drm_display *display = exynos_drm_get_display(encoder);
-	struct drm_connector *connector;
-	int type;
-	int err;
-
-	exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL);
-	if (!exynos_connector)
-		return NULL;
-
-	connector = &exynos_connector->drm_connector;
-
-	switch (display->type) {
-	case EXYNOS_DISPLAY_TYPE_HDMI:
-		type = DRM_MODE_CONNECTOR_HDMIA;
-		connector->interlace_allowed = true;
-		connector->polled = DRM_CONNECTOR_POLL_HPD;
-		break;
-	case EXYNOS_DISPLAY_TYPE_VIDI:
-		type = DRM_MODE_CONNECTOR_VIRTUAL;
-		connector->polled = DRM_CONNECTOR_POLL_HPD;
-		break;
-	default:
-		type = DRM_MODE_CONNECTOR_Unknown;
-		break;
-	}
-
-	drm_connector_init(dev, connector, &exynos_connector_funcs, type);
-	drm_connector_helper_add(connector, &exynos_connector_helper_funcs);
-
-	err = drm_sysfs_connector_add(connector);
-	if (err)
-		goto err_connector;
-
-	exynos_connector->encoder_id = encoder->base.id;
-	exynos_connector->display = display;
-	connector->dpms = DRM_MODE_DPMS_OFF;
-	connector->encoder = encoder;
-
-	err = drm_mode_connector_attach_encoder(connector, encoder);
-	if (err) {
-		DRM_ERROR("failed to attach a connector to a encoder\n");
-		goto err_sysfs;
-	}
-
-	DRM_DEBUG_KMS("connector has been created\n");
-
-	return connector;
-
-err_sysfs:
-	drm_sysfs_connector_remove(connector);
-err_connector:
-	drm_connector_cleanup(connector);
-	kfree(exynos_connector);
-	return NULL;
-}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.h b/drivers/gpu/drm/exynos/exynos_drm_connector.h
deleted file mode 100644
index 4eb20d7..0000000
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- *	Inki Dae <inki.dae@samsung.com>
- *	Joonyoung Shim <jy0922.shim@samsung.com>
- *	Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * 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 _EXYNOS_DRM_CONNECTOR_H_
-#define _EXYNOS_DRM_CONNECTOR_H_
-
-struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
-						   struct drm_encoder *encoder);
-
-#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
index 2446352..4ab10ca 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_core.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
@@ -17,7 +17,6 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_encoder.h"
-#include "exynos_drm_connector.h"
 #include "exynos_drm_fbdev.h"
 
 static LIST_HEAD(exynos_drm_subdrv_list);
@@ -28,7 +27,6 @@ static int exynos_drm_create_enc_conn(struct drm_device *dev,
 					struct exynos_drm_display *display)
 {
 	struct drm_encoder *encoder;
-	struct drm_connector *connector;
 	struct exynos_drm_manager *manager;
 	int ret;
 	unsigned long possible_crtcs = 0;
@@ -46,22 +44,12 @@ static int exynos_drm_create_enc_conn(struct drm_device *dev,
 	}
 	display->encoder = encoder;
 
-	if (display->ops->create_connector)
-		return display->ops->create_connector(display, encoder);
-
-	/*
-	 * create and initialize a connector for this sub driver and
-	 * attach the encoder created above to the connector.
-	 */
-	connector = exynos_drm_connector_create(dev, encoder);
-	if (!connector) {
-		DRM_ERROR("failed to create connector\n");
-		ret = -EFAULT;
+	ret = display->ops->create_connector(display, encoder);
+	if (ret) {
+		DRM_ERROR("failed to create connector ret=%d\n", ret);
 		goto err_destroy_encoder;
 	}
 
-	display->connector = connector;
-
 	return 0;
 
 err_destroy_encoder:
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index db6a3b2..26bf10a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -124,10 +124,6 @@ struct exynos_drm_overlay {
  *
  * @initialize: initializes the display with drm_dev
  * @remove: cleans up the display for removal
- * @is_connected: check for that display is connected or not.
- * @get_max_resol: get maximum resolution to specific hardware.
- * @get_edid: get edid modes from display driver.
- * @get_panel: get panel object from display driver.
  * @mode_fixup: fix mode data comparing to hw specific display mode.
  * @mode_set: convert drm_display_mode to hw specific display mode and
  *	      would be called by encoder->mode_set().
@@ -142,13 +138,6 @@ struct exynos_drm_display_ops {
 	int (*create_connector)(struct exynos_drm_display *display,
 				struct drm_encoder *encoder);
 	void (*remove)(struct exynos_drm_display *display);
-	bool (*is_connected)(struct exynos_drm_display *display);
-	void (*get_max_resol)(struct exynos_drm_display *display,
-				unsigned int *width,
-				unsigned int *height);
-	struct edid *(*get_edid)(struct exynos_drm_display *display,
-				struct drm_connector *connector);
-	void *(*get_panel)(struct exynos_drm_display *display);
 	void (*mode_fixup)(struct exynos_drm_display *display,
 				struct drm_connector *connector,
 				const struct drm_display_mode *mode,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index bfa2f17..835c0f1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -17,7 +17,6 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_encoder.h"
-#include "exynos_drm_connector.h"
 
 #define to_exynos_encoder(x)	container_of(x, struct exynos_drm_encoder,\
 				drm_encoder)
-- 
1.8.4

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

* RE: [PATCH v3 01/32] drm/exynos: Remove useless slab.h include
  2013-10-29 16:12 ` [PATCH v3 01/32] drm/exynos: Remove useless slab.h include Sean Paul
@ 2013-10-31 10:24   ` Inki Dae
  2013-10-31 23:32   ` Tomasz Figa
  1 sibling, 0 replies; 130+ messages in thread
From: Inki Dae @ 2013-10-31 10:24 UTC (permalink / raw)
  To: 'Sean Paul', dri-devel; +Cc: marcheu, 'Jingoo Han'


CCing Jingoo,

> -----Original Message-----
> From: Sean Paul [mailto:seanpaul@chromium.org]
> Sent: Wednesday, October 30, 2013 1:13 AM
> To: dri-devel@lists.freedesktop.org; inki.dae@samsung.com
> Cc: airlied@linux.ie; tomasz.figa@gmail.com; marcheu@chromium.org; Sean
> Paul
> Subject: [PATCH v3 01/32] drm/exynos: Remove useless slab.h include
> 
> From: Stéphane Marchesin <marcheu@chromium.org>
> 
> Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/video/exynos/exynos_dp_core.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/video/exynos/exynos_dp_core.c
> b/drivers/video/exynos/exynos_dp_core.c
> index 12bbede..089ae22 100644
> --- a/drivers/video/exynos/exynos_dp_core.c
> +++ b/drivers/video/exynos/exynos_dp_core.c
> @@ -12,7 +12,6 @@
> 
>  #include <linux/module.h>
>  #include <linux/platform_device.h>
> -#include <linux/slab.h>
>  #include <linux/err.h>
>  #include <linux/clk.h>
>  #include <linux/io.h>
> --
> 1.8.4

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

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

* RE: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-10-29 16:12 ` [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv Sean Paul
@ 2013-10-31 10:30   ` Inki Dae
  2013-10-31 16:08     ` Sean Paul
  2013-11-10 21:09   ` Tomasz Figa
  1 sibling, 1 reply; 130+ messages in thread
From: Inki Dae @ 2013-10-31 10:30 UTC (permalink / raw)
  To: 'Sean Paul', dri-devel; +Cc: marcheu



> -----Original Message-----
> From: Sean Paul [mailto:seanpaul@chromium.org]
> Sent: Wednesday, October 30, 2013 1:13 AM
> To: dri-devel@lists.freedesktop.org; inki.dae@samsung.com
> Cc: airlied@linux.ie; tomasz.figa@gmail.com; marcheu@chromium.org; Sean
> Paul
> Subject: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
> 
> This patch splits display and manager from subdrv. The result is that
> crtc functions can directly call into manager callbacks and encoder
> functions can directly call into display callbacks. This will allow
> us to remove the exynos_drm_hdmi shim and support mixer/hdmi & fimd/dp
> with common code.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2:
> 	- Pass display into display_ops instead of context
> Changes in v3:
> 	- Changed vidi args to exynos_drm_display instead of void
> 	- Moved exynos_drm_hdmi.c removal into next patch
> 
>  drivers/gpu/drm/exynos/exynos_drm_connector.c |  50 ++---
>  drivers/gpu/drm/exynos/exynos_drm_core.c      | 181 +++++++++++++-----
>  drivers/gpu/drm/exynos/exynos_drm_crtc.c      | 115 +++++++++---
>  drivers/gpu/drm/exynos/exynos_drm_crtc.h      |  20 +-
>  drivers/gpu/drm/exynos/exynos_drm_drv.c       |  29 +--
>  drivers/gpu/drm/exynos/exynos_drm_drv.h       | 106 +++++++----
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c   | 258
++++------------------
> ----
>  drivers/gpu/drm/exynos/exynos_drm_encoder.h   |  18 +-
>  drivers/gpu/drm/exynos/exynos_drm_fb.c        |   4 +-
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 161 ++++++++--------
>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c      | 211 +++++++++------------
>  drivers/gpu/drm/exynos/exynos_drm_hdmi.h      |   2 +
>  drivers/gpu/drm/exynos/exynos_drm_plane.c     |  15 +-
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 129 ++++++-------
>  14 files changed, 615 insertions(+), 684 deletions(-)
> 
>  static int exynos_drm_create_enc_conn(struct drm_device *dev,
> -					struct exynos_drm_subdrv *subdrv)
> +					struct exynos_drm_display *display)
>  {
>  	struct drm_encoder *encoder;
>  	struct drm_connector *connector;
> +	struct exynos_drm_manager *manager;
>  	int ret;
> +	unsigned long possible_crtcs = 0;
> 
> -	subdrv->manager->dev = subdrv->dev;
> +	/* Find possible crtcs for this display */
> +	list_for_each_entry(manager, &exynos_drm_manager_list, list)
> +		if (manager->type == display->type)
> +			possible_crtcs |= 1 << manager->pipe;
> 
>  	/* create and initialize a encoder for this sub driver. */
> -	encoder = exynos_drm_encoder_create(dev, subdrv->manager,
> -			(1 << MAX_CRTC) - 1);
> +	encoder = exynos_drm_encoder_create(dev, display, possible_crtcs);
>  	if (!encoder) {
>  		DRM_ERROR("failed to create encoder\n");
>  		return -EFAULT;
>  	}
> -	subdrv->encoder = encoder;
> +	display->encoder = encoder;
> 
> -	if (subdrv->manager->display_ops->type == EXYNOS_DISPLAY_TYPE_LCD)
> {
> +	if (display->type == EXYNOS_DISPLAY_TYPE_LCD) {
>  		ret = exynos_drm_attach_lcd_bridge(dev, encoder);

The lvds bridge related codes need more reviews so I'll merge this patch
manually excepting the lvds bridge related codes. Let's discuss lvds bridge
later.

Thanks,
Inki Dae

>  		if (ret)
>  			return 0;
> @@ -91,7 +98,7 @@ static int exynos_drm_create_enc_conn(struct drm_device
> *dev,
>  		goto err_destroy_encoder;
>  	}
> 
> -	subdrv->connector = connector;
> +	display->connector = connector;
> 
>  	return 0;

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

* RE: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
  2013-10-29 16:13 ` [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/ Sean Paul
@ 2013-10-31 10:46   ` Inki Dae
  2013-10-31 16:05     ` Sean Paul
  2013-10-31 23:06       ` Jingoo Han
       [not found]   ` <3513711.0qTZKxmOZX@flatron>
  1 sibling, 2 replies; 130+ messages in thread
From: Inki Dae @ 2013-10-31 10:46 UTC (permalink / raw)
  To: 'Sean Paul', dri-devel; +Cc: marcheu, 'Jingoo Han'

CCing Jingoo,

Is that ok to remove eDP driver from video/exynos? Isn't this driver really
used by Linux framebuffer driver, s3c-fb.c?

Of course, now s3c-fb driver is dead code because this driver doesn't
support device tree yet but we would need more reviews and discussions about
moving this driver into drm side. Let's watch new rules for device tree
bindings of DRM world. So I'd not like to merge this driver yet.

Thanks,
Inki Dae

> -----Original Message-----
> From: Sean Paul [mailto:seanpaul@chromium.org]
> Sent: Wednesday, October 30, 2013 1:13 AM
> To: dri-devel@lists.freedesktop.org; inki.dae@samsung.com
> Cc: airlied@linux.ie; tomasz.figa@gmail.com; marcheu@chromium.org; Sean
> Paul
> Subject: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
> 
> This patch moves the code from video/ to drm/
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/Kconfig          |    7 +
>  drivers/gpu/drm/exynos/Makefile         |    1 +
>  drivers/gpu/drm/exynos/exynos_dp_core.c | 1213
> ++++++++++++++++++++++++++++++
>  drivers/gpu/drm/exynos/exynos_dp_core.h |  210 ++++++
>  drivers/gpu/drm/exynos/exynos_dp_reg.c  | 1245
> +++++++++++++++++++++++++++++++
>  drivers/gpu/drm/exynos/exynos_dp_reg.h  |  366 +++++++++
>  drivers/video/exynos/Kconfig            |    7 -
>  drivers/video/exynos/Makefile           |    1 -
>  drivers/video/exynos/exynos_dp_core.c   | 1213
---------------------------
> ---
>  drivers/video/exynos/exynos_dp_core.h   |  210 ------
>  drivers/video/exynos/exynos_dp_reg.c    | 1245
---------------------------
> ----
>  drivers/video/exynos/exynos_dp_reg.h    |  366 ---------
>  12 files changed, 3042 insertions(+), 3042 deletions(-)
>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c
>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h
>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c
>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.h
>  delete mode 100644 drivers/video/exynos/exynos_dp_core.c
>  delete mode 100644 drivers/video/exynos/exynos_dp_core.h
>  delete mode 100644 drivers/video/exynos/exynos_dp_reg.c
>  delete mode 100644 drivers/video/exynos/exynos_dp_reg.h
> 
> diff --git a/drivers/gpu/drm/exynos/Kconfig
> b/drivers/gpu/drm/exynos/Kconfig
> index 45b6ef5..3ace74f 100644
> --- a/drivers/gpu/drm/exynos/Kconfig
> +++ b/drivers/gpu/drm/exynos/Kconfig
> @@ -30,6 +30,13 @@ config DRM_EXYNOS_FIMD
>  	help
>  	  Choose this option if you want to use Exynos FIMD for DRM.
> 
> +config DRM_EXYNOS_DP
> +	bool "EXYNOS DRM DP driver support"
> +	depends on ARCH_EXYNOS
> +	default n
> +	help
> +	  This enables support for DP device.
> +
>  config DRM_EXYNOS_HDMI
>  	bool "Exynos DRM HDMI"
>  	depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV
> diff --git a/drivers/gpu/drm/exynos/Makefile
> b/drivers/gpu/drm/exynos/Makefile
> index afbe499..fc8555c 100644
> --- a/drivers/gpu/drm/exynos/Makefile
> +++ b/drivers/gpu/drm/exynos/Makefile
> @@ -11,6 +11,7 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o
> exynos_drm_connector.o \
>  exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
>  exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
>  exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)	+= exynos_drm_fimd.o
> +exynosdrm-$(CONFIG_DRM_EXYNOS_DP)	+= exynos_dp_core.o
> exynos_dp_reg.o
>  exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)	+= exynos_hdmi.o exynos_mixer.o
>  exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)	+= exynos_drm_vidi.o
>  exynosdrm-$(CONFIG_DRM_EXYNOS_G2D)	+= exynos_drm_g2d.o
> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c
> b/drivers/gpu/drm/exynos/exynos_dp_core.c
> new file mode 100644
> index 0000000..089ae22
> --- /dev/null
> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
> @@ -0,0 +1,1213 @@
> +/*
> + * Samsung SoC DP (Display Port) interface driver.
> + *
> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> + * Author: Jingoo Han <jg1.han@samsung.com>
> + *
> + * 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/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/err.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/of.h>
> +
> +#include <video/exynos_dp.h>
> +
> +#include "exynos_dp_core.h"
> +
> +static int exynos_dp_init_dp(struct exynos_dp_device *dp)
> +{
> +	exynos_dp_reset(dp);
> +
> +	exynos_dp_swreset(dp);
> +
> +	exynos_dp_init_analog_param(dp);
> +	exynos_dp_init_interrupt(dp);
> +
> +	/* SW defined function Normal operation */
> +	exynos_dp_enable_sw_function(dp);
> +
> +	exynos_dp_config_interrupt(dp);
> +	exynos_dp_init_analog_func(dp);
> +
> +	exynos_dp_init_hpd(dp);
> +	exynos_dp_init_aux(dp);
> +
> +	return 0;
> +}
> +
> +static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
> +{
> +	int timeout_loop = 0;
> +
> +	while (exynos_dp_get_plug_in_status(dp) != 0) {
> +		timeout_loop++;
> +		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> +			dev_err(dp->dev, "failed to get hpd plug status\n");
> +			return -ETIMEDOUT;
> +		}
> +		usleep_range(10, 11);
> +	}
> +
> +	return 0;
> +}
> +
> +static unsigned char exynos_dp_calc_edid_check_sum(unsigned char
> *edid_data)
> +{
> +	int i;
> +	unsigned char sum = 0;
> +
> +	for (i = 0; i < EDID_BLOCK_LENGTH; i++)
> +		sum = sum + edid_data[i];
> +
> +	return sum;
> +}
> +
> +static int exynos_dp_read_edid(struct exynos_dp_device *dp)
> +{
> +	unsigned char edid[EDID_BLOCK_LENGTH * 2];
> +	unsigned int extend_block = 0;
> +	unsigned char sum;
> +	unsigned char test_vector;
> +	int retval;
> +
> +	/*
> +	 * EDID device address is 0x50.
> +	 * However, if necessary, you must have set upper address
> +	 * into E-EDID in I2C device, 0x30.
> +	 */
> +
> +	/* Read Extension Flag, Number of 128-byte EDID extension blocks */
> +	retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
> +				EDID_EXTENSION_FLAG,
> +				&extend_block);
> +	if (retval)
> +		return retval;
> +
> +	if (extend_block > 0) {
> +		dev_dbg(dp->dev, "EDID data includes a single
extension!\n");
> +
> +		/* Read EDID data */
> +		retval = exynos_dp_read_bytes_from_i2c(dp,
> I2C_EDID_DEVICE_ADDR,
> +						EDID_HEADER_PATTERN,
> +						EDID_BLOCK_LENGTH,
> +						&edid[EDID_HEADER_PATTERN]);
> +		if (retval != 0) {
> +			dev_err(dp->dev, "EDID Read failed!\n");
> +			return -EIO;
> +		}
> +		sum = exynos_dp_calc_edid_check_sum(edid);
> +		if (sum != 0) {
> +			dev_err(dp->dev, "EDID bad checksum!\n");
> +			return -EIO;
> +		}
> +
> +		/* Read additional EDID data */
> +		retval = exynos_dp_read_bytes_from_i2c(dp,
> +				I2C_EDID_DEVICE_ADDR,
> +				EDID_BLOCK_LENGTH,
> +				EDID_BLOCK_LENGTH,
> +				&edid[EDID_BLOCK_LENGTH]);
> +		if (retval != 0) {
> +			dev_err(dp->dev, "EDID Read failed!\n");
> +			return -EIO;
> +		}
> +		sum =
> exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
> +		if (sum != 0) {
> +			dev_err(dp->dev, "EDID bad checksum!\n");
> +			return -EIO;
> +		}
> +
> +		exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
> +					&test_vector);
> +		if (test_vector & DPCD_TEST_EDID_READ) {
> +			exynos_dp_write_byte_to_dpcd(dp,
> +				DPCD_ADDR_TEST_EDID_CHECKSUM,
> +				edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
> +			exynos_dp_write_byte_to_dpcd(dp,
> +				DPCD_ADDR_TEST_RESPONSE,
> +				DPCD_TEST_EDID_CHECKSUM_WRITE);
> +		}
> +	} else {
> +		dev_info(dp->dev, "EDID data does not include any
> extensions.\n");
> +
> +		/* Read EDID data */
> +		retval = exynos_dp_read_bytes_from_i2c(dp,
> +				I2C_EDID_DEVICE_ADDR,
> +				EDID_HEADER_PATTERN,
> +				EDID_BLOCK_LENGTH,
> +				&edid[EDID_HEADER_PATTERN]);
> +		if (retval != 0) {
> +			dev_err(dp->dev, "EDID Read failed!\n");
> +			return -EIO;
> +		}
> +		sum = exynos_dp_calc_edid_check_sum(edid);
> +		if (sum != 0) {
> +			dev_err(dp->dev, "EDID bad checksum!\n");
> +			return -EIO;
> +		}
> +
> +		exynos_dp_read_byte_from_dpcd(dp,
> +			DPCD_ADDR_TEST_REQUEST,
> +			&test_vector);
> +		if (test_vector & DPCD_TEST_EDID_READ) {
> +			exynos_dp_write_byte_to_dpcd(dp,
> +				DPCD_ADDR_TEST_EDID_CHECKSUM,
> +				edid[EDID_CHECKSUM]);
> +			exynos_dp_write_byte_to_dpcd(dp,
> +				DPCD_ADDR_TEST_RESPONSE,
> +				DPCD_TEST_EDID_CHECKSUM_WRITE);
> +		}
> +	}
> +
> +	dev_err(dp->dev, "EDID Read success!\n");
> +	return 0;
> +}
> +
> +static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
> +{
> +	u8 buf[12];
> +	int i;
> +	int retval;
> +
> +	/* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
> +	retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
> +				12, buf);
> +	if (retval)
> +		return retval;
> +
> +	/* Read EDID */
> +	for (i = 0; i < 3; i++) {
> +		retval = exynos_dp_read_edid(dp);
> +		if (!retval)
> +			break;
> +	}
> +
> +	return retval;
> +}
> +
> +static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device
> *dp,
> +						bool enable)
> +{
> +	u8 data;
> +
> +	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
> +
> +	if (enable)
> +		exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
> +			DPCD_ENHANCED_FRAME_EN |
> +			DPCD_LANE_COUNT_SET(data));
> +	else
> +		exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
> +			DPCD_LANE_COUNT_SET(data));
> +}
> +
> +static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device
> *dp)
> +{
> +	u8 data;
> +	int retval;
> +
> +	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
> +	retval = DPCD_ENHANCED_FRAME_CAP(data);
> +
> +	return retval;
> +}
> +
> +static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
> +{
> +	u8 data;
> +
> +	data = exynos_dp_is_enhanced_mode_available(dp);
> +	exynos_dp_enable_rx_to_enhanced_mode(dp, data);
> +	exynos_dp_enable_enhanced_mode(dp, data);
> +}
> +
> +static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
> +{
> +	exynos_dp_set_training_pattern(dp, DP_NONE);
> +
> +	exynos_dp_write_byte_to_dpcd(dp,
> +		DPCD_ADDR_TRAINING_PATTERN_SET,
> +		DPCD_TRAINING_PATTERN_DISABLED);
> +}
> +
> +static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device
> *dp,
> +					int pre_emphasis, int lane)
> +{
> +	switch (lane) {
> +	case 0:
> +		exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
> +		break;
> +	case 1:
> +		exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
> +		break;
> +
> +	case 2:
> +		exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
> +		break;
> +
> +	case 3:
> +		exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
> +		break;
> +	}
> +}
> +
> +static int exynos_dp_link_start(struct exynos_dp_device *dp)
> +{
> +	u8 buf[4];
> +	int lane, lane_count, pll_tries, retval;
> +
> +	lane_count = dp->link_train.lane_count;
> +
> +	dp->link_train.lt_state = CLOCK_RECOVERY;
> +	dp->link_train.eq_loop = 0;
> +
> +	for (lane = 0; lane < lane_count; lane++)
> +		dp->link_train.cr_loop[lane] = 0;
> +
> +	/* Set link rate and count as you want to establish*/
> +	exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
> +	exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
> +
> +	/* Setup RX configuration */
> +	buf[0] = dp->link_train.link_rate;
> +	buf[1] = dp->link_train.lane_count;
> +	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
> +				2, buf);
> +	if (retval)
> +		return retval;
> +
> +	/* Set TX pre-emphasis to minimum */
> +	for (lane = 0; lane < lane_count; lane++)
> +		exynos_dp_set_lane_lane_pre_emphasis(dp,
> +			PRE_EMPHASIS_LEVEL_0, lane);
> +
> +	/* Wait for PLL lock */
> +	pll_tries = 0;
> +	while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
> +		if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
> +			dev_err(dp->dev, "Wait for PLL lock timed out\n");
> +			return -ETIMEDOUT;
> +		}
> +
> +		pll_tries++;
> +		usleep_range(90, 120);
> +	}
> +
> +	/* Set training pattern 1 */
> +	exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
> +
> +	/* Set RX training pattern */
> +	retval = exynos_dp_write_byte_to_dpcd(dp,
> +			DPCD_ADDR_TRAINING_PATTERN_SET,
> +			DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
> +	if (retval)
> +		return retval;
> +
> +	for (lane = 0; lane < lane_count; lane++)
> +		buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
> +			    DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
> +
> +	retval = exynos_dp_write_bytes_to_dpcd(dp,
> DPCD_ADDR_TRAINING_LANE0_SET,
> +			lane_count, buf);
> +
> +	return retval;
> +}
> +
> +static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int
> lane)
> +{
> +	int shift = (lane & 1) * 4;
> +	u8 link_value = link_status[lane>>1];
> +
> +	return (link_value >> shift) & 0xf;
> +}
> +
> +static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
> +{
> +	int lane;
> +	u8 lane_status;
> +
> +	for (lane = 0; lane < lane_count; lane++) {
> +		lane_status = exynos_dp_get_lane_status(link_status, lane);
> +		if ((lane_status & DPCD_LANE_CR_DONE) == 0)
> +			return -EINVAL;
> +	}
> +	return 0;
> +}
> +
> +static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
> +				int lane_count)
> +{
> +	int lane;
> +	u8 lane_status;
> +
> +	if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
> +		return -EINVAL;
> +
> +	for (lane = 0; lane < lane_count; lane++) {
> +		lane_status = exynos_dp_get_lane_status(link_status, lane);
> +		lane_status &= DPCD_CHANNEL_EQ_BITS;
> +		if (lane_status != DPCD_CHANNEL_EQ_BITS)
> +			return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static unsigned char exynos_dp_get_adjust_request_voltage(u8
> adjust_request[2],
> +							int lane)
> +{
> +	int shift = (lane & 1) * 4;
> +	u8 link_value = adjust_request[lane>>1];
> +
> +	return (link_value >> shift) & 0x3;
> +}
> +
> +static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
> +					u8 adjust_request[2],
> +					int lane)
> +{
> +	int shift = (lane & 1) * 4;
> +	u8 link_value = adjust_request[lane>>1];
> +
> +	return ((link_value >> shift) & 0xc) >> 2;
> +}
> +
> +static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
> +					u8 training_lane_set, int lane)
> +{
> +	switch (lane) {
> +	case 0:
> +		exynos_dp_set_lane0_link_training(dp, training_lane_set);
> +		break;
> +	case 1:
> +		exynos_dp_set_lane1_link_training(dp, training_lane_set);
> +		break;
> +
> +	case 2:
> +		exynos_dp_set_lane2_link_training(dp, training_lane_set);
> +		break;
> +
> +	case 3:
> +		exynos_dp_set_lane3_link_training(dp, training_lane_set);
> +		break;
> +	}
> +}
> +
> +static unsigned int exynos_dp_get_lane_link_training(
> +				struct exynos_dp_device *dp,
> +				int lane)
> +{
> +	u32 reg;
> +
> +	switch (lane) {
> +	case 0:
> +		reg = exynos_dp_get_lane0_link_training(dp);
> +		break;
> +	case 1:
> +		reg = exynos_dp_get_lane1_link_training(dp);
> +		break;
> +	case 2:
> +		reg = exynos_dp_get_lane2_link_training(dp);
> +		break;
> +	case 3:
> +		reg = exynos_dp_get_lane3_link_training(dp);
> +		break;
> +	default:
> +		WARN_ON(1);
> +		return 0;
> +	}
> +
> +	return reg;
> +}
> +
> +static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
> +{
> +	exynos_dp_training_pattern_dis(dp);
> +	exynos_dp_set_enhanced_mode(dp);
> +
> +	dp->link_train.lt_state = FAILED;
> +}
> +
> +static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device
> *dp,
> +					u8 adjust_request[2])
> +{
> +	int lane, lane_count;
> +	u8 voltage_swing, pre_emphasis, training_lane;
> +
> +	lane_count = dp->link_train.lane_count;
> +	for (lane = 0; lane < lane_count; lane++) {
> +		voltage_swing = exynos_dp_get_adjust_request_voltage(
> +						adjust_request, lane);
> +		pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
> +						adjust_request, lane);
> +		training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
> +				DPCD_PRE_EMPHASIS_SET(pre_emphasis);
> +
> +		if (voltage_swing == VOLTAGE_LEVEL_3)
> +			training_lane |= DPCD_MAX_SWING_REACHED;
> +		if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
> +			training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
> +
> +		dp->link_train.training_lane[lane] = training_lane;
> +	}
> +}
> +
> +static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
> +{
> +	int lane, lane_count, retval;
> +	u8 voltage_swing, pre_emphasis, training_lane;
> +	u8 link_status[2], adjust_request[2];
> +
> +	usleep_range(100, 101);
> +
> +	lane_count = dp->link_train.lane_count;
> +
> +	retval =  exynos_dp_read_bytes_from_dpcd(dp,
> +			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
> +	if (retval)
> +		return retval;
> +
> +	retval =  exynos_dp_read_bytes_from_dpcd(dp,
> +			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2,
adjust_request);
> +	if (retval)
> +		return retval;
> +
> +	if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
> +		/* set training pattern 2 for EQ */
> +		exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
> +
> +		retval = exynos_dp_write_byte_to_dpcd(dp,
> +				DPCD_ADDR_TRAINING_PATTERN_SET,
> +				DPCD_SCRAMBLING_DISABLED |
> +				DPCD_TRAINING_PATTERN_2);
> +		if (retval)
> +			return retval;
> +
> +		dev_info(dp->dev, "Link Training Clock Recovery success\n");
> +		dp->link_train.lt_state = EQUALIZER_TRAINING;
> +	} else {
> +		for (lane = 0; lane < lane_count; lane++) {
> +			training_lane = exynos_dp_get_lane_link_training(
> +							dp, lane);
> +			voltage_swing =
exynos_dp_get_adjust_request_voltage(
> +							adjust_request,
lane);
> +			pre_emphasis =
> exynos_dp_get_adjust_request_pre_emphasis(
> +							adjust_request,
lane);
> +
> +			if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
> +					voltage_swing &&
> +			    DPCD_PRE_EMPHASIS_GET(training_lane) ==
> +					pre_emphasis)
> +				dp->link_train.cr_loop[lane]++;
> +
> +			if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
> +			    voltage_swing == VOLTAGE_LEVEL_3 ||
> +			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
> +				dev_err(dp->dev, "CR Max reached
(%d,%d,%d)\n",
> +					dp->link_train.cr_loop[lane],
> +					voltage_swing, pre_emphasis);
> +				exynos_dp_reduce_link_rate(dp);
> +				return -EIO;
> +			}
> +		}
> +	}
> +
> +	exynos_dp_get_adjust_training_lane(dp, adjust_request);
> +
> +	for (lane = 0; lane < lane_count; lane++)
> +		exynos_dp_set_lane_link_training(dp,
> +			dp->link_train.training_lane[lane], lane);
> +
> +	retval = exynos_dp_write_bytes_to_dpcd(dp,
> +			DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
> +			dp->link_train.training_lane);
> +	if (retval)
> +		return retval;
> +
> +	return retval;
> +}
> +
> +static int exynos_dp_process_equalizer_training(struct exynos_dp_device
> *dp)
> +{
> +	int lane, lane_count, retval;
> +	u32 reg;
> +	u8 link_align, link_status[2], adjust_request[2];
> +
> +	usleep_range(400, 401);
> +
> +	lane_count = dp->link_train.lane_count;
> +
> +	retval = exynos_dp_read_bytes_from_dpcd(dp,
> +			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
> +	if (retval)
> +		return retval;
> +
> +	if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
> +		exynos_dp_reduce_link_rate(dp);
> +		return -EIO;
> +	}
> +
> +	retval = exynos_dp_read_bytes_from_dpcd(dp,
> +			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2,
adjust_request);
> +	if (retval)
> +		return retval;
> +
> +	retval = exynos_dp_read_byte_from_dpcd(dp,
> +			DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
> +	if (retval)
> +		return retval;
> +
> +	exynos_dp_get_adjust_training_lane(dp, adjust_request);
> +
> +	if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count))
> {
> +		/* traing pattern Set to Normal */
> +		exynos_dp_training_pattern_dis(dp);
> +
> +		dev_info(dp->dev, "Link Training success!\n");
> +
> +		exynos_dp_get_link_bandwidth(dp, &reg);
> +		dp->link_train.link_rate = reg;
> +		dev_dbg(dp->dev, "final bandwidth = %.2x\n",
> +			dp->link_train.link_rate);
> +
> +		exynos_dp_get_lane_count(dp, &reg);
> +		dp->link_train.lane_count = reg;
> +		dev_dbg(dp->dev, "final lane count = %.2x\n",
> +			dp->link_train.lane_count);
> +
> +		/* set enhanced mode if available */
> +		exynos_dp_set_enhanced_mode(dp);
> +		dp->link_train.lt_state = FINISHED;
> +
> +		return 0;
> +	}
> +
> +	/* not all locked */
> +	dp->link_train.eq_loop++;
> +
> +	if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
> +		dev_err(dp->dev, "EQ Max loop\n");
> +		exynos_dp_reduce_link_rate(dp);
> +		return -EIO;
> +	}
> +
> +	for (lane = 0; lane < lane_count; lane++)
> +		exynos_dp_set_lane_link_training(dp,
> +			dp->link_train.training_lane[lane], lane);
> +
> +	retval = exynos_dp_write_bytes_to_dpcd(dp,
> DPCD_ADDR_TRAINING_LANE0_SET,
> +			lane_count, dp->link_train.training_lane);
> +
> +	return retval;
> +}
> +
> +static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
> +					u8 *bandwidth)
> +{
> +	u8 data;
> +
> +	/*
> +	 * For DP rev.1.1, Maximum link rate of Main Link lanes
> +	 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
> +	 */
> +	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
> +	*bandwidth = data;
> +}
> +
> +static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
> +					u8 *lane_count)
> +{
> +	u8 data;
> +
> +	/*
> +	 * For DP rev.1.1, Maximum number of Main Link lanes
> +	 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
> +	 */
> +	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
> +	*lane_count = DPCD_MAX_LANE_COUNT(data);
> +}
> +
> +static void exynos_dp_init_training(struct exynos_dp_device *dp,
> +			enum link_lane_count_type max_lane,
> +			enum link_rate_type max_rate)
> +{
> +	/*
> +	 * MACRO_RST must be applied after the PLL_LOCK to avoid
> +	 * the DP inter pair skew issue for at least 10 us
> +	 */
> +	exynos_dp_reset_macro(dp);
> +
> +	/* Initialize by reading RX's DPCD */
> +	exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
> +	exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
> +
> +	if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
> +	   (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
> +		dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
> +			dp->link_train.link_rate);
> +		dp->link_train.link_rate = LINK_RATE_1_62GBPS;
> +	}
> +
> +	if (dp->link_train.lane_count == 0) {
> +		dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
> +			dp->link_train.lane_count);
> +		dp->link_train.lane_count = (u8)LANE_COUNT1;
> +	}
> +
> +	/* Setup TX lane count & rate */
> +	if (dp->link_train.lane_count > max_lane)
> +		dp->link_train.lane_count = max_lane;
> +	if (dp->link_train.link_rate > max_rate)
> +		dp->link_train.link_rate = max_rate;
> +
> +	/* All DP analog module power up */
> +	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
> +}
> +
> +static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
> +{
> +	int retval = 0, training_finished = 0;
> +
> +	dp->link_train.lt_state = START;
> +
> +	/* Process here */
> +	while (!retval && !training_finished) {
> +		switch (dp->link_train.lt_state) {
> +		case START:
> +			retval = exynos_dp_link_start(dp);
> +			if (retval)
> +				dev_err(dp->dev, "LT link start failed!\n");
> +			break;
> +		case CLOCK_RECOVERY:
> +			retval = exynos_dp_process_clock_recovery(dp);
> +			if (retval)
> +				dev_err(dp->dev, "LT CR failed!\n");
> +			break;
> +		case EQUALIZER_TRAINING:
> +			retval = exynos_dp_process_equalizer_training(dp);
> +			if (retval)
> +				dev_err(dp->dev, "LT EQ failed!\n");
> +			break;
> +		case FINISHED:
> +			training_finished = 1;
> +			break;
> +		case FAILED:
> +			return -EREMOTEIO;
> +		}
> +	}
> +	if (retval)
> +		dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
> +
> +	return retval;
> +}
> +
> +static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
> +				u32 count,
> +				u32 bwtype)
> +{
> +	int i;
> +	int retval;
> +
> +	for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
> +		exynos_dp_init_training(dp, count, bwtype);
> +		retval = exynos_dp_sw_link_training(dp);
> +		if (retval == 0)
> +			break;
> +
> +		usleep_range(100, 110);
> +	}
> +
> +	return retval;
> +}
> +
> +static int exynos_dp_config_video(struct exynos_dp_device *dp)
> +{
> +	int retval = 0;
> +	int timeout_loop = 0;
> +	int done_count = 0;
> +
> +	exynos_dp_config_video_slave_mode(dp);
> +
> +	exynos_dp_set_video_color_format(dp);
> +
> +	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
> +		dev_err(dp->dev, "PLL is not locked yet.\n");
> +		return -EINVAL;
> +	}
> +
> +	for (;;) {
> +		timeout_loop++;
> +		if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
> +			break;
> +		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> +			dev_err(dp->dev, "Timeout of video streamclk ok\n");
> +			return -ETIMEDOUT;
> +		}
> +
> +		usleep_range(1, 2);
> +	}
> +
> +	/* Set to use the register calculated M/N video */
> +	exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
> +
> +	/* For video bist, Video timing must be generated by register */
> +	exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
> +
> +	/* Disable video mute */
> +	exynos_dp_enable_video_mute(dp, 0);
> +
> +	/* Configure video slave mode */
> +	exynos_dp_enable_video_master(dp, 0);
> +
> +	/* Enable video */
> +	exynos_dp_start_video(dp);
> +
> +	timeout_loop = 0;
> +
> +	for (;;) {
> +		timeout_loop++;
> +		if (exynos_dp_is_video_stream_on(dp) == 0) {
> +			done_count++;
> +			if (done_count > 10)
> +				break;
> +		} else if (done_count) {
> +			done_count = 0;
> +		}
> +		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> +			dev_err(dp->dev, "Timeout of video streamclk ok\n");
> +			return -ETIMEDOUT;
> +		}
> +
> +		usleep_range(1000, 1001);
> +	}
> +
> +	if (retval != 0)
> +		dev_err(dp->dev, "Video stream is not detected!\n");
> +
> +	return retval;
> +}
> +
> +static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool
> enable)
> +{
> +	u8 data;
> +
> +	if (enable) {
> +		exynos_dp_enable_scrambling(dp);
> +
> +		exynos_dp_read_byte_from_dpcd(dp,
> +			DPCD_ADDR_TRAINING_PATTERN_SET,
> +			&data);
> +		exynos_dp_write_byte_to_dpcd(dp,
> +			DPCD_ADDR_TRAINING_PATTERN_SET,
> +			(u8)(data & ~DPCD_SCRAMBLING_DISABLED));
> +	} else {
> +		exynos_dp_disable_scrambling(dp);
> +
> +		exynos_dp_read_byte_from_dpcd(dp,
> +			DPCD_ADDR_TRAINING_PATTERN_SET,
> +			&data);
> +		exynos_dp_write_byte_to_dpcd(dp,
> +			DPCD_ADDR_TRAINING_PATTERN_SET,
> +			(u8)(data | DPCD_SCRAMBLING_DISABLED));
> +	}
> +}
> +
> +static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
> +{
> +	struct exynos_dp_device *dp = arg;
> +
> +	enum dp_irq_type irq_type;
> +
> +	irq_type = exynos_dp_get_irq_type(dp);
> +	switch (irq_type) {
> +	case DP_IRQ_TYPE_HP_CABLE_IN:
> +		dev_dbg(dp->dev, "Received irq - cable in\n");
> +		schedule_work(&dp->hotplug_work);
> +		exynos_dp_clear_hotplug_interrupts(dp);
> +		break;
> +	case DP_IRQ_TYPE_HP_CABLE_OUT:
> +		dev_dbg(dp->dev, "Received irq - cable out\n");
> +		exynos_dp_clear_hotplug_interrupts(dp);
> +		break;
> +	case DP_IRQ_TYPE_HP_CHANGE:
> +		/*
> +		 * We get these change notifications once in a while, but
> there
> +		 * is nothing we can do with them. Just ignore it for now
and
> +		 * only handle cable changes.
> +		 */
> +		dev_dbg(dp->dev, "Received irq - hotplug change;
> ignoring.\n");
> +		exynos_dp_clear_hotplug_interrupts(dp);
> +		break;
> +	default:
> +		dev_err(dp->dev, "Received irq - unknown type!\n");
> +		break;
> +	}
> +	return IRQ_HANDLED;
> +}
> +
> +static void exynos_dp_hotplug(struct work_struct *work)
> +{
> +	struct exynos_dp_device *dp;
> +	int ret;
> +
> +	dp = container_of(work, struct exynos_dp_device, hotplug_work);
> +
> +	ret = exynos_dp_detect_hpd(dp);
> +	if (ret) {
> +		/* Cable has been disconnected, we're done */
> +		return;
> +	}
> +
> +	ret = exynos_dp_handle_edid(dp);
> +	if (ret) {
> +		dev_err(dp->dev, "unable to handle edid\n");
> +		return;
> +	}
> +
> +	ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
> +					dp->video_info->link_rate);
> +	if (ret) {
> +		dev_err(dp->dev, "unable to do link train\n");
> +		return;
> +	}
> +
> +	exynos_dp_enable_scramble(dp, 1);
> +	exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
> +	exynos_dp_enable_enhanced_mode(dp, 1);
> +
> +	exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
> +	exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
> +
> +	exynos_dp_init_video(dp);
> +	ret = exynos_dp_config_video(dp);
> +	if (ret)
> +		dev_err(dp->dev, "unable to config video\n");
> +}
> +
> +#ifdef CONFIG_OF
> +static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device
> *dev)
> +{
> +	struct device_node *dp_node = dev->of_node;
> +	struct exynos_dp_platdata *pd;
> +	struct video_info *dp_video_config;
> +
> +	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
> +	if (!pd) {
> +		dev_err(dev, "memory allocation for pdata failed\n");
> +		return ERR_PTR(-ENOMEM);
> +	}
> +	dp_video_config = devm_kzalloc(dev,
> +				sizeof(*dp_video_config), GFP_KERNEL);
> +
> +	if (!dp_video_config) {
> +		dev_err(dev, "memory allocation for video config failed\n");
> +		return ERR_PTR(-ENOMEM);
> +	}
> +	pd->video_info = dp_video_config;
> +
> +	dp_video_config->h_sync_polarity =
> +		of_property_read_bool(dp_node, "hsync-active-high");
> +
> +	dp_video_config->v_sync_polarity =
> +		of_property_read_bool(dp_node, "vsync-active-high");
> +
> +	dp_video_config->interlaced =
> +		of_property_read_bool(dp_node, "interlaced");
> +
> +	if (of_property_read_u32(dp_node, "samsung,color-space",
> +				&dp_video_config->color_space)) {
> +		dev_err(dev, "failed to get color-space\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	if (of_property_read_u32(dp_node, "samsung,dynamic-range",
> +				&dp_video_config->dynamic_range)) {
> +		dev_err(dev, "failed to get dynamic-range\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
> +				&dp_video_config->ycbcr_coeff)) {
> +		dev_err(dev, "failed to get ycbcr-coeff\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	if (of_property_read_u32(dp_node, "samsung,color-depth",
> +				&dp_video_config->color_depth)) {
> +		dev_err(dev, "failed to get color-depth\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	if (of_property_read_u32(dp_node, "samsung,link-rate",
> +				&dp_video_config->link_rate)) {
> +		dev_err(dev, "failed to get link-rate\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	if (of_property_read_u32(dp_node, "samsung,lane-count",
> +				&dp_video_config->lane_count)) {
> +		dev_err(dev, "failed to get lane-count\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	return pd;
> +}
> +
> +static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
> +{
> +	struct device_node *dp_phy_node = of_node_get(dp->dev->of_node);
> +	u32 phy_base;
> +	int ret = 0;
> +
> +	dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
> +	if (!dp_phy_node) {
> +		dev_err(dp->dev, "could not find dptx-phy node\n");
> +		return -ENODEV;
> +	}
> +
> +	if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
> +		dev_err(dp->dev, "failed to get reg for dptx-phy\n");
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +
> +	if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
> +				&dp->enable_mask)) {
> +		dev_err(dp->dev, "failed to get enable-mask for
dptx-phy\n");
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +
> +	dp->phy_addr = ioremap(phy_base, SZ_4);
> +	if (!dp->phy_addr) {
> +		dev_err(dp->dev, "failed to ioremap dp-phy\n");
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +err:
> +	of_node_put(dp_phy_node);
> +
> +	return ret;
> +}
> +
> +static void exynos_dp_phy_init(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = __raw_readl(dp->phy_addr);
> +	reg |= dp->enable_mask;
> +	__raw_writel(reg, dp->phy_addr);
> +}
> +
> +static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = __raw_readl(dp->phy_addr);
> +	reg &= ~(dp->enable_mask);
> +	__raw_writel(reg, dp->phy_addr);
> +}
> +#else
> +static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device
> *dev)
> +{
> +	return NULL;
> +}
> +
> +static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
> +{
> +	return -EINVAL;
> +}
> +
> +static void exynos_dp_phy_init(struct exynos_dp_device *dp)
> +{
> +	return;
> +}
> +
> +static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
> +{
> +	return;
> +}
> +#endif /* CONFIG_OF */
> +
> +static int exynos_dp_probe(struct platform_device *pdev)
> +{
> +	struct resource *res;
> +	struct exynos_dp_device *dp;
> +	struct exynos_dp_platdata *pdata;
> +
> +	int ret = 0;
> +
> +	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
> +				GFP_KERNEL);
> +	if (!dp) {
> +		dev_err(&pdev->dev, "no memory for device data\n");
> +		return -ENOMEM;
> +	}
> +
> +	dp->dev = &pdev->dev;
> +
> +	if (pdev->dev.of_node) {
> +		pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
> +		if (IS_ERR(pdata))
> +			return PTR_ERR(pdata);
> +
> +		ret = exynos_dp_dt_parse_phydata(dp);
> +		if (ret)
> +			return ret;
> +	} else {
> +		pdata = pdev->dev.platform_data;
> +		if (!pdata) {
> +			dev_err(&pdev->dev, "no platform data\n");
> +			return -EINVAL;
> +		}
> +	}
> +
> +	dp->clock = devm_clk_get(&pdev->dev, "dp");
> +	if (IS_ERR(dp->clock)) {
> +		dev_err(&pdev->dev, "failed to get clock\n");
> +		return PTR_ERR(dp->clock);
> +	}
> +
> +	clk_prepare_enable(dp->clock);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(dp->reg_base))
> +		return PTR_ERR(dp->reg_base);
> +
> +	dp->irq = platform_get_irq(pdev, 0);
> +	if (dp->irq == -ENXIO) {
> +		dev_err(&pdev->dev, "failed to get irq\n");
> +		return -ENODEV;
> +	}
> +
> +	INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
> +
> +	dp->video_info = pdata->video_info;
> +
> +	if (pdev->dev.of_node) {
> +		if (dp->phy_addr)
> +			exynos_dp_phy_init(dp);
> +	} else {
> +		if (pdata->phy_init)
> +			pdata->phy_init();
> +	}
> +
> +	exynos_dp_init_dp(dp);
> +
> +	ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler,
> 0,
> +				"exynos-dp", dp);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to request irq\n");
> +		return ret;
> +	}
> +
> +	platform_set_drvdata(pdev, dp);
> +
> +	return 0;
> +}
> +
> +static int exynos_dp_remove(struct platform_device *pdev)
> +{
> +	struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> +	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
> +
> +	flush_work(&dp->hotplug_work);
> +
> +	if (pdev->dev.of_node) {
> +		if (dp->phy_addr)
> +			exynos_dp_phy_exit(dp);
> +	} else {
> +		if (pdata->phy_exit)
> +			pdata->phy_exit();
> +	}
> +
> +	clk_disable_unprepare(dp->clock);
> +
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int exynos_dp_suspend(struct device *dev)
> +{
> +	struct exynos_dp_platdata *pdata = dev->platform_data;
> +	struct exynos_dp_device *dp = dev_get_drvdata(dev);
> +
> +	disable_irq(dp->irq);
> +
> +	flush_work(&dp->hotplug_work);
> +
> +	if (dev->of_node) {
> +		if (dp->phy_addr)
> +			exynos_dp_phy_exit(dp);
> +	} else {
> +		if (pdata->phy_exit)
> +			pdata->phy_exit();
> +	}
> +
> +	clk_disable_unprepare(dp->clock);
> +
> +	return 0;
> +}
> +
> +static int exynos_dp_resume(struct device *dev)
> +{
> +	struct exynos_dp_platdata *pdata = dev->platform_data;
> +	struct exynos_dp_device *dp = dev_get_drvdata(dev);
> +
> +	if (dev->of_node) {
> +		if (dp->phy_addr)
> +			exynos_dp_phy_init(dp);
> +	} else {
> +		if (pdata->phy_init)
> +			pdata->phy_init();
> +	}
> +
> +	clk_prepare_enable(dp->clock);
> +
> +	exynos_dp_init_dp(dp);
> +
> +	enable_irq(dp->irq);
> +
> +	return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops exynos_dp_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
> +};
> +
> +static const struct of_device_id exynos_dp_match[] = {
> +	{ .compatible = "samsung,exynos5-dp" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, exynos_dp_match);
> +
> +static struct platform_driver exynos_dp_driver = {
> +	.probe		= exynos_dp_probe,
> +	.remove		= exynos_dp_remove,
> +	.driver		= {
> +		.name	= "exynos-dp",
> +		.owner	= THIS_MODULE,
> +		.pm	= &exynos_dp_pm_ops,
> +		.of_match_table = of_match_ptr(exynos_dp_match),
> +	},
> +};
> +
> +module_platform_driver(exynos_dp_driver);
> +
> +MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
> +MODULE_DESCRIPTION("Samsung SoC DP Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h
> b/drivers/gpu/drm/exynos/exynos_dp_core.h
> new file mode 100644
> index 0000000..6c567bbf
> --- /dev/null
> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
> @@ -0,0 +1,210 @@
> +/*
> + * Header file for Samsung DP (Display Port) interface driver.
> + *
> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> + * Author: Jingoo Han <jg1.han@samsung.com>
> + *
> + * 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 _EXYNOS_DP_CORE_H
> +#define _EXYNOS_DP_CORE_H
> +
> +enum dp_irq_type {
> +	DP_IRQ_TYPE_HP_CABLE_IN,
> +	DP_IRQ_TYPE_HP_CABLE_OUT,
> +	DP_IRQ_TYPE_HP_CHANGE,
> +	DP_IRQ_TYPE_UNKNOWN,
> +};
> +
> +struct link_train {
> +	int eq_loop;
> +	int cr_loop[4];
> +
> +	u8 link_rate;
> +	u8 lane_count;
> +	u8 training_lane[4];
> +
> +	enum link_training_state lt_state;
> +};
> +
> +struct exynos_dp_device {
> +	struct device		*dev;
> +	struct clk		*clock;
> +	unsigned int		irq;
> +	void __iomem		*reg_base;
> +	void __iomem		*phy_addr;
> +	unsigned int		enable_mask;
> +
> +	struct video_info	*video_info;
> +	struct link_train	link_train;
> +	struct work_struct	hotplug_work;
> +};
> +
> +/* exynos_dp_reg.c */
> +void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool
> enable);
> +void exynos_dp_stop_video(struct exynos_dp_device *dp);
> +void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
> +void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
> +void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
> +void exynos_dp_reset(struct exynos_dp_device *dp);
> +void exynos_dp_swreset(struct exynos_dp_device *dp);
> +void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
> +enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device
> *dp);
> +void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool
> enable);
> +void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
> +				enum analog_power_block block,
> +				bool enable);
> +void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
> +void exynos_dp_init_hpd(struct exynos_dp_device *dp);
> +enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
> +void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
> +void exynos_dp_reset_aux(struct exynos_dp_device *dp);
> +void exynos_dp_init_aux(struct exynos_dp_device *dp);
> +int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
> +void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
> +int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
> +int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
> +				unsigned int reg_addr,
> +				unsigned char data);
> +int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
> +				unsigned int reg_addr,
> +				unsigned char *data);
> +int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
> +				unsigned int reg_addr,
> +				unsigned int count,
> +				unsigned char data[]);
> +int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
> +				unsigned int reg_addr,
> +				unsigned int count,
> +				unsigned char data[]);
> +int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
> +				unsigned int device_addr,
> +				unsigned int reg_addr);
> +int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
> +				unsigned int device_addr,
> +				unsigned int reg_addr,
> +				unsigned int *data);
> +int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
> +				unsigned int device_addr,
> +				unsigned int reg_addr,
> +				unsigned int count,
> +				unsigned char edid[]);
> +void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32
> bwtype);
> +void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32
> *bwtype);
> +void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
> +void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
> +void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool
> enable);
> +void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
> +				 enum pattern_set pattern);
> +void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32
> level);
> +void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32
> level);
> +void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32
> level);
> +void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32
> level);
> +void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
> +				u32 training_lane);
> +void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
> +				u32 training_lane);
> +void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
> +				u32 training_lane);
> +void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
> +				u32 training_lane);
> +u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
> +u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
> +u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
> +u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
> +void exynos_dp_reset_macro(struct exynos_dp_device *dp);
> +void exynos_dp_init_video(struct exynos_dp_device *dp);
> +
> +void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
> +int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device
*dp);
> +void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
> +			enum clock_recovery_m_value_type type,
> +			u32 m_value,
> +			u32 n_value);
> +void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32
> type);
> +void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool
> enable);
> +void exynos_dp_start_video(struct exynos_dp_device *dp);
> +int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
> +void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
> +void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
> +void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
> +
> +/* I2C EDID Chip ID, Slave Address */
> +#define I2C_EDID_DEVICE_ADDR			0x50
> +#define I2C_E_EDID_DEVICE_ADDR			0x30
> +
> +#define EDID_BLOCK_LENGTH			0x80
> +#define EDID_HEADER_PATTERN			0x00
> +#define EDID_EXTENSION_FLAG			0x7e
> +#define EDID_CHECKSUM				0x7f
> +
> +/* Definition for DPCD Register */
> +#define DPCD_ADDR_DPCD_REV			0x0000
> +#define DPCD_ADDR_MAX_LINK_RATE			0x0001
> +#define DPCD_ADDR_MAX_LANE_COUNT		0x0002
> +#define DPCD_ADDR_LINK_BW_SET			0x0100
> +#define DPCD_ADDR_LANE_COUNT_SET		0x0101
> +#define DPCD_ADDR_TRAINING_PATTERN_SET		0x0102
> +#define DPCD_ADDR_TRAINING_LANE0_SET		0x0103
> +#define DPCD_ADDR_LANE0_1_STATUS		0x0202
> +#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED	0x0204
> +#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1	0x0206
> +#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3	0x0207
> +#define DPCD_ADDR_TEST_REQUEST			0x0218
> +#define DPCD_ADDR_TEST_RESPONSE			0x0260
> +#define DPCD_ADDR_TEST_EDID_CHECKSUM		0x0261
> +#define DPCD_ADDR_SINK_POWER_STATE		0x0600
> +
> +/* DPCD_ADDR_MAX_LANE_COUNT */
> +#define DPCD_ENHANCED_FRAME_CAP(x)		(((x) >> 7) & 0x1)
> +#define DPCD_MAX_LANE_COUNT(x)			((x) & 0x1f)
> +
> +/* DPCD_ADDR_LANE_COUNT_SET */
> +#define DPCD_ENHANCED_FRAME_EN			(0x1 << 7)
> +#define DPCD_LANE_COUNT_SET(x)			((x) & 0x1f)
> +
> +/* DPCD_ADDR_TRAINING_PATTERN_SET */
> +#define DPCD_SCRAMBLING_DISABLED		(0x1 << 5)
> +#define DPCD_SCRAMBLING_ENABLED			(0x0 << 5)
> +#define DPCD_TRAINING_PATTERN_2			(0x2 << 0)
> +#define DPCD_TRAINING_PATTERN_1			(0x1 << 0)
> +#define DPCD_TRAINING_PATTERN_DISABLED		(0x0 << 0)
> +
> +/* DPCD_ADDR_TRAINING_LANE0_SET */
> +#define DPCD_MAX_PRE_EMPHASIS_REACHED		(0x1 << 5)
> +#define DPCD_PRE_EMPHASIS_SET(x)		(((x) & 0x3) << 3)
> +#define DPCD_PRE_EMPHASIS_GET(x)		(((x) >> 3) & 0x3)
> +#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0	(0x0 << 3)
> +#define DPCD_MAX_SWING_REACHED			(0x1 << 2)
> +#define DPCD_VOLTAGE_SWING_SET(x)		(((x) & 0x3) << 0)
> +#define DPCD_VOLTAGE_SWING_GET(x)		(((x) >> 0) & 0x3)
> +#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0	(0x0 << 0)
> +
> +/* DPCD_ADDR_LANE0_1_STATUS */
> +#define DPCD_LANE_SYMBOL_LOCKED			(0x1 << 2)
> +#define DPCD_LANE_CHANNEL_EQ_DONE		(0x1 << 1)
> +#define DPCD_LANE_CR_DONE			(0x1 << 0)
> +#define DPCD_CHANNEL_EQ_BITS			(DPCD_LANE_CR_DONE|	\
> +						 DPCD_LANE_CHANNEL_EQ_DONE|\
> +						 DPCD_LANE_SYMBOL_LOCKED)
> +
> +/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
> +#define DPCD_LINK_STATUS_UPDATED		(0x1 << 7)
> +#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED	(0x1 << 6)
> +#define DPCD_INTERLANE_ALIGN_DONE		(0x1 << 0)
> +
> +/* DPCD_ADDR_TEST_REQUEST */
> +#define DPCD_TEST_EDID_READ			(0x1 << 2)
> +
> +/* DPCD_ADDR_TEST_RESPONSE */
> +#define DPCD_TEST_EDID_CHECKSUM_WRITE		(0x1 << 2)
> +
> +/* DPCD_ADDR_SINK_POWER_STATE */
> +#define DPCD_SET_POWER_STATE_D0			(0x1 << 0)
> +#define DPCD_SET_POWER_STATE_D4			(0x2 << 0)
> +
> +#endif /* _EXYNOS_DP_CORE_H */
> diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.c
> b/drivers/gpu/drm/exynos/exynos_dp_reg.c
> new file mode 100644
> index 0000000..29d9d03
> --- /dev/null
> +++ b/drivers/gpu/drm/exynos/exynos_dp_reg.c
> @@ -0,0 +1,1245 @@
> +/*
> + * Samsung DP (Display port) register interface driver.
> + *
> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> + * Author: Jingoo Han <jg1.han@samsung.com>
> + *
> + * 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/device.h>
> +#include <linux/io.h>
> +#include <linux/delay.h>
> +
> +#include <video/exynos_dp.h>
> +
> +#include "exynos_dp_core.h"
> +#include "exynos_dp_reg.h"
> +
> +#define COMMON_INT_MASK_1	0
> +#define COMMON_INT_MASK_2	0
> +#define COMMON_INT_MASK_3	0
> +#define COMMON_INT_MASK_4	(HOTPLUG_CHG | HPD_LOST | PLUG)
> +#define INT_STA_MASK		INT_HPD
> +
> +void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool
enable)
> +{
> +	u32 reg;
> +
> +	if (enable) {
> +		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +		reg |= HDCP_VIDEO_MUTE;
> +		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +	} else {
> +		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +		reg &= ~HDCP_VIDEO_MUTE;
> +		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +	}
> +}
> +
> +void exynos_dp_stop_video(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +	reg &= ~VIDEO_EN;
> +	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +}
> +
> +void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
> +{
> +	u32 reg;
> +
> +	if (enable)
> +		reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
> +			LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
> +	else
> +		reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
> +			LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
> +
> +	writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
> +}
> +
> +void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = TX_TERMINAL_CTRL_50_OHM;
> +	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
> +
> +	reg = SEL_24M | TX_DVDD_BIT_1_0625V;
> +	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
> +
> +	reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
> +	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
> +
> +	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
> +		TX_CUR1_2X | TX_CUR_16_MA;
> +	writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
> +
> +	reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
> +		CH1_AMP_400_MV | CH0_AMP_400_MV;
> +	writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
> +}
> +
> +void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
> +{
> +	/* Set interrupt pin assertion polarity as high */
> +	writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
> +
> +	/* Clear pending regisers */
> +	writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
> +	writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
> +	writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
> +	writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
> +	writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
> +
> +	/* 0:mask,1: unmask */
> +	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
> +	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
> +	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
> +	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
> +	writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
> +}
> +
> +void exynos_dp_reset(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	exynos_dp_stop_video(dp);
> +	exynos_dp_enable_video_mute(dp, 0);
> +
> +	reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
> +		AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
> +		HDCP_FUNC_EN_N | SW_FUNC_EN_N;
> +	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
> +
> +	reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
> +		SERDES_FIFO_FUNC_EN_N |
> +		LS_CLK_DOMAIN_FUNC_EN_N;
> +	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> +
> +	usleep_range(20, 30);
> +
> +	exynos_dp_lane_swap(dp, 0);
> +
> +	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> +	writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> +	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> +	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +
> +	writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
> +	writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
> +
> +	writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
> +	writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
> +
> +	writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
> +
> +	writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
> +
> +	writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
> +	writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
> +
> +	writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
> +	writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
> +
> +	writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> +}
> +
> +void exynos_dp_swreset(struct exynos_dp_device *dp)
> +{
> +	writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
> +}
> +
> +void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	/* 0: mask, 1: unmask */
> +	reg = COMMON_INT_MASK_1;
> +	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
> +
> +	reg = COMMON_INT_MASK_2;
> +	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
> +
> +	reg = COMMON_INT_MASK_3;
> +	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
> +
> +	reg = COMMON_INT_MASK_4;
> +	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
> +
> +	reg = INT_STA_MASK;
> +	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
> +}
> +
> +enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device
*dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
> +	if (reg & PLL_LOCK)
> +		return PLL_LOCKED;
> +	else
> +		return PLL_UNLOCKED;
> +}
> +
> +void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool
> enable)
> +{
> +	u32 reg;
> +
> +	if (enable) {
> +		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
> +		reg |= DP_PLL_PD;
> +		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
> +	} else {
> +		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
> +		reg &= ~DP_PLL_PD;
> +		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
> +	}
> +}
> +
> +void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
> +				enum analog_power_block block,
> +				bool enable)
> +{
> +	u32 reg;
> +
> +	switch (block) {
> +	case AUX_BLOCK:
> +		if (enable) {
> +			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +			reg |= AUX_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		} else {
> +			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +			reg &= ~AUX_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		}
> +		break;
> +	case CH0_BLOCK:
> +		if (enable) {
> +			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +			reg |= CH0_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		} else {
> +			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +			reg &= ~CH0_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		}
> +		break;
> +	case CH1_BLOCK:
> +		if (enable) {
> +			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +			reg |= CH1_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		} else {
> +			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +			reg &= ~CH1_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		}
> +		break;
> +	case CH2_BLOCK:
> +		if (enable) {
> +			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +			reg |= CH2_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		} else {
> +			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +			reg &= ~CH2_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		}
> +		break;
> +	case CH3_BLOCK:
> +		if (enable) {
> +			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +			reg |= CH3_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		} else {
> +			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +			reg &= ~CH3_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		}
> +		break;
> +	case ANALOG_TOTAL:
> +		if (enable) {
> +			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +			reg |= DP_PHY_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		} else {
> +			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +			reg &= ~DP_PHY_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		}
> +		break;
> +	case POWER_ALL:
> +		if (enable) {
> +			reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
> +				CH1_PD | CH0_PD;
> +			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		} else {
> +			writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
> +		}
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +	int timeout_loop = 0;
> +
> +	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
> +
> +	reg = PLL_LOCK_CHG;
> +	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
> +	reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
> +	writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
> +
> +	/* Power up PLL */
> +	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
> +		exynos_dp_set_pll_power_down(dp, 0);
> +
> +		while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
> +			timeout_loop++;
> +			if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> +				dev_err(dp->dev, "failed to get pll lock
> status\n");
> +				return;
> +			}
> +			usleep_range(10, 20);
> +		}
> +	}
> +
> +	/* Enable Serdes FIFO function and Link symbol clock domain module
> */
> +	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> +	reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
> +		| AUX_FUNC_EN_N);
> +	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> +}
> +
> +void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = HOTPLUG_CHG | HPD_LOST | PLUG;
> +	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
> +
> +	reg = INT_HPD;
> +	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
> +}
> +
> +void exynos_dp_init_hpd(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	exynos_dp_clear_hotplug_interrupts(dp);
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> +	reg &= ~(F_HPD | HPD_CTRL);
> +	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> +}
> +
> +enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	/* Parse hotplug interrupt status register */
> +	reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
> +
> +	if (reg & PLUG)
> +		return DP_IRQ_TYPE_HP_CABLE_IN;
> +
> +	if (reg & HPD_LOST)
> +		return DP_IRQ_TYPE_HP_CABLE_OUT;
> +
> +	if (reg & HOTPLUG_CHG)
> +		return DP_IRQ_TYPE_HP_CHANGE;
> +
> +	return DP_IRQ_TYPE_UNKNOWN;
> +}
> +
> +void exynos_dp_reset_aux(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	/* Disable AUX channel module */
> +	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> +	reg |= AUX_FUNC_EN_N;
> +	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> +}
> +
> +void exynos_dp_init_aux(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	/* Clear inerrupts related to AUX channel */
> +	reg = RPLY_RECEIV | AUX_ERR;
> +	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
> +
> +	exynos_dp_reset_aux(dp);
> +
> +	/* Disable AUX transaction H/W retry */
> +	reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
> +		AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
> +	writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
> +
> +	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
> +	reg = DEFER_CTRL_EN | DEFER_COUNT(1);
> +	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
> +
> +	/* Enable AUX channel module */
> +	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> +	reg &= ~AUX_FUNC_EN_N;
> +	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> +}
> +
> +int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> +	if (reg & HPD_STATUS)
> +		return 0;
> +
> +	return -EINVAL;
> +}
> +
> +void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
> +	reg &= ~SW_FUNC_EN_N;
> +	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
> +}
> +
> +int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
> +{
> +	int reg;
> +	int retval = 0;
> +	int timeout_loop = 0;
> +
> +	/* Enable AUX CH operation */
> +	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> +	reg |= AUX_EN;
> +	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> +
> +	/* Is AUX CH command reply received? */
> +	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
> +	while (!(reg & RPLY_RECEIV)) {
> +		timeout_loop++;
> +		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> +			dev_err(dp->dev, "AUX CH command reply failed!\n");
> +			return -ETIMEDOUT;
> +		}
> +		reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
> +		usleep_range(10, 11);
> +	}
> +
> +	/* Clear interrupt source for AUX CH command reply */
> +	writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
> +
> +	/* Clear interrupt source for AUX CH access error */
> +	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
> +	if (reg & AUX_ERR) {
> +		writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
> +		return -EREMOTEIO;
> +	}
> +
> +	/* Check AUX CH error access status */
> +	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
> +	if ((reg & AUX_STATUS_MASK) != 0) {
> +		dev_err(dp->dev, "AUX CH error happens: %d\n\n",
> +			reg & AUX_STATUS_MASK);
> +		return -EREMOTEIO;
> +	}
> +
> +	return retval;
> +}
> +
> +int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
> +				unsigned int reg_addr,
> +				unsigned char data)
> +{
> +	u32 reg;
> +	int i;
> +	int retval;
> +
> +	for (i = 0; i < 3; i++) {
> +		/* Clear AUX CH data buffer */
> +		reg = BUF_CLR;
> +		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
> +
> +		/* Select DPCD device address */
> +		reg = AUX_ADDR_7_0(reg_addr);
> +		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> +		reg = AUX_ADDR_15_8(reg_addr);
> +		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> +		reg = AUX_ADDR_19_16(reg_addr);
> +		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
> +
> +		/* Write data buffer */
> +		reg = (unsigned int)data;
> +		writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
> +
> +		/*
> +		 * Set DisplayPort transaction and write 1 byte
> +		 * If bit 3 is 1, DisplayPort transaction.
> +		 * If Bit 3 is 0, I2C transaction.
> +		 */
> +		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
> +		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
> +
> +		/* Start AUX transaction */
> +		retval = exynos_dp_start_aux_transaction(dp);
> +		if (retval == 0)
> +			break;
> +		else
> +			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
> +				__func__);
> +	}
> +
> +	return retval;
> +}
> +
> +int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
> +				unsigned int reg_addr,
> +				unsigned char *data)
> +{
> +	u32 reg;
> +	int i;
> +	int retval;
> +
> +	for (i = 0; i < 3; i++) {
> +		/* Clear AUX CH data buffer */
> +		reg = BUF_CLR;
> +		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
> +
> +		/* Select DPCD device address */
> +		reg = AUX_ADDR_7_0(reg_addr);
> +		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> +		reg = AUX_ADDR_15_8(reg_addr);
> +		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> +		reg = AUX_ADDR_19_16(reg_addr);
> +		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
> +
> +		/*
> +		 * Set DisplayPort transaction and read 1 byte
> +		 * If bit 3 is 1, DisplayPort transaction.
> +		 * If Bit 3 is 0, I2C transaction.
> +		 */
> +		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
> +		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
> +
> +		/* Start AUX transaction */
> +		retval = exynos_dp_start_aux_transaction(dp);
> +		if (retval == 0)
> +			break;
> +		else
> +			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
> +				__func__);
> +	}
> +
> +	/* Read data buffer */
> +	reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
> +	*data = (unsigned char)(reg & 0xff);
> +
> +	return retval;
> +}
> +
> +int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
> +				unsigned int reg_addr,
> +				unsigned int count,
> +				unsigned char data[])
> +{
> +	u32 reg;
> +	unsigned int start_offset;
> +	unsigned int cur_data_count;
> +	unsigned int cur_data_idx;
> +	int i;
> +	int retval = 0;
> +
> +	/* Clear AUX CH data buffer */
> +	reg = BUF_CLR;
> +	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
> +
> +	start_offset = 0;
> +	while (start_offset < count) {
> +		/* Buffer size of AUX CH is 16 * 4bytes */
> +		if ((count - start_offset) > 16)
> +			cur_data_count = 16;
> +		else
> +			cur_data_count = count - start_offset;
> +
> +		for (i = 0; i < 3; i++) {
> +			/* Select DPCD device address */
> +			reg = AUX_ADDR_7_0(reg_addr + start_offset);
> +			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> +			reg = AUX_ADDR_15_8(reg_addr + start_offset);
> +			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> +			reg = AUX_ADDR_19_16(reg_addr + start_offset);
> +			writel(reg, dp->reg_base +
EXYNOS_DP_AUX_ADDR_19_16);
> +
> +			for (cur_data_idx = 0; cur_data_idx <
cur_data_count;
> +			     cur_data_idx++) {
> +				reg = data[start_offset + cur_data_idx];
> +				writel(reg, dp->reg_base +
EXYNOS_DP_BUF_DATA_0
> +							  + 4 *
cur_data_idx);
> +			}
> +
> +			/*
> +			 * Set DisplayPort transaction and write
> +			 * If bit 3 is 1, DisplayPort transaction.
> +			 * If Bit 3 is 0, I2C transaction.
> +			 */
> +			reg = AUX_LENGTH(cur_data_count) |
> +				AUX_TX_COMM_DP_TRANSACTION |
AUX_TX_COMM_WRITE;
> +			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
> +
> +			/* Start AUX transaction */
> +			retval = exynos_dp_start_aux_transaction(dp);
> +			if (retval == 0)
> +				break;
> +			else
> +				dev_dbg(dp->dev, "%s: Aux Transaction
fail!\n",
> +					__func__);
> +		}
> +
> +		start_offset += cur_data_count;
> +	}
> +
> +	return retval;
> +}
> +
> +int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
> +				unsigned int reg_addr,
> +				unsigned int count,
> +				unsigned char data[])
> +{
> +	u32 reg;
> +	unsigned int start_offset;
> +	unsigned int cur_data_count;
> +	unsigned int cur_data_idx;
> +	int i;
> +	int retval = 0;
> +
> +	/* Clear AUX CH data buffer */
> +	reg = BUF_CLR;
> +	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
> +
> +	start_offset = 0;
> +	while (start_offset < count) {
> +		/* Buffer size of AUX CH is 16 * 4bytes */
> +		if ((count - start_offset) > 16)
> +			cur_data_count = 16;
> +		else
> +			cur_data_count = count - start_offset;
> +
> +		/* AUX CH Request Transaction process */
> +		for (i = 0; i < 3; i++) {
> +			/* Select DPCD device address */
> +			reg = AUX_ADDR_7_0(reg_addr + start_offset);
> +			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> +			reg = AUX_ADDR_15_8(reg_addr + start_offset);
> +			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> +			reg = AUX_ADDR_19_16(reg_addr + start_offset);
> +			writel(reg, dp->reg_base +
EXYNOS_DP_AUX_ADDR_19_16);
> +
> +			/*
> +			 * Set DisplayPort transaction and read
> +			 * If bit 3 is 1, DisplayPort transaction.
> +			 * If Bit 3 is 0, I2C transaction.
> +			 */
> +			reg = AUX_LENGTH(cur_data_count) |
> +				AUX_TX_COMM_DP_TRANSACTION |
AUX_TX_COMM_READ;
> +			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
> +
> +			/* Start AUX transaction */
> +			retval = exynos_dp_start_aux_transaction(dp);
> +			if (retval == 0)
> +				break;
> +			else
> +				dev_dbg(dp->dev, "%s: Aux Transaction
fail!\n",
> +					__func__);
> +		}
> +
> +		for (cur_data_idx = 0; cur_data_idx < cur_data_count;
> +		    cur_data_idx++) {
> +			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
> +						 + 4 * cur_data_idx);
> +			data[start_offset + cur_data_idx] =
> +				(unsigned char)reg;
> +		}
> +
> +		start_offset += cur_data_count;
> +	}
> +
> +	return retval;
> +}
> +
> +int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
> +				unsigned int device_addr,
> +				unsigned int reg_addr)
> +{
> +	u32 reg;
> +	int retval;
> +
> +	/* Set EDID device address */
> +	reg = device_addr;
> +	writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> +	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> +	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
> +
> +	/* Set offset from base address of EDID device */
> +	writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
> +
> +	/*
> +	 * Set I2C transaction and write address
> +	 * If bit 3 is 1, DisplayPort transaction.
> +	 * If Bit 3 is 0, I2C transaction.
> +	 */
> +	reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
> +		AUX_TX_COMM_WRITE;
> +	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
> +
> +	/* Start AUX transaction */
> +	retval = exynos_dp_start_aux_transaction(dp);
> +	if (retval != 0)
> +		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
> +
> +	return retval;
> +}
> +
> +int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
> +				unsigned int device_addr,
> +				unsigned int reg_addr,
> +				unsigned int *data)
> +{
> +	u32 reg;
> +	int i;
> +	int retval;
> +
> +	for (i = 0; i < 3; i++) {
> +		/* Clear AUX CH data buffer */
> +		reg = BUF_CLR;
> +		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
> +
> +		/* Select EDID device */
> +		retval = exynos_dp_select_i2c_device(dp, device_addr,
> reg_addr);
> +		if (retval != 0)
> +			continue;
> +
> +		/*
> +		 * Set I2C transaction and read data
> +		 * If bit 3 is 1, DisplayPort transaction.
> +		 * If Bit 3 is 0, I2C transaction.
> +		 */
> +		reg = AUX_TX_COMM_I2C_TRANSACTION |
> +			AUX_TX_COMM_READ;
> +		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
> +
> +		/* Start AUX transaction */
> +		retval = exynos_dp_start_aux_transaction(dp);
> +		if (retval == 0)
> +			break;
> +		else
> +			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
> +				__func__);
> +	}
> +
> +	/* Read data */
> +	if (retval == 0)
> +		*data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
> +
> +	return retval;
> +}
> +
> +int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
> +				unsigned int device_addr,
> +				unsigned int reg_addr,
> +				unsigned int count,
> +				unsigned char edid[])
> +{
> +	u32 reg;
> +	unsigned int i, j;
> +	unsigned int cur_data_idx;
> +	unsigned int defer = 0;
> +	int retval = 0;
> +
> +	for (i = 0; i < count; i += 16) {
> +		for (j = 0; j < 3; j++) {
> +			/* Clear AUX CH data buffer */
> +			reg = BUF_CLR;
> +			writel(reg, dp->reg_base +
EXYNOS_DP_BUFFER_DATA_CTL);
> +
> +			/* Set normal AUX CH command */
> +			reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> +			reg &= ~ADDR_ONLY;
> +			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> +
> +			/*
> +			 * If Rx sends defer, Tx sends only reads
> +			 * request without sending address
> +			 */
> +			if (!defer)
> +				retval = exynos_dp_select_i2c_device(dp,
> +						device_addr, reg_addr + i);
> +			else
> +				defer = 0;
> +
> +			if (retval == 0) {
> +				/*
> +				 * Set I2C transaction and write data
> +				 * If bit 3 is 1, DisplayPort transaction.
> +				 * If Bit 3 is 0, I2C transaction.
> +				 */
> +				reg = AUX_LENGTH(16) |
> +					AUX_TX_COMM_I2C_TRANSACTION |
> +					AUX_TX_COMM_READ;
> +				writel(reg, dp->reg_base +
> +					EXYNOS_DP_AUX_CH_CTL_1);
> +
> +				/* Start AUX transaction */
> +				retval =
exynos_dp_start_aux_transaction(dp);
> +				if (retval == 0)
> +					break;
> +				else
> +					dev_dbg(dp->dev,
> +						"%s: Aux Transaction
fail!\n",
> +						__func__);
> +			}
> +			/* Check if Rx sends defer */
> +			reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
> +			if (reg == AUX_RX_COMM_AUX_DEFER ||
> +				reg == AUX_RX_COMM_I2C_DEFER) {
> +				dev_err(dp->dev, "Defer: %d\n\n", reg);
> +				defer = 1;
> +			}
> +		}
> +
> +		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
> +			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
> +						 + 4 * cur_data_idx);
> +			edid[i + cur_data_idx] = (unsigned char)reg;
> +		}
> +	}
> +
> +	return retval;
> +}
> +
> +void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32
bwtype)
> +{
> +	u32 reg;
> +
> +	reg = bwtype;
> +	if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype ==
> LINK_RATE_1_62GBPS))
> +		writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
> +}
> +
> +void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32
> *bwtype)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
> +	*bwtype = reg;
> +}
> +
> +void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
> +{
> +	u32 reg;
> +
> +	reg = count;
> +	writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
> +}
> +
> +void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
> +	*count = reg;
> +}
> +
> +void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool
> enable)
> +{
> +	u32 reg;
> +
> +	if (enable) {
> +		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +		reg |= ENHANCED;
> +		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +	} else {
> +		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +		reg &= ~ENHANCED;
> +		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +	}
> +}
> +
> +void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
> +				 enum pattern_set pattern)
> +{
> +	u32 reg;
> +
> +	switch (pattern) {
> +	case PRBS7:
> +		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
> +		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +		break;
> +	case D10_2:
> +		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
> +		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +		break;
> +	case TRAINING_PTN1:
> +		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
> +		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +		break;
> +	case TRAINING_PTN2:
> +		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
> +		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +		break;
> +	case DP_NONE:
> +		reg = SCRAMBLING_ENABLE |
> +			LINK_QUAL_PATTERN_SET_DISABLE |
> +			SW_TRAINING_PATTERN_SET_NORMAL;
> +		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32
> level)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> +	reg &= ~PRE_EMPHASIS_SET_MASK;
> +	reg |= level << PRE_EMPHASIS_SET_SHIFT;
> +	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> +}
> +
> +void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32
> level)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> +	reg &= ~PRE_EMPHASIS_SET_MASK;
> +	reg |= level << PRE_EMPHASIS_SET_SHIFT;
> +	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> +}
> +
> +void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32
> level)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> +	reg &= ~PRE_EMPHASIS_SET_MASK;
> +	reg |= level << PRE_EMPHASIS_SET_SHIFT;
> +	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> +}
> +
> +void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32
> level)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> +	reg &= ~PRE_EMPHASIS_SET_MASK;
> +	reg |= level << PRE_EMPHASIS_SET_SHIFT;
> +	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> +}
> +
> +void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
> +					u32 training_lane)
> +{
> +	u32 reg;
> +
> +	reg = training_lane;
> +	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> +}
> +
> +void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
> +					u32 training_lane)
> +{
> +	u32 reg;
> +
> +	reg = training_lane;
> +	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> +}
> +
> +void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
> +					u32 training_lane)
> +{
> +	u32 reg;
> +
> +	reg = training_lane;
> +	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> +}
> +
> +void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
> +					u32 training_lane)
> +{
> +	u32 reg;
> +
> +	reg = training_lane;
> +	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> +}
> +
> +u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> +	return reg;
> +}
> +
> +u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> +	return reg;
> +}
> +
> +u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> +	return reg;
> +}
> +
> +u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> +	return reg;
> +}
> +
> +void exynos_dp_reset_macro(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
> +	reg |= MACRO_RST;
> +	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
> +
> +	/* 10 us is the minimum reset time. */
> +	usleep_range(10, 20);
> +
> +	reg &= ~MACRO_RST;
> +	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
> +}
> +
> +void exynos_dp_init_video(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
> +	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
> +
> +	reg = 0x0;
> +	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> +
> +	reg = CHA_CRI(4) | CHA_CTRL;
> +	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> +
> +	reg = 0x0;
> +	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> +
> +	reg = VID_HRES_TH(2) | VID_VRES_TH(0);
> +	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
> +}
> +
> +void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	/* Configure the input color depth, color space, dynamic range */
> +	reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
> +		(dp->video_info->color_depth << IN_BPC_SHIFT) |
> +		(dp->video_info->color_space << IN_COLOR_F_SHIFT);
> +	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
> +
> +	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
> +	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
> +	reg &= ~IN_YC_COEFFI_MASK;
> +	if (dp->video_info->ycbcr_coeff)
> +		reg |= IN_YC_COEFFI_ITU709;
> +	else
> +		reg |= IN_YC_COEFFI_ITU601;
> +	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
> +}
> +
> +int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> +	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> +
> +	if (!(reg & DET_STA)) {
> +		dev_dbg(dp->dev, "Input stream clock not detected.\n");
> +		return -EINVAL;
> +	}
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> +	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> +	dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
> +
> +	if (reg & CHA_STA) {
> +		dev_dbg(dp->dev, "Input stream clk is changing\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
> +		enum clock_recovery_m_value_type type,
> +		u32 m_value,
> +		u32 n_value)
> +{
> +	u32 reg;
> +
> +	if (type == REGISTER_M) {
> +		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +		reg |= FIX_M_VID;
> +		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +		reg = m_value & 0xff;
> +		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
> +		reg = (m_value >> 8) & 0xff;
> +		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
> +		reg = (m_value >> 16) & 0xff;
> +		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
> +
> +		reg = n_value & 0xff;
> +		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
> +		reg = (n_value >> 8) & 0xff;
> +		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
> +		reg = (n_value >> 16) & 0xff;
> +		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
> +	} else  {
> +		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +		reg &= ~FIX_M_VID;
> +		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +
> +		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
> +		writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
> +		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
> +	}
> +}
> +
> +void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32
> type)
> +{
> +	u32 reg;
> +
> +	if (type == VIDEO_TIMING_FROM_CAPTURE) {
> +		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +		reg &= ~FORMAT_SEL;
> +		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +	} else {
> +		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +		reg |= FORMAT_SEL;
> +		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +	}
> +}
> +
> +void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool
> enable)
> +{
> +	u32 reg;
> +
> +	if (enable) {
> +		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> +		reg &= ~VIDEO_MODE_MASK;
> +		reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
> +		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> +	} else {
> +		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> +		reg &= ~VIDEO_MODE_MASK;
> +		reg |= VIDEO_MODE_SLAVE_MODE;
> +		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> +	}
> +}
> +
> +void exynos_dp_start_video(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +	reg |= VIDEO_EN;
> +	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +}
> +
> +int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> +	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> +	if (!(reg & STRM_VALID)) {
> +		dev_dbg(dp->dev, "Input video stream is not detected.\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
> +	reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
> +	reg |= MASTER_VID_FUNC_EN_N;
> +	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +	reg &= ~INTERACE_SCAN_CFG;
> +	reg |= (dp->video_info->interlaced << 2);
> +	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +	reg &= ~VSYNC_POLARITY_CFG;
> +	reg |= (dp->video_info->v_sync_polarity << 1);
> +	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +	reg &= ~HSYNC_POLARITY_CFG;
> +	reg |= (dp->video_info->h_sync_polarity << 0);
> +	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +
> +	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
> +	writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> +}
> +
> +void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +	reg &= ~SCRAMBLING_DISABLE;
> +	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +}
> +
> +void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
> +{
> +	u32 reg;
> +
> +	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +	reg |= SCRAMBLING_DISABLE;
> +	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +}
> diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.h
> b/drivers/gpu/drm/exynos/exynos_dp_reg.h
> new file mode 100644
> index 0000000..2e9bd0e
> --- /dev/null
> +++ b/drivers/gpu/drm/exynos/exynos_dp_reg.h
> @@ -0,0 +1,366 @@
> +/*
> + * Register definition file for Samsung DP driver
> + *
> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> + * Author: Jingoo Han <jg1.han@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _EXYNOS_DP_REG_H
> +#define _EXYNOS_DP_REG_H
> +
> +#define EXYNOS_DP_TX_SW_RESET			0x14
> +#define EXYNOS_DP_FUNC_EN_1			0x18
> +#define EXYNOS_DP_FUNC_EN_2			0x1C
> +#define EXYNOS_DP_VIDEO_CTL_1			0x20
> +#define EXYNOS_DP_VIDEO_CTL_2			0x24
> +#define EXYNOS_DP_VIDEO_CTL_3			0x28
> +
> +#define EXYNOS_DP_VIDEO_CTL_8			0x3C
> +#define EXYNOS_DP_VIDEO_CTL_10			0x44
> +
> +#define EXYNOS_DP_LANE_MAP			0x35C
> +
> +#define EXYNOS_DP_ANALOG_CTL_1			0x370
> +#define EXYNOS_DP_ANALOG_CTL_2			0x374
> +#define EXYNOS_DP_ANALOG_CTL_3			0x378
> +#define EXYNOS_DP_PLL_FILTER_CTL_1		0x37C
> +#define EXYNOS_DP_TX_AMP_TUNING_CTL		0x380
> +
> +#define EXYNOS_DP_AUX_HW_RETRY_CTL		0x390
> +
> +#define EXYNOS_DP_COMMON_INT_STA_1		0x3C4
> +#define EXYNOS_DP_COMMON_INT_STA_2		0x3C8
> +#define EXYNOS_DP_COMMON_INT_STA_3		0x3CC
> +#define EXYNOS_DP_COMMON_INT_STA_4		0x3D0
> +#define EXYNOS_DP_INT_STA			0x3DC
> +#define EXYNOS_DP_COMMON_INT_MASK_1		0x3E0
> +#define EXYNOS_DP_COMMON_INT_MASK_2		0x3E4
> +#define EXYNOS_DP_COMMON_INT_MASK_3		0x3E8
> +#define EXYNOS_DP_COMMON_INT_MASK_4		0x3EC
> +#define EXYNOS_DP_INT_STA_MASK			0x3F8
> +#define EXYNOS_DP_INT_CTL			0x3FC
> +
> +#define EXYNOS_DP_SYS_CTL_1			0x600
> +#define EXYNOS_DP_SYS_CTL_2			0x604
> +#define EXYNOS_DP_SYS_CTL_3			0x608
> +#define EXYNOS_DP_SYS_CTL_4			0x60C
> +
> +#define EXYNOS_DP_PKT_SEND_CTL			0x640
> +#define EXYNOS_DP_HDCP_CTL			0x648
> +
> +#define EXYNOS_DP_LINK_BW_SET			0x680
> +#define EXYNOS_DP_LANE_COUNT_SET		0x684
> +#define EXYNOS_DP_TRAINING_PTN_SET		0x688
> +#define EXYNOS_DP_LN0_LINK_TRAINING_CTL		0x68C
> +#define EXYNOS_DP_LN1_LINK_TRAINING_CTL		0x690
> +#define EXYNOS_DP_LN2_LINK_TRAINING_CTL		0x694
> +#define EXYNOS_DP_LN3_LINK_TRAINING_CTL		0x698
> +
> +#define EXYNOS_DP_DEBUG_CTL			0x6C0
> +#define EXYNOS_DP_HPD_DEGLITCH_L		0x6C4
> +#define EXYNOS_DP_HPD_DEGLITCH_H		0x6C8
> +#define EXYNOS_DP_LINK_DEBUG_CTL		0x6E0
> +
> +#define EXYNOS_DP_M_VID_0			0x700
> +#define EXYNOS_DP_M_VID_1			0x704
> +#define EXYNOS_DP_M_VID_2			0x708
> +#define EXYNOS_DP_N_VID_0			0x70C
> +#define EXYNOS_DP_N_VID_1			0x710
> +#define EXYNOS_DP_N_VID_2			0x714
> +
> +#define EXYNOS_DP_PLL_CTL			0x71C
> +#define EXYNOS_DP_PHY_PD			0x720
> +#define EXYNOS_DP_PHY_TEST			0x724
> +
> +#define EXYNOS_DP_VIDEO_FIFO_THRD		0x730
> +#define EXYNOS_DP_AUDIO_MARGIN			0x73C
> +
> +#define EXYNOS_DP_M_VID_GEN_FILTER_TH		0x764
> +#define EXYNOS_DP_M_AUD_GEN_FILTER_TH		0x778
> +#define EXYNOS_DP_AUX_CH_STA			0x780
> +#define EXYNOS_DP_AUX_CH_DEFER_CTL		0x788
> +#define EXYNOS_DP_AUX_RX_COMM			0x78C
> +#define EXYNOS_DP_BUFFER_DATA_CTL		0x790
> +#define EXYNOS_DP_AUX_CH_CTL_1			0x794
> +#define EXYNOS_DP_AUX_ADDR_7_0			0x798
> +#define EXYNOS_DP_AUX_ADDR_15_8			0x79C
> +#define EXYNOS_DP_AUX_ADDR_19_16		0x7A0
> +#define EXYNOS_DP_AUX_CH_CTL_2			0x7A4
> +
> +#define EXYNOS_DP_BUF_DATA_0			0x7C0
> +
> +#define EXYNOS_DP_SOC_GENERAL_CTL		0x800
> +
> +/* EXYNOS_DP_TX_SW_RESET */
> +#define RESET_DP_TX				(0x1 << 0)
> +
> +/* EXYNOS_DP_FUNC_EN_1 */
> +#define MASTER_VID_FUNC_EN_N			(0x1 << 7)
> +#define SLAVE_VID_FUNC_EN_N			(0x1 << 5)
> +#define AUD_FIFO_FUNC_EN_N			(0x1 << 4)
> +#define AUD_FUNC_EN_N				(0x1 << 3)
> +#define HDCP_FUNC_EN_N				(0x1 << 2)
> +#define CRC_FUNC_EN_N				(0x1 << 1)
> +#define SW_FUNC_EN_N				(0x1 << 0)
> +
> +/* EXYNOS_DP_FUNC_EN_2 */
> +#define SSC_FUNC_EN_N				(0x1 << 7)
> +#define AUX_FUNC_EN_N				(0x1 << 2)
> +#define SERDES_FIFO_FUNC_EN_N			(0x1 << 1)
> +#define LS_CLK_DOMAIN_FUNC_EN_N			(0x1 << 0)
> +
> +/* EXYNOS_DP_VIDEO_CTL_1 */
> +#define VIDEO_EN				(0x1 << 7)
> +#define HDCP_VIDEO_MUTE				(0x1 << 6)
> +
> +/* EXYNOS_DP_VIDEO_CTL_1 */
> +#define IN_D_RANGE_MASK				(0x1 << 7)
> +#define IN_D_RANGE_SHIFT			(7)
> +#define IN_D_RANGE_CEA				(0x1 << 7)
> +#define IN_D_RANGE_VESA				(0x0 << 7)
> +#define IN_BPC_MASK				(0x7 << 4)
> +#define IN_BPC_SHIFT				(4)
> +#define IN_BPC_12_BITS				(0x3 << 4)
> +#define IN_BPC_10_BITS				(0x2 << 4)
> +#define IN_BPC_8_BITS				(0x1 << 4)
> +#define IN_BPC_6_BITS				(0x0 << 4)
> +#define IN_COLOR_F_MASK				(0x3 << 0)
> +#define IN_COLOR_F_SHIFT			(0)
> +#define IN_COLOR_F_YCBCR444			(0x2 << 0)
> +#define IN_COLOR_F_YCBCR422			(0x1 << 0)
> +#define IN_COLOR_F_RGB				(0x0 << 0)
> +
> +/* EXYNOS_DP_VIDEO_CTL_3 */
> +#define IN_YC_COEFFI_MASK			(0x1 << 7)
> +#define IN_YC_COEFFI_SHIFT			(7)
> +#define IN_YC_COEFFI_ITU709			(0x1 << 7)
> +#define IN_YC_COEFFI_ITU601			(0x0 << 7)
> +#define VID_CHK_UPDATE_TYPE_MASK		(0x1 << 4)
> +#define VID_CHK_UPDATE_TYPE_SHIFT		(4)
> +#define VID_CHK_UPDATE_TYPE_1			(0x1 << 4)
> +#define VID_CHK_UPDATE_TYPE_0			(0x0 << 4)
> +
> +/* EXYNOS_DP_VIDEO_CTL_8 */
> +#define VID_HRES_TH(x)				(((x) & 0xf) << 4)
> +#define VID_VRES_TH(x)				(((x) & 0xf) << 0)
> +
> +/* EXYNOS_DP_VIDEO_CTL_10 */
> +#define FORMAT_SEL				(0x1 << 4)
> +#define INTERACE_SCAN_CFG			(0x1 << 2)
> +#define VSYNC_POLARITY_CFG			(0x1 << 1)
> +#define HSYNC_POLARITY_CFG			(0x1 << 0)
> +
> +/* EXYNOS_DP_LANE_MAP */
> +#define LANE3_MAP_LOGIC_LANE_0			(0x0 << 6)
> +#define LANE3_MAP_LOGIC_LANE_1			(0x1 << 6)
> +#define LANE3_MAP_LOGIC_LANE_2			(0x2 << 6)
> +#define LANE3_MAP_LOGIC_LANE_3			(0x3 << 6)
> +#define LANE2_MAP_LOGIC_LANE_0			(0x0 << 4)
> +#define LANE2_MAP_LOGIC_LANE_1			(0x1 << 4)
> +#define LANE2_MAP_LOGIC_LANE_2			(0x2 << 4)
> +#define LANE2_MAP_LOGIC_LANE_3			(0x3 << 4)
> +#define LANE1_MAP_LOGIC_LANE_0			(0x0 << 2)
> +#define LANE1_MAP_LOGIC_LANE_1			(0x1 << 2)
> +#define LANE1_MAP_LOGIC_LANE_2			(0x2 << 2)
> +#define LANE1_MAP_LOGIC_LANE_3			(0x3 << 2)
> +#define LANE0_MAP_LOGIC_LANE_0			(0x0 << 0)
> +#define LANE0_MAP_LOGIC_LANE_1			(0x1 << 0)
> +#define LANE0_MAP_LOGIC_LANE_2			(0x2 << 0)
> +#define LANE0_MAP_LOGIC_LANE_3			(0x3 << 0)
> +
> +/* EXYNOS_DP_ANALOG_CTL_1 */
> +#define TX_TERMINAL_CTRL_50_OHM			(0x1 << 4)
> +
> +/* EXYNOS_DP_ANALOG_CTL_2 */
> +#define SEL_24M					(0x1 << 3)
> +#define TX_DVDD_BIT_1_0625V			(0x4 << 0)
> +
> +/* EXYNOS_DP_ANALOG_CTL_3 */
> +#define DRIVE_DVDD_BIT_1_0625V			(0x4 << 5)
> +#define VCO_BIT_600_MICRO			(0x5 << 0)
> +
> +/* EXYNOS_DP_PLL_FILTER_CTL_1 */
> +#define PD_RING_OSC				(0x1 << 6)
> +#define AUX_TERMINAL_CTRL_50_OHM		(0x2 << 4)
> +#define TX_CUR1_2X				(0x1 << 2)
> +#define TX_CUR_16_MA				(0x3 << 0)
> +
> +/* EXYNOS_DP_TX_AMP_TUNING_CTL */
> +#define CH3_AMP_400_MV				(0x0 << 24)
> +#define CH2_AMP_400_MV				(0x0 << 16)
> +#define CH1_AMP_400_MV				(0x0 << 8)
> +#define CH0_AMP_400_MV				(0x0 << 0)
> +
> +/* EXYNOS_DP_AUX_HW_RETRY_CTL */
> +#define AUX_BIT_PERIOD_EXPECTED_DELAY(x)	(((x) & 0x7) << 8)
> +#define AUX_HW_RETRY_INTERVAL_MASK		(0x3 << 3)
> +#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS	(0x0 << 3)
> +#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS	(0x1 << 3)
> +#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS	(0x2 << 3)
> +#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS	(0x3 << 3)
> +#define AUX_HW_RETRY_COUNT_SEL(x)		(((x) & 0x7) << 0)
> +
> +/* EXYNOS_DP_COMMON_INT_STA_1 */
> +#define VSYNC_DET				(0x1 << 7)
> +#define PLL_LOCK_CHG				(0x1 << 6)
> +#define SPDIF_ERR				(0x1 << 5)
> +#define SPDIF_UNSTBL				(0x1 << 4)
> +#define VID_FORMAT_CHG				(0x1 << 3)
> +#define AUD_CLK_CHG				(0x1 << 2)
> +#define VID_CLK_CHG				(0x1 << 1)
> +#define SW_INT					(0x1 << 0)
> +
> +/* EXYNOS_DP_COMMON_INT_STA_2 */
> +#define ENC_EN_CHG				(0x1 << 6)
> +#define HW_BKSV_RDY				(0x1 << 3)
> +#define HW_SHA_DONE				(0x1 << 2)
> +#define HW_AUTH_STATE_CHG			(0x1 << 1)
> +#define HW_AUTH_DONE				(0x1 << 0)
> +
> +/* EXYNOS_DP_COMMON_INT_STA_3 */
> +#define AFIFO_UNDER				(0x1 << 7)
> +#define AFIFO_OVER				(0x1 << 6)
> +#define R0_CHK_FLAG				(0x1 << 5)
> +
> +/* EXYNOS_DP_COMMON_INT_STA_4 */
> +#define PSR_ACTIVE				(0x1 << 7)
> +#define PSR_INACTIVE				(0x1 << 6)
> +#define SPDIF_BI_PHASE_ERR			(0x1 << 5)
> +#define HOTPLUG_CHG				(0x1 << 2)
> +#define HPD_LOST				(0x1 << 1)
> +#define PLUG					(0x1 << 0)
> +
> +/* EXYNOS_DP_INT_STA */
> +#define INT_HPD					(0x1 << 6)
> +#define HW_TRAINING_FINISH			(0x1 << 5)
> +#define RPLY_RECEIV				(0x1 << 1)
> +#define AUX_ERR					(0x1 << 0)
> +
> +/* EXYNOS_DP_INT_CTL */
> +#define SOFT_INT_CTRL				(0x1 << 2)
> +#define INT_POL1				(0x1 << 1)
> +#define INT_POL0				(0x1 << 0)
> +
> +/* EXYNOS_DP_SYS_CTL_1 */
> +#define DET_STA					(0x1 << 2)
> +#define FORCE_DET				(0x1 << 1)
> +#define DET_CTRL				(0x1 << 0)
> +
> +/* EXYNOS_DP_SYS_CTL_2 */
> +#define CHA_CRI(x)				(((x) & 0xf) << 4)
> +#define CHA_STA					(0x1 << 2)
> +#define FORCE_CHA				(0x1 << 1)
> +#define CHA_CTRL				(0x1 << 0)
> +
> +/* EXYNOS_DP_SYS_CTL_3 */
> +#define HPD_STATUS				(0x1 << 6)
> +#define F_HPD					(0x1 << 5)
> +#define HPD_CTRL				(0x1 << 4)
> +#define HDCP_RDY				(0x1 << 3)
> +#define STRM_VALID				(0x1 << 2)
> +#define F_VALID					(0x1 << 1)
> +#define VALID_CTRL				(0x1 << 0)
> +
> +/* EXYNOS_DP_SYS_CTL_4 */
> +#define FIX_M_AUD				(0x1 << 4)
> +#define ENHANCED				(0x1 << 3)
> +#define FIX_M_VID				(0x1 << 2)
> +#define M_VID_UPDATE_CTRL			(0x3 << 0)
> +
> +/* EXYNOS_DP_TRAINING_PTN_SET */
> +#define SCRAMBLER_TYPE				(0x1 << 9)
> +#define HW_LINK_TRAINING_PATTERN		(0x1 << 8)
> +#define SCRAMBLING_DISABLE			(0x1 << 5)
> +#define SCRAMBLING_ENABLE			(0x0 << 5)
> +#define LINK_QUAL_PATTERN_SET_MASK		(0x3 << 2)
> +#define LINK_QUAL_PATTERN_SET_PRBS7		(0x3 << 2)
> +#define LINK_QUAL_PATTERN_SET_D10_2		(0x1 << 2)
> +#define LINK_QUAL_PATTERN_SET_DISABLE		(0x0 << 2)
> +#define SW_TRAINING_PATTERN_SET_MASK		(0x3 << 0)
> +#define SW_TRAINING_PATTERN_SET_PTN2		(0x2 << 0)
> +#define SW_TRAINING_PATTERN_SET_PTN1		(0x1 << 0)
> +#define SW_TRAINING_PATTERN_SET_NORMAL		(0x0 << 0)
> +
> +/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
> +#define PRE_EMPHASIS_SET_MASK			(0x3 << 3)
> +#define PRE_EMPHASIS_SET_SHIFT			(3)
> +
> +/* EXYNOS_DP_DEBUG_CTL */
> +#define PLL_LOCK				(0x1 << 4)
> +#define F_PLL_LOCK				(0x1 << 3)
> +#define PLL_LOCK_CTRL				(0x1 << 2)
> +#define PN_INV					(0x1 << 0)
> +
> +/* EXYNOS_DP_PLL_CTL */
> +#define DP_PLL_PD				(0x1 << 7)
> +#define DP_PLL_RESET				(0x1 << 6)
> +#define DP_PLL_LOOP_BIT_DEFAULT			(0x1 << 4)
> +#define DP_PLL_REF_BIT_1_1250V			(0x5 << 0)
> +#define DP_PLL_REF_BIT_1_2500V			(0x7 << 0)
> +
> +/* EXYNOS_DP_PHY_PD */
> +#define DP_PHY_PD				(0x1 << 5)
> +#define AUX_PD					(0x1 << 4)
> +#define CH3_PD					(0x1 << 3)
> +#define CH2_PD					(0x1 << 2)
> +#define CH1_PD					(0x1 << 1)
> +#define CH0_PD					(0x1 << 0)
> +
> +/* EXYNOS_DP_PHY_TEST */
> +#define MACRO_RST				(0x1 << 5)
> +#define CH1_TEST				(0x1 << 1)
> +#define CH0_TEST				(0x1 << 0)
> +
> +/* EXYNOS_DP_AUX_CH_STA */
> +#define AUX_BUSY				(0x1 << 4)
> +#define AUX_STATUS_MASK				(0xf << 0)
> +
> +/* EXYNOS_DP_AUX_CH_DEFER_CTL */
> +#define DEFER_CTRL_EN				(0x1 << 7)
> +#define DEFER_COUNT(x)				(((x) & 0x7f) << 0)
> +
> +/* EXYNOS_DP_AUX_RX_COMM */
> +#define AUX_RX_COMM_I2C_DEFER			(0x2 << 2)
> +#define AUX_RX_COMM_AUX_DEFER			(0x2 << 0)
> +
> +/* EXYNOS_DP_BUFFER_DATA_CTL */
> +#define BUF_CLR					(0x1 << 7)
> +#define BUF_DATA_COUNT(x)			(((x) & 0x1f) << 0)
> +
> +/* EXYNOS_DP_AUX_CH_CTL_1 */
> +#define AUX_LENGTH(x)				(((x - 1) & 0xf) <<
4)
> +#define AUX_TX_COMM_MASK			(0xf << 0)
> +#define AUX_TX_COMM_DP_TRANSACTION		(0x1 << 3)
> +#define AUX_TX_COMM_I2C_TRANSACTION		(0x0 << 3)
> +#define AUX_TX_COMM_MOT				(0x1 << 2)
> +#define AUX_TX_COMM_WRITE			(0x0 << 0)
> +#define AUX_TX_COMM_READ			(0x1 << 0)
> +
> +/* EXYNOS_DP_AUX_ADDR_7_0 */
> +#define AUX_ADDR_7_0(x)				(((x) >> 0) & 0xff)
> +
> +/* EXYNOS_DP_AUX_ADDR_15_8 */
> +#define AUX_ADDR_15_8(x)			(((x) >> 8) & 0xff)
> +
> +/* EXYNOS_DP_AUX_ADDR_19_16 */
> +#define AUX_ADDR_19_16(x)			(((x) >> 16) & 0x0f)
> +
> +/* EXYNOS_DP_AUX_CH_CTL_2 */
> +#define ADDR_ONLY				(0x1 << 1)
> +#define AUX_EN					(0x1 << 0)
> +
> +/* EXYNOS_DP_SOC_GENERAL_CTL */
> +#define AUDIO_MODE_SPDIF_MODE			(0x1 << 8)
> +#define AUDIO_MODE_MASTER_MODE			(0x0 << 8)
> +#define MASTER_VIDEO_INTERLACE_EN		(0x1 << 4)
> +#define VIDEO_MASTER_CLK_SEL			(0x1 << 2)
> +#define VIDEO_MASTER_MODE_EN			(0x1 << 1)
> +#define VIDEO_MODE_MASK				(0x1 << 0)
> +#define VIDEO_MODE_SLAVE_MODE			(0x1 << 0)
> +#define VIDEO_MODE_MASTER_MODE			(0x0 << 0)
> +
> +#endif /* _EXYNOS_DP_REG_H */
> diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
> index 1b035b2..7032ad9 100644
> --- a/drivers/video/exynos/Kconfig
> +++ b/drivers/video/exynos/Kconfig
> @@ -27,11 +27,4 @@ config EXYNOS_LCD_S6E8AX0
>  	  If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
>  	  LCD control driver.
> 
> -config EXYNOS_DP
> -	bool "EXYNOS DP driver support"
> -	depends on ARCH_EXYNOS
> -	default n
> -	help
> -	  This enables support for DP device.
> -
>  endif # EXYNOS_VIDEO
> diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile
> index ec7772e..b5b1bd2 100644
> --- a/drivers/video/exynos/Makefile
> +++ b/drivers/video/exynos/Makefile
> @@ -5,4 +5,3 @@
>  obj-$(CONFIG_EXYNOS_MIPI_DSI)		+= exynos_mipi_dsi.o
> exynos_mipi_dsi_common.o \
>  				     	exynos_mipi_dsi_lowlevel.o
>  obj-$(CONFIG_EXYNOS_LCD_S6E8AX0)	+= s6e8ax0.o
> -obj-$(CONFIG_EXYNOS_DP)			+= exynos_dp_core.o
> exynos_dp_reg.o
> diff --git a/drivers/video/exynos/exynos_dp_core.c
> b/drivers/video/exynos/exynos_dp_core.c
> deleted file mode 100644
> index 089ae22..0000000
> --- a/drivers/video/exynos/exynos_dp_core.c
> +++ /dev/null
> @@ -1,1213 +0,0 @@
> -/*
> - * Samsung SoC DP (Display Port) interface driver.
> - *
> - * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> - * Author: Jingoo Han <jg1.han@samsung.com>
> - *
> - * 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/module.h>
> -#include <linux/platform_device.h>
> -#include <linux/err.h>
> -#include <linux/clk.h>
> -#include <linux/io.h>
> -#include <linux/interrupt.h>
> -#include <linux/delay.h>
> -#include <linux/of.h>
> -
> -#include <video/exynos_dp.h>
> -
> -#include "exynos_dp_core.h"
> -
> -static int exynos_dp_init_dp(struct exynos_dp_device *dp)
> -{
> -	exynos_dp_reset(dp);
> -
> -	exynos_dp_swreset(dp);
> -
> -	exynos_dp_init_analog_param(dp);
> -	exynos_dp_init_interrupt(dp);
> -
> -	/* SW defined function Normal operation */
> -	exynos_dp_enable_sw_function(dp);
> -
> -	exynos_dp_config_interrupt(dp);
> -	exynos_dp_init_analog_func(dp);
> -
> -	exynos_dp_init_hpd(dp);
> -	exynos_dp_init_aux(dp);
> -
> -	return 0;
> -}
> -
> -static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
> -{
> -	int timeout_loop = 0;
> -
> -	while (exynos_dp_get_plug_in_status(dp) != 0) {
> -		timeout_loop++;
> -		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> -			dev_err(dp->dev, "failed to get hpd plug status\n");
> -			return -ETIMEDOUT;
> -		}
> -		usleep_range(10, 11);
> -	}
> -
> -	return 0;
> -}
> -
> -static unsigned char exynos_dp_calc_edid_check_sum(unsigned char
> *edid_data)
> -{
> -	int i;
> -	unsigned char sum = 0;
> -
> -	for (i = 0; i < EDID_BLOCK_LENGTH; i++)
> -		sum = sum + edid_data[i];
> -
> -	return sum;
> -}
> -
> -static int exynos_dp_read_edid(struct exynos_dp_device *dp)
> -{
> -	unsigned char edid[EDID_BLOCK_LENGTH * 2];
> -	unsigned int extend_block = 0;
> -	unsigned char sum;
> -	unsigned char test_vector;
> -	int retval;
> -
> -	/*
> -	 * EDID device address is 0x50.
> -	 * However, if necessary, you must have set upper address
> -	 * into E-EDID in I2C device, 0x30.
> -	 */
> -
> -	/* Read Extension Flag, Number of 128-byte EDID extension blocks */
> -	retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
> -				EDID_EXTENSION_FLAG,
> -				&extend_block);
> -	if (retval)
> -		return retval;
> -
> -	if (extend_block > 0) {
> -		dev_dbg(dp->dev, "EDID data includes a single
extension!\n");
> -
> -		/* Read EDID data */
> -		retval = exynos_dp_read_bytes_from_i2c(dp,
> I2C_EDID_DEVICE_ADDR,
> -						EDID_HEADER_PATTERN,
> -						EDID_BLOCK_LENGTH,
> -						&edid[EDID_HEADER_PATTERN]);
> -		if (retval != 0) {
> -			dev_err(dp->dev, "EDID Read failed!\n");
> -			return -EIO;
> -		}
> -		sum = exynos_dp_calc_edid_check_sum(edid);
> -		if (sum != 0) {
> -			dev_err(dp->dev, "EDID bad checksum!\n");
> -			return -EIO;
> -		}
> -
> -		/* Read additional EDID data */
> -		retval = exynos_dp_read_bytes_from_i2c(dp,
> -				I2C_EDID_DEVICE_ADDR,
> -				EDID_BLOCK_LENGTH,
> -				EDID_BLOCK_LENGTH,
> -				&edid[EDID_BLOCK_LENGTH]);
> -		if (retval != 0) {
> -			dev_err(dp->dev, "EDID Read failed!\n");
> -			return -EIO;
> -		}
> -		sum =
> exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
> -		if (sum != 0) {
> -			dev_err(dp->dev, "EDID bad checksum!\n");
> -			return -EIO;
> -		}
> -
> -		exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
> -					&test_vector);
> -		if (test_vector & DPCD_TEST_EDID_READ) {
> -			exynos_dp_write_byte_to_dpcd(dp,
> -				DPCD_ADDR_TEST_EDID_CHECKSUM,
> -				edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
> -			exynos_dp_write_byte_to_dpcd(dp,
> -				DPCD_ADDR_TEST_RESPONSE,
> -				DPCD_TEST_EDID_CHECKSUM_WRITE);
> -		}
> -	} else {
> -		dev_info(dp->dev, "EDID data does not include any
> extensions.\n");
> -
> -		/* Read EDID data */
> -		retval = exynos_dp_read_bytes_from_i2c(dp,
> -				I2C_EDID_DEVICE_ADDR,
> -				EDID_HEADER_PATTERN,
> -				EDID_BLOCK_LENGTH,
> -				&edid[EDID_HEADER_PATTERN]);
> -		if (retval != 0) {
> -			dev_err(dp->dev, "EDID Read failed!\n");
> -			return -EIO;
> -		}
> -		sum = exynos_dp_calc_edid_check_sum(edid);
> -		if (sum != 0) {
> -			dev_err(dp->dev, "EDID bad checksum!\n");
> -			return -EIO;
> -		}
> -
> -		exynos_dp_read_byte_from_dpcd(dp,
> -			DPCD_ADDR_TEST_REQUEST,
> -			&test_vector);
> -		if (test_vector & DPCD_TEST_EDID_READ) {
> -			exynos_dp_write_byte_to_dpcd(dp,
> -				DPCD_ADDR_TEST_EDID_CHECKSUM,
> -				edid[EDID_CHECKSUM]);
> -			exynos_dp_write_byte_to_dpcd(dp,
> -				DPCD_ADDR_TEST_RESPONSE,
> -				DPCD_TEST_EDID_CHECKSUM_WRITE);
> -		}
> -	}
> -
> -	dev_err(dp->dev, "EDID Read success!\n");
> -	return 0;
> -}
> -
> -static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
> -{
> -	u8 buf[12];
> -	int i;
> -	int retval;
> -
> -	/* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
> -	retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
> -				12, buf);
> -	if (retval)
> -		return retval;
> -
> -	/* Read EDID */
> -	for (i = 0; i < 3; i++) {
> -		retval = exynos_dp_read_edid(dp);
> -		if (!retval)
> -			break;
> -	}
> -
> -	return retval;
> -}
> -
> -static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device
> *dp,
> -						bool enable)
> -{
> -	u8 data;
> -
> -	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
> -
> -	if (enable)
> -		exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
> -			DPCD_ENHANCED_FRAME_EN |
> -			DPCD_LANE_COUNT_SET(data));
> -	else
> -		exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
> -			DPCD_LANE_COUNT_SET(data));
> -}
> -
> -static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device
> *dp)
> -{
> -	u8 data;
> -	int retval;
> -
> -	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
> -	retval = DPCD_ENHANCED_FRAME_CAP(data);
> -
> -	return retval;
> -}
> -
> -static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
> -{
> -	u8 data;
> -
> -	data = exynos_dp_is_enhanced_mode_available(dp);
> -	exynos_dp_enable_rx_to_enhanced_mode(dp, data);
> -	exynos_dp_enable_enhanced_mode(dp, data);
> -}
> -
> -static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
> -{
> -	exynos_dp_set_training_pattern(dp, DP_NONE);
> -
> -	exynos_dp_write_byte_to_dpcd(dp,
> -		DPCD_ADDR_TRAINING_PATTERN_SET,
> -		DPCD_TRAINING_PATTERN_DISABLED);
> -}
> -
> -static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device
> *dp,
> -					int pre_emphasis, int lane)
> -{
> -	switch (lane) {
> -	case 0:
> -		exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
> -		break;
> -	case 1:
> -		exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
> -		break;
> -
> -	case 2:
> -		exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
> -		break;
> -
> -	case 3:
> -		exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
> -		break;
> -	}
> -}
> -
> -static int exynos_dp_link_start(struct exynos_dp_device *dp)
> -{
> -	u8 buf[4];
> -	int lane, lane_count, pll_tries, retval;
> -
> -	lane_count = dp->link_train.lane_count;
> -
> -	dp->link_train.lt_state = CLOCK_RECOVERY;
> -	dp->link_train.eq_loop = 0;
> -
> -	for (lane = 0; lane < lane_count; lane++)
> -		dp->link_train.cr_loop[lane] = 0;
> -
> -	/* Set link rate and count as you want to establish*/
> -	exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
> -	exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
> -
> -	/* Setup RX configuration */
> -	buf[0] = dp->link_train.link_rate;
> -	buf[1] = dp->link_train.lane_count;
> -	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
> -				2, buf);
> -	if (retval)
> -		return retval;
> -
> -	/* Set TX pre-emphasis to minimum */
> -	for (lane = 0; lane < lane_count; lane++)
> -		exynos_dp_set_lane_lane_pre_emphasis(dp,
> -			PRE_EMPHASIS_LEVEL_0, lane);
> -
> -	/* Wait for PLL lock */
> -	pll_tries = 0;
> -	while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
> -		if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
> -			dev_err(dp->dev, "Wait for PLL lock timed out\n");
> -			return -ETIMEDOUT;
> -		}
> -
> -		pll_tries++;
> -		usleep_range(90, 120);
> -	}
> -
> -	/* Set training pattern 1 */
> -	exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
> -
> -	/* Set RX training pattern */
> -	retval = exynos_dp_write_byte_to_dpcd(dp,
> -			DPCD_ADDR_TRAINING_PATTERN_SET,
> -			DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
> -	if (retval)
> -		return retval;
> -
> -	for (lane = 0; lane < lane_count; lane++)
> -		buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
> -			    DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
> -
> -	retval = exynos_dp_write_bytes_to_dpcd(dp,
> DPCD_ADDR_TRAINING_LANE0_SET,
> -			lane_count, buf);
> -
> -	return retval;
> -}
> -
> -static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int
> lane)
> -{
> -	int shift = (lane & 1) * 4;
> -	u8 link_value = link_status[lane>>1];
> -
> -	return (link_value >> shift) & 0xf;
> -}
> -
> -static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
> -{
> -	int lane;
> -	u8 lane_status;
> -
> -	for (lane = 0; lane < lane_count; lane++) {
> -		lane_status = exynos_dp_get_lane_status(link_status, lane);
> -		if ((lane_status & DPCD_LANE_CR_DONE) == 0)
> -			return -EINVAL;
> -	}
> -	return 0;
> -}
> -
> -static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
> -				int lane_count)
> -{
> -	int lane;
> -	u8 lane_status;
> -
> -	if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
> -		return -EINVAL;
> -
> -	for (lane = 0; lane < lane_count; lane++) {
> -		lane_status = exynos_dp_get_lane_status(link_status, lane);
> -		lane_status &= DPCD_CHANNEL_EQ_BITS;
> -		if (lane_status != DPCD_CHANNEL_EQ_BITS)
> -			return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
> -static unsigned char exynos_dp_get_adjust_request_voltage(u8
> adjust_request[2],
> -							int lane)
> -{
> -	int shift = (lane & 1) * 4;
> -	u8 link_value = adjust_request[lane>>1];
> -
> -	return (link_value >> shift) & 0x3;
> -}
> -
> -static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
> -					u8 adjust_request[2],
> -					int lane)
> -{
> -	int shift = (lane & 1) * 4;
> -	u8 link_value = adjust_request[lane>>1];
> -
> -	return ((link_value >> shift) & 0xc) >> 2;
> -}
> -
> -static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
> -					u8 training_lane_set, int lane)
> -{
> -	switch (lane) {
> -	case 0:
> -		exynos_dp_set_lane0_link_training(dp, training_lane_set);
> -		break;
> -	case 1:
> -		exynos_dp_set_lane1_link_training(dp, training_lane_set);
> -		break;
> -
> -	case 2:
> -		exynos_dp_set_lane2_link_training(dp, training_lane_set);
> -		break;
> -
> -	case 3:
> -		exynos_dp_set_lane3_link_training(dp, training_lane_set);
> -		break;
> -	}
> -}
> -
> -static unsigned int exynos_dp_get_lane_link_training(
> -				struct exynos_dp_device *dp,
> -				int lane)
> -{
> -	u32 reg;
> -
> -	switch (lane) {
> -	case 0:
> -		reg = exynos_dp_get_lane0_link_training(dp);
> -		break;
> -	case 1:
> -		reg = exynos_dp_get_lane1_link_training(dp);
> -		break;
> -	case 2:
> -		reg = exynos_dp_get_lane2_link_training(dp);
> -		break;
> -	case 3:
> -		reg = exynos_dp_get_lane3_link_training(dp);
> -		break;
> -	default:
> -		WARN_ON(1);
> -		return 0;
> -	}
> -
> -	return reg;
> -}
> -
> -static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
> -{
> -	exynos_dp_training_pattern_dis(dp);
> -	exynos_dp_set_enhanced_mode(dp);
> -
> -	dp->link_train.lt_state = FAILED;
> -}
> -
> -static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device
> *dp,
> -					u8 adjust_request[2])
> -{
> -	int lane, lane_count;
> -	u8 voltage_swing, pre_emphasis, training_lane;
> -
> -	lane_count = dp->link_train.lane_count;
> -	for (lane = 0; lane < lane_count; lane++) {
> -		voltage_swing = exynos_dp_get_adjust_request_voltage(
> -						adjust_request, lane);
> -		pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
> -						adjust_request, lane);
> -		training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
> -				DPCD_PRE_EMPHASIS_SET(pre_emphasis);
> -
> -		if (voltage_swing == VOLTAGE_LEVEL_3)
> -			training_lane |= DPCD_MAX_SWING_REACHED;
> -		if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
> -			training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
> -
> -		dp->link_train.training_lane[lane] = training_lane;
> -	}
> -}
> -
> -static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
> -{
> -	int lane, lane_count, retval;
> -	u8 voltage_swing, pre_emphasis, training_lane;
> -	u8 link_status[2], adjust_request[2];
> -
> -	usleep_range(100, 101);
> -
> -	lane_count = dp->link_train.lane_count;
> -
> -	retval =  exynos_dp_read_bytes_from_dpcd(dp,
> -			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
> -	if (retval)
> -		return retval;
> -
> -	retval =  exynos_dp_read_bytes_from_dpcd(dp,
> -			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2,
adjust_request);
> -	if (retval)
> -		return retval;
> -
> -	if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
> -		/* set training pattern 2 for EQ */
> -		exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
> -
> -		retval = exynos_dp_write_byte_to_dpcd(dp,
> -				DPCD_ADDR_TRAINING_PATTERN_SET,
> -				DPCD_SCRAMBLING_DISABLED |
> -				DPCD_TRAINING_PATTERN_2);
> -		if (retval)
> -			return retval;
> -
> -		dev_info(dp->dev, "Link Training Clock Recovery success\n");
> -		dp->link_train.lt_state = EQUALIZER_TRAINING;
> -	} else {
> -		for (lane = 0; lane < lane_count; lane++) {
> -			training_lane = exynos_dp_get_lane_link_training(
> -							dp, lane);
> -			voltage_swing =
exynos_dp_get_adjust_request_voltage(
> -							adjust_request,
lane);
> -			pre_emphasis =
> exynos_dp_get_adjust_request_pre_emphasis(
> -							adjust_request,
lane);
> -
> -			if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
> -					voltage_swing &&
> -			    DPCD_PRE_EMPHASIS_GET(training_lane) ==
> -					pre_emphasis)
> -				dp->link_train.cr_loop[lane]++;
> -
> -			if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
> -			    voltage_swing == VOLTAGE_LEVEL_3 ||
> -			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
> -				dev_err(dp->dev, "CR Max reached
(%d,%d,%d)\n",
> -					dp->link_train.cr_loop[lane],
> -					voltage_swing, pre_emphasis);
> -				exynos_dp_reduce_link_rate(dp);
> -				return -EIO;
> -			}
> -		}
> -	}
> -
> -	exynos_dp_get_adjust_training_lane(dp, adjust_request);
> -
> -	for (lane = 0; lane < lane_count; lane++)
> -		exynos_dp_set_lane_link_training(dp,
> -			dp->link_train.training_lane[lane], lane);
> -
> -	retval = exynos_dp_write_bytes_to_dpcd(dp,
> -			DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
> -			dp->link_train.training_lane);
> -	if (retval)
> -		return retval;
> -
> -	return retval;
> -}
> -
> -static int exynos_dp_process_equalizer_training(struct exynos_dp_device
> *dp)
> -{
> -	int lane, lane_count, retval;
> -	u32 reg;
> -	u8 link_align, link_status[2], adjust_request[2];
> -
> -	usleep_range(400, 401);
> -
> -	lane_count = dp->link_train.lane_count;
> -
> -	retval = exynos_dp_read_bytes_from_dpcd(dp,
> -			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
> -	if (retval)
> -		return retval;
> -
> -	if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
> -		exynos_dp_reduce_link_rate(dp);
> -		return -EIO;
> -	}
> -
> -	retval = exynos_dp_read_bytes_from_dpcd(dp,
> -			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2,
adjust_request);
> -	if (retval)
> -		return retval;
> -
> -	retval = exynos_dp_read_byte_from_dpcd(dp,
> -			DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
> -	if (retval)
> -		return retval;
> -
> -	exynos_dp_get_adjust_training_lane(dp, adjust_request);
> -
> -	if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count))
> {
> -		/* traing pattern Set to Normal */
> -		exynos_dp_training_pattern_dis(dp);
> -
> -		dev_info(dp->dev, "Link Training success!\n");
> -
> -		exynos_dp_get_link_bandwidth(dp, &reg);
> -		dp->link_train.link_rate = reg;
> -		dev_dbg(dp->dev, "final bandwidth = %.2x\n",
> -			dp->link_train.link_rate);
> -
> -		exynos_dp_get_lane_count(dp, &reg);
> -		dp->link_train.lane_count = reg;
> -		dev_dbg(dp->dev, "final lane count = %.2x\n",
> -			dp->link_train.lane_count);
> -
> -		/* set enhanced mode if available */
> -		exynos_dp_set_enhanced_mode(dp);
> -		dp->link_train.lt_state = FINISHED;
> -
> -		return 0;
> -	}
> -
> -	/* not all locked */
> -	dp->link_train.eq_loop++;
> -
> -	if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
> -		dev_err(dp->dev, "EQ Max loop\n");
> -		exynos_dp_reduce_link_rate(dp);
> -		return -EIO;
> -	}
> -
> -	for (lane = 0; lane < lane_count; lane++)
> -		exynos_dp_set_lane_link_training(dp,
> -			dp->link_train.training_lane[lane], lane);
> -
> -	retval = exynos_dp_write_bytes_to_dpcd(dp,
> DPCD_ADDR_TRAINING_LANE0_SET,
> -			lane_count, dp->link_train.training_lane);
> -
> -	return retval;
> -}
> -
> -static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
> -					u8 *bandwidth)
> -{
> -	u8 data;
> -
> -	/*
> -	 * For DP rev.1.1, Maximum link rate of Main Link lanes
> -	 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
> -	 */
> -	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
> -	*bandwidth = data;
> -}
> -
> -static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
> -					u8 *lane_count)
> -{
> -	u8 data;
> -
> -	/*
> -	 * For DP rev.1.1, Maximum number of Main Link lanes
> -	 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
> -	 */
> -	exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
> -	*lane_count = DPCD_MAX_LANE_COUNT(data);
> -}
> -
> -static void exynos_dp_init_training(struct exynos_dp_device *dp,
> -			enum link_lane_count_type max_lane,
> -			enum link_rate_type max_rate)
> -{
> -	/*
> -	 * MACRO_RST must be applied after the PLL_LOCK to avoid
> -	 * the DP inter pair skew issue for at least 10 us
> -	 */
> -	exynos_dp_reset_macro(dp);
> -
> -	/* Initialize by reading RX's DPCD */
> -	exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
> -	exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
> -
> -	if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
> -	   (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
> -		dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
> -			dp->link_train.link_rate);
> -		dp->link_train.link_rate = LINK_RATE_1_62GBPS;
> -	}
> -
> -	if (dp->link_train.lane_count == 0) {
> -		dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
> -			dp->link_train.lane_count);
> -		dp->link_train.lane_count = (u8)LANE_COUNT1;
> -	}
> -
> -	/* Setup TX lane count & rate */
> -	if (dp->link_train.lane_count > max_lane)
> -		dp->link_train.lane_count = max_lane;
> -	if (dp->link_train.link_rate > max_rate)
> -		dp->link_train.link_rate = max_rate;
> -
> -	/* All DP analog module power up */
> -	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
> -}
> -
> -static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
> -{
> -	int retval = 0, training_finished = 0;
> -
> -	dp->link_train.lt_state = START;
> -
> -	/* Process here */
> -	while (!retval && !training_finished) {
> -		switch (dp->link_train.lt_state) {
> -		case START:
> -			retval = exynos_dp_link_start(dp);
> -			if (retval)
> -				dev_err(dp->dev, "LT link start failed!\n");
> -			break;
> -		case CLOCK_RECOVERY:
> -			retval = exynos_dp_process_clock_recovery(dp);
> -			if (retval)
> -				dev_err(dp->dev, "LT CR failed!\n");
> -			break;
> -		case EQUALIZER_TRAINING:
> -			retval = exynos_dp_process_equalizer_training(dp);
> -			if (retval)
> -				dev_err(dp->dev, "LT EQ failed!\n");
> -			break;
> -		case FINISHED:
> -			training_finished = 1;
> -			break;
> -		case FAILED:
> -			return -EREMOTEIO;
> -		}
> -	}
> -	if (retval)
> -		dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
> -
> -	return retval;
> -}
> -
> -static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
> -				u32 count,
> -				u32 bwtype)
> -{
> -	int i;
> -	int retval;
> -
> -	for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
> -		exynos_dp_init_training(dp, count, bwtype);
> -		retval = exynos_dp_sw_link_training(dp);
> -		if (retval == 0)
> -			break;
> -
> -		usleep_range(100, 110);
> -	}
> -
> -	return retval;
> -}
> -
> -static int exynos_dp_config_video(struct exynos_dp_device *dp)
> -{
> -	int retval = 0;
> -	int timeout_loop = 0;
> -	int done_count = 0;
> -
> -	exynos_dp_config_video_slave_mode(dp);
> -
> -	exynos_dp_set_video_color_format(dp);
> -
> -	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
> -		dev_err(dp->dev, "PLL is not locked yet.\n");
> -		return -EINVAL;
> -	}
> -
> -	for (;;) {
> -		timeout_loop++;
> -		if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
> -			break;
> -		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> -			dev_err(dp->dev, "Timeout of video streamclk ok\n");
> -			return -ETIMEDOUT;
> -		}
> -
> -		usleep_range(1, 2);
> -	}
> -
> -	/* Set to use the register calculated M/N video */
> -	exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
> -
> -	/* For video bist, Video timing must be generated by register */
> -	exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
> -
> -	/* Disable video mute */
> -	exynos_dp_enable_video_mute(dp, 0);
> -
> -	/* Configure video slave mode */
> -	exynos_dp_enable_video_master(dp, 0);
> -
> -	/* Enable video */
> -	exynos_dp_start_video(dp);
> -
> -	timeout_loop = 0;
> -
> -	for (;;) {
> -		timeout_loop++;
> -		if (exynos_dp_is_video_stream_on(dp) == 0) {
> -			done_count++;
> -			if (done_count > 10)
> -				break;
> -		} else if (done_count) {
> -			done_count = 0;
> -		}
> -		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> -			dev_err(dp->dev, "Timeout of video streamclk ok\n");
> -			return -ETIMEDOUT;
> -		}
> -
> -		usleep_range(1000, 1001);
> -	}
> -
> -	if (retval != 0)
> -		dev_err(dp->dev, "Video stream is not detected!\n");
> -
> -	return retval;
> -}
> -
> -static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool
> enable)
> -{
> -	u8 data;
> -
> -	if (enable) {
> -		exynos_dp_enable_scrambling(dp);
> -
> -		exynos_dp_read_byte_from_dpcd(dp,
> -			DPCD_ADDR_TRAINING_PATTERN_SET,
> -			&data);
> -		exynos_dp_write_byte_to_dpcd(dp,
> -			DPCD_ADDR_TRAINING_PATTERN_SET,
> -			(u8)(data & ~DPCD_SCRAMBLING_DISABLED));
> -	} else {
> -		exynos_dp_disable_scrambling(dp);
> -
> -		exynos_dp_read_byte_from_dpcd(dp,
> -			DPCD_ADDR_TRAINING_PATTERN_SET,
> -			&data);
> -		exynos_dp_write_byte_to_dpcd(dp,
> -			DPCD_ADDR_TRAINING_PATTERN_SET,
> -			(u8)(data | DPCD_SCRAMBLING_DISABLED));
> -	}
> -}
> -
> -static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
> -{
> -	struct exynos_dp_device *dp = arg;
> -
> -	enum dp_irq_type irq_type;
> -
> -	irq_type = exynos_dp_get_irq_type(dp);
> -	switch (irq_type) {
> -	case DP_IRQ_TYPE_HP_CABLE_IN:
> -		dev_dbg(dp->dev, "Received irq - cable in\n");
> -		schedule_work(&dp->hotplug_work);
> -		exynos_dp_clear_hotplug_interrupts(dp);
> -		break;
> -	case DP_IRQ_TYPE_HP_CABLE_OUT:
> -		dev_dbg(dp->dev, "Received irq - cable out\n");
> -		exynos_dp_clear_hotplug_interrupts(dp);
> -		break;
> -	case DP_IRQ_TYPE_HP_CHANGE:
> -		/*
> -		 * We get these change notifications once in a while, but
> there
> -		 * is nothing we can do with them. Just ignore it for now
and
> -		 * only handle cable changes.
> -		 */
> -		dev_dbg(dp->dev, "Received irq - hotplug change;
> ignoring.\n");
> -		exynos_dp_clear_hotplug_interrupts(dp);
> -		break;
> -	default:
> -		dev_err(dp->dev, "Received irq - unknown type!\n");
> -		break;
> -	}
> -	return IRQ_HANDLED;
> -}
> -
> -static void exynos_dp_hotplug(struct work_struct *work)
> -{
> -	struct exynos_dp_device *dp;
> -	int ret;
> -
> -	dp = container_of(work, struct exynos_dp_device, hotplug_work);
> -
> -	ret = exynos_dp_detect_hpd(dp);
> -	if (ret) {
> -		/* Cable has been disconnected, we're done */
> -		return;
> -	}
> -
> -	ret = exynos_dp_handle_edid(dp);
> -	if (ret) {
> -		dev_err(dp->dev, "unable to handle edid\n");
> -		return;
> -	}
> -
> -	ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
> -					dp->video_info->link_rate);
> -	if (ret) {
> -		dev_err(dp->dev, "unable to do link train\n");
> -		return;
> -	}
> -
> -	exynos_dp_enable_scramble(dp, 1);
> -	exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
> -	exynos_dp_enable_enhanced_mode(dp, 1);
> -
> -	exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
> -	exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
> -
> -	exynos_dp_init_video(dp);
> -	ret = exynos_dp_config_video(dp);
> -	if (ret)
> -		dev_err(dp->dev, "unable to config video\n");
> -}
> -
> -#ifdef CONFIG_OF
> -static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device
> *dev)
> -{
> -	struct device_node *dp_node = dev->of_node;
> -	struct exynos_dp_platdata *pd;
> -	struct video_info *dp_video_config;
> -
> -	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
> -	if (!pd) {
> -		dev_err(dev, "memory allocation for pdata failed\n");
> -		return ERR_PTR(-ENOMEM);
> -	}
> -	dp_video_config = devm_kzalloc(dev,
> -				sizeof(*dp_video_config), GFP_KERNEL);
> -
> -	if (!dp_video_config) {
> -		dev_err(dev, "memory allocation for video config failed\n");
> -		return ERR_PTR(-ENOMEM);
> -	}
> -	pd->video_info = dp_video_config;
> -
> -	dp_video_config->h_sync_polarity =
> -		of_property_read_bool(dp_node, "hsync-active-high");
> -
> -	dp_video_config->v_sync_polarity =
> -		of_property_read_bool(dp_node, "vsync-active-high");
> -
> -	dp_video_config->interlaced =
> -		of_property_read_bool(dp_node, "interlaced");
> -
> -	if (of_property_read_u32(dp_node, "samsung,color-space",
> -				&dp_video_config->color_space)) {
> -		dev_err(dev, "failed to get color-space\n");
> -		return ERR_PTR(-EINVAL);
> -	}
> -
> -	if (of_property_read_u32(dp_node, "samsung,dynamic-range",
> -				&dp_video_config->dynamic_range)) {
> -		dev_err(dev, "failed to get dynamic-range\n");
> -		return ERR_PTR(-EINVAL);
> -	}
> -
> -	if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
> -				&dp_video_config->ycbcr_coeff)) {
> -		dev_err(dev, "failed to get ycbcr-coeff\n");
> -		return ERR_PTR(-EINVAL);
> -	}
> -
> -	if (of_property_read_u32(dp_node, "samsung,color-depth",
> -				&dp_video_config->color_depth)) {
> -		dev_err(dev, "failed to get color-depth\n");
> -		return ERR_PTR(-EINVAL);
> -	}
> -
> -	if (of_property_read_u32(dp_node, "samsung,link-rate",
> -				&dp_video_config->link_rate)) {
> -		dev_err(dev, "failed to get link-rate\n");
> -		return ERR_PTR(-EINVAL);
> -	}
> -
> -	if (of_property_read_u32(dp_node, "samsung,lane-count",
> -				&dp_video_config->lane_count)) {
> -		dev_err(dev, "failed to get lane-count\n");
> -		return ERR_PTR(-EINVAL);
> -	}
> -
> -	return pd;
> -}
> -
> -static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
> -{
> -	struct device_node *dp_phy_node = of_node_get(dp->dev->of_node);
> -	u32 phy_base;
> -	int ret = 0;
> -
> -	dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
> -	if (!dp_phy_node) {
> -		dev_err(dp->dev, "could not find dptx-phy node\n");
> -		return -ENODEV;
> -	}
> -
> -	if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
> -		dev_err(dp->dev, "failed to get reg for dptx-phy\n");
> -		ret = -EINVAL;
> -		goto err;
> -	}
> -
> -	if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
> -				&dp->enable_mask)) {
> -		dev_err(dp->dev, "failed to get enable-mask for
dptx-phy\n");
> -		ret = -EINVAL;
> -		goto err;
> -	}
> -
> -	dp->phy_addr = ioremap(phy_base, SZ_4);
> -	if (!dp->phy_addr) {
> -		dev_err(dp->dev, "failed to ioremap dp-phy\n");
> -		ret = -ENOMEM;
> -		goto err;
> -	}
> -
> -err:
> -	of_node_put(dp_phy_node);
> -
> -	return ret;
> -}
> -
> -static void exynos_dp_phy_init(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = __raw_readl(dp->phy_addr);
> -	reg |= dp->enable_mask;
> -	__raw_writel(reg, dp->phy_addr);
> -}
> -
> -static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = __raw_readl(dp->phy_addr);
> -	reg &= ~(dp->enable_mask);
> -	__raw_writel(reg, dp->phy_addr);
> -}
> -#else
> -static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device
> *dev)
> -{
> -	return NULL;
> -}
> -
> -static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
> -{
> -	return -EINVAL;
> -}
> -
> -static void exynos_dp_phy_init(struct exynos_dp_device *dp)
> -{
> -	return;
> -}
> -
> -static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
> -{
> -	return;
> -}
> -#endif /* CONFIG_OF */
> -
> -static int exynos_dp_probe(struct platform_device *pdev)
> -{
> -	struct resource *res;
> -	struct exynos_dp_device *dp;
> -	struct exynos_dp_platdata *pdata;
> -
> -	int ret = 0;
> -
> -	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
> -				GFP_KERNEL);
> -	if (!dp) {
> -		dev_err(&pdev->dev, "no memory for device data\n");
> -		return -ENOMEM;
> -	}
> -
> -	dp->dev = &pdev->dev;
> -
> -	if (pdev->dev.of_node) {
> -		pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
> -		if (IS_ERR(pdata))
> -			return PTR_ERR(pdata);
> -
> -		ret = exynos_dp_dt_parse_phydata(dp);
> -		if (ret)
> -			return ret;
> -	} else {
> -		pdata = pdev->dev.platform_data;
> -		if (!pdata) {
> -			dev_err(&pdev->dev, "no platform data\n");
> -			return -EINVAL;
> -		}
> -	}
> -
> -	dp->clock = devm_clk_get(&pdev->dev, "dp");
> -	if (IS_ERR(dp->clock)) {
> -		dev_err(&pdev->dev, "failed to get clock\n");
> -		return PTR_ERR(dp->clock);
> -	}
> -
> -	clk_prepare_enable(dp->clock);
> -
> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -
> -	dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
> -	if (IS_ERR(dp->reg_base))
> -		return PTR_ERR(dp->reg_base);
> -
> -	dp->irq = platform_get_irq(pdev, 0);
> -	if (dp->irq == -ENXIO) {
> -		dev_err(&pdev->dev, "failed to get irq\n");
> -		return -ENODEV;
> -	}
> -
> -	INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
> -
> -	dp->video_info = pdata->video_info;
> -
> -	if (pdev->dev.of_node) {
> -		if (dp->phy_addr)
> -			exynos_dp_phy_init(dp);
> -	} else {
> -		if (pdata->phy_init)
> -			pdata->phy_init();
> -	}
> -
> -	exynos_dp_init_dp(dp);
> -
> -	ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler,
> 0,
> -				"exynos-dp", dp);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to request irq\n");
> -		return ret;
> -	}
> -
> -	platform_set_drvdata(pdev, dp);
> -
> -	return 0;
> -}
> -
> -static int exynos_dp_remove(struct platform_device *pdev)
> -{
> -	struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> -	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
> -
> -	flush_work(&dp->hotplug_work);
> -
> -	if (pdev->dev.of_node) {
> -		if (dp->phy_addr)
> -			exynos_dp_phy_exit(dp);
> -	} else {
> -		if (pdata->phy_exit)
> -			pdata->phy_exit();
> -	}
> -
> -	clk_disable_unprepare(dp->clock);
> -
> -
> -	return 0;
> -}
> -
> -#ifdef CONFIG_PM_SLEEP
> -static int exynos_dp_suspend(struct device *dev)
> -{
> -	struct exynos_dp_platdata *pdata = dev->platform_data;
> -	struct exynos_dp_device *dp = dev_get_drvdata(dev);
> -
> -	disable_irq(dp->irq);
> -
> -	flush_work(&dp->hotplug_work);
> -
> -	if (dev->of_node) {
> -		if (dp->phy_addr)
> -			exynos_dp_phy_exit(dp);
> -	} else {
> -		if (pdata->phy_exit)
> -			pdata->phy_exit();
> -	}
> -
> -	clk_disable_unprepare(dp->clock);
> -
> -	return 0;
> -}
> -
> -static int exynos_dp_resume(struct device *dev)
> -{
> -	struct exynos_dp_platdata *pdata = dev->platform_data;
> -	struct exynos_dp_device *dp = dev_get_drvdata(dev);
> -
> -	if (dev->of_node) {
> -		if (dp->phy_addr)
> -			exynos_dp_phy_init(dp);
> -	} else {
> -		if (pdata->phy_init)
> -			pdata->phy_init();
> -	}
> -
> -	clk_prepare_enable(dp->clock);
> -
> -	exynos_dp_init_dp(dp);
> -
> -	enable_irq(dp->irq);
> -
> -	return 0;
> -}
> -#endif
> -
> -static const struct dev_pm_ops exynos_dp_pm_ops = {
> -	SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
> -};
> -
> -static const struct of_device_id exynos_dp_match[] = {
> -	{ .compatible = "samsung,exynos5-dp" },
> -	{},
> -};
> -MODULE_DEVICE_TABLE(of, exynos_dp_match);
> -
> -static struct platform_driver exynos_dp_driver = {
> -	.probe		= exynos_dp_probe,
> -	.remove		= exynos_dp_remove,
> -	.driver		= {
> -		.name	= "exynos-dp",
> -		.owner	= THIS_MODULE,
> -		.pm	= &exynos_dp_pm_ops,
> -		.of_match_table = of_match_ptr(exynos_dp_match),
> -	},
> -};
> -
> -module_platform_driver(exynos_dp_driver);
> -
> -MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
> -MODULE_DESCRIPTION("Samsung SoC DP Driver");
> -MODULE_LICENSE("GPL");
> diff --git a/drivers/video/exynos/exynos_dp_core.h
> b/drivers/video/exynos/exynos_dp_core.h
> deleted file mode 100644
> index 6c567bbf..0000000
> --- a/drivers/video/exynos/exynos_dp_core.h
> +++ /dev/null
> @@ -1,210 +0,0 @@
> -/*
> - * Header file for Samsung DP (Display Port) interface driver.
> - *
> - * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> - * Author: Jingoo Han <jg1.han@samsung.com>
> - *
> - * 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 _EXYNOS_DP_CORE_H
> -#define _EXYNOS_DP_CORE_H
> -
> -enum dp_irq_type {
> -	DP_IRQ_TYPE_HP_CABLE_IN,
> -	DP_IRQ_TYPE_HP_CABLE_OUT,
> -	DP_IRQ_TYPE_HP_CHANGE,
> -	DP_IRQ_TYPE_UNKNOWN,
> -};
> -
> -struct link_train {
> -	int eq_loop;
> -	int cr_loop[4];
> -
> -	u8 link_rate;
> -	u8 lane_count;
> -	u8 training_lane[4];
> -
> -	enum link_training_state lt_state;
> -};
> -
> -struct exynos_dp_device {
> -	struct device		*dev;
> -	struct clk		*clock;
> -	unsigned int		irq;
> -	void __iomem		*reg_base;
> -	void __iomem		*phy_addr;
> -	unsigned int		enable_mask;
> -
> -	struct video_info	*video_info;
> -	struct link_train	link_train;
> -	struct work_struct	hotplug_work;
> -};
> -
> -/* exynos_dp_reg.c */
> -void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool
> enable);
> -void exynos_dp_stop_video(struct exynos_dp_device *dp);
> -void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
> -void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
> -void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
> -void exynos_dp_reset(struct exynos_dp_device *dp);
> -void exynos_dp_swreset(struct exynos_dp_device *dp);
> -void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
> -enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device
> *dp);
> -void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool
> enable);
> -void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
> -				enum analog_power_block block,
> -				bool enable);
> -void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
> -void exynos_dp_init_hpd(struct exynos_dp_device *dp);
> -enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
> -void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
> -void exynos_dp_reset_aux(struct exynos_dp_device *dp);
> -void exynos_dp_init_aux(struct exynos_dp_device *dp);
> -int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
> -void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
> -int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
> -int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
> -				unsigned int reg_addr,
> -				unsigned char data);
> -int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
> -				unsigned int reg_addr,
> -				unsigned char *data);
> -int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
> -				unsigned int reg_addr,
> -				unsigned int count,
> -				unsigned char data[]);
> -int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
> -				unsigned int reg_addr,
> -				unsigned int count,
> -				unsigned char data[]);
> -int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
> -				unsigned int device_addr,
> -				unsigned int reg_addr);
> -int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
> -				unsigned int device_addr,
> -				unsigned int reg_addr,
> -				unsigned int *data);
> -int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
> -				unsigned int device_addr,
> -				unsigned int reg_addr,
> -				unsigned int count,
> -				unsigned char edid[]);
> -void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32
> bwtype);
> -void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32
> *bwtype);
> -void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
> -void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
> -void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool
> enable);
> -void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
> -				 enum pattern_set pattern);
> -void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32
> level);
> -void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32
> level);
> -void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32
> level);
> -void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32
> level);
> -void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
> -				u32 training_lane);
> -void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
> -				u32 training_lane);
> -void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
> -				u32 training_lane);
> -void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
> -				u32 training_lane);
> -u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
> -u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
> -u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
> -u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
> -void exynos_dp_reset_macro(struct exynos_dp_device *dp);
> -void exynos_dp_init_video(struct exynos_dp_device *dp);
> -
> -void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
> -int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device
*dp);
> -void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
> -			enum clock_recovery_m_value_type type,
> -			u32 m_value,
> -			u32 n_value);
> -void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32
> type);
> -void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool
> enable);
> -void exynos_dp_start_video(struct exynos_dp_device *dp);
> -int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
> -void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
> -void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
> -void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
> -
> -/* I2C EDID Chip ID, Slave Address */
> -#define I2C_EDID_DEVICE_ADDR			0x50
> -#define I2C_E_EDID_DEVICE_ADDR			0x30
> -
> -#define EDID_BLOCK_LENGTH			0x80
> -#define EDID_HEADER_PATTERN			0x00
> -#define EDID_EXTENSION_FLAG			0x7e
> -#define EDID_CHECKSUM				0x7f
> -
> -/* Definition for DPCD Register */
> -#define DPCD_ADDR_DPCD_REV			0x0000
> -#define DPCD_ADDR_MAX_LINK_RATE			0x0001
> -#define DPCD_ADDR_MAX_LANE_COUNT		0x0002
> -#define DPCD_ADDR_LINK_BW_SET			0x0100
> -#define DPCD_ADDR_LANE_COUNT_SET		0x0101
> -#define DPCD_ADDR_TRAINING_PATTERN_SET		0x0102
> -#define DPCD_ADDR_TRAINING_LANE0_SET		0x0103
> -#define DPCD_ADDR_LANE0_1_STATUS		0x0202
> -#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED	0x0204
> -#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1	0x0206
> -#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3	0x0207
> -#define DPCD_ADDR_TEST_REQUEST			0x0218
> -#define DPCD_ADDR_TEST_RESPONSE			0x0260
> -#define DPCD_ADDR_TEST_EDID_CHECKSUM		0x0261
> -#define DPCD_ADDR_SINK_POWER_STATE		0x0600
> -
> -/* DPCD_ADDR_MAX_LANE_COUNT */
> -#define DPCD_ENHANCED_FRAME_CAP(x)		(((x) >> 7) & 0x1)
> -#define DPCD_MAX_LANE_COUNT(x)			((x) & 0x1f)
> -
> -/* DPCD_ADDR_LANE_COUNT_SET */
> -#define DPCD_ENHANCED_FRAME_EN			(0x1 << 7)
> -#define DPCD_LANE_COUNT_SET(x)			((x) & 0x1f)
> -
> -/* DPCD_ADDR_TRAINING_PATTERN_SET */
> -#define DPCD_SCRAMBLING_DISABLED		(0x1 << 5)
> -#define DPCD_SCRAMBLING_ENABLED			(0x0 << 5)
> -#define DPCD_TRAINING_PATTERN_2			(0x2 << 0)
> -#define DPCD_TRAINING_PATTERN_1			(0x1 << 0)
> -#define DPCD_TRAINING_PATTERN_DISABLED		(0x0 << 0)
> -
> -/* DPCD_ADDR_TRAINING_LANE0_SET */
> -#define DPCD_MAX_PRE_EMPHASIS_REACHED		(0x1 << 5)
> -#define DPCD_PRE_EMPHASIS_SET(x)		(((x) & 0x3) << 3)
> -#define DPCD_PRE_EMPHASIS_GET(x)		(((x) >> 3) & 0x3)
> -#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0	(0x0 << 3)
> -#define DPCD_MAX_SWING_REACHED			(0x1 << 2)
> -#define DPCD_VOLTAGE_SWING_SET(x)		(((x) & 0x3) << 0)
> -#define DPCD_VOLTAGE_SWING_GET(x)		(((x) >> 0) & 0x3)
> -#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0	(0x0 << 0)
> -
> -/* DPCD_ADDR_LANE0_1_STATUS */
> -#define DPCD_LANE_SYMBOL_LOCKED			(0x1 << 2)
> -#define DPCD_LANE_CHANNEL_EQ_DONE		(0x1 << 1)
> -#define DPCD_LANE_CR_DONE			(0x1 << 0)
> -#define DPCD_CHANNEL_EQ_BITS			(DPCD_LANE_CR_DONE|	\
> -						 DPCD_LANE_CHANNEL_EQ_DONE|\
> -						 DPCD_LANE_SYMBOL_LOCKED)
> -
> -/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
> -#define DPCD_LINK_STATUS_UPDATED		(0x1 << 7)
> -#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED	(0x1 << 6)
> -#define DPCD_INTERLANE_ALIGN_DONE		(0x1 << 0)
> -
> -/* DPCD_ADDR_TEST_REQUEST */
> -#define DPCD_TEST_EDID_READ			(0x1 << 2)
> -
> -/* DPCD_ADDR_TEST_RESPONSE */
> -#define DPCD_TEST_EDID_CHECKSUM_WRITE		(0x1 << 2)
> -
> -/* DPCD_ADDR_SINK_POWER_STATE */
> -#define DPCD_SET_POWER_STATE_D0			(0x1 << 0)
> -#define DPCD_SET_POWER_STATE_D4			(0x2 << 0)
> -
> -#endif /* _EXYNOS_DP_CORE_H */
> diff --git a/drivers/video/exynos/exynos_dp_reg.c
> b/drivers/video/exynos/exynos_dp_reg.c
> deleted file mode 100644
> index 29d9d03..0000000
> --- a/drivers/video/exynos/exynos_dp_reg.c
> +++ /dev/null
> @@ -1,1245 +0,0 @@
> -/*
> - * Samsung DP (Display port) register interface driver.
> - *
> - * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> - * Author: Jingoo Han <jg1.han@samsung.com>
> - *
> - * 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/device.h>
> -#include <linux/io.h>
> -#include <linux/delay.h>
> -
> -#include <video/exynos_dp.h>
> -
> -#include "exynos_dp_core.h"
> -#include "exynos_dp_reg.h"
> -
> -#define COMMON_INT_MASK_1	0
> -#define COMMON_INT_MASK_2	0
> -#define COMMON_INT_MASK_3	0
> -#define COMMON_INT_MASK_4	(HOTPLUG_CHG | HPD_LOST | PLUG)
> -#define INT_STA_MASK		INT_HPD
> -
> -void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool
enable)
> -{
> -	u32 reg;
> -
> -	if (enable) {
> -		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -		reg |= HDCP_VIDEO_MUTE;
> -		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -	} else {
> -		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -		reg &= ~HDCP_VIDEO_MUTE;
> -		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -	}
> -}
> -
> -void exynos_dp_stop_video(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -	reg &= ~VIDEO_EN;
> -	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -}
> -
> -void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
> -{
> -	u32 reg;
> -
> -	if (enable)
> -		reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
> -			LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
> -	else
> -		reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
> -			LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
> -
> -	writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
> -}
> -
> -void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = TX_TERMINAL_CTRL_50_OHM;
> -	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
> -
> -	reg = SEL_24M | TX_DVDD_BIT_1_0625V;
> -	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
> -
> -	reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
> -	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
> -
> -	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
> -		TX_CUR1_2X | TX_CUR_16_MA;
> -	writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
> -
> -	reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
> -		CH1_AMP_400_MV | CH0_AMP_400_MV;
> -	writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
> -}
> -
> -void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
> -{
> -	/* Set interrupt pin assertion polarity as high */
> -	writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
> -
> -	/* Clear pending regisers */
> -	writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
> -	writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
> -	writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
> -	writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
> -	writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
> -
> -	/* 0:mask,1: unmask */
> -	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
> -	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
> -	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
> -	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
> -	writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
> -}
> -
> -void exynos_dp_reset(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	exynos_dp_stop_video(dp);
> -	exynos_dp_enable_video_mute(dp, 0);
> -
> -	reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
> -		AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
> -		HDCP_FUNC_EN_N | SW_FUNC_EN_N;
> -	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
> -
> -	reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
> -		SERDES_FIFO_FUNC_EN_N |
> -		LS_CLK_DOMAIN_FUNC_EN_N;
> -	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> -
> -	usleep_range(20, 30);
> -
> -	exynos_dp_lane_swap(dp, 0);
> -
> -	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> -	writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> -	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -
> -	writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
> -	writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
> -
> -	writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
> -	writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
> -
> -	writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
> -
> -	writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
> -
> -	writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
> -	writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
> -
> -	writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
> -	writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
> -
> -	writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> -}
> -
> -void exynos_dp_swreset(struct exynos_dp_device *dp)
> -{
> -	writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
> -}
> -
> -void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	/* 0: mask, 1: unmask */
> -	reg = COMMON_INT_MASK_1;
> -	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
> -
> -	reg = COMMON_INT_MASK_2;
> -	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
> -
> -	reg = COMMON_INT_MASK_3;
> -	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
> -
> -	reg = COMMON_INT_MASK_4;
> -	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
> -
> -	reg = INT_STA_MASK;
> -	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
> -}
> -
> -enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device
*dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
> -	if (reg & PLL_LOCK)
> -		return PLL_LOCKED;
> -	else
> -		return PLL_UNLOCKED;
> -}
> -
> -void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool
> enable)
> -{
> -	u32 reg;
> -
> -	if (enable) {
> -		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
> -		reg |= DP_PLL_PD;
> -		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
> -	} else {
> -		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
> -		reg &= ~DP_PLL_PD;
> -		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
> -	}
> -}
> -
> -void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
> -				enum analog_power_block block,
> -				bool enable)
> -{
> -	u32 reg;
> -
> -	switch (block) {
> -	case AUX_BLOCK:
> -		if (enable) {
> -			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -			reg |= AUX_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		} else {
> -			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -			reg &= ~AUX_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		}
> -		break;
> -	case CH0_BLOCK:
> -		if (enable) {
> -			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -			reg |= CH0_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		} else {
> -			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -			reg &= ~CH0_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		}
> -		break;
> -	case CH1_BLOCK:
> -		if (enable) {
> -			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -			reg |= CH1_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		} else {
> -			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -			reg &= ~CH1_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		}
> -		break;
> -	case CH2_BLOCK:
> -		if (enable) {
> -			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -			reg |= CH2_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		} else {
> -			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -			reg &= ~CH2_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		}
> -		break;
> -	case CH3_BLOCK:
> -		if (enable) {
> -			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -			reg |= CH3_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		} else {
> -			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -			reg &= ~CH3_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		}
> -		break;
> -	case ANALOG_TOTAL:
> -		if (enable) {
> -			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -			reg |= DP_PHY_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		} else {
> -			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -			reg &= ~DP_PHY_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		}
> -		break;
> -	case POWER_ALL:
> -		if (enable) {
> -			reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
> -				CH1_PD | CH0_PD;
> -			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		} else {
> -			writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
> -		}
> -		break;
> -	default:
> -		break;
> -	}
> -}
> -
> -void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -	int timeout_loop = 0;
> -
> -	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
> -
> -	reg = PLL_LOCK_CHG;
> -	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
> -	reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
> -	writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
> -
> -	/* Power up PLL */
> -	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
> -		exynos_dp_set_pll_power_down(dp, 0);
> -
> -		while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
> -			timeout_loop++;
> -			if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> -				dev_err(dp->dev, "failed to get pll lock
> status\n");
> -				return;
> -			}
> -			usleep_range(10, 20);
> -		}
> -	}
> -
> -	/* Enable Serdes FIFO function and Link symbol clock domain module
> */
> -	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> -	reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
> -		| AUX_FUNC_EN_N);
> -	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> -}
> -
> -void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = HOTPLUG_CHG | HPD_LOST | PLUG;
> -	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
> -
> -	reg = INT_HPD;
> -	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
> -}
> -
> -void exynos_dp_init_hpd(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	exynos_dp_clear_hotplug_interrupts(dp);
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -	reg &= ~(F_HPD | HPD_CTRL);
> -	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -}
> -
> -enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	/* Parse hotplug interrupt status register */
> -	reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
> -
> -	if (reg & PLUG)
> -		return DP_IRQ_TYPE_HP_CABLE_IN;
> -
> -	if (reg & HPD_LOST)
> -		return DP_IRQ_TYPE_HP_CABLE_OUT;
> -
> -	if (reg & HOTPLUG_CHG)
> -		return DP_IRQ_TYPE_HP_CHANGE;
> -
> -	return DP_IRQ_TYPE_UNKNOWN;
> -}
> -
> -void exynos_dp_reset_aux(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	/* Disable AUX channel module */
> -	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> -	reg |= AUX_FUNC_EN_N;
> -	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> -}
> -
> -void exynos_dp_init_aux(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	/* Clear inerrupts related to AUX channel */
> -	reg = RPLY_RECEIV | AUX_ERR;
> -	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
> -
> -	exynos_dp_reset_aux(dp);
> -
> -	/* Disable AUX transaction H/W retry */
> -	reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
> -		AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
> -	writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
> -
> -	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
> -	reg = DEFER_CTRL_EN | DEFER_COUNT(1);
> -	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
> -
> -	/* Enable AUX channel module */
> -	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> -	reg &= ~AUX_FUNC_EN_N;
> -	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> -}
> -
> -int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -	if (reg & HPD_STATUS)
> -		return 0;
> -
> -	return -EINVAL;
> -}
> -
> -void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
> -	reg &= ~SW_FUNC_EN_N;
> -	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
> -}
> -
> -int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
> -{
> -	int reg;
> -	int retval = 0;
> -	int timeout_loop = 0;
> -
> -	/* Enable AUX CH operation */
> -	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> -	reg |= AUX_EN;
> -	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> -
> -	/* Is AUX CH command reply received? */
> -	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
> -	while (!(reg & RPLY_RECEIV)) {
> -		timeout_loop++;
> -		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> -			dev_err(dp->dev, "AUX CH command reply failed!\n");
> -			return -ETIMEDOUT;
> -		}
> -		reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
> -		usleep_range(10, 11);
> -	}
> -
> -	/* Clear interrupt source for AUX CH command reply */
> -	writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
> -
> -	/* Clear interrupt source for AUX CH access error */
> -	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
> -	if (reg & AUX_ERR) {
> -		writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
> -		return -EREMOTEIO;
> -	}
> -
> -	/* Check AUX CH error access status */
> -	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
> -	if ((reg & AUX_STATUS_MASK) != 0) {
> -		dev_err(dp->dev, "AUX CH error happens: %d\n\n",
> -			reg & AUX_STATUS_MASK);
> -		return -EREMOTEIO;
> -	}
> -
> -	return retval;
> -}
> -
> -int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
> -				unsigned int reg_addr,
> -				unsigned char data)
> -{
> -	u32 reg;
> -	int i;
> -	int retval;
> -
> -	for (i = 0; i < 3; i++) {
> -		/* Clear AUX CH data buffer */
> -		reg = BUF_CLR;
> -		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
> -
> -		/* Select DPCD device address */
> -		reg = AUX_ADDR_7_0(reg_addr);
> -		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> -		reg = AUX_ADDR_15_8(reg_addr);
> -		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> -		reg = AUX_ADDR_19_16(reg_addr);
> -		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
> -
> -		/* Write data buffer */
> -		reg = (unsigned int)data;
> -		writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
> -
> -		/*
> -		 * Set DisplayPort transaction and write 1 byte
> -		 * If bit 3 is 1, DisplayPort transaction.
> -		 * If Bit 3 is 0, I2C transaction.
> -		 */
> -		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
> -		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
> -
> -		/* Start AUX transaction */
> -		retval = exynos_dp_start_aux_transaction(dp);
> -		if (retval == 0)
> -			break;
> -		else
> -			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
> -				__func__);
> -	}
> -
> -	return retval;
> -}
> -
> -int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
> -				unsigned int reg_addr,
> -				unsigned char *data)
> -{
> -	u32 reg;
> -	int i;
> -	int retval;
> -
> -	for (i = 0; i < 3; i++) {
> -		/* Clear AUX CH data buffer */
> -		reg = BUF_CLR;
> -		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
> -
> -		/* Select DPCD device address */
> -		reg = AUX_ADDR_7_0(reg_addr);
> -		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> -		reg = AUX_ADDR_15_8(reg_addr);
> -		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> -		reg = AUX_ADDR_19_16(reg_addr);
> -		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
> -
> -		/*
> -		 * Set DisplayPort transaction and read 1 byte
> -		 * If bit 3 is 1, DisplayPort transaction.
> -		 * If Bit 3 is 0, I2C transaction.
> -		 */
> -		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
> -		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
> -
> -		/* Start AUX transaction */
> -		retval = exynos_dp_start_aux_transaction(dp);
> -		if (retval == 0)
> -			break;
> -		else
> -			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
> -				__func__);
> -	}
> -
> -	/* Read data buffer */
> -	reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
> -	*data = (unsigned char)(reg & 0xff);
> -
> -	return retval;
> -}
> -
> -int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
> -				unsigned int reg_addr,
> -				unsigned int count,
> -				unsigned char data[])
> -{
> -	u32 reg;
> -	unsigned int start_offset;
> -	unsigned int cur_data_count;
> -	unsigned int cur_data_idx;
> -	int i;
> -	int retval = 0;
> -
> -	/* Clear AUX CH data buffer */
> -	reg = BUF_CLR;
> -	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
> -
> -	start_offset = 0;
> -	while (start_offset < count) {
> -		/* Buffer size of AUX CH is 16 * 4bytes */
> -		if ((count - start_offset) > 16)
> -			cur_data_count = 16;
> -		else
> -			cur_data_count = count - start_offset;
> -
> -		for (i = 0; i < 3; i++) {
> -			/* Select DPCD device address */
> -			reg = AUX_ADDR_7_0(reg_addr + start_offset);
> -			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> -			reg = AUX_ADDR_15_8(reg_addr + start_offset);
> -			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> -			reg = AUX_ADDR_19_16(reg_addr + start_offset);
> -			writel(reg, dp->reg_base +
EXYNOS_DP_AUX_ADDR_19_16);
> -
> -			for (cur_data_idx = 0; cur_data_idx <
cur_data_count;
> -			     cur_data_idx++) {
> -				reg = data[start_offset + cur_data_idx];
> -				writel(reg, dp->reg_base +
EXYNOS_DP_BUF_DATA_0
> -							  + 4 *
cur_data_idx);
> -			}
> -
> -			/*
> -			 * Set DisplayPort transaction and write
> -			 * If bit 3 is 1, DisplayPort transaction.
> -			 * If Bit 3 is 0, I2C transaction.
> -			 */
> -			reg = AUX_LENGTH(cur_data_count) |
> -				AUX_TX_COMM_DP_TRANSACTION |
AUX_TX_COMM_WRITE;
> -			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
> -
> -			/* Start AUX transaction */
> -			retval = exynos_dp_start_aux_transaction(dp);
> -			if (retval == 0)
> -				break;
> -			else
> -				dev_dbg(dp->dev, "%s: Aux Transaction
fail!\n",
> -					__func__);
> -		}
> -
> -		start_offset += cur_data_count;
> -	}
> -
> -	return retval;
> -}
> -
> -int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
> -				unsigned int reg_addr,
> -				unsigned int count,
> -				unsigned char data[])
> -{
> -	u32 reg;
> -	unsigned int start_offset;
> -	unsigned int cur_data_count;
> -	unsigned int cur_data_idx;
> -	int i;
> -	int retval = 0;
> -
> -	/* Clear AUX CH data buffer */
> -	reg = BUF_CLR;
> -	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
> -
> -	start_offset = 0;
> -	while (start_offset < count) {
> -		/* Buffer size of AUX CH is 16 * 4bytes */
> -		if ((count - start_offset) > 16)
> -			cur_data_count = 16;
> -		else
> -			cur_data_count = count - start_offset;
> -
> -		/* AUX CH Request Transaction process */
> -		for (i = 0; i < 3; i++) {
> -			/* Select DPCD device address */
> -			reg = AUX_ADDR_7_0(reg_addr + start_offset);
> -			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> -			reg = AUX_ADDR_15_8(reg_addr + start_offset);
> -			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> -			reg = AUX_ADDR_19_16(reg_addr + start_offset);
> -			writel(reg, dp->reg_base +
EXYNOS_DP_AUX_ADDR_19_16);
> -
> -			/*
> -			 * Set DisplayPort transaction and read
> -			 * If bit 3 is 1, DisplayPort transaction.
> -			 * If Bit 3 is 0, I2C transaction.
> -			 */
> -			reg = AUX_LENGTH(cur_data_count) |
> -				AUX_TX_COMM_DP_TRANSACTION |
AUX_TX_COMM_READ;
> -			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
> -
> -			/* Start AUX transaction */
> -			retval = exynos_dp_start_aux_transaction(dp);
> -			if (retval == 0)
> -				break;
> -			else
> -				dev_dbg(dp->dev, "%s: Aux Transaction
fail!\n",
> -					__func__);
> -		}
> -
> -		for (cur_data_idx = 0; cur_data_idx < cur_data_count;
> -		    cur_data_idx++) {
> -			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
> -						 + 4 * cur_data_idx);
> -			data[start_offset + cur_data_idx] =
> -				(unsigned char)reg;
> -		}
> -
> -		start_offset += cur_data_count;
> -	}
> -
> -	return retval;
> -}
> -
> -int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
> -				unsigned int device_addr,
> -				unsigned int reg_addr)
> -{
> -	u32 reg;
> -	int retval;
> -
> -	/* Set EDID device address */
> -	reg = device_addr;
> -	writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> -	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> -	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
> -
> -	/* Set offset from base address of EDID device */
> -	writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
> -
> -	/*
> -	 * Set I2C transaction and write address
> -	 * If bit 3 is 1, DisplayPort transaction.
> -	 * If Bit 3 is 0, I2C transaction.
> -	 */
> -	reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
> -		AUX_TX_COMM_WRITE;
> -	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
> -
> -	/* Start AUX transaction */
> -	retval = exynos_dp_start_aux_transaction(dp);
> -	if (retval != 0)
> -		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
> -
> -	return retval;
> -}
> -
> -int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
> -				unsigned int device_addr,
> -				unsigned int reg_addr,
> -				unsigned int *data)
> -{
> -	u32 reg;
> -	int i;
> -	int retval;
> -
> -	for (i = 0; i < 3; i++) {
> -		/* Clear AUX CH data buffer */
> -		reg = BUF_CLR;
> -		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
> -
> -		/* Select EDID device */
> -		retval = exynos_dp_select_i2c_device(dp, device_addr,
> reg_addr);
> -		if (retval != 0)
> -			continue;
> -
> -		/*
> -		 * Set I2C transaction and read data
> -		 * If bit 3 is 1, DisplayPort transaction.
> -		 * If Bit 3 is 0, I2C transaction.
> -		 */
> -		reg = AUX_TX_COMM_I2C_TRANSACTION |
> -			AUX_TX_COMM_READ;
> -		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
> -
> -		/* Start AUX transaction */
> -		retval = exynos_dp_start_aux_transaction(dp);
> -		if (retval == 0)
> -			break;
> -		else
> -			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
> -				__func__);
> -	}
> -
> -	/* Read data */
> -	if (retval == 0)
> -		*data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
> -
> -	return retval;
> -}
> -
> -int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
> -				unsigned int device_addr,
> -				unsigned int reg_addr,
> -				unsigned int count,
> -				unsigned char edid[])
> -{
> -	u32 reg;
> -	unsigned int i, j;
> -	unsigned int cur_data_idx;
> -	unsigned int defer = 0;
> -	int retval = 0;
> -
> -	for (i = 0; i < count; i += 16) {
> -		for (j = 0; j < 3; j++) {
> -			/* Clear AUX CH data buffer */
> -			reg = BUF_CLR;
> -			writel(reg, dp->reg_base +
EXYNOS_DP_BUFFER_DATA_CTL);
> -
> -			/* Set normal AUX CH command */
> -			reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> -			reg &= ~ADDR_ONLY;
> -			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> -
> -			/*
> -			 * If Rx sends defer, Tx sends only reads
> -			 * request without sending address
> -			 */
> -			if (!defer)
> -				retval = exynos_dp_select_i2c_device(dp,
> -						device_addr, reg_addr + i);
> -			else
> -				defer = 0;
> -
> -			if (retval == 0) {
> -				/*
> -				 * Set I2C transaction and write data
> -				 * If bit 3 is 1, DisplayPort transaction.
> -				 * If Bit 3 is 0, I2C transaction.
> -				 */
> -				reg = AUX_LENGTH(16) |
> -					AUX_TX_COMM_I2C_TRANSACTION |
> -					AUX_TX_COMM_READ;
> -				writel(reg, dp->reg_base +
> -					EXYNOS_DP_AUX_CH_CTL_1);
> -
> -				/* Start AUX transaction */
> -				retval =
exynos_dp_start_aux_transaction(dp);
> -				if (retval == 0)
> -					break;
> -				else
> -					dev_dbg(dp->dev,
> -						"%s: Aux Transaction
fail!\n",
> -						__func__);
> -			}
> -			/* Check if Rx sends defer */
> -			reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
> -			if (reg == AUX_RX_COMM_AUX_DEFER ||
> -				reg == AUX_RX_COMM_I2C_DEFER) {
> -				dev_err(dp->dev, "Defer: %d\n\n", reg);
> -				defer = 1;
> -			}
> -		}
> -
> -		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
> -			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
> -						 + 4 * cur_data_idx);
> -			edid[i + cur_data_idx] = (unsigned char)reg;
> -		}
> -	}
> -
> -	return retval;
> -}
> -
> -void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32
bwtype)
> -{
> -	u32 reg;
> -
> -	reg = bwtype;
> -	if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype ==
> LINK_RATE_1_62GBPS))
> -		writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
> -}
> -
> -void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32
> *bwtype)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
> -	*bwtype = reg;
> -}
> -
> -void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
> -{
> -	u32 reg;
> -
> -	reg = count;
> -	writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
> -}
> -
> -void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
> -	*count = reg;
> -}
> -
> -void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool
> enable)
> -{
> -	u32 reg;
> -
> -	if (enable) {
> -		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -		reg |= ENHANCED;
> -		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -	} else {
> -		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -		reg &= ~ENHANCED;
> -		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -	}
> -}
> -
> -void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
> -				 enum pattern_set pattern)
> -{
> -	u32 reg;
> -
> -	switch (pattern) {
> -	case PRBS7:
> -		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
> -		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -		break;
> -	case D10_2:
> -		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
> -		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -		break;
> -	case TRAINING_PTN1:
> -		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
> -		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -		break;
> -	case TRAINING_PTN2:
> -		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
> -		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -		break;
> -	case DP_NONE:
> -		reg = SCRAMBLING_ENABLE |
> -			LINK_QUAL_PATTERN_SET_DISABLE |
> -			SW_TRAINING_PATTERN_SET_NORMAL;
> -		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -		break;
> -	default:
> -		break;
> -	}
> -}
> -
> -void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32
> level)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> -	reg &= ~PRE_EMPHASIS_SET_MASK;
> -	reg |= level << PRE_EMPHASIS_SET_SHIFT;
> -	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32
> level)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> -	reg &= ~PRE_EMPHASIS_SET_MASK;
> -	reg |= level << PRE_EMPHASIS_SET_SHIFT;
> -	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32
> level)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> -	reg &= ~PRE_EMPHASIS_SET_MASK;
> -	reg |= level << PRE_EMPHASIS_SET_SHIFT;
> -	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32
> level)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> -	reg &= ~PRE_EMPHASIS_SET_MASK;
> -	reg |= level << PRE_EMPHASIS_SET_SHIFT;
> -	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
> -					u32 training_lane)
> -{
> -	u32 reg;
> -
> -	reg = training_lane;
> -	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
> -					u32 training_lane)
> -{
> -	u32 reg;
> -
> -	reg = training_lane;
> -	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
> -					u32 training_lane)
> -{
> -	u32 reg;
> -
> -	reg = training_lane;
> -	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
> -					u32 training_lane)
> -{
> -	u32 reg;
> -
> -	reg = training_lane;
> -	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> -}
> -
> -u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> -	return reg;
> -}
> -
> -u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> -	return reg;
> -}
> -
> -u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> -	return reg;
> -}
> -
> -u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> -	return reg;
> -}
> -
> -void exynos_dp_reset_macro(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
> -	reg |= MACRO_RST;
> -	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
> -
> -	/* 10 us is the minimum reset time. */
> -	usleep_range(10, 20);
> -
> -	reg &= ~MACRO_RST;
> -	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
> -}
> -
> -void exynos_dp_init_video(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
> -	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
> -
> -	reg = 0x0;
> -	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> -
> -	reg = CHA_CRI(4) | CHA_CTRL;
> -	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> -
> -	reg = 0x0;
> -	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -
> -	reg = VID_HRES_TH(2) | VID_VRES_TH(0);
> -	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
> -}
> -
> -void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	/* Configure the input color depth, color space, dynamic range */
> -	reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
> -		(dp->video_info->color_depth << IN_BPC_SHIFT) |
> -		(dp->video_info->color_space << IN_COLOR_F_SHIFT);
> -	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
> -
> -	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
> -	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
> -	reg &= ~IN_YC_COEFFI_MASK;
> -	if (dp->video_info->ycbcr_coeff)
> -		reg |= IN_YC_COEFFI_ITU709;
> -	else
> -		reg |= IN_YC_COEFFI_ITU601;
> -	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
> -}
> -
> -int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> -	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> -
> -	if (!(reg & DET_STA)) {
> -		dev_dbg(dp->dev, "Input stream clock not detected.\n");
> -		return -EINVAL;
> -	}
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> -	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> -	dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
> -
> -	if (reg & CHA_STA) {
> -		dev_dbg(dp->dev, "Input stream clk is changing\n");
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
> -void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
> -		enum clock_recovery_m_value_type type,
> -		u32 m_value,
> -		u32 n_value)
> -{
> -	u32 reg;
> -
> -	if (type == REGISTER_M) {
> -		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -		reg |= FIX_M_VID;
> -		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -		reg = m_value & 0xff;
> -		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
> -		reg = (m_value >> 8) & 0xff;
> -		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
> -		reg = (m_value >> 16) & 0xff;
> -		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
> -
> -		reg = n_value & 0xff;
> -		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
> -		reg = (n_value >> 8) & 0xff;
> -		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
> -		reg = (n_value >> 16) & 0xff;
> -		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
> -	} else  {
> -		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -		reg &= ~FIX_M_VID;
> -		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -
> -		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
> -		writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
> -		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
> -	}
> -}
> -
> -void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32
> type)
> -{
> -	u32 reg;
> -
> -	if (type == VIDEO_TIMING_FROM_CAPTURE) {
> -		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -		reg &= ~FORMAT_SEL;
> -		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -	} else {
> -		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -		reg |= FORMAT_SEL;
> -		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -	}
> -}
> -
> -void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool
> enable)
> -{
> -	u32 reg;
> -
> -	if (enable) {
> -		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> -		reg &= ~VIDEO_MODE_MASK;
> -		reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
> -		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> -	} else {
> -		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> -		reg &= ~VIDEO_MODE_MASK;
> -		reg |= VIDEO_MODE_SLAVE_MODE;
> -		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> -	}
> -}
> -
> -void exynos_dp_start_video(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -	reg |= VIDEO_EN;
> -	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -}
> -
> -int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -	if (!(reg & STRM_VALID)) {
> -		dev_dbg(dp->dev, "Input video stream is not detected.\n");
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
> -void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
> -	reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
> -	reg |= MASTER_VID_FUNC_EN_N;
> -	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -	reg &= ~INTERACE_SCAN_CFG;
> -	reg |= (dp->video_info->interlaced << 2);
> -	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -	reg &= ~VSYNC_POLARITY_CFG;
> -	reg |= (dp->video_info->v_sync_polarity << 1);
> -	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -	reg &= ~HSYNC_POLARITY_CFG;
> -	reg |= (dp->video_info->h_sync_polarity << 0);
> -	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -
> -	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
> -	writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> -}
> -
> -void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -	reg &= ~SCRAMBLING_DISABLE;
> -	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -}
> -
> -void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
> -{
> -	u32 reg;
> -
> -	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -	reg |= SCRAMBLING_DISABLE;
> -	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -}
> diff --git a/drivers/video/exynos/exynos_dp_reg.h
> b/drivers/video/exynos/exynos_dp_reg.h
> deleted file mode 100644
> index 2e9bd0e..0000000
> --- a/drivers/video/exynos/exynos_dp_reg.h
> +++ /dev/null
> @@ -1,366 +0,0 @@
> -/*
> - * Register definition file for Samsung DP driver
> - *
> - * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> - * Author: Jingoo Han <jg1.han@samsung.com>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - */
> -
> -#ifndef _EXYNOS_DP_REG_H
> -#define _EXYNOS_DP_REG_H
> -
> -#define EXYNOS_DP_TX_SW_RESET			0x14
> -#define EXYNOS_DP_FUNC_EN_1			0x18
> -#define EXYNOS_DP_FUNC_EN_2			0x1C
> -#define EXYNOS_DP_VIDEO_CTL_1			0x20
> -#define EXYNOS_DP_VIDEO_CTL_2			0x24
> -#define EXYNOS_DP_VIDEO_CTL_3			0x28
> -
> -#define EXYNOS_DP_VIDEO_CTL_8			0x3C
> -#define EXYNOS_DP_VIDEO_CTL_10			0x44
> -
> -#define EXYNOS_DP_LANE_MAP			0x35C
> -
> -#define EXYNOS_DP_ANALOG_CTL_1			0x370
> -#define EXYNOS_DP_ANALOG_CTL_2			0x374
> -#define EXYNOS_DP_ANALOG_CTL_3			0x378
> -#define EXYNOS_DP_PLL_FILTER_CTL_1		0x37C
> -#define EXYNOS_DP_TX_AMP_TUNING_CTL		0x380
> -
> -#define EXYNOS_DP_AUX_HW_RETRY_CTL		0x390
> -
> -#define EXYNOS_DP_COMMON_INT_STA_1		0x3C4
> -#define EXYNOS_DP_COMMON_INT_STA_2		0x3C8
> -#define EXYNOS_DP_COMMON_INT_STA_3		0x3CC
> -#define EXYNOS_DP_COMMON_INT_STA_4		0x3D0
> -#define EXYNOS_DP_INT_STA			0x3DC
> -#define EXYNOS_DP_COMMON_INT_MASK_1		0x3E0
> -#define EXYNOS_DP_COMMON_INT_MASK_2		0x3E4
> -#define EXYNOS_DP_COMMON_INT_MASK_3		0x3E8
> -#define EXYNOS_DP_COMMON_INT_MASK_4		0x3EC
> -#define EXYNOS_DP_INT_STA_MASK			0x3F8
> -#define EXYNOS_DP_INT_CTL			0x3FC
> -
> -#define EXYNOS_DP_SYS_CTL_1			0x600
> -#define EXYNOS_DP_SYS_CTL_2			0x604
> -#define EXYNOS_DP_SYS_CTL_3			0x608
> -#define EXYNOS_DP_SYS_CTL_4			0x60C
> -
> -#define EXYNOS_DP_PKT_SEND_CTL			0x640
> -#define EXYNOS_DP_HDCP_CTL			0x648
> -
> -#define EXYNOS_DP_LINK_BW_SET			0x680
> -#define EXYNOS_DP_LANE_COUNT_SET		0x684
> -#define EXYNOS_DP_TRAINING_PTN_SET		0x688
> -#define EXYNOS_DP_LN0_LINK_TRAINING_CTL		0x68C
> -#define EXYNOS_DP_LN1_LINK_TRAINING_CTL		0x690
> -#define EXYNOS_DP_LN2_LINK_TRAINING_CTL		0x694
> -#define EXYNOS_DP_LN3_LINK_TRAINING_CTL		0x698
> -
> -#define EXYNOS_DP_DEBUG_CTL			0x6C0
> -#define EXYNOS_DP_HPD_DEGLITCH_L		0x6C4
> -#define EXYNOS_DP_HPD_DEGLITCH_H		0x6C8
> -#define EXYNOS_DP_LINK_DEBUG_CTL		0x6E0
> -
> -#define EXYNOS_DP_M_VID_0			0x700
> -#define EXYNOS_DP_M_VID_1			0x704
> -#define EXYNOS_DP_M_VID_2			0x708
> -#define EXYNOS_DP_N_VID_0			0x70C
> -#define EXYNOS_DP_N_VID_1			0x710
> -#define EXYNOS_DP_N_VID_2			0x714
> -
> -#define EXYNOS_DP_PLL_CTL			0x71C
> -#define EXYNOS_DP_PHY_PD			0x720
> -#define EXYNOS_DP_PHY_TEST			0x724
> -
> -#define EXYNOS_DP_VIDEO_FIFO_THRD		0x730
> -#define EXYNOS_DP_AUDIO_MARGIN			0x73C
> -
> -#define EXYNOS_DP_M_VID_GEN_FILTER_TH		0x764
> -#define EXYNOS_DP_M_AUD_GEN_FILTER_TH		0x778
> -#define EXYNOS_DP_AUX_CH_STA			0x780
> -#define EXYNOS_DP_AUX_CH_DEFER_CTL		0x788
> -#define EXYNOS_DP_AUX_RX_COMM			0x78C
> -#define EXYNOS_DP_BUFFER_DATA_CTL		0x790
> -#define EXYNOS_DP_AUX_CH_CTL_1			0x794
> -#define EXYNOS_DP_AUX_ADDR_7_0			0x798
> -#define EXYNOS_DP_AUX_ADDR_15_8			0x79C
> -#define EXYNOS_DP_AUX_ADDR_19_16		0x7A0
> -#define EXYNOS_DP_AUX_CH_CTL_2			0x7A4
> -
> -#define EXYNOS_DP_BUF_DATA_0			0x7C0
> -
> -#define EXYNOS_DP_SOC_GENERAL_CTL		0x800
> -
> -/* EXYNOS_DP_TX_SW_RESET */
> -#define RESET_DP_TX				(0x1 << 0)
> -
> -/* EXYNOS_DP_FUNC_EN_1 */
> -#define MASTER_VID_FUNC_EN_N			(0x1 << 7)
> -#define SLAVE_VID_FUNC_EN_N			(0x1 << 5)
> -#define AUD_FIFO_FUNC_EN_N			(0x1 << 4)
> -#define AUD_FUNC_EN_N				(0x1 << 3)
> -#define HDCP_FUNC_EN_N				(0x1 << 2)
> -#define CRC_FUNC_EN_N				(0x1 << 1)
> -#define SW_FUNC_EN_N				(0x1 << 0)
> -
> -/* EXYNOS_DP_FUNC_EN_2 */
> -#define SSC_FUNC_EN_N				(0x1 << 7)
> -#define AUX_FUNC_EN_N				(0x1 << 2)
> -#define SERDES_FIFO_FUNC_EN_N			(0x1 << 1)
> -#define LS_CLK_DOMAIN_FUNC_EN_N			(0x1 << 0)
> -
> -/* EXYNOS_DP_VIDEO_CTL_1 */
> -#define VIDEO_EN				(0x1 << 7)
> -#define HDCP_VIDEO_MUTE				(0x1 << 6)
> -
> -/* EXYNOS_DP_VIDEO_CTL_1 */
> -#define IN_D_RANGE_MASK				(0x1 << 7)
> -#define IN_D_RANGE_SHIFT			(7)
> -#define IN_D_RANGE_CEA				(0x1 << 7)
> -#define IN_D_RANGE_VESA				(0x0 << 7)
> -#define IN_BPC_MASK				(0x7 << 4)
> -#define IN_BPC_SHIFT				(4)
> -#define IN_BPC_12_BITS				(0x3 << 4)
> -#define IN_BPC_10_BITS				(0x2 << 4)
> -#define IN_BPC_8_BITS				(0x1 << 4)
> -#define IN_BPC_6_BITS				(0x0 << 4)
> -#define IN_COLOR_F_MASK				(0x3 << 0)
> -#define IN_COLOR_F_SHIFT			(0)
> -#define IN_COLOR_F_YCBCR444			(0x2 << 0)
> -#define IN_COLOR_F_YCBCR422			(0x1 << 0)
> -#define IN_COLOR_F_RGB				(0x0 << 0)
> -
> -/* EXYNOS_DP_VIDEO_CTL_3 */
> -#define IN_YC_COEFFI_MASK			(0x1 << 7)
> -#define IN_YC_COEFFI_SHIFT			(7)
> -#define IN_YC_COEFFI_ITU709			(0x1 << 7)
> -#define IN_YC_COEFFI_ITU601			(0x0 << 7)
> -#define VID_CHK_UPDATE_TYPE_MASK		(0x1 << 4)
> -#define VID_CHK_UPDATE_TYPE_SHIFT		(4)
> -#define VID_CHK_UPDATE_TYPE_1			(0x1 << 4)
> -#define VID_CHK_UPDATE_TYPE_0			(0x0 << 4)
> -
> -/* EXYNOS_DP_VIDEO_CTL_8 */
> -#define VID_HRES_TH(x)				(((x) & 0xf) << 4)
> -#define VID_VRES_TH(x)				(((x) & 0xf) << 0)
> -
> -/* EXYNOS_DP_VIDEO_CTL_10 */
> -#define FORMAT_SEL				(0x1 << 4)
> -#define INTERACE_SCAN_CFG			(0x1 << 2)
> -#define VSYNC_POLARITY_CFG			(0x1 << 1)
> -#define HSYNC_POLARITY_CFG			(0x1 << 0)
> -
> -/* EXYNOS_DP_LANE_MAP */
> -#define LANE3_MAP_LOGIC_LANE_0			(0x0 << 6)
> -#define LANE3_MAP_LOGIC_LANE_1			(0x1 << 6)
> -#define LANE3_MAP_LOGIC_LANE_2			(0x2 << 6)
> -#define LANE3_MAP_LOGIC_LANE_3			(0x3 << 6)
> -#define LANE2_MAP_LOGIC_LANE_0			(0x0 << 4)
> -#define LANE2_MAP_LOGIC_LANE_1			(0x1 << 4)
> -#define LANE2_MAP_LOGIC_LANE_2			(0x2 << 4)
> -#define LANE2_MAP_LOGIC_LANE_3			(0x3 << 4)
> -#define LANE1_MAP_LOGIC_LANE_0			(0x0 << 2)
> -#define LANE1_MAP_LOGIC_LANE_1			(0x1 << 2)
> -#define LANE1_MAP_LOGIC_LANE_2			(0x2 << 2)
> -#define LANE1_MAP_LOGIC_LANE_3			(0x3 << 2)
> -#define LANE0_MAP_LOGIC_LANE_0			(0x0 << 0)
> -#define LANE0_MAP_LOGIC_LANE_1			(0x1 << 0)
> -#define LANE0_MAP_LOGIC_LANE_2			(0x2 << 0)
> -#define LANE0_MAP_LOGIC_LANE_3			(0x3 << 0)
> -
> -/* EXYNOS_DP_ANALOG_CTL_1 */
> -#define TX_TERMINAL_CTRL_50_OHM			(0x1 << 4)
> -
> -/* EXYNOS_DP_ANALOG_CTL_2 */
> -#define SEL_24M					(0x1 << 3)
> -#define TX_DVDD_BIT_1_0625V			(0x4 << 0)
> -
> -/* EXYNOS_DP_ANALOG_CTL_3 */
> -#define DRIVE_DVDD_BIT_1_0625V			(0x4 << 5)
> -#define VCO_BIT_600_MICRO			(0x5 << 0)
> -
> -/* EXYNOS_DP_PLL_FILTER_CTL_1 */
> -#define PD_RING_OSC				(0x1 << 6)
> -#define AUX_TERMINAL_CTRL_50_OHM		(0x2 << 4)
> -#define TX_CUR1_2X				(0x1 << 2)
> -#define TX_CUR_16_MA				(0x3 << 0)
> -
> -/* EXYNOS_DP_TX_AMP_TUNING_CTL */
> -#define CH3_AMP_400_MV				(0x0 << 24)
> -#define CH2_AMP_400_MV				(0x0 << 16)
> -#define CH1_AMP_400_MV				(0x0 << 8)
> -#define CH0_AMP_400_MV				(0x0 << 0)
> -
> -/* EXYNOS_DP_AUX_HW_RETRY_CTL */
> -#define AUX_BIT_PERIOD_EXPECTED_DELAY(x)	(((x) & 0x7) << 8)
> -#define AUX_HW_RETRY_INTERVAL_MASK		(0x3 << 3)
> -#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS	(0x0 << 3)
> -#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS	(0x1 << 3)
> -#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS	(0x2 << 3)
> -#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS	(0x3 << 3)
> -#define AUX_HW_RETRY_COUNT_SEL(x)		(((x) & 0x7) << 0)
> -
> -/* EXYNOS_DP_COMMON_INT_STA_1 */
> -#define VSYNC_DET				(0x1 << 7)
> -#define PLL_LOCK_CHG				(0x1 << 6)
> -#define SPDIF_ERR				(0x1 << 5)
> -#define SPDIF_UNSTBL				(0x1 << 4)
> -#define VID_FORMAT_CHG				(0x1 << 3)
> -#define AUD_CLK_CHG				(0x1 << 2)
> -#define VID_CLK_CHG				(0x1 << 1)
> -#define SW_INT					(0x1 << 0)
> -
> -/* EXYNOS_DP_COMMON_INT_STA_2 */
> -#define ENC_EN_CHG				(0x1 << 6)
> -#define HW_BKSV_RDY				(0x1 << 3)
> -#define HW_SHA_DONE				(0x1 << 2)
> -#define HW_AUTH_STATE_CHG			(0x1 << 1)
> -#define HW_AUTH_DONE				(0x1 << 0)
> -
> -/* EXYNOS_DP_COMMON_INT_STA_3 */
> -#define AFIFO_UNDER				(0x1 << 7)
> -#define AFIFO_OVER				(0x1 << 6)
> -#define R0_CHK_FLAG				(0x1 << 5)
> -
> -/* EXYNOS_DP_COMMON_INT_STA_4 */
> -#define PSR_ACTIVE				(0x1 << 7)
> -#define PSR_INACTIVE				(0x1 << 6)
> -#define SPDIF_BI_PHASE_ERR			(0x1 << 5)
> -#define HOTPLUG_CHG				(0x1 << 2)
> -#define HPD_LOST				(0x1 << 1)
> -#define PLUG					(0x1 << 0)
> -
> -/* EXYNOS_DP_INT_STA */
> -#define INT_HPD					(0x1 << 6)
> -#define HW_TRAINING_FINISH			(0x1 << 5)
> -#define RPLY_RECEIV				(0x1 << 1)
> -#define AUX_ERR					(0x1 << 0)
> -
> -/* EXYNOS_DP_INT_CTL */
> -#define SOFT_INT_CTRL				(0x1 << 2)
> -#define INT_POL1				(0x1 << 1)
> -#define INT_POL0				(0x1 << 0)
> -
> -/* EXYNOS_DP_SYS_CTL_1 */
> -#define DET_STA					(0x1 << 2)
> -#define FORCE_DET				(0x1 << 1)
> -#define DET_CTRL				(0x1 << 0)
> -
> -/* EXYNOS_DP_SYS_CTL_2 */
> -#define CHA_CRI(x)				(((x) & 0xf) << 4)
> -#define CHA_STA					(0x1 << 2)
> -#define FORCE_CHA				(0x1 << 1)
> -#define CHA_CTRL				(0x1 << 0)
> -
> -/* EXYNOS_DP_SYS_CTL_3 */
> -#define HPD_STATUS				(0x1 << 6)
> -#define F_HPD					(0x1 << 5)
> -#define HPD_CTRL				(0x1 << 4)
> -#define HDCP_RDY				(0x1 << 3)
> -#define STRM_VALID				(0x1 << 2)
> -#define F_VALID					(0x1 << 1)
> -#define VALID_CTRL				(0x1 << 0)
> -
> -/* EXYNOS_DP_SYS_CTL_4 */
> -#define FIX_M_AUD				(0x1 << 4)
> -#define ENHANCED				(0x1 << 3)
> -#define FIX_M_VID				(0x1 << 2)
> -#define M_VID_UPDATE_CTRL			(0x3 << 0)
> -
> -/* EXYNOS_DP_TRAINING_PTN_SET */
> -#define SCRAMBLER_TYPE				(0x1 << 9)
> -#define HW_LINK_TRAINING_PATTERN		(0x1 << 8)
> -#define SCRAMBLING_DISABLE			(0x1 << 5)
> -#define SCRAMBLING_ENABLE			(0x0 << 5)
> -#define LINK_QUAL_PATTERN_SET_MASK		(0x3 << 2)
> -#define LINK_QUAL_PATTERN_SET_PRBS7		(0x3 << 2)
> -#define LINK_QUAL_PATTERN_SET_D10_2		(0x1 << 2)
> -#define LINK_QUAL_PATTERN_SET_DISABLE		(0x0 << 2)
> -#define SW_TRAINING_PATTERN_SET_MASK		(0x3 << 0)
> -#define SW_TRAINING_PATTERN_SET_PTN2		(0x2 << 0)
> -#define SW_TRAINING_PATTERN_SET_PTN1		(0x1 << 0)
> -#define SW_TRAINING_PATTERN_SET_NORMAL		(0x0 << 0)
> -
> -/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
> -#define PRE_EMPHASIS_SET_MASK			(0x3 << 3)
> -#define PRE_EMPHASIS_SET_SHIFT			(3)
> -
> -/* EXYNOS_DP_DEBUG_CTL */
> -#define PLL_LOCK				(0x1 << 4)
> -#define F_PLL_LOCK				(0x1 << 3)
> -#define PLL_LOCK_CTRL				(0x1 << 2)
> -#define PN_INV					(0x1 << 0)
> -
> -/* EXYNOS_DP_PLL_CTL */
> -#define DP_PLL_PD				(0x1 << 7)
> -#define DP_PLL_RESET				(0x1 << 6)
> -#define DP_PLL_LOOP_BIT_DEFAULT			(0x1 << 4)
> -#define DP_PLL_REF_BIT_1_1250V			(0x5 << 0)
> -#define DP_PLL_REF_BIT_1_2500V			(0x7 << 0)
> -
> -/* EXYNOS_DP_PHY_PD */
> -#define DP_PHY_PD				(0x1 << 5)
> -#define AUX_PD					(0x1 << 4)
> -#define CH3_PD					(0x1 << 3)
> -#define CH2_PD					(0x1 << 2)
> -#define CH1_PD					(0x1 << 1)
> -#define CH0_PD					(0x1 << 0)
> -
> -/* EXYNOS_DP_PHY_TEST */
> -#define MACRO_RST				(0x1 << 5)
> -#define CH1_TEST				(0x1 << 1)
> -#define CH0_TEST				(0x1 << 0)
> -
> -/* EXYNOS_DP_AUX_CH_STA */
> -#define AUX_BUSY				(0x1 << 4)
> -#define AUX_STATUS_MASK				(0xf << 0)
> -
> -/* EXYNOS_DP_AUX_CH_DEFER_CTL */
> -#define DEFER_CTRL_EN				(0x1 << 7)
> -#define DEFER_COUNT(x)				(((x) & 0x7f) << 0)
> -
> -/* EXYNOS_DP_AUX_RX_COMM */
> -#define AUX_RX_COMM_I2C_DEFER			(0x2 << 2)
> -#define AUX_RX_COMM_AUX_DEFER			(0x2 << 0)
> -
> -/* EXYNOS_DP_BUFFER_DATA_CTL */
> -#define BUF_CLR					(0x1 << 7)
> -#define BUF_DATA_COUNT(x)			(((x) & 0x1f) << 0)
> -
> -/* EXYNOS_DP_AUX_CH_CTL_1 */
> -#define AUX_LENGTH(x)				(((x - 1) & 0xf) <<
4)
> -#define AUX_TX_COMM_MASK			(0xf << 0)
> -#define AUX_TX_COMM_DP_TRANSACTION		(0x1 << 3)
> -#define AUX_TX_COMM_I2C_TRANSACTION		(0x0 << 3)
> -#define AUX_TX_COMM_MOT				(0x1 << 2)
> -#define AUX_TX_COMM_WRITE			(0x0 << 0)
> -#define AUX_TX_COMM_READ			(0x1 << 0)
> -
> -/* EXYNOS_DP_AUX_ADDR_7_0 */
> -#define AUX_ADDR_7_0(x)				(((x) >> 0) & 0xff)
> -
> -/* EXYNOS_DP_AUX_ADDR_15_8 */
> -#define AUX_ADDR_15_8(x)			(((x) >> 8) & 0xff)
> -
> -/* EXYNOS_DP_AUX_ADDR_19_16 */
> -#define AUX_ADDR_19_16(x)			(((x) >> 16) & 0x0f)
> -
> -/* EXYNOS_DP_AUX_CH_CTL_2 */
> -#define ADDR_ONLY				(0x1 << 1)
> -#define AUX_EN					(0x1 << 0)
> -
> -/* EXYNOS_DP_SOC_GENERAL_CTL */
> -#define AUDIO_MODE_SPDIF_MODE			(0x1 << 8)
> -#define AUDIO_MODE_MASTER_MODE			(0x0 << 8)
> -#define MASTER_VIDEO_INTERLACE_EN		(0x1 << 4)
> -#define VIDEO_MASTER_CLK_SEL			(0x1 << 2)
> -#define VIDEO_MASTER_MODE_EN			(0x1 << 1)
> -#define VIDEO_MODE_MASK				(0x1 << 0)
> -#define VIDEO_MODE_SLAVE_MODE			(0x1 << 0)
> -#define VIDEO_MODE_MASTER_MODE			(0x0 << 0)
> -
> -#endif /* _EXYNOS_DP_REG_H */
> --
> 1.8.4

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

* RE: [PATCH v3 25/32] drm/exynos: Clean up FIMD power on/off routines
  2013-10-29 16:13 ` [PATCH v3 25/32] drm/exynos: Clean up FIMD power on/off routines Sean Paul
@ 2013-10-31 10:54   ` Inki Dae
       [not found]     ` <1630995.NnKzZB9Rl5@flatron>
  2013-11-11  2:09   ` Tomasz Figa
  1 sibling, 1 reply; 130+ messages in thread
From: Inki Dae @ 2013-10-31 10:54 UTC (permalink / raw)
  To: 'Sean Paul', dri-devel; +Cc: marcheu


As I mentioned already, I'll not merge eDP related codes yet. So can you
rebase patche 25 through 26 to top of patch 20?

Thanks,
Inki Dae


> -----Original Message-----
> From: Sean Paul [mailto:seanpaul@chromium.org]
> Sent: Wednesday, October 30, 2013 1:13 AM
> To: dri-devel@lists.freedesktop.org; inki.dae@samsung.com
> Cc: airlied@linux.ie; tomasz.figa@gmail.com; marcheu@chromium.org; Sean
> Paul
> Subject: [PATCH v3 25/32] drm/exynos: Clean up FIMD power on/off routines
> 
> This patch separates the fimd_activate function into poweron/poweroff
> functions to be more consistent with the other drivers in exynos drm. It
> also properly cleans up after failures in poweron. The functions have
> also been shuffled around such that they are all in the same
> spot in the file and poweron/poweroff can be called from the dpms
function.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2:
> 	- Added to the patchset
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 247 +++++++++++++++++---------
> -----
>  1 file changed, 135 insertions(+), 112 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> index c6a05f6..ba12916 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> @@ -324,6 +324,12 @@ static void fimd_win_commit(struct exynos_drm_manager
> *mgr, int zpos)
> 
>  	win_data = &ctx->win_data[win];
> 
> +	/* If suspended, enable this on resume */
> +	if (ctx->suspended) {
> +		win_data->resume = true;
> +		return;
> +	}
> +
>  	/*
>  	 * SHADOWCON/PRTCON register is used for enabling timing.
>  	 *
> @@ -505,35 +511,6 @@ static void fimd_mgr_remove(struct exynos_drm_manager
> *mgr)
>  		drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
>  }
> 
> -static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
> -{
> -	struct fimd_context *ctx = mgr->ctx;
> -
> -	DRM_DEBUG_KMS("%d\n", mode);
> -
> -	switch (mode) {
> -	case DRM_MODE_DPMS_ON:
> -		/*
> -		 * enable fimd hardware only if suspended status.
> -		 *
> -		 * P.S. fimd_dpms function would be called at booting time
so
> -		 * clk_enable could be called double time.
> -		 */
> -		if (ctx->suspended)
> -			pm_runtime_get_sync(ctx->dev);
> -		break;
> -	case DRM_MODE_DPMS_STANDBY:
> -	case DRM_MODE_DPMS_SUSPEND:
> -	case DRM_MODE_DPMS_OFF:
> -		if (!ctx->suspended)
> -			pm_runtime_put_sync(ctx->dev);
> -		break;
> -	default:
> -		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
> -		break;
> -	}
> -}
> -
>  static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
>  		const struct drm_display_mode *mode)
>  {
> @@ -726,6 +703,130 @@ static void fimd_wait_for_vblank(struct
> exynos_drm_manager *mgr)
>  		DRM_DEBUG_KMS("vblank wait timed out.\n");
>  }
> 
> +static void fimd_window_suspend(struct exynos_drm_manager *mgr)
> +{
> +	struct fimd_context *ctx = mgr->ctx;
> +	struct fimd_win_data *win_data;
> +	int i;
> +
> +	for (i = 0; i < WINDOWS_NR; i++) {
> +		win_data = &ctx->win_data[i];
> +		win_data->resume = win_data->enabled;
> +		if (win_data->enabled)
> +			fimd_win_disable(mgr, i);
> +	}
> +	fimd_wait_for_vblank(mgr);
> +}
> +
> +static void fimd_window_resume(struct exynos_drm_manager *mgr)
> +{
> +	struct fimd_context *ctx = mgr->ctx;
> +	struct fimd_win_data *win_data;
> +	int i;
> +
> +	for (i = 0; i < WINDOWS_NR; i++) {
> +		win_data = &ctx->win_data[i];
> +		win_data->enabled = win_data->resume;
> +		win_data->resume = false;
> +	}
> +}
> +
> +static int fimd_poweron(struct exynos_drm_manager *mgr)
> +{
> +	struct fimd_context *ctx = mgr->ctx;
> +	int ret;
> +
> +	if (!ctx->suspended)
> +		return 0;
> +
> +	ctx->suspended = false;
> +
> +	ret = clk_prepare_enable(ctx->bus_clk);
> +	if (ret < 0) {
> +		DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n",
> ret);
> +		goto bus_clk_err;
> +	}
> +
> +	ret = clk_prepare_enable(ctx->lcd_clk);
> +	if  (ret < 0) {
> +		DRM_ERROR("Failed to prepare_enable the lcd clk [%d]\n",
> ret);
> +		goto lcd_clk_err;
> +	}
> +
> +	/* if vblank was enabled status, enable it again. */
> +	if (test_and_clear_bit(0, &ctx->irq_flags)) {
> +		ret = fimd_enable_vblank(mgr);
> +		if (ret) {
> +			DRM_ERROR("Failed to re-enable vblank [%d]\n", ret);
> +			goto enable_vblank_err;
> +		}
> +	}
> +
> +	fimd_window_resume(mgr);
> +
> +	fimd_apply(mgr);
> +
> +	return 0;
> +
> +enable_vblank_err:
> +	clk_disable_unprepare(ctx->lcd_clk);
> +lcd_clk_err:
> +	clk_disable_unprepare(ctx->bus_clk);
> +bus_clk_err:
> +	ctx->suspended = true;
> +	return ret;
> +}
> +
> +static int fimd_poweroff(struct exynos_drm_manager *mgr)
> +{
> +	struct fimd_context *ctx = mgr->ctx;
> +
> +	if (ctx->suspended)
> +		return 0;
> +
> +	/*
> +	 * We need to make sure that all windows are disabled before we
> +	 * suspend that connector. Otherwise we might try to scan from
> +	 * a destroyed buffer later.
> +	 */
> +	fimd_window_suspend(mgr);
> +
> +	clk_disable_unprepare(ctx->lcd_clk);
> +	clk_disable_unprepare(ctx->bus_clk);
> +
> +	ctx->suspended = true;
> +	return 0;
> +}
> +
> +static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
> +{
> +	struct fimd_context *ctx = mgr->ctx;
> +
> +	DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
> +
> +	switch (mode) {
> +	case DRM_MODE_DPMS_ON:
> +		/*
> +		 * enable fimd hardware only if suspended status.
> +		 *
> +		 * P.S. fimd_dpms function would be called at booting time
so
> +		 * clk_enable could be called double time.
> +		 */
> +		if (ctx->suspended)
> +			pm_runtime_get_sync(ctx->dev);
> +		break;
> +	case DRM_MODE_DPMS_STANDBY:
> +	case DRM_MODE_DPMS_SUSPEND:
> +	case DRM_MODE_DPMS_OFF:
> +		if (!ctx->suspended)
> +			pm_runtime_put_sync(ctx->dev);
> +		break;
> +	default:
> +		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
> +		break;
> +	}
> +}
> +
>  static struct exynos_drm_manager_ops fimd_manager_ops = {
>  	.initialize = fimd_mgr_initialize,
>  	.remove = fimd_mgr_remove,
> @@ -786,85 +887,6 @@ static void fimd_clear_win(struct fimd_context *ctx,
> int win)
>  	fimd_shadow_protect_win(ctx, win, false);
>  }
> 
> -static int fimd_clock(struct fimd_context *ctx, bool enable)
> -{
> -	if (enable) {
> -		int ret;
> -
> -		ret = clk_prepare_enable(ctx->bus_clk);
> -		if (ret < 0)
> -			return ret;
> -
> -		ret = clk_prepare_enable(ctx->lcd_clk);
> -		if  (ret < 0) {
> -			clk_disable_unprepare(ctx->bus_clk);
> -			return ret;
> -		}
> -	} else {
> -		clk_disable_unprepare(ctx->lcd_clk);
> -		clk_disable_unprepare(ctx->bus_clk);
> -	}
> -
> -	return 0;
> -}
> -
> -static void fimd_window_suspend(struct exynos_drm_manager *mgr)
> -{
> -	struct fimd_context *ctx = mgr->ctx;
> -	struct fimd_win_data *win_data;
> -	int i;
> -
> -	for (i = 0; i < WINDOWS_NR; i++) {
> -		win_data = &ctx->win_data[i];
> -		win_data->resume = win_data->enabled;
> -		fimd_win_disable(mgr, i);
> -	}
> -	fimd_wait_for_vblank(mgr);
> -}
> -
> -static void fimd_window_resume(struct exynos_drm_manager *mgr)
> -{
> -	struct fimd_context *ctx = mgr->ctx;
> -	struct fimd_win_data *win_data;
> -	int i;
> -
> -	for (i = 0; i < WINDOWS_NR; i++) {
> -		win_data = &ctx->win_data[i];
> -		win_data->enabled = win_data->resume;
> -		win_data->resume = false;
> -	}
> -}
> -
> -static int fimd_activate(struct exynos_drm_manager *mgr, bool enable)
> -{
> -	struct fimd_context *ctx = mgr->ctx;
> -
> -	if (enable) {
> -		int ret;
> -
> -		ret = fimd_clock(ctx, true);
> -		if (ret < 0)
> -			return ret;
> -
> -		ctx->suspended = false;
> -
> -		/* if vblank was enabled status, enable it again. */
> -		if (test_and_clear_bit(0, &ctx->irq_flags))
> -			fimd_enable_vblank(mgr);
> -
> -		fimd_window_resume(mgr);
> -
> -		fimd_apply(mgr);
> -	} else {
> -		fimd_window_suspend(mgr);
> -
> -		fimd_clock(ctx, false);
> -		ctx->suspended = true;
> -	}
> -
> -	return 0;
> -}
> -
>  static int fimd_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -881,6 +903,7 @@ static int fimd_probe(struct platform_device *pdev)
>  		return -ENOMEM;
> 
>  	ctx->dev = dev;
> +	ctx->suspended = true;
> 
>  	if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
>  		ctx->vidcon1 |= VIDCON1_INV_VDEN;
> @@ -967,7 +990,7 @@ static int fimd_suspend(struct device *dev)
>  	 * because the usage_count of pm runtime is more than 1.
>  	 */
>  	if (!pm_runtime_suspended(dev))
> -		return fimd_activate(mgr, false);
> +		return fimd_poweroff(mgr);
> 
>  	return 0;
>  }
> @@ -984,7 +1007,7 @@ static int fimd_resume(struct device *dev)
>  	if (pm_runtime_suspended(dev))
>  		return 0;
> 
> -	return fimd_activate(mgr, true);
> +	return fimd_poweron(mgr);
>  }
>  #endif
> 
> @@ -993,14 +1016,14 @@ static int fimd_runtime_suspend(struct device *dev)
>  {
>  	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
> 
> -	return fimd_activate(mgr, false);
> +	return fimd_poweroff(mgr);
>  }
> 
>  static int fimd_runtime_resume(struct device *dev)
>  {
>  	struct exynos_drm_manager *mgr = get_fimd_manager(dev);
> 
> -	return fimd_activate(mgr, true);
> +	return fimd_poweron(mgr);
>  }
>  #endif
> 
> --
> 1.8.4

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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
  2013-10-31 10:46   ` Inki Dae
@ 2013-10-31 16:05     ` Sean Paul
  2013-10-31 23:06       ` Jingoo Han
  1 sibling, 0 replies; 130+ messages in thread
From: Sean Paul @ 2013-10-31 16:05 UTC (permalink / raw)
  To: Inki Dae; +Cc: Stéphane Marchesin, Jingoo Han, dri-devel

On Thu, Oct 31, 2013 at 6:46 AM, Inki Dae <inki.dae@samsung.com> wrote:
> CCing Jingoo,
>
> Is that ok to remove eDP driver from video/exynos? Isn't this driver really
> used by Linux framebuffer driver, s3c-fb.c?
>
> Of course, now s3c-fb driver is dead code because this driver doesn't
> support device tree yet but we would need more reviews and discussions about
> moving this driver into drm side. Let's watch new rules for device tree
> bindings of DRM world. So I'd not like to merge this driver yet.
>

Hi Inki,
I don't think that the dt bindings conversation has any bearing on
this patch. IMO, the justification for doing this is:

- Suspend/resume/dpms is currently broken for boards that use the edp driver
- HDMI driver is already in drm, so it makes sense to have DP in as well
- This allows us to do things like proper hpd, and EDID in DP driver
- Allows us to remove all encoder/connector oriented code from fimd

We've been talking about this for over 10 months now, is there really
anything left to discuss?

Sean



> Thanks,
> Inki Dae
>
>> -----Original Message-----
>> From: Sean Paul [mailto:seanpaul@chromium.org]
>> Sent: Wednesday, October 30, 2013 1:13 AM
>> To: dri-devel@lists.freedesktop.org; inki.dae@samsung.com
>> Cc: airlied@linux.ie; tomasz.figa@gmail.com; marcheu@chromium.org; Sean
>> Paul
>> Subject: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
>>
>> This patch moves the code from video/ to drm/
>>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>
>> Changes in v2: None
>> Changes in v3: None
>>
>>  drivers/gpu/drm/exynos/Kconfig          |    7 +
>>  drivers/gpu/drm/exynos/Makefile         |    1 +
>>  drivers/gpu/drm/exynos/exynos_dp_core.c | 1213
>> ++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/exynos/exynos_dp_core.h |  210 ++++++
>>  drivers/gpu/drm/exynos/exynos_dp_reg.c  | 1245
>> +++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/exynos/exynos_dp_reg.h  |  366 +++++++++
>>  drivers/video/exynos/Kconfig            |    7 -
>>  drivers/video/exynos/Makefile           |    1 -
>>  drivers/video/exynos/exynos_dp_core.c   | 1213
> ---------------------------
>> ---
>>  drivers/video/exynos/exynos_dp_core.h   |  210 ------
>>  drivers/video/exynos/exynos_dp_reg.c    | 1245
> ---------------------------
>> ----
>>  drivers/video/exynos/exynos_dp_reg.h    |  366 ---------
>>  12 files changed, 3042 insertions(+), 3042 deletions(-)
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.h
>>  delete mode 100644 drivers/video/exynos/exynos_dp_core.c
>>  delete mode 100644 drivers/video/exynos/exynos_dp_core.h
>>  delete mode 100644 drivers/video/exynos/exynos_dp_reg.c
>>  delete mode 100644 drivers/video/exynos/exynos_dp_reg.h
>>
>> diff --git a/drivers/gpu/drm/exynos/Kconfig
>> b/drivers/gpu/drm/exynos/Kconfig
>> index 45b6ef5..3ace74f 100644
>> --- a/drivers/gpu/drm/exynos/Kconfig
>> +++ b/drivers/gpu/drm/exynos/Kconfig
>> @@ -30,6 +30,13 @@ config DRM_EXYNOS_FIMD
>>       help
>>         Choose this option if you want to use Exynos FIMD for DRM.
>>
>> +config DRM_EXYNOS_DP
>> +     bool "EXYNOS DRM DP driver support"
>> +     depends on ARCH_EXYNOS
>> +     default n
>> +     help
>> +       This enables support for DP device.
>> +
>>  config DRM_EXYNOS_HDMI
>>       bool "Exynos DRM HDMI"
>>       depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV
>> diff --git a/drivers/gpu/drm/exynos/Makefile
>> b/drivers/gpu/drm/exynos/Makefile
>> index afbe499..fc8555c 100644
>> --- a/drivers/gpu/drm/exynos/Makefile
>> +++ b/drivers/gpu/drm/exynos/Makefile
>> @@ -11,6 +11,7 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o
>> exynos_drm_connector.o \
>>  exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
>>  exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
>>  exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)  += exynos_drm_fimd.o
>> +exynosdrm-$(CONFIG_DRM_EXYNOS_DP)    += exynos_dp_core.o
>> exynos_dp_reg.o
>>  exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)  += exynos_hdmi.o exynos_mixer.o
>>  exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)  += exynos_drm_vidi.o
>>  exynosdrm-$(CONFIG_DRM_EXYNOS_G2D)   += exynos_drm_g2d.o
>> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c
>> b/drivers/gpu/drm/exynos/exynos_dp_core.c
>> new file mode 100644
>> index 0000000..089ae22
>> --- /dev/null
>> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
>> @@ -0,0 +1,1213 @@
>> +/*
>> + * Samsung SoC DP (Display Port) interface driver.
>> + *
>> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
>> + * Author: Jingoo Han <jg1.han@samsung.com>
>> + *
>> + * 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/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/err.h>
>> +#include <linux/clk.h>
>> +#include <linux/io.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/delay.h>
>> +#include <linux/of.h>
>> +
>> +#include <video/exynos_dp.h>
>> +
>> +#include "exynos_dp_core.h"
>> +
>> +static int exynos_dp_init_dp(struct exynos_dp_device *dp)
>> +{
>> +     exynos_dp_reset(dp);
>> +
>> +     exynos_dp_swreset(dp);
>> +
>> +     exynos_dp_init_analog_param(dp);
>> +     exynos_dp_init_interrupt(dp);
>> +
>> +     /* SW defined function Normal operation */
>> +     exynos_dp_enable_sw_function(dp);
>> +
>> +     exynos_dp_config_interrupt(dp);
>> +     exynos_dp_init_analog_func(dp);
>> +
>> +     exynos_dp_init_hpd(dp);
>> +     exynos_dp_init_aux(dp);
>> +
>> +     return 0;
>> +}
>> +
>> +static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
>> +{
>> +     int timeout_loop = 0;
>> +
>> +     while (exynos_dp_get_plug_in_status(dp) != 0) {
>> +             timeout_loop++;
>> +             if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
>> +                     dev_err(dp->dev, "failed to get hpd plug status\n");
>> +                     return -ETIMEDOUT;
>> +             }
>> +             usleep_range(10, 11);
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static unsigned char exynos_dp_calc_edid_check_sum(unsigned char
>> *edid_data)
>> +{
>> +     int i;
>> +     unsigned char sum = 0;
>> +
>> +     for (i = 0; i < EDID_BLOCK_LENGTH; i++)
>> +             sum = sum + edid_data[i];
>> +
>> +     return sum;
>> +}
>> +
>> +static int exynos_dp_read_edid(struct exynos_dp_device *dp)
>> +{
>> +     unsigned char edid[EDID_BLOCK_LENGTH * 2];
>> +     unsigned int extend_block = 0;
>> +     unsigned char sum;
>> +     unsigned char test_vector;
>> +     int retval;
>> +
>> +     /*
>> +      * EDID device address is 0x50.
>> +      * However, if necessary, you must have set upper address
>> +      * into E-EDID in I2C device, 0x30.
>> +      */
>> +
>> +     /* Read Extension Flag, Number of 128-byte EDID extension blocks */
>> +     retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
>> +                             EDID_EXTENSION_FLAG,
>> +                             &extend_block);
>> +     if (retval)
>> +             return retval;
>> +
>> +     if (extend_block > 0) {
>> +             dev_dbg(dp->dev, "EDID data includes a single
> extension!\n");
>> +
>> +             /* Read EDID data */
>> +             retval = exynos_dp_read_bytes_from_i2c(dp,
>> I2C_EDID_DEVICE_ADDR,
>> +                                             EDID_HEADER_PATTERN,
>> +                                             EDID_BLOCK_LENGTH,
>> +                                             &edid[EDID_HEADER_PATTERN]);
>> +             if (retval != 0) {
>> +                     dev_err(dp->dev, "EDID Read failed!\n");
>> +                     return -EIO;
>> +             }
>> +             sum = exynos_dp_calc_edid_check_sum(edid);
>> +             if (sum != 0) {
>> +                     dev_err(dp->dev, "EDID bad checksum!\n");
>> +                     return -EIO;
>> +             }
>> +
>> +             /* Read additional EDID data */
>> +             retval = exynos_dp_read_bytes_from_i2c(dp,
>> +                             I2C_EDID_DEVICE_ADDR,
>> +                             EDID_BLOCK_LENGTH,
>> +                             EDID_BLOCK_LENGTH,
>> +                             &edid[EDID_BLOCK_LENGTH]);
>> +             if (retval != 0) {
>> +                     dev_err(dp->dev, "EDID Read failed!\n");
>> +                     return -EIO;
>> +             }
>> +             sum =
>> exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
>> +             if (sum != 0) {
>> +                     dev_err(dp->dev, "EDID bad checksum!\n");
>> +                     return -EIO;
>> +             }
>> +
>> +             exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
>> +                                     &test_vector);
>> +             if (test_vector & DPCD_TEST_EDID_READ) {
>> +                     exynos_dp_write_byte_to_dpcd(dp,
>> +                             DPCD_ADDR_TEST_EDID_CHECKSUM,
>> +                             edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
>> +                     exynos_dp_write_byte_to_dpcd(dp,
>> +                             DPCD_ADDR_TEST_RESPONSE,
>> +                             DPCD_TEST_EDID_CHECKSUM_WRITE);
>> +             }
>> +     } else {
>> +             dev_info(dp->dev, "EDID data does not include any
>> extensions.\n");
>> +
>> +             /* Read EDID data */
>> +             retval = exynos_dp_read_bytes_from_i2c(dp,
>> +                             I2C_EDID_DEVICE_ADDR,
>> +                             EDID_HEADER_PATTERN,
>> +                             EDID_BLOCK_LENGTH,
>> +                             &edid[EDID_HEADER_PATTERN]);
>> +             if (retval != 0) {
>> +                     dev_err(dp->dev, "EDID Read failed!\n");
>> +                     return -EIO;
>> +             }
>> +             sum = exynos_dp_calc_edid_check_sum(edid);
>> +             if (sum != 0) {
>> +                     dev_err(dp->dev, "EDID bad checksum!\n");
>> +                     return -EIO;
>> +             }
>> +
>> +             exynos_dp_read_byte_from_dpcd(dp,
>> +                     DPCD_ADDR_TEST_REQUEST,
>> +                     &test_vector);
>> +             if (test_vector & DPCD_TEST_EDID_READ) {
>> +                     exynos_dp_write_byte_to_dpcd(dp,
>> +                             DPCD_ADDR_TEST_EDID_CHECKSUM,
>> +                             edid[EDID_CHECKSUM]);
>> +                     exynos_dp_write_byte_to_dpcd(dp,
>> +                             DPCD_ADDR_TEST_RESPONSE,
>> +                             DPCD_TEST_EDID_CHECKSUM_WRITE);
>> +             }
>> +     }
>> +
>> +     dev_err(dp->dev, "EDID Read success!\n");
>> +     return 0;
>> +}
>> +
>> +static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
>> +{
>> +     u8 buf[12];
>> +     int i;
>> +     int retval;
>> +
>> +     /* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
>> +     retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
>> +                             12, buf);
>> +     if (retval)
>> +             return retval;
>> +
>> +     /* Read EDID */
>> +     for (i = 0; i < 3; i++) {
>> +             retval = exynos_dp_read_edid(dp);
>> +             if (!retval)
>> +                     break;
>> +     }
>> +
>> +     return retval;
>> +}
>> +
>> +static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device
>> *dp,
>> +                                             bool enable)
>> +{
>> +     u8 data;
>> +
>> +     exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
>> +
>> +     if (enable)
>> +             exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
>> +                     DPCD_ENHANCED_FRAME_EN |
>> +                     DPCD_LANE_COUNT_SET(data));
>> +     else
>> +             exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
>> +                     DPCD_LANE_COUNT_SET(data));
>> +}
>> +
>> +static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device
>> *dp)
>> +{
>> +     u8 data;
>> +     int retval;
>> +
>> +     exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
>> +     retval = DPCD_ENHANCED_FRAME_CAP(data);
>> +
>> +     return retval;
>> +}
>> +
>> +static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
>> +{
>> +     u8 data;
>> +
>> +     data = exynos_dp_is_enhanced_mode_available(dp);
>> +     exynos_dp_enable_rx_to_enhanced_mode(dp, data);
>> +     exynos_dp_enable_enhanced_mode(dp, data);
>> +}
>> +
>> +static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
>> +{
>> +     exynos_dp_set_training_pattern(dp, DP_NONE);
>> +
>> +     exynos_dp_write_byte_to_dpcd(dp,
>> +             DPCD_ADDR_TRAINING_PATTERN_SET,
>> +             DPCD_TRAINING_PATTERN_DISABLED);
>> +}
>> +
>> +static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device
>> *dp,
>> +                                     int pre_emphasis, int lane)
>> +{
>> +     switch (lane) {
>> +     case 0:
>> +             exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
>> +             break;
>> +     case 1:
>> +             exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
>> +             break;
>> +
>> +     case 2:
>> +             exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
>> +             break;
>> +
>> +     case 3:
>> +             exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
>> +             break;
>> +     }
>> +}
>> +
>> +static int exynos_dp_link_start(struct exynos_dp_device *dp)
>> +{
>> +     u8 buf[4];
>> +     int lane, lane_count, pll_tries, retval;
>> +
>> +     lane_count = dp->link_train.lane_count;
>> +
>> +     dp->link_train.lt_state = CLOCK_RECOVERY;
>> +     dp->link_train.eq_loop = 0;
>> +
>> +     for (lane = 0; lane < lane_count; lane++)
>> +             dp->link_train.cr_loop[lane] = 0;
>> +
>> +     /* Set link rate and count as you want to establish*/
>> +     exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
>> +     exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
>> +
>> +     /* Setup RX configuration */
>> +     buf[0] = dp->link_train.link_rate;
>> +     buf[1] = dp->link_train.lane_count;
>> +     retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
>> +                             2, buf);
>> +     if (retval)
>> +             return retval;
>> +
>> +     /* Set TX pre-emphasis to minimum */
>> +     for (lane = 0; lane < lane_count; lane++)
>> +             exynos_dp_set_lane_lane_pre_emphasis(dp,
>> +                     PRE_EMPHASIS_LEVEL_0, lane);
>> +
>> +     /* Wait for PLL lock */
>> +     pll_tries = 0;
>> +     while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
>> +             if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
>> +                     dev_err(dp->dev, "Wait for PLL lock timed out\n");
>> +                     return -ETIMEDOUT;
>> +             }
>> +
>> +             pll_tries++;
>> +             usleep_range(90, 120);
>> +     }
>> +
>> +     /* Set training pattern 1 */
>> +     exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
>> +
>> +     /* Set RX training pattern */
>> +     retval = exynos_dp_write_byte_to_dpcd(dp,
>> +                     DPCD_ADDR_TRAINING_PATTERN_SET,
>> +                     DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
>> +     if (retval)
>> +             return retval;
>> +
>> +     for (lane = 0; lane < lane_count; lane++)
>> +             buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
>> +                         DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
>> +
>> +     retval = exynos_dp_write_bytes_to_dpcd(dp,
>> DPCD_ADDR_TRAINING_LANE0_SET,
>> +                     lane_count, buf);
>> +
>> +     return retval;
>> +}
>> +
>> +static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int
>> lane)
>> +{
>> +     int shift = (lane & 1) * 4;
>> +     u8 link_value = link_status[lane>>1];
>> +
>> +     return (link_value >> shift) & 0xf;
>> +}
>> +
>> +static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
>> +{
>> +     int lane;
>> +     u8 lane_status;
>> +
>> +     for (lane = 0; lane < lane_count; lane++) {
>> +             lane_status = exynos_dp_get_lane_status(link_status, lane);
>> +             if ((lane_status & DPCD_LANE_CR_DONE) == 0)
>> +                     return -EINVAL;
>> +     }
>> +     return 0;
>> +}
>> +
>> +static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
>> +                             int lane_count)
>> +{
>> +     int lane;
>> +     u8 lane_status;
>> +
>> +     if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
>> +             return -EINVAL;
>> +
>> +     for (lane = 0; lane < lane_count; lane++) {
>> +             lane_status = exynos_dp_get_lane_status(link_status, lane);
>> +             lane_status &= DPCD_CHANNEL_EQ_BITS;
>> +             if (lane_status != DPCD_CHANNEL_EQ_BITS)
>> +                     return -EINVAL;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static unsigned char exynos_dp_get_adjust_request_voltage(u8
>> adjust_request[2],
>> +                                                     int lane)
>> +{
>> +     int shift = (lane & 1) * 4;
>> +     u8 link_value = adjust_request[lane>>1];
>> +
>> +     return (link_value >> shift) & 0x3;
>> +}
>> +
>> +static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
>> +                                     u8 adjust_request[2],
>> +                                     int lane)
>> +{
>> +     int shift = (lane & 1) * 4;
>> +     u8 link_value = adjust_request[lane>>1];
>> +
>> +     return ((link_value >> shift) & 0xc) >> 2;
>> +}
>> +
>> +static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
>> +                                     u8 training_lane_set, int lane)
>> +{
>> +     switch (lane) {
>> +     case 0:
>> +             exynos_dp_set_lane0_link_training(dp, training_lane_set);
>> +             break;
>> +     case 1:
>> +             exynos_dp_set_lane1_link_training(dp, training_lane_set);
>> +             break;
>> +
>> +     case 2:
>> +             exynos_dp_set_lane2_link_training(dp, training_lane_set);
>> +             break;
>> +
>> +     case 3:
>> +             exynos_dp_set_lane3_link_training(dp, training_lane_set);
>> +             break;
>> +     }
>> +}
>> +
>> +static unsigned int exynos_dp_get_lane_link_training(
>> +                             struct exynos_dp_device *dp,
>> +                             int lane)
>> +{
>> +     u32 reg;
>> +
>> +     switch (lane) {
>> +     case 0:
>> +             reg = exynos_dp_get_lane0_link_training(dp);
>> +             break;
>> +     case 1:
>> +             reg = exynos_dp_get_lane1_link_training(dp);
>> +             break;
>> +     case 2:
>> +             reg = exynos_dp_get_lane2_link_training(dp);
>> +             break;
>> +     case 3:
>> +             reg = exynos_dp_get_lane3_link_training(dp);
>> +             break;
>> +     default:
>> +             WARN_ON(1);
>> +             return 0;
>> +     }
>> +
>> +     return reg;
>> +}
>> +
>> +static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
>> +{
>> +     exynos_dp_training_pattern_dis(dp);
>> +     exynos_dp_set_enhanced_mode(dp);
>> +
>> +     dp->link_train.lt_state = FAILED;
>> +}
>> +
>> +static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device
>> *dp,
>> +                                     u8 adjust_request[2])
>> +{
>> +     int lane, lane_count;
>> +     u8 voltage_swing, pre_emphasis, training_lane;
>> +
>> +     lane_count = dp->link_train.lane_count;
>> +     for (lane = 0; lane < lane_count; lane++) {
>> +             voltage_swing = exynos_dp_get_adjust_request_voltage(
>> +                                             adjust_request, lane);
>> +             pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
>> +                                             adjust_request, lane);
>> +             training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
>> +                             DPCD_PRE_EMPHASIS_SET(pre_emphasis);
>> +
>> +             if (voltage_swing == VOLTAGE_LEVEL_3)
>> +                     training_lane |= DPCD_MAX_SWING_REACHED;
>> +             if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
>> +                     training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
>> +
>> +             dp->link_train.training_lane[lane] = training_lane;
>> +     }
>> +}
>> +
>> +static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
>> +{
>> +     int lane, lane_count, retval;
>> +     u8 voltage_swing, pre_emphasis, training_lane;
>> +     u8 link_status[2], adjust_request[2];
>> +
>> +     usleep_range(100, 101);
>> +
>> +     lane_count = dp->link_train.lane_count;
>> +
>> +     retval =  exynos_dp_read_bytes_from_dpcd(dp,
>> +                     DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
>> +     if (retval)
>> +             return retval;
>> +
>> +     retval =  exynos_dp_read_bytes_from_dpcd(dp,
>> +                     DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2,
> adjust_request);
>> +     if (retval)
>> +             return retval;
>> +
>> +     if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
>> +             /* set training pattern 2 for EQ */
>> +             exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
>> +
>> +             retval = exynos_dp_write_byte_to_dpcd(dp,
>> +                             DPCD_ADDR_TRAINING_PATTERN_SET,
>> +                             DPCD_SCRAMBLING_DISABLED |
>> +                             DPCD_TRAINING_PATTERN_2);
>> +             if (retval)
>> +                     return retval;
>> +
>> +             dev_info(dp->dev, "Link Training Clock Recovery success\n");
>> +             dp->link_train.lt_state = EQUALIZER_TRAINING;
>> +     } else {
>> +             for (lane = 0; lane < lane_count; lane++) {
>> +                     training_lane = exynos_dp_get_lane_link_training(
>> +                                                     dp, lane);
>> +                     voltage_swing =
> exynos_dp_get_adjust_request_voltage(
>> +                                                     adjust_request,
> lane);
>> +                     pre_emphasis =
>> exynos_dp_get_adjust_request_pre_emphasis(
>> +                                                     adjust_request,
> lane);
>> +
>> +                     if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
>> +                                     voltage_swing &&
>> +                         DPCD_PRE_EMPHASIS_GET(training_lane) ==
>> +                                     pre_emphasis)
>> +                             dp->link_train.cr_loop[lane]++;
>> +
>> +                     if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
>> +                         voltage_swing == VOLTAGE_LEVEL_3 ||
>> +                         pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
>> +                             dev_err(dp->dev, "CR Max reached
> (%d,%d,%d)\n",
>> +                                     dp->link_train.cr_loop[lane],
>> +                                     voltage_swing, pre_emphasis);
>> +                             exynos_dp_reduce_link_rate(dp);
>> +                             return -EIO;
>> +                     }
>> +             }
>> +     }
>> +
>> +     exynos_dp_get_adjust_training_lane(dp, adjust_request);
>> +
>> +     for (lane = 0; lane < lane_count; lane++)
>> +             exynos_dp_set_lane_link_training(dp,
>> +                     dp->link_train.training_lane[lane], lane);
>> +
>> +     retval = exynos_dp_write_bytes_to_dpcd(dp,
>> +                     DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
>> +                     dp->link_train.training_lane);
>> +     if (retval)
>> +             return retval;
>> +
>> +     return retval;
>> +}
>> +
>> +static int exynos_dp_process_equalizer_training(struct exynos_dp_device
>> *dp)
>> +{
>> +     int lane, lane_count, retval;
>> +     u32 reg;
>> +     u8 link_align, link_status[2], adjust_request[2];
>> +
>> +     usleep_range(400, 401);
>> +
>> +     lane_count = dp->link_train.lane_count;
>> +
>> +     retval = exynos_dp_read_bytes_from_dpcd(dp,
>> +                     DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
>> +     if (retval)
>> +             return retval;
>> +
>> +     if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
>> +             exynos_dp_reduce_link_rate(dp);
>> +             return -EIO;
>> +     }
>> +
>> +     retval = exynos_dp_read_bytes_from_dpcd(dp,
>> +                     DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2,
> adjust_request);
>> +     if (retval)
>> +             return retval;
>> +
>> +     retval = exynos_dp_read_byte_from_dpcd(dp,
>> +                     DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
>> +     if (retval)
>> +             return retval;
>> +
>> +     exynos_dp_get_adjust_training_lane(dp, adjust_request);
>> +
>> +     if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count))
>> {
>> +             /* traing pattern Set to Normal */
>> +             exynos_dp_training_pattern_dis(dp);
>> +
>> +             dev_info(dp->dev, "Link Training success!\n");
>> +
>> +             exynos_dp_get_link_bandwidth(dp, &reg);
>> +             dp->link_train.link_rate = reg;
>> +             dev_dbg(dp->dev, "final bandwidth = %.2x\n",
>> +                     dp->link_train.link_rate);
>> +
>> +             exynos_dp_get_lane_count(dp, &reg);
>> +             dp->link_train.lane_count = reg;
>> +             dev_dbg(dp->dev, "final lane count = %.2x\n",
>> +                     dp->link_train.lane_count);
>> +
>> +             /* set enhanced mode if available */
>> +             exynos_dp_set_enhanced_mode(dp);
>> +             dp->link_train.lt_state = FINISHED;
>> +
>> +             return 0;
>> +     }
>> +
>> +     /* not all locked */
>> +     dp->link_train.eq_loop++;
>> +
>> +     if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
>> +             dev_err(dp->dev, "EQ Max loop\n");
>> +             exynos_dp_reduce_link_rate(dp);
>> +             return -EIO;
>> +     }
>> +
>> +     for (lane = 0; lane < lane_count; lane++)
>> +             exynos_dp_set_lane_link_training(dp,
>> +                     dp->link_train.training_lane[lane], lane);
>> +
>> +     retval = exynos_dp_write_bytes_to_dpcd(dp,
>> DPCD_ADDR_TRAINING_LANE0_SET,
>> +                     lane_count, dp->link_train.training_lane);
>> +
>> +     return retval;
>> +}
>> +
>> +static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
>> +                                     u8 *bandwidth)
>> +{
>> +     u8 data;
>> +
>> +     /*
>> +      * For DP rev.1.1, Maximum link rate of Main Link lanes
>> +      * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
>> +      */
>> +     exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
>> +     *bandwidth = data;
>> +}
>> +
>> +static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
>> +                                     u8 *lane_count)
>> +{
>> +     u8 data;
>> +
>> +     /*
>> +      * For DP rev.1.1, Maximum number of Main Link lanes
>> +      * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
>> +      */
>> +     exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
>> +     *lane_count = DPCD_MAX_LANE_COUNT(data);
>> +}
>> +
>> +static void exynos_dp_init_training(struct exynos_dp_device *dp,
>> +                     enum link_lane_count_type max_lane,
>> +                     enum link_rate_type max_rate)
>> +{
>> +     /*
>> +      * MACRO_RST must be applied after the PLL_LOCK to avoid
>> +      * the DP inter pair skew issue for at least 10 us
>> +      */
>> +     exynos_dp_reset_macro(dp);
>> +
>> +     /* Initialize by reading RX's DPCD */
>> +     exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
>> +     exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
>> +
>> +     if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
>> +        (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
>> +             dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
>> +                     dp->link_train.link_rate);
>> +             dp->link_train.link_rate = LINK_RATE_1_62GBPS;
>> +     }
>> +
>> +     if (dp->link_train.lane_count == 0) {
>> +             dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
>> +                     dp->link_train.lane_count);
>> +             dp->link_train.lane_count = (u8)LANE_COUNT1;
>> +     }
>> +
>> +     /* Setup TX lane count & rate */
>> +     if (dp->link_train.lane_count > max_lane)
>> +             dp->link_train.lane_count = max_lane;
>> +     if (dp->link_train.link_rate > max_rate)
>> +             dp->link_train.link_rate = max_rate;
>> +
>> +     /* All DP analog module power up */
>> +     exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
>> +}
>> +
>> +static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
>> +{
>> +     int retval = 0, training_finished = 0;
>> +
>> +     dp->link_train.lt_state = START;
>> +
>> +     /* Process here */
>> +     while (!retval && !training_finished) {
>> +             switch (dp->link_train.lt_state) {
>> +             case START:
>> +                     retval = exynos_dp_link_start(dp);
>> +                     if (retval)
>> +                             dev_err(dp->dev, "LT link start failed!\n");
>> +                     break;
>> +             case CLOCK_RECOVERY:
>> +                     retval = exynos_dp_process_clock_recovery(dp);
>> +                     if (retval)
>> +                             dev_err(dp->dev, "LT CR failed!\n");
>> +                     break;
>> +             case EQUALIZER_TRAINING:
>> +                     retval = exynos_dp_process_equalizer_training(dp);
>> +                     if (retval)
>> +                             dev_err(dp->dev, "LT EQ failed!\n");
>> +                     break;
>> +             case FINISHED:
>> +                     training_finished = 1;
>> +                     break;
>> +             case FAILED:
>> +                     return -EREMOTEIO;
>> +             }
>> +     }
>> +     if (retval)
>> +             dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
>> +
>> +     return retval;
>> +}
>> +
>> +static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
>> +                             u32 count,
>> +                             u32 bwtype)
>> +{
>> +     int i;
>> +     int retval;
>> +
>> +     for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
>> +             exynos_dp_init_training(dp, count, bwtype);
>> +             retval = exynos_dp_sw_link_training(dp);
>> +             if (retval == 0)
>> +                     break;
>> +
>> +             usleep_range(100, 110);
>> +     }
>> +
>> +     return retval;
>> +}
>> +
>> +static int exynos_dp_config_video(struct exynos_dp_device *dp)
>> +{
>> +     int retval = 0;
>> +     int timeout_loop = 0;
>> +     int done_count = 0;
>> +
>> +     exynos_dp_config_video_slave_mode(dp);
>> +
>> +     exynos_dp_set_video_color_format(dp);
>> +
>> +     if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
>> +             dev_err(dp->dev, "PLL is not locked yet.\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     for (;;) {
>> +             timeout_loop++;
>> +             if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
>> +                     break;
>> +             if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
>> +                     dev_err(dp->dev, "Timeout of video streamclk ok\n");
>> +                     return -ETIMEDOUT;
>> +             }
>> +
>> +             usleep_range(1, 2);
>> +     }
>> +
>> +     /* Set to use the register calculated M/N video */
>> +     exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
>> +
>> +     /* For video bist, Video timing must be generated by register */
>> +     exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
>> +
>> +     /* Disable video mute */
>> +     exynos_dp_enable_video_mute(dp, 0);
>> +
>> +     /* Configure video slave mode */
>> +     exynos_dp_enable_video_master(dp, 0);
>> +
>> +     /* Enable video */
>> +     exynos_dp_start_video(dp);
>> +
>> +     timeout_loop = 0;
>> +
>> +     for (;;) {
>> +             timeout_loop++;
>> +             if (exynos_dp_is_video_stream_on(dp) == 0) {
>> +                     done_count++;
>> +                     if (done_count > 10)
>> +                             break;
>> +             } else if (done_count) {
>> +                     done_count = 0;
>> +             }
>> +             if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
>> +                     dev_err(dp->dev, "Timeout of video streamclk ok\n");
>> +                     return -ETIMEDOUT;
>> +             }
>> +
>> +             usleep_range(1000, 1001);
>> +     }
>> +
>> +     if (retval != 0)
>> +             dev_err(dp->dev, "Video stream is not detected!\n");
>> +
>> +     return retval;
>> +}
>> +
>> +static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool
>> enable)
>> +{
>> +     u8 data;
>> +
>> +     if (enable) {
>> +             exynos_dp_enable_scrambling(dp);
>> +
>> +             exynos_dp_read_byte_from_dpcd(dp,
>> +                     DPCD_ADDR_TRAINING_PATTERN_SET,
>> +                     &data);
>> +             exynos_dp_write_byte_to_dpcd(dp,
>> +                     DPCD_ADDR_TRAINING_PATTERN_SET,
>> +                     (u8)(data & ~DPCD_SCRAMBLING_DISABLED));
>> +     } else {
>> +             exynos_dp_disable_scrambling(dp);
>> +
>> +             exynos_dp_read_byte_from_dpcd(dp,
>> +                     DPCD_ADDR_TRAINING_PATTERN_SET,
>> +                     &data);
>> +             exynos_dp_write_byte_to_dpcd(dp,
>> +                     DPCD_ADDR_TRAINING_PATTERN_SET,
>> +                     (u8)(data | DPCD_SCRAMBLING_DISABLED));
>> +     }
>> +}
>> +
>> +static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
>> +{
>> +     struct exynos_dp_device *dp = arg;
>> +
>> +     enum dp_irq_type irq_type;
>> +
>> +     irq_type = exynos_dp_get_irq_type(dp);
>> +     switch (irq_type) {
>> +     case DP_IRQ_TYPE_HP_CABLE_IN:
>> +             dev_dbg(dp->dev, "Received irq - cable in\n");
>> +             schedule_work(&dp->hotplug_work);
>> +             exynos_dp_clear_hotplug_interrupts(dp);
>> +             break;
>> +     case DP_IRQ_TYPE_HP_CABLE_OUT:
>> +             dev_dbg(dp->dev, "Received irq - cable out\n");
>> +             exynos_dp_clear_hotplug_interrupts(dp);
>> +             break;
>> +     case DP_IRQ_TYPE_HP_CHANGE:
>> +             /*
>> +              * We get these change notifications once in a while, but
>> there
>> +              * is nothing we can do with them. Just ignore it for now
> and
>> +              * only handle cable changes.
>> +              */
>> +             dev_dbg(dp->dev, "Received irq - hotplug change;
>> ignoring.\n");
>> +             exynos_dp_clear_hotplug_interrupts(dp);
>> +             break;
>> +     default:
>> +             dev_err(dp->dev, "Received irq - unknown type!\n");
>> +             break;
>> +     }
>> +     return IRQ_HANDLED;
>> +}
>> +
>> +static void exynos_dp_hotplug(struct work_struct *work)
>> +{
>> +     struct exynos_dp_device *dp;
>> +     int ret;
>> +
>> +     dp = container_of(work, struct exynos_dp_device, hotplug_work);
>> +
>> +     ret = exynos_dp_detect_hpd(dp);
>> +     if (ret) {
>> +             /* Cable has been disconnected, we're done */
>> +             return;
>> +     }
>> +
>> +     ret = exynos_dp_handle_edid(dp);
>> +     if (ret) {
>> +             dev_err(dp->dev, "unable to handle edid\n");
>> +             return;
>> +     }
>> +
>> +     ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
>> +                                     dp->video_info->link_rate);
>> +     if (ret) {
>> +             dev_err(dp->dev, "unable to do link train\n");
>> +             return;
>> +     }
>> +
>> +     exynos_dp_enable_scramble(dp, 1);
>> +     exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
>> +     exynos_dp_enable_enhanced_mode(dp, 1);
>> +
>> +     exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
>> +     exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
>> +
>> +     exynos_dp_init_video(dp);
>> +     ret = exynos_dp_config_video(dp);
>> +     if (ret)
>> +             dev_err(dp->dev, "unable to config video\n");
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device
>> *dev)
>> +{
>> +     struct device_node *dp_node = dev->of_node;
>> +     struct exynos_dp_platdata *pd;
>> +     struct video_info *dp_video_config;
>> +
>> +     pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
>> +     if (!pd) {
>> +             dev_err(dev, "memory allocation for pdata failed\n");
>> +             return ERR_PTR(-ENOMEM);
>> +     }
>> +     dp_video_config = devm_kzalloc(dev,
>> +                             sizeof(*dp_video_config), GFP_KERNEL);
>> +
>> +     if (!dp_video_config) {
>> +             dev_err(dev, "memory allocation for video config failed\n");
>> +             return ERR_PTR(-ENOMEM);
>> +     }
>> +     pd->video_info = dp_video_config;
>> +
>> +     dp_video_config->h_sync_polarity =
>> +             of_property_read_bool(dp_node, "hsync-active-high");
>> +
>> +     dp_video_config->v_sync_polarity =
>> +             of_property_read_bool(dp_node, "vsync-active-high");
>> +
>> +     dp_video_config->interlaced =
>> +             of_property_read_bool(dp_node, "interlaced");
>> +
>> +     if (of_property_read_u32(dp_node, "samsung,color-space",
>> +                             &dp_video_config->color_space)) {
>> +             dev_err(dev, "failed to get color-space\n");
>> +             return ERR_PTR(-EINVAL);
>> +     }
>> +
>> +     if (of_property_read_u32(dp_node, "samsung,dynamic-range",
>> +                             &dp_video_config->dynamic_range)) {
>> +             dev_err(dev, "failed to get dynamic-range\n");
>> +             return ERR_PTR(-EINVAL);
>> +     }
>> +
>> +     if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
>> +                             &dp_video_config->ycbcr_coeff)) {
>> +             dev_err(dev, "failed to get ycbcr-coeff\n");
>> +             return ERR_PTR(-EINVAL);
>> +     }
>> +
>> +     if (of_property_read_u32(dp_node, "samsung,color-depth",
>> +                             &dp_video_config->color_depth)) {
>> +             dev_err(dev, "failed to get color-depth\n");
>> +             return ERR_PTR(-EINVAL);
>> +     }
>> +
>> +     if (of_property_read_u32(dp_node, "samsung,link-rate",
>> +                             &dp_video_config->link_rate)) {
>> +             dev_err(dev, "failed to get link-rate\n");
>> +             return ERR_PTR(-EINVAL);
>> +     }
>> +
>> +     if (of_property_read_u32(dp_node, "samsung,lane-count",
>> +                             &dp_video_config->lane_count)) {
>> +             dev_err(dev, "failed to get lane-count\n");
>> +             return ERR_PTR(-EINVAL);
>> +     }
>> +
>> +     return pd;
>> +}
>> +
>> +static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
>> +{
>> +     struct device_node *dp_phy_node = of_node_get(dp->dev->of_node);
>> +     u32 phy_base;
>> +     int ret = 0;
>> +
>> +     dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
>> +     if (!dp_phy_node) {
>> +             dev_err(dp->dev, "could not find dptx-phy node\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
>> +             dev_err(dp->dev, "failed to get reg for dptx-phy\n");
>> +             ret = -EINVAL;
>> +             goto err;
>> +     }
>> +
>> +     if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
>> +                             &dp->enable_mask)) {
>> +             dev_err(dp->dev, "failed to get enable-mask for
> dptx-phy\n");
>> +             ret = -EINVAL;
>> +             goto err;
>> +     }
>> +
>> +     dp->phy_addr = ioremap(phy_base, SZ_4);
>> +     if (!dp->phy_addr) {
>> +             dev_err(dp->dev, "failed to ioremap dp-phy\n");
>> +             ret = -ENOMEM;
>> +             goto err;
>> +     }
>> +
>> +err:
>> +     of_node_put(dp_phy_node);
>> +
>> +     return ret;
>> +}
>> +
>> +static void exynos_dp_phy_init(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = __raw_readl(dp->phy_addr);
>> +     reg |= dp->enable_mask;
>> +     __raw_writel(reg, dp->phy_addr);
>> +}
>> +
>> +static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = __raw_readl(dp->phy_addr);
>> +     reg &= ~(dp->enable_mask);
>> +     __raw_writel(reg, dp->phy_addr);
>> +}
>> +#else
>> +static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device
>> *dev)
>> +{
>> +     return NULL;
>> +}
>> +
>> +static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
>> +{
>> +     return -EINVAL;
>> +}
>> +
>> +static void exynos_dp_phy_init(struct exynos_dp_device *dp)
>> +{
>> +     return;
>> +}
>> +
>> +static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
>> +{
>> +     return;
>> +}
>> +#endif /* CONFIG_OF */
>> +
>> +static int exynos_dp_probe(struct platform_device *pdev)
>> +{
>> +     struct resource *res;
>> +     struct exynos_dp_device *dp;
>> +     struct exynos_dp_platdata *pdata;
>> +
>> +     int ret = 0;
>> +
>> +     dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
>> +                             GFP_KERNEL);
>> +     if (!dp) {
>> +             dev_err(&pdev->dev, "no memory for device data\n");
>> +             return -ENOMEM;
>> +     }
>> +
>> +     dp->dev = &pdev->dev;
>> +
>> +     if (pdev->dev.of_node) {
>> +             pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
>> +             if (IS_ERR(pdata))
>> +                     return PTR_ERR(pdata);
>> +
>> +             ret = exynos_dp_dt_parse_phydata(dp);
>> +             if (ret)
>> +                     return ret;
>> +     } else {
>> +             pdata = pdev->dev.platform_data;
>> +             if (!pdata) {
>> +                     dev_err(&pdev->dev, "no platform data\n");
>> +                     return -EINVAL;
>> +             }
>> +     }
>> +
>> +     dp->clock = devm_clk_get(&pdev->dev, "dp");
>> +     if (IS_ERR(dp->clock)) {
>> +             dev_err(&pdev->dev, "failed to get clock\n");
>> +             return PTR_ERR(dp->clock);
>> +     }
>> +
>> +     clk_prepare_enable(dp->clock);
>> +
>> +     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +
>> +     dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
>> +     if (IS_ERR(dp->reg_base))
>> +             return PTR_ERR(dp->reg_base);
>> +
>> +     dp->irq = platform_get_irq(pdev, 0);
>> +     if (dp->irq == -ENXIO) {
>> +             dev_err(&pdev->dev, "failed to get irq\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
>> +
>> +     dp->video_info = pdata->video_info;
>> +
>> +     if (pdev->dev.of_node) {
>> +             if (dp->phy_addr)
>> +                     exynos_dp_phy_init(dp);
>> +     } else {
>> +             if (pdata->phy_init)
>> +                     pdata->phy_init();
>> +     }
>> +
>> +     exynos_dp_init_dp(dp);
>> +
>> +     ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler,
>> 0,
>> +                             "exynos-dp", dp);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "failed to request irq\n");
>> +             return ret;
>> +     }
>> +
>> +     platform_set_drvdata(pdev, dp);
>> +
>> +     return 0;
>> +}
>> +
>> +static int exynos_dp_remove(struct platform_device *pdev)
>> +{
>> +     struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
>> +     struct exynos_dp_device *dp = platform_get_drvdata(pdev);
>> +
>> +     flush_work(&dp->hotplug_work);
>> +
>> +     if (pdev->dev.of_node) {
>> +             if (dp->phy_addr)
>> +                     exynos_dp_phy_exit(dp);
>> +     } else {
>> +             if (pdata->phy_exit)
>> +                     pdata->phy_exit();
>> +     }
>> +
>> +     clk_disable_unprepare(dp->clock);
>> +
>> +
>> +     return 0;
>> +}
>> +
>> +#ifdef CONFIG_PM_SLEEP
>> +static int exynos_dp_suspend(struct device *dev)
>> +{
>> +     struct exynos_dp_platdata *pdata = dev->platform_data;
>> +     struct exynos_dp_device *dp = dev_get_drvdata(dev);
>> +
>> +     disable_irq(dp->irq);
>> +
>> +     flush_work(&dp->hotplug_work);
>> +
>> +     if (dev->of_node) {
>> +             if (dp->phy_addr)
>> +                     exynos_dp_phy_exit(dp);
>> +     } else {
>> +             if (pdata->phy_exit)
>> +                     pdata->phy_exit();
>> +     }
>> +
>> +     clk_disable_unprepare(dp->clock);
>> +
>> +     return 0;
>> +}
>> +
>> +static int exynos_dp_resume(struct device *dev)
>> +{
>> +     struct exynos_dp_platdata *pdata = dev->platform_data;
>> +     struct exynos_dp_device *dp = dev_get_drvdata(dev);
>> +
>> +     if (dev->of_node) {
>> +             if (dp->phy_addr)
>> +                     exynos_dp_phy_init(dp);
>> +     } else {
>> +             if (pdata->phy_init)
>> +                     pdata->phy_init();
>> +     }
>> +
>> +     clk_prepare_enable(dp->clock);
>> +
>> +     exynos_dp_init_dp(dp);
>> +
>> +     enable_irq(dp->irq);
>> +
>> +     return 0;
>> +}
>> +#endif
>> +
>> +static const struct dev_pm_ops exynos_dp_pm_ops = {
>> +     SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
>> +};
>> +
>> +static const struct of_device_id exynos_dp_match[] = {
>> +     { .compatible = "samsung,exynos5-dp" },
>> +     {},
>> +};
>> +MODULE_DEVICE_TABLE(of, exynos_dp_match);
>> +
>> +static struct platform_driver exynos_dp_driver = {
>> +     .probe          = exynos_dp_probe,
>> +     .remove         = exynos_dp_remove,
>> +     .driver         = {
>> +             .name   = "exynos-dp",
>> +             .owner  = THIS_MODULE,
>> +             .pm     = &exynos_dp_pm_ops,
>> +             .of_match_table = of_match_ptr(exynos_dp_match),
>> +     },
>> +};
>> +
>> +module_platform_driver(exynos_dp_driver);
>> +
>> +MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
>> +MODULE_DESCRIPTION("Samsung SoC DP Driver");
>> +MODULE_LICENSE("GPL");
>> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h
>> b/drivers/gpu/drm/exynos/exynos_dp_core.h
>> new file mode 100644
>> index 0000000..6c567bbf
>> --- /dev/null
>> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
>> @@ -0,0 +1,210 @@
>> +/*
>> + * Header file for Samsung DP (Display Port) interface driver.
>> + *
>> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
>> + * Author: Jingoo Han <jg1.han@samsung.com>
>> + *
>> + * 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 _EXYNOS_DP_CORE_H
>> +#define _EXYNOS_DP_CORE_H
>> +
>> +enum dp_irq_type {
>> +     DP_IRQ_TYPE_HP_CABLE_IN,
>> +     DP_IRQ_TYPE_HP_CABLE_OUT,
>> +     DP_IRQ_TYPE_HP_CHANGE,
>> +     DP_IRQ_TYPE_UNKNOWN,
>> +};
>> +
>> +struct link_train {
>> +     int eq_loop;
>> +     int cr_loop[4];
>> +
>> +     u8 link_rate;
>> +     u8 lane_count;
>> +     u8 training_lane[4];
>> +
>> +     enum link_training_state lt_state;
>> +};
>> +
>> +struct exynos_dp_device {
>> +     struct device           *dev;
>> +     struct clk              *clock;
>> +     unsigned int            irq;
>> +     void __iomem            *reg_base;
>> +     void __iomem            *phy_addr;
>> +     unsigned int            enable_mask;
>> +
>> +     struct video_info       *video_info;
>> +     struct link_train       link_train;
>> +     struct work_struct      hotplug_work;
>> +};
>> +
>> +/* exynos_dp_reg.c */
>> +void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool
>> enable);
>> +void exynos_dp_stop_video(struct exynos_dp_device *dp);
>> +void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
>> +void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
>> +void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
>> +void exynos_dp_reset(struct exynos_dp_device *dp);
>> +void exynos_dp_swreset(struct exynos_dp_device *dp);
>> +void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
>> +enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device
>> *dp);
>> +void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool
>> enable);
>> +void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
>> +                             enum analog_power_block block,
>> +                             bool enable);
>> +void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
>> +void exynos_dp_init_hpd(struct exynos_dp_device *dp);
>> +enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
>> +void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
>> +void exynos_dp_reset_aux(struct exynos_dp_device *dp);
>> +void exynos_dp_init_aux(struct exynos_dp_device *dp);
>> +int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
>> +void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
>> +int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
>> +int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
>> +                             unsigned int reg_addr,
>> +                             unsigned char data);
>> +int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
>> +                             unsigned int reg_addr,
>> +                             unsigned char *data);
>> +int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
>> +                             unsigned int reg_addr,
>> +                             unsigned int count,
>> +                             unsigned char data[]);
>> +int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
>> +                             unsigned int reg_addr,
>> +                             unsigned int count,
>> +                             unsigned char data[]);
>> +int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
>> +                             unsigned int device_addr,
>> +                             unsigned int reg_addr);
>> +int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
>> +                             unsigned int device_addr,
>> +                             unsigned int reg_addr,
>> +                             unsigned int *data);
>> +int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
>> +                             unsigned int device_addr,
>> +                             unsigned int reg_addr,
>> +                             unsigned int count,
>> +                             unsigned char edid[]);
>> +void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32
>> bwtype);
>> +void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32
>> *bwtype);
>> +void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
>> +void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
>> +void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool
>> enable);
>> +void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
>> +                              enum pattern_set pattern);
>> +void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32
>> level);
>> +void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32
>> level);
>> +void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32
>> level);
>> +void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32
>> level);
>> +void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
>> +                             u32 training_lane);
>> +void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
>> +                             u32 training_lane);
>> +void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
>> +                             u32 training_lane);
>> +void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
>> +                             u32 training_lane);
>> +u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
>> +u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
>> +u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
>> +u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
>> +void exynos_dp_reset_macro(struct exynos_dp_device *dp);
>> +void exynos_dp_init_video(struct exynos_dp_device *dp);
>> +
>> +void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
>> +int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device
> *dp);
>> +void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
>> +                     enum clock_recovery_m_value_type type,
>> +                     u32 m_value,
>> +                     u32 n_value);
>> +void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32
>> type);
>> +void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool
>> enable);
>> +void exynos_dp_start_video(struct exynos_dp_device *dp);
>> +int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
>> +void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
>> +void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
>> +void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
>> +
>> +/* I2C EDID Chip ID, Slave Address */
>> +#define I2C_EDID_DEVICE_ADDR                 0x50
>> +#define I2C_E_EDID_DEVICE_ADDR                       0x30
>> +
>> +#define EDID_BLOCK_LENGTH                    0x80
>> +#define EDID_HEADER_PATTERN                  0x00
>> +#define EDID_EXTENSION_FLAG                  0x7e
>> +#define EDID_CHECKSUM                                0x7f
>> +
>> +/* Definition for DPCD Register */
>> +#define DPCD_ADDR_DPCD_REV                   0x0000
>> +#define DPCD_ADDR_MAX_LINK_RATE                      0x0001
>> +#define DPCD_ADDR_MAX_LANE_COUNT             0x0002
>> +#define DPCD_ADDR_LINK_BW_SET                        0x0100
>> +#define DPCD_ADDR_LANE_COUNT_SET             0x0101
>> +#define DPCD_ADDR_TRAINING_PATTERN_SET               0x0102
>> +#define DPCD_ADDR_TRAINING_LANE0_SET         0x0103
>> +#define DPCD_ADDR_LANE0_1_STATUS             0x0202
>> +#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED  0x0204
>> +#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1     0x0206
>> +#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3     0x0207
>> +#define DPCD_ADDR_TEST_REQUEST                       0x0218
>> +#define DPCD_ADDR_TEST_RESPONSE                      0x0260
>> +#define DPCD_ADDR_TEST_EDID_CHECKSUM         0x0261
>> +#define DPCD_ADDR_SINK_POWER_STATE           0x0600
>> +
>> +/* DPCD_ADDR_MAX_LANE_COUNT */
>> +#define DPCD_ENHANCED_FRAME_CAP(x)           (((x) >> 7) & 0x1)
>> +#define DPCD_MAX_LANE_COUNT(x)                       ((x) & 0x1f)
>> +
>> +/* DPCD_ADDR_LANE_COUNT_SET */
>> +#define DPCD_ENHANCED_FRAME_EN                       (0x1 << 7)
>> +#define DPCD_LANE_COUNT_SET(x)                       ((x) & 0x1f)
>> +
>> +/* DPCD_ADDR_TRAINING_PATTERN_SET */
>> +#define DPCD_SCRAMBLING_DISABLED             (0x1 << 5)
>> +#define DPCD_SCRAMBLING_ENABLED                      (0x0 << 5)
>> +#define DPCD_TRAINING_PATTERN_2                      (0x2 << 0)
>> +#define DPCD_TRAINING_PATTERN_1                      (0x1 << 0)
>> +#define DPCD_TRAINING_PATTERN_DISABLED               (0x0 << 0)
>> +
>> +/* DPCD_ADDR_TRAINING_LANE0_SET */
>> +#define DPCD_MAX_PRE_EMPHASIS_REACHED                (0x1 << 5)
>> +#define DPCD_PRE_EMPHASIS_SET(x)             (((x) & 0x3) << 3)
>> +#define DPCD_PRE_EMPHASIS_GET(x)             (((x) >> 3) & 0x3)
>> +#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0    (0x0 << 3)
>> +#define DPCD_MAX_SWING_REACHED                       (0x1 << 2)
>> +#define DPCD_VOLTAGE_SWING_SET(x)            (((x) & 0x3) << 0)
>> +#define DPCD_VOLTAGE_SWING_GET(x)            (((x) >> 0) & 0x3)
>> +#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0   (0x0 << 0)
>> +
>> +/* DPCD_ADDR_LANE0_1_STATUS */
>> +#define DPCD_LANE_SYMBOL_LOCKED                      (0x1 << 2)
>> +#define DPCD_LANE_CHANNEL_EQ_DONE            (0x1 << 1)
>> +#define DPCD_LANE_CR_DONE                    (0x1 << 0)
>> +#define DPCD_CHANNEL_EQ_BITS                 (DPCD_LANE_CR_DONE|     \
>> +                                              DPCD_LANE_CHANNEL_EQ_DONE|\
>> +                                              DPCD_LANE_SYMBOL_LOCKED)
>> +
>> +/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
>> +#define DPCD_LINK_STATUS_UPDATED             (0x1 << 7)
>> +#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED  (0x1 << 6)
>> +#define DPCD_INTERLANE_ALIGN_DONE            (0x1 << 0)
>> +
>> +/* DPCD_ADDR_TEST_REQUEST */
>> +#define DPCD_TEST_EDID_READ                  (0x1 << 2)
>> +
>> +/* DPCD_ADDR_TEST_RESPONSE */
>> +#define DPCD_TEST_EDID_CHECKSUM_WRITE                (0x1 << 2)
>> +
>> +/* DPCD_ADDR_SINK_POWER_STATE */
>> +#define DPCD_SET_POWER_STATE_D0                      (0x1 << 0)
>> +#define DPCD_SET_POWER_STATE_D4                      (0x2 << 0)
>> +
>> +#endif /* _EXYNOS_DP_CORE_H */
>> diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.c
>> b/drivers/gpu/drm/exynos/exynos_dp_reg.c
>> new file mode 100644
>> index 0000000..29d9d03
>> --- /dev/null
>> +++ b/drivers/gpu/drm/exynos/exynos_dp_reg.c
>> @@ -0,0 +1,1245 @@
>> +/*
>> + * Samsung DP (Display port) register interface driver.
>> + *
>> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
>> + * Author: Jingoo Han <jg1.han@samsung.com>
>> + *
>> + * 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/device.h>
>> +#include <linux/io.h>
>> +#include <linux/delay.h>
>> +
>> +#include <video/exynos_dp.h>
>> +
>> +#include "exynos_dp_core.h"
>> +#include "exynos_dp_reg.h"
>> +
>> +#define COMMON_INT_MASK_1    0
>> +#define COMMON_INT_MASK_2    0
>> +#define COMMON_INT_MASK_3    0
>> +#define COMMON_INT_MASK_4    (HOTPLUG_CHG | HPD_LOST | PLUG)
>> +#define INT_STA_MASK         INT_HPD
>> +
>> +void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool
> enable)
>> +{
>> +     u32 reg;
>> +
>> +     if (enable) {
>> +             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> +             reg |= HDCP_VIDEO_MUTE;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> +     } else {
>> +             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> +             reg &= ~HDCP_VIDEO_MUTE;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> +     }
>> +}
>> +
>> +void exynos_dp_stop_video(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> +     reg &= ~VIDEO_EN;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> +}
>> +
>> +void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
>> +{
>> +     u32 reg;
>> +
>> +     if (enable)
>> +             reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
>> +                     LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
>> +     else
>> +             reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
>> +                     LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
>> +
>> +     writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
>> +}
>> +
>> +void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = TX_TERMINAL_CTRL_50_OHM;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
>> +
>> +     reg = SEL_24M | TX_DVDD_BIT_1_0625V;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
>> +
>> +     reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
>> +
>> +     reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
>> +             TX_CUR1_2X | TX_CUR_16_MA;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
>> +
>> +     reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
>> +             CH1_AMP_400_MV | CH0_AMP_400_MV;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
>> +}
>> +
>> +void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
>> +{
>> +     /* Set interrupt pin assertion polarity as high */
>> +     writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
>> +
>> +     /* Clear pending regisers */
>> +     writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
>> +     writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
>> +     writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
>> +     writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
>> +     writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
>> +
>> +     /* 0:mask,1: unmask */
>> +     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
>> +     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
>> +     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
>> +     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
>> +     writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
>> +}
>> +
>> +void exynos_dp_reset(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     exynos_dp_stop_video(dp);
>> +     exynos_dp_enable_video_mute(dp, 0);
>> +
>> +     reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
>> +             AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
>> +             HDCP_FUNC_EN_N | SW_FUNC_EN_N;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
>> +
>> +     reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
>> +             SERDES_FIFO_FUNC_EN_N |
>> +             LS_CLK_DOMAIN_FUNC_EN_N;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> +
>> +     usleep_range(20, 30);
>> +
>> +     exynos_dp_lane_swap(dp, 0);
>> +
>> +     writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
>> +     writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
>> +     writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> +     writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> +
>> +     writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
>> +     writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
>> +
>> +     writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
>> +     writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
>> +
>> +     writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
>> +
>> +     writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
>> +
>> +     writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
>> +     writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
>> +
>> +     writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
>> +     writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
>> +
>> +     writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
>> +}
>> +
>> +void exynos_dp_swreset(struct exynos_dp_device *dp)
>> +{
>> +     writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
>> +}
>> +
>> +void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     /* 0: mask, 1: unmask */
>> +     reg = COMMON_INT_MASK_1;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
>> +
>> +     reg = COMMON_INT_MASK_2;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
>> +
>> +     reg = COMMON_INT_MASK_3;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
>> +
>> +     reg = COMMON_INT_MASK_4;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
>> +
>> +     reg = INT_STA_MASK;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
>> +}
>> +
>> +enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device
> *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
>> +     if (reg & PLL_LOCK)
>> +             return PLL_LOCKED;
>> +     else
>> +             return PLL_UNLOCKED;
>> +}
>> +
>> +void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool
>> enable)
>> +{
>> +     u32 reg;
>> +
>> +     if (enable) {
>> +             reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
>> +             reg |= DP_PLL_PD;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
>> +     } else {
>> +             reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
>> +             reg &= ~DP_PLL_PD;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
>> +     }
>> +}
>> +
>> +void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
>> +                             enum analog_power_block block,
>> +                             bool enable)
>> +{
>> +     u32 reg;
>> +
>> +     switch (block) {
>> +     case AUX_BLOCK:
>> +             if (enable) {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> +                     reg |= AUX_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             } else {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> +                     reg &= ~AUX_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             }
>> +             break;
>> +     case CH0_BLOCK:
>> +             if (enable) {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> +                     reg |= CH0_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             } else {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> +                     reg &= ~CH0_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             }
>> +             break;
>> +     case CH1_BLOCK:
>> +             if (enable) {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> +                     reg |= CH1_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             } else {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> +                     reg &= ~CH1_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             }
>> +             break;
>> +     case CH2_BLOCK:
>> +             if (enable) {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> +                     reg |= CH2_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             } else {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> +                     reg &= ~CH2_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             }
>> +             break;
>> +     case CH3_BLOCK:
>> +             if (enable) {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> +                     reg |= CH3_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             } else {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> +                     reg &= ~CH3_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             }
>> +             break;
>> +     case ANALOG_TOTAL:
>> +             if (enable) {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> +                     reg |= DP_PHY_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             } else {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> +                     reg &= ~DP_PHY_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             }
>> +             break;
>> +     case POWER_ALL:
>> +             if (enable) {
>> +                     reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
>> +                             CH1_PD | CH0_PD;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             } else {
>> +                     writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
>> +             }
>> +             break;
>> +     default:
>> +             break;
>> +     }
>> +}
>> +
>> +void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +     int timeout_loop = 0;
>> +
>> +     exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
>> +
>> +     reg = PLL_LOCK_CHG;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
>> +     reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
>> +     writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
>> +
>> +     /* Power up PLL */
>> +     if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
>> +             exynos_dp_set_pll_power_down(dp, 0);
>> +
>> +             while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
>> +                     timeout_loop++;
>> +                     if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
>> +                             dev_err(dp->dev, "failed to get pll lock
>> status\n");
>> +                             return;
>> +                     }
>> +                     usleep_range(10, 20);
>> +             }
>> +     }
>> +
>> +     /* Enable Serdes FIFO function and Link symbol clock domain module
>> */
>> +     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> +     reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
>> +             | AUX_FUNC_EN_N);
>> +     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> +}
>> +
>> +void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = HOTPLUG_CHG | HPD_LOST | PLUG;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
>> +
>> +     reg = INT_HPD;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
>> +}
>> +
>> +void exynos_dp_init_hpd(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     exynos_dp_clear_hotplug_interrupts(dp);
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> +     reg &= ~(F_HPD | HPD_CTRL);
>> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> +}
>> +
>> +enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     /* Parse hotplug interrupt status register */
>> +     reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
>> +
>> +     if (reg & PLUG)
>> +             return DP_IRQ_TYPE_HP_CABLE_IN;
>> +
>> +     if (reg & HPD_LOST)
>> +             return DP_IRQ_TYPE_HP_CABLE_OUT;
>> +
>> +     if (reg & HOTPLUG_CHG)
>> +             return DP_IRQ_TYPE_HP_CHANGE;
>> +
>> +     return DP_IRQ_TYPE_UNKNOWN;
>> +}
>> +
>> +void exynos_dp_reset_aux(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     /* Disable AUX channel module */
>> +     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> +     reg |= AUX_FUNC_EN_N;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> +}
>> +
>> +void exynos_dp_init_aux(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     /* Clear inerrupts related to AUX channel */
>> +     reg = RPLY_RECEIV | AUX_ERR;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
>> +
>> +     exynos_dp_reset_aux(dp);
>> +
>> +     /* Disable AUX transaction H/W retry */
>> +     reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
>> +             AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
>> +
>> +     /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
>> +     reg = DEFER_CTRL_EN | DEFER_COUNT(1);
>> +     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
>> +
>> +     /* Enable AUX channel module */
>> +     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> +     reg &= ~AUX_FUNC_EN_N;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> +}
>> +
>> +int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> +     if (reg & HPD_STATUS)
>> +             return 0;
>> +
>> +     return -EINVAL;
>> +}
>> +
>> +void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
>> +     reg &= ~SW_FUNC_EN_N;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
>> +}
>> +
>> +int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
>> +{
>> +     int reg;
>> +     int retval = 0;
>> +     int timeout_loop = 0;
>> +
>> +     /* Enable AUX CH operation */
>> +     reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
>> +     reg |= AUX_EN;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
>> +
>> +     /* Is AUX CH command reply received? */
>> +     reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
>> +     while (!(reg & RPLY_RECEIV)) {
>> +             timeout_loop++;
>> +             if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
>> +                     dev_err(dp->dev, "AUX CH command reply failed!\n");
>> +                     return -ETIMEDOUT;
>> +             }
>> +             reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
>> +             usleep_range(10, 11);
>> +     }
>> +
>> +     /* Clear interrupt source for AUX CH command reply */
>> +     writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
>> +
>> +     /* Clear interrupt source for AUX CH access error */
>> +     reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
>> +     if (reg & AUX_ERR) {
>> +             writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
>> +             return -EREMOTEIO;
>> +     }
>> +
>> +     /* Check AUX CH error access status */
>> +     reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
>> +     if ((reg & AUX_STATUS_MASK) != 0) {
>> +             dev_err(dp->dev, "AUX CH error happens: %d\n\n",
>> +                     reg & AUX_STATUS_MASK);
>> +             return -EREMOTEIO;
>> +     }
>> +
>> +     return retval;
>> +}
>> +
>> +int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
>> +                             unsigned int reg_addr,
>> +                             unsigned char data)
>> +{
>> +     u32 reg;
>> +     int i;
>> +     int retval;
>> +
>> +     for (i = 0; i < 3; i++) {
>> +             /* Clear AUX CH data buffer */
>> +             reg = BUF_CLR;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
>> +
>> +             /* Select DPCD device address */
>> +             reg = AUX_ADDR_7_0(reg_addr);
>> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
>> +             reg = AUX_ADDR_15_8(reg_addr);
>> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
>> +             reg = AUX_ADDR_19_16(reg_addr);
>> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
>> +
>> +             /* Write data buffer */
>> +             reg = (unsigned int)data;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
>> +
>> +             /*
>> +              * Set DisplayPort transaction and write 1 byte
>> +              * If bit 3 is 1, DisplayPort transaction.
>> +              * If Bit 3 is 0, I2C transaction.
>> +              */
>> +             reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
>> +
>> +             /* Start AUX transaction */
>> +             retval = exynos_dp_start_aux_transaction(dp);
>> +             if (retval == 0)
>> +                     break;
>> +             else
>> +                     dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
>> +                             __func__);
>> +     }
>> +
>> +     return retval;
>> +}
>> +
>> +int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
>> +                             unsigned int reg_addr,
>> +                             unsigned char *data)
>> +{
>> +     u32 reg;
>> +     int i;
>> +     int retval;
>> +
>> +     for (i = 0; i < 3; i++) {
>> +             /* Clear AUX CH data buffer */
>> +             reg = BUF_CLR;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
>> +
>> +             /* Select DPCD device address */
>> +             reg = AUX_ADDR_7_0(reg_addr);
>> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
>> +             reg = AUX_ADDR_15_8(reg_addr);
>> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
>> +             reg = AUX_ADDR_19_16(reg_addr);
>> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
>> +
>> +             /*
>> +              * Set DisplayPort transaction and read 1 byte
>> +              * If bit 3 is 1, DisplayPort transaction.
>> +              * If Bit 3 is 0, I2C transaction.
>> +              */
>> +             reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
>> +
>> +             /* Start AUX transaction */
>> +             retval = exynos_dp_start_aux_transaction(dp);
>> +             if (retval == 0)
>> +                     break;
>> +             else
>> +                     dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
>> +                             __func__);
>> +     }
>> +
>> +     /* Read data buffer */
>> +     reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
>> +     *data = (unsigned char)(reg & 0xff);
>> +
>> +     return retval;
>> +}
>> +
>> +int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
>> +                             unsigned int reg_addr,
>> +                             unsigned int count,
>> +                             unsigned char data[])
>> +{
>> +     u32 reg;
>> +     unsigned int start_offset;
>> +     unsigned int cur_data_count;
>> +     unsigned int cur_data_idx;
>> +     int i;
>> +     int retval = 0;
>> +
>> +     /* Clear AUX CH data buffer */
>> +     reg = BUF_CLR;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
>> +
>> +     start_offset = 0;
>> +     while (start_offset < count) {
>> +             /* Buffer size of AUX CH is 16 * 4bytes */
>> +             if ((count - start_offset) > 16)
>> +                     cur_data_count = 16;
>> +             else
>> +                     cur_data_count = count - start_offset;
>> +
>> +             for (i = 0; i < 3; i++) {
>> +                     /* Select DPCD device address */
>> +                     reg = AUX_ADDR_7_0(reg_addr + start_offset);
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
>> +                     reg = AUX_ADDR_15_8(reg_addr + start_offset);
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
>> +                     reg = AUX_ADDR_19_16(reg_addr + start_offset);
>> +                     writel(reg, dp->reg_base +
> EXYNOS_DP_AUX_ADDR_19_16);
>> +
>> +                     for (cur_data_idx = 0; cur_data_idx <
> cur_data_count;
>> +                          cur_data_idx++) {
>> +                             reg = data[start_offset + cur_data_idx];
>> +                             writel(reg, dp->reg_base +
> EXYNOS_DP_BUF_DATA_0
>> +                                                       + 4 *
> cur_data_idx);
>> +                     }
>> +
>> +                     /*
>> +                      * Set DisplayPort transaction and write
>> +                      * If bit 3 is 1, DisplayPort transaction.
>> +                      * If Bit 3 is 0, I2C transaction.
>> +                      */
>> +                     reg = AUX_LENGTH(cur_data_count) |
>> +                             AUX_TX_COMM_DP_TRANSACTION |
> AUX_TX_COMM_WRITE;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
>> +
>> +                     /* Start AUX transaction */
>> +                     retval = exynos_dp_start_aux_transaction(dp);
>> +                     if (retval == 0)
>> +                             break;
>> +                     else
>> +                             dev_dbg(dp->dev, "%s: Aux Transaction
> fail!\n",
>> +                                     __func__);
>> +             }
>> +
>> +             start_offset += cur_data_count;
>> +     }
>> +
>> +     return retval;
>> +}
>> +
>> +int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
>> +                             unsigned int reg_addr,
>> +                             unsigned int count,
>> +                             unsigned char data[])
>> +{
>> +     u32 reg;
>> +     unsigned int start_offset;
>> +     unsigned int cur_data_count;
>> +     unsigned int cur_data_idx;
>> +     int i;
>> +     int retval = 0;
>> +
>> +     /* Clear AUX CH data buffer */
>> +     reg = BUF_CLR;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
>> +
>> +     start_offset = 0;
>> +     while (start_offset < count) {
>> +             /* Buffer size of AUX CH is 16 * 4bytes */
>> +             if ((count - start_offset) > 16)
>> +                     cur_data_count = 16;
>> +             else
>> +                     cur_data_count = count - start_offset;
>> +
>> +             /* AUX CH Request Transaction process */
>> +             for (i = 0; i < 3; i++) {
>> +                     /* Select DPCD device address */
>> +                     reg = AUX_ADDR_7_0(reg_addr + start_offset);
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
>> +                     reg = AUX_ADDR_15_8(reg_addr + start_offset);
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
>> +                     reg = AUX_ADDR_19_16(reg_addr + start_offset);
>> +                     writel(reg, dp->reg_base +
> EXYNOS_DP_AUX_ADDR_19_16);
>> +
>> +                     /*
>> +                      * Set DisplayPort transaction and read
>> +                      * If bit 3 is 1, DisplayPort transaction.
>> +                      * If Bit 3 is 0, I2C transaction.
>> +                      */
>> +                     reg = AUX_LENGTH(cur_data_count) |
>> +                             AUX_TX_COMM_DP_TRANSACTION |
> AUX_TX_COMM_READ;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
>> +
>> +                     /* Start AUX transaction */
>> +                     retval = exynos_dp_start_aux_transaction(dp);
>> +                     if (retval == 0)
>> +                             break;
>> +                     else
>> +                             dev_dbg(dp->dev, "%s: Aux Transaction
> fail!\n",
>> +                                     __func__);
>> +             }
>> +
>> +             for (cur_data_idx = 0; cur_data_idx < cur_data_count;
>> +                 cur_data_idx++) {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
>> +                                              + 4 * cur_data_idx);
>> +                     data[start_offset + cur_data_idx] =
>> +                             (unsigned char)reg;
>> +             }
>> +
>> +             start_offset += cur_data_count;
>> +     }
>> +
>> +     return retval;
>> +}
>> +
>> +int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
>> +                             unsigned int device_addr,
>> +                             unsigned int reg_addr)
>> +{
>> +     u32 reg;
>> +     int retval;
>> +
>> +     /* Set EDID device address */
>> +     reg = device_addr;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
>> +     writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
>> +     writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
>> +
>> +     /* Set offset from base address of EDID device */
>> +     writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
>> +
>> +     /*
>> +      * Set I2C transaction and write address
>> +      * If bit 3 is 1, DisplayPort transaction.
>> +      * If Bit 3 is 0, I2C transaction.
>> +      */
>> +     reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
>> +             AUX_TX_COMM_WRITE;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
>> +
>> +     /* Start AUX transaction */
>> +     retval = exynos_dp_start_aux_transaction(dp);
>> +     if (retval != 0)
>> +             dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
>> +
>> +     return retval;
>> +}
>> +
>> +int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
>> +                             unsigned int device_addr,
>> +                             unsigned int reg_addr,
>> +                             unsigned int *data)
>> +{
>> +     u32 reg;
>> +     int i;
>> +     int retval;
>> +
>> +     for (i = 0; i < 3; i++) {
>> +             /* Clear AUX CH data buffer */
>> +             reg = BUF_CLR;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
>> +
>> +             /* Select EDID device */
>> +             retval = exynos_dp_select_i2c_device(dp, device_addr,
>> reg_addr);
>> +             if (retval != 0)
>> +                     continue;
>> +
>> +             /*
>> +              * Set I2C transaction and read data
>> +              * If bit 3 is 1, DisplayPort transaction.
>> +              * If Bit 3 is 0, I2C transaction.
>> +              */
>> +             reg = AUX_TX_COMM_I2C_TRANSACTION |
>> +                     AUX_TX_COMM_READ;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
>> +
>> +             /* Start AUX transaction */
>> +             retval = exynos_dp_start_aux_transaction(dp);
>> +             if (retval == 0)
>> +                     break;
>> +             else
>> +                     dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
>> +                             __func__);
>> +     }
>> +
>> +     /* Read data */
>> +     if (retval == 0)
>> +             *data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
>> +
>> +     return retval;
>> +}
>> +
>> +int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
>> +                             unsigned int device_addr,
>> +                             unsigned int reg_addr,
>> +                             unsigned int count,
>> +                             unsigned char edid[])
>> +{
>> +     u32 reg;
>> +     unsigned int i, j;
>> +     unsigned int cur_data_idx;
>> +     unsigned int defer = 0;
>> +     int retval = 0;
>> +
>> +     for (i = 0; i < count; i += 16) {
>> +             for (j = 0; j < 3; j++) {
>> +                     /* Clear AUX CH data buffer */
>> +                     reg = BUF_CLR;
>> +                     writel(reg, dp->reg_base +
> EXYNOS_DP_BUFFER_DATA_CTL);
>> +
>> +                     /* Set normal AUX CH command */
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
>> +                     reg &= ~ADDR_ONLY;
>> +                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
>> +
>> +                     /*
>> +                      * If Rx sends defer, Tx sends only reads
>> +                      * request without sending address
>> +                      */
>> +                     if (!defer)
>> +                             retval = exynos_dp_select_i2c_device(dp,
>> +                                             device_addr, reg_addr + i);
>> +                     else
>> +                             defer = 0;
>> +
>> +                     if (retval == 0) {
>> +                             /*
>> +                              * Set I2C transaction and write data
>> +                              * If bit 3 is 1, DisplayPort transaction.
>> +                              * If Bit 3 is 0, I2C transaction.
>> +                              */
>> +                             reg = AUX_LENGTH(16) |
>> +                                     AUX_TX_COMM_I2C_TRANSACTION |
>> +                                     AUX_TX_COMM_READ;
>> +                             writel(reg, dp->reg_base +
>> +                                     EXYNOS_DP_AUX_CH_CTL_1);
>> +
>> +                             /* Start AUX transaction */
>> +                             retval =
> exynos_dp_start_aux_transaction(dp);
>> +                             if (retval == 0)
>> +                                     break;
>> +                             else
>> +                                     dev_dbg(dp->dev,
>> +                                             "%s: Aux Transaction
> fail!\n",
>> +                                             __func__);
>> +                     }
>> +                     /* Check if Rx sends defer */
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
>> +                     if (reg == AUX_RX_COMM_AUX_DEFER ||
>> +                             reg == AUX_RX_COMM_I2C_DEFER) {
>> +                             dev_err(dp->dev, "Defer: %d\n\n", reg);
>> +                             defer = 1;
>> +                     }
>> +             }
>> +
>> +             for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
>> +                     reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
>> +                                              + 4 * cur_data_idx);
>> +                     edid[i + cur_data_idx] = (unsigned char)reg;
>> +             }
>> +     }
>> +
>> +     return retval;
>> +}
>> +
>> +void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32
> bwtype)
>> +{
>> +     u32 reg;
>> +
>> +     reg = bwtype;
>> +     if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype ==
>> LINK_RATE_1_62GBPS))
>> +             writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
>> +}
>> +
>> +void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32
>> *bwtype)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
>> +     *bwtype = reg;
>> +}
>> +
>> +void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
>> +{
>> +     u32 reg;
>> +
>> +     reg = count;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
>> +}
>> +
>> +void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
>> +     *count = reg;
>> +}
>> +
>> +void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool
>> enable)
>> +{
>> +     u32 reg;
>> +
>> +     if (enable) {
>> +             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> +             reg |= ENHANCED;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> +     } else {
>> +             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> +             reg &= ~ENHANCED;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> +     }
>> +}
>> +
>> +void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
>> +                              enum pattern_set pattern)
>> +{
>> +     u32 reg;
>> +
>> +     switch (pattern) {
>> +     case PRBS7:
>> +             reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> +             break;
>> +     case D10_2:
>> +             reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> +             break;
>> +     case TRAINING_PTN1:
>> +             reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> +             break;
>> +     case TRAINING_PTN2:
>> +             reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> +             break;
>> +     case DP_NONE:
>> +             reg = SCRAMBLING_ENABLE |
>> +                     LINK_QUAL_PATTERN_SET_DISABLE |
>> +                     SW_TRAINING_PATTERN_SET_NORMAL;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> +             break;
>> +     default:
>> +             break;
>> +     }
>> +}
>> +
>> +void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32
>> level)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
>> +     reg &= ~PRE_EMPHASIS_SET_MASK;
>> +     reg |= level << PRE_EMPHASIS_SET_SHIFT;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
>> +}
>> +
>> +void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32
>> level)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
>> +     reg &= ~PRE_EMPHASIS_SET_MASK;
>> +     reg |= level << PRE_EMPHASIS_SET_SHIFT;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
>> +}
>> +
>> +void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32
>> level)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
>> +     reg &= ~PRE_EMPHASIS_SET_MASK;
>> +     reg |= level << PRE_EMPHASIS_SET_SHIFT;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
>> +}
>> +
>> +void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32
>> level)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
>> +     reg &= ~PRE_EMPHASIS_SET_MASK;
>> +     reg |= level << PRE_EMPHASIS_SET_SHIFT;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
>> +}
>> +
>> +void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
>> +                                     u32 training_lane)
>> +{
>> +     u32 reg;
>> +
>> +     reg = training_lane;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
>> +}
>> +
>> +void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
>> +                                     u32 training_lane)
>> +{
>> +     u32 reg;
>> +
>> +     reg = training_lane;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
>> +}
>> +
>> +void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
>> +                                     u32 training_lane)
>> +{
>> +     u32 reg;
>> +
>> +     reg = training_lane;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
>> +}
>> +
>> +void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
>> +                                     u32 training_lane)
>> +{
>> +     u32 reg;
>> +
>> +     reg = training_lane;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
>> +}
>> +
>> +u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
>> +     return reg;
>> +}
>> +
>> +u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
>> +     return reg;
>> +}
>> +
>> +u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
>> +     return reg;
>> +}
>> +
>> +u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
>> +     return reg;
>> +}
>> +
>> +void exynos_dp_reset_macro(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
>> +     reg |= MACRO_RST;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
>> +
>> +     /* 10 us is the minimum reset time. */
>> +     usleep_range(10, 20);
>> +
>> +     reg &= ~MACRO_RST;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
>> +}
>> +
>> +void exynos_dp_init_video(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
>> +
>> +     reg = 0x0;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
>> +
>> +     reg = CHA_CRI(4) | CHA_CTRL;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
>> +
>> +     reg = 0x0;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> +
>> +     reg = VID_HRES_TH(2) | VID_VRES_TH(0);
>> +     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
>> +}
>> +
>> +void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     /* Configure the input color depth, color space, dynamic range */
>> +     reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
>> +             (dp->video_info->color_depth << IN_BPC_SHIFT) |
>> +             (dp->video_info->color_space << IN_COLOR_F_SHIFT);
>> +     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
>> +
>> +     /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
>> +     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
>> +     reg &= ~IN_YC_COEFFI_MASK;
>> +     if (dp->video_info->ycbcr_coeff)
>> +             reg |= IN_YC_COEFFI_ITU709;
>> +     else
>> +             reg |= IN_YC_COEFFI_ITU601;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
>> +}
>> +
>> +int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
>> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
>> +
>> +     if (!(reg & DET_STA)) {
>> +             dev_dbg(dp->dev, "Input stream clock not detected.\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
>> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
>> +     dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
>> +
>> +     if (reg & CHA_STA) {
>> +             dev_dbg(dp->dev, "Input stream clk is changing\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
>> +             enum clock_recovery_m_value_type type,
>> +             u32 m_value,
>> +             u32 n_value)
>> +{
>> +     u32 reg;
>> +
>> +     if (type == REGISTER_M) {
>> +             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> +             reg |= FIX_M_VID;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> +             reg = m_value & 0xff;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
>> +             reg = (m_value >> 8) & 0xff;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
>> +             reg = (m_value >> 16) & 0xff;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
>> +
>> +             reg = n_value & 0xff;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
>> +             reg = (n_value >> 8) & 0xff;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
>> +             reg = (n_value >> 16) & 0xff;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
>> +     } else  {
>> +             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> +             reg &= ~FIX_M_VID;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> +
>> +             writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
>> +             writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
>> +             writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
>> +     }
>> +}
>> +
>> +void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32
>> type)
>> +{
>> +     u32 reg;
>> +
>> +     if (type == VIDEO_TIMING_FROM_CAPTURE) {
>> +             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> +             reg &= ~FORMAT_SEL;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> +     } else {
>> +             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> +             reg |= FORMAT_SEL;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> +     }
>> +}
>> +
>> +void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool
>> enable)
>> +{
>> +     u32 reg;
>> +
>> +     if (enable) {
>> +             reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
>> +             reg &= ~VIDEO_MODE_MASK;
>> +             reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
>> +     } else {
>> +             reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
>> +             reg &= ~VIDEO_MODE_MASK;
>> +             reg |= VIDEO_MODE_SLAVE_MODE;
>> +             writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
>> +     }
>> +}
>> +
>> +void exynos_dp_start_video(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> +     reg |= VIDEO_EN;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> +}
>> +
>> +int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> +     if (!(reg & STRM_VALID)) {
>> +             dev_dbg(dp->dev, "Input video stream is not detected.\n");
>> +             return -EINVAL;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
>> +     reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
>> +     reg |= MASTER_VID_FUNC_EN_N;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> +     reg &= ~INTERACE_SCAN_CFG;
>> +     reg |= (dp->video_info->interlaced << 2);
>> +     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> +     reg &= ~VSYNC_POLARITY_CFG;
>> +     reg |= (dp->video_info->v_sync_polarity << 1);
>> +     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> +     reg &= ~HSYNC_POLARITY_CFG;
>> +     reg |= (dp->video_info->h_sync_polarity << 0);
>> +     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> +
>> +     reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
>> +}
>> +
>> +void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> +     reg &= ~SCRAMBLING_DISABLE;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> +}
>> +
>> +void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
>> +{
>> +     u32 reg;
>> +
>> +     reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> +     reg |= SCRAMBLING_DISABLE;
>> +     writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> +}
>> diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.h
>> b/drivers/gpu/drm/exynos/exynos_dp_reg.h
>> new file mode 100644
>> index 0000000..2e9bd0e
>> --- /dev/null
>> +++ b/drivers/gpu/drm/exynos/exynos_dp_reg.h
>> @@ -0,0 +1,366 @@
>> +/*
>> + * Register definition file for Samsung DP driver
>> + *
>> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
>> + * Author: Jingoo Han <jg1.han@samsung.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#ifndef _EXYNOS_DP_REG_H
>> +#define _EXYNOS_DP_REG_H
>> +
>> +#define EXYNOS_DP_TX_SW_RESET                        0x14
>> +#define EXYNOS_DP_FUNC_EN_1                  0x18
>> +#define EXYNOS_DP_FUNC_EN_2                  0x1C
>> +#define EXYNOS_DP_VIDEO_CTL_1                        0x20
>> +#define EXYNOS_DP_VIDEO_CTL_2                        0x24
>> +#define EXYNOS_DP_VIDEO_CTL_3                        0x28
>> +
>> +#define EXYNOS_DP_VIDEO_CTL_8                        0x3C
>> +#define EXYNOS_DP_VIDEO_CTL_10                       0x44
>> +
>> +#define EXYNOS_DP_LANE_MAP                   0x35C
>> +
>> +#define EXYNOS_DP_ANALOG_CTL_1                       0x370
>> +#define EXYNOS_DP_ANALOG_CTL_2                       0x374
>> +#define EXYNOS_DP_ANALOG_CTL_3                       0x378
>> +#define EXYNOS_DP_PLL_FILTER_CTL_1           0x37C
>> +#define EXYNOS_DP_TX_AMP_TUNING_CTL          0x380
>> +
>> +#define EXYNOS_DP_AUX_HW_RETRY_CTL           0x390
>> +
>> +#define EXYNOS_DP_COMMON_INT_STA_1           0x3C4
>> +#define EXYNOS_DP_COMMON_INT_STA_2           0x3C8
>> +#define EXYNOS_DP_COMMON_INT_STA_3           0x3CC
>> +#define EXYNOS_DP_COMMON_INT_STA_4           0x3D0
>> +#define EXYNOS_DP_INT_STA                    0x3DC
>> +#define EXYNOS_DP_COMMON_INT_MASK_1          0x3E0
>> +#define EXYNOS_DP_COMMON_INT_MASK_2          0x3E4
>> +#define EXYNOS_DP_COMMON_INT_MASK_3          0x3E8
>> +#define EXYNOS_DP_COMMON_INT_MASK_4          0x3EC
>> +#define EXYNOS_DP_INT_STA_MASK                       0x3F8
>> +#define EXYNOS_DP_INT_CTL                    0x3FC
>> +
>> +#define EXYNOS_DP_SYS_CTL_1                  0x600
>> +#define EXYNOS_DP_SYS_CTL_2                  0x604
>> +#define EXYNOS_DP_SYS_CTL_3                  0x608
>> +#define EXYNOS_DP_SYS_CTL_4                  0x60C
>> +
>> +#define EXYNOS_DP_PKT_SEND_CTL                       0x640
>> +#define EXYNOS_DP_HDCP_CTL                   0x648
>> +
>> +#define EXYNOS_DP_LINK_BW_SET                        0x680
>> +#define EXYNOS_DP_LANE_COUNT_SET             0x684
>> +#define EXYNOS_DP_TRAINING_PTN_SET           0x688
>> +#define EXYNOS_DP_LN0_LINK_TRAINING_CTL              0x68C
>> +#define EXYNOS_DP_LN1_LINK_TRAINING_CTL              0x690
>> +#define EXYNOS_DP_LN2_LINK_TRAINING_CTL              0x694
>> +#define EXYNOS_DP_LN3_LINK_TRAINING_CTL              0x698
>> +
>> +#define EXYNOS_DP_DEBUG_CTL                  0x6C0
>> +#define EXYNOS_DP_HPD_DEGLITCH_L             0x6C4
>> +#define EXYNOS_DP_HPD_DEGLITCH_H             0x6C8
>> +#define EXYNOS_DP_LINK_DEBUG_CTL             0x6E0
>> +
>> +#define EXYNOS_DP_M_VID_0                    0x700
>> +#define EXYNOS_DP_M_VID_1                    0x704
>> +#define EXYNOS_DP_M_VID_2                    0x708
>> +#define EXYNOS_DP_N_VID_0                    0x70C
>> +#define EXYNOS_DP_N_VID_1                    0x710
>> +#define EXYNOS_DP_N_VID_2                    0x714
>> +
>> +#define EXYNOS_DP_PLL_CTL                    0x71C
>> +#define EXYNOS_DP_PHY_PD                     0x720
>> +#define EXYNOS_DP_PHY_TEST                   0x724
>> +
>> +#define EXYNOS_DP_VIDEO_FIFO_THRD            0x730
>> +#define EXYNOS_DP_AUDIO_MARGIN                       0x73C
>> +
>> +#define EXYNOS_DP_M_VID_GEN_FILTER_TH                0x764
>> +#define EXYNOS_DP_M_AUD_GEN_FILTER_TH                0x778
>> +#define EXYNOS_DP_AUX_CH_STA                 0x780
>> +#define EXYNOS_DP_AUX_CH_DEFER_CTL           0x788
>> +#define EXYNOS_DP_AUX_RX_COMM                        0x78C
>> +#define EXYNOS_DP_BUFFER_DATA_CTL            0x790
>> +#define EXYNOS_DP_AUX_CH_CTL_1                       0x794
>> +#define EXYNOS_DP_AUX_ADDR_7_0                       0x798
>> +#define EXYNOS_DP_AUX_ADDR_15_8                      0x79C
>> +#define EXYNOS_DP_AUX_ADDR_19_16             0x7A0
>> +#define EXYNOS_DP_AUX_CH_CTL_2                       0x7A4
>> +
>> +#define EXYNOS_DP_BUF_DATA_0                 0x7C0
>> +
>> +#define EXYNOS_DP_SOC_GENERAL_CTL            0x800
>> +
>> +/* EXYNOS_DP_TX_SW_RESET */
>> +#define RESET_DP_TX                          (0x1 << 0)
>> +
>> +/* EXYNOS_DP_FUNC_EN_1 */
>> +#define MASTER_VID_FUNC_EN_N                 (0x1 << 7)
>> +#define SLAVE_VID_FUNC_EN_N                  (0x1 << 5)
>> +#define AUD_FIFO_FUNC_EN_N                   (0x1 << 4)
>> +#define AUD_FUNC_EN_N                                (0x1 << 3)
>> +#define HDCP_FUNC_EN_N                               (0x1 << 2)
>> +#define CRC_FUNC_EN_N                                (0x1 << 1)
>> +#define SW_FUNC_EN_N                         (0x1 << 0)
>> +
>> +/* EXYNOS_DP_FUNC_EN_2 */
>> +#define SSC_FUNC_EN_N                                (0x1 << 7)
>> +#define AUX_FUNC_EN_N                                (0x1 << 2)
>> +#define SERDES_FIFO_FUNC_EN_N                        (0x1 << 1)
>> +#define LS_CLK_DOMAIN_FUNC_EN_N                      (0x1 << 0)
>> +
>> +/* EXYNOS_DP_VIDEO_CTL_1 */
>> +#define VIDEO_EN                             (0x1 << 7)
>> +#define HDCP_VIDEO_MUTE                              (0x1 << 6)
>> +
>> +/* EXYNOS_DP_VIDEO_CTL_1 */
>> +#define IN_D_RANGE_MASK                              (0x1 << 7)
>> +#define IN_D_RANGE_SHIFT                     (7)
>> +#define IN_D_RANGE_CEA                               (0x1 << 7)
>> +#define IN_D_RANGE_VESA                              (0x0 << 7)
>> +#define IN_BPC_MASK                          (0x7 << 4)
>> +#define IN_BPC_SHIFT                         (4)
>> +#define IN_BPC_12_BITS                               (0x3 << 4)
>> +#define IN_BPC_10_BITS                               (0x2 << 4)
>> +#define IN_BPC_8_BITS                                (0x1 << 4)
>> +#define IN_BPC_6_BITS                                (0x0 << 4)
>> +#define IN_COLOR_F_MASK                              (0x3 << 0)
>> +#define IN_COLOR_F_SHIFT                     (0)
>> +#define IN_COLOR_F_YCBCR444                  (0x2 << 0)
>> +#define IN_COLOR_F_YCBCR422                  (0x1 << 0)
>> +#define IN_COLOR_F_RGB                               (0x0 << 0)
>> +
>> +/* EXYNOS_DP_VIDEO_CTL_3 */
>> +#define IN_YC_COEFFI_MASK                    (0x1 << 7)
>> +#define IN_YC_COEFFI_SHIFT                   (7)
>> +#define IN_YC_COEFFI_ITU709                  (0x1 << 7)
>> +#define IN_YC_COEFFI_ITU601                  (0x0 << 7)
>> +#define VID_CHK_UPDATE_TYPE_MASK             (0x1 << 4)
>> +#define VID_CHK_UPDATE_TYPE_SHIFT            (4)
>> +#define VID_CHK_UPDATE_TYPE_1                        (0x1 << 4)
>> +#define VID_CHK_UPDATE_TYPE_0                        (0x0 << 4)
>> +
>> +/* EXYNOS_DP_VIDEO_CTL_8 */
>> +#define VID_HRES_TH(x)                               (((x) & 0xf) << 4)
>> +#define VID_VRES_TH(x)                               (((x) & 0xf) << 0)
>> +
>> +/* EXYNOS_DP_VIDEO_CTL_10 */
>> +#define FORMAT_SEL                           (0x1 << 4)
>> +#define INTERACE_SCAN_CFG                    (0x1 << 2)
>> +#define VSYNC_POLARITY_CFG                   (0x1 << 1)
>> +#define HSYNC_POLARITY_CFG                   (0x1 << 0)
>> +
>> +/* EXYNOS_DP_LANE_MAP */
>> +#define LANE3_MAP_LOGIC_LANE_0                       (0x0 << 6)
>> +#define LANE3_MAP_LOGIC_LANE_1                       (0x1 << 6)
>> +#define LANE3_MAP_LOGIC_LANE_2                       (0x2 << 6)
>> +#define LANE3_MAP_LOGIC_LANE_3                       (0x3 << 6)
>> +#define LANE2_MAP_LOGIC_LANE_0                       (0x0 << 4)
>> +#define LANE2_MAP_LOGIC_LANE_1                       (0x1 << 4)
>> +#define LANE2_MAP_LOGIC_LANE_2                       (0x2 << 4)
>> +#define LANE2_MAP_LOGIC_LANE_3                       (0x3 << 4)
>> +#define LANE1_MAP_LOGIC_LANE_0                       (0x0 << 2)
>> +#define LANE1_MAP_LOGIC_LANE_1                       (0x1 << 2)
>> +#define LANE1_MAP_LOGIC_LANE_2                       (0x2 << 2)
>> +#define LANE1_MAP_LOGIC_LANE_3                       (0x3 << 2)
>> +#define LANE0_MAP_LOGIC_LANE_0                       (0x0 << 0)
>> +#define LANE0_MAP_LOGIC_LANE_1                       (0x1 << 0)
>> +#define LANE0_MAP_LOGIC_LANE_2                       (0x2 << 0)
>> +#define LANE0_MAP_LOGIC_LANE_3                       (0x3 << 0)
>> +
>> +/* EXYNOS_DP_ANALOG_CTL_1 */
>> +#define TX_TERMINAL_CTRL_50_OHM                      (0x1 << 4)
>> +
>> +/* EXYNOS_DP_ANALOG_CTL_2 */
>> +#define SEL_24M                                      (0x1 << 3)
>> +#define TX_DVDD_BIT_1_0625V                  (0x4 << 0)
>> +
>> +/* EXYNOS_DP_ANALOG_CTL_3 */
>> +#define DRIVE_DVDD_BIT_1_0625V                       (0x4 << 5)
>> +#define VCO_BIT_600_MICRO                    (0x5 << 0)
>> +
>> +/* EXYNOS_DP_PLL_FILTER_CTL_1 */
>> +#define PD_RING_OSC                          (0x1 << 6)
>> +#define AUX_TERMINAL_CTRL_50_OHM             (0x2 << 4)
>> +#define TX_CUR1_2X                           (0x1 << 2)
>> +#define TX_CUR_16_MA                         (0x3 << 0)
>> +
>> +/* EXYNOS_DP_TX_AMP_TUNING_CTL */
>> +#define CH3_AMP_400_MV                               (0x0 << 24)
>> +#define CH2_AMP_400_MV                               (0x0 << 16)
>> +#define CH1_AMP_400_MV                               (0x0 << 8)
>> +#define CH0_AMP_400_MV                               (0x0 << 0)
>> +
>> +/* EXYNOS_DP_AUX_HW_RETRY_CTL */
>> +#define AUX_BIT_PERIOD_EXPECTED_DELAY(x)     (((x) & 0x7) << 8)
>> +#define AUX_HW_RETRY_INTERVAL_MASK           (0x3 << 3)
>> +#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS       (0x0 << 3)
>> +#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS       (0x1 << 3)
>> +#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS      (0x2 << 3)
>> +#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS      (0x3 << 3)
>> +#define AUX_HW_RETRY_COUNT_SEL(x)            (((x) & 0x7) << 0)
>> +
>> +/* EXYNOS_DP_COMMON_INT_STA_1 */
>> +#define VSYNC_DET                            (0x1 << 7)
>> +#define PLL_LOCK_CHG                         (0x1 << 6)
>> +#define SPDIF_ERR                            (0x1 << 5)
>> +#define SPDIF_UNSTBL                         (0x1 << 4)
>> +#define VID_FORMAT_CHG                               (0x1 << 3)
>> +#define AUD_CLK_CHG                          (0x1 << 2)
>> +#define VID_CLK_CHG                          (0x1 << 1)
>> +#define SW_INT                                       (0x1 << 0)
>> +
>> +/* EXYNOS_DP_COMMON_INT_STA_2 */
>> +#define ENC_EN_CHG                           (0x1 << 6)
>> +#define HW_BKSV_RDY                          (0x1 << 3)
>> +#define HW_SHA_DONE                          (0x1 << 2)
>> +#define HW_AUTH_STATE_CHG                    (0x1 << 1)
>> +#define HW_AUTH_DONE                         (0x1 << 0)
>> +
>> +/* EXYNOS_DP_COMMON_INT_STA_3 */
>> +#define AFIFO_UNDER                          (0x1 << 7)
>> +#define AFIFO_OVER                           (0x1 << 6)
>> +#define R0_CHK_FLAG                          (0x1 << 5)
>> +
>> +/* EXYNOS_DP_COMMON_INT_STA_4 */
>> +#define PSR_ACTIVE                           (0x1 << 7)
>> +#define PSR_INACTIVE                         (0x1 << 6)
>> +#define SPDIF_BI_PHASE_ERR                   (0x1 << 5)
>> +#define HOTPLUG_CHG                          (0x1 << 2)
>> +#define HPD_LOST                             (0x1 << 1)
>> +#define PLUG                                 (0x1 << 0)
>> +
>> +/* EXYNOS_DP_INT_STA */
>> +#define INT_HPD                                      (0x1 << 6)
>> +#define HW_TRAINING_FINISH                   (0x1 << 5)
>> +#define RPLY_RECEIV                          (0x1 << 1)
>> +#define AUX_ERR                                      (0x1 << 0)
>> +
>> +/* EXYNOS_DP_INT_CTL */
>> +#define SOFT_INT_CTRL                                (0x1 << 2)
>> +#define INT_POL1                             (0x1 << 1)
>> +#define INT_POL0                             (0x1 << 0)
>> +
>> +/* EXYNOS_DP_SYS_CTL_1 */
>> +#define DET_STA                                      (0x1 << 2)
>> +#define FORCE_DET                            (0x1 << 1)
>> +#define DET_CTRL                             (0x1 << 0)
>> +
>> +/* EXYNOS_DP_SYS_CTL_2 */
>> +#define CHA_CRI(x)                           (((x) & 0xf) << 4)
>> +#define CHA_STA                                      (0x1 << 2)
>> +#define FORCE_CHA                            (0x1 << 1)
>> +#define CHA_CTRL                             (0x1 << 0)
>> +
>> +/* EXYNOS_DP_SYS_CTL_3 */
>> +#define HPD_STATUS                           (0x1 << 6)
>> +#define F_HPD                                        (0x1 << 5)
>> +#define HPD_CTRL                             (0x1 << 4)
>> +#define HDCP_RDY                             (0x1 << 3)
>> +#define STRM_VALID                           (0x1 << 2)
>> +#define F_VALID                                      (0x1 << 1)
>> +#define VALID_CTRL                           (0x1 << 0)
>> +
>> +/* EXYNOS_DP_SYS_CTL_4 */
>> +#define FIX_M_AUD                            (0x1 << 4)
>> +#define ENHANCED                             (0x1 << 3)
>> +#define FIX_M_VID                            (0x1 << 2)
>> +#define M_VID_UPDATE_CTRL                    (0x3 << 0)
>> +
>> +/* EXYNOS_DP_TRAINING_PTN_SET */
>> +#define SCRAMBLER_TYPE                               (0x1 << 9)
>> +#define HW_LINK_TRAINING_PATTERN             (0x1 << 8)
>> +#define SCRAMBLING_DISABLE                   (0x1 << 5)
>> +#define SCRAMBLING_ENABLE                    (0x0 << 5)
>> +#define LINK_QUAL_PATTERN_SET_MASK           (0x3 << 2)
>> +#define LINK_QUAL_PATTERN_SET_PRBS7          (0x3 << 2)
>> +#define LINK_QUAL_PATTERN_SET_D10_2          (0x1 << 2)
>> +#define LINK_QUAL_PATTERN_SET_DISABLE                (0x0 << 2)
>> +#define SW_TRAINING_PATTERN_SET_MASK         (0x3 << 0)
>> +#define SW_TRAINING_PATTERN_SET_PTN2         (0x2 << 0)
>> +#define SW_TRAINING_PATTERN_SET_PTN1         (0x1 << 0)
>> +#define SW_TRAINING_PATTERN_SET_NORMAL               (0x0 << 0)
>> +
>> +/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
>> +#define PRE_EMPHASIS_SET_MASK                        (0x3 << 3)
>> +#define PRE_EMPHASIS_SET_SHIFT                       (3)
>> +
>> +/* EXYNOS_DP_DEBUG_CTL */
>> +#define PLL_LOCK                             (0x1 << 4)
>> +#define F_PLL_LOCK                           (0x1 << 3)
>> +#define PLL_LOCK_CTRL                                (0x1 << 2)
>> +#define PN_INV                                       (0x1 << 0)
>> +
>> +/* EXYNOS_DP_PLL_CTL */
>> +#define DP_PLL_PD                            (0x1 << 7)
>> +#define DP_PLL_RESET                         (0x1 << 6)
>> +#define DP_PLL_LOOP_BIT_DEFAULT                      (0x1 << 4)
>> +#define DP_PLL_REF_BIT_1_1250V                       (0x5 << 0)
>> +#define DP_PLL_REF_BIT_1_2500V                       (0x7 << 0)
>> +
>> +/* EXYNOS_DP_PHY_PD */
>> +#define DP_PHY_PD                            (0x1 << 5)
>> +#define AUX_PD                                       (0x1 << 4)
>> +#define CH3_PD                                       (0x1 << 3)
>> +#define CH2_PD                                       (0x1 << 2)
>> +#define CH1_PD                                       (0x1 << 1)
>> +#define CH0_PD                                       (0x1 << 0)
>> +
>> +/* EXYNOS_DP_PHY_TEST */
>> +#define MACRO_RST                            (0x1 << 5)
>> +#define CH1_TEST                             (0x1 << 1)
>> +#define CH0_TEST                             (0x1 << 0)
>> +
>> +/* EXYNOS_DP_AUX_CH_STA */
>> +#define AUX_BUSY                             (0x1 << 4)
>> +#define AUX_STATUS_MASK                              (0xf << 0)
>> +
>> +/* EXYNOS_DP_AUX_CH_DEFER_CTL */
>> +#define DEFER_CTRL_EN                                (0x1 << 7)
>> +#define DEFER_COUNT(x)                               (((x) & 0x7f) << 0)
>> +
>> +/* EXYNOS_DP_AUX_RX_COMM */
>> +#define AUX_RX_COMM_I2C_DEFER                        (0x2 << 2)
>> +#define AUX_RX_COMM_AUX_DEFER                        (0x2 << 0)
>> +
>> +/* EXYNOS_DP_BUFFER_DATA_CTL */
>> +#define BUF_CLR                                      (0x1 << 7)
>> +#define BUF_DATA_COUNT(x)                    (((x) & 0x1f) << 0)
>> +
>> +/* EXYNOS_DP_AUX_CH_CTL_1 */
>> +#define AUX_LENGTH(x)                                (((x - 1) & 0xf) <<
> 4)
>> +#define AUX_TX_COMM_MASK                     (0xf << 0)
>> +#define AUX_TX_COMM_DP_TRANSACTION           (0x1 << 3)
>> +#define AUX_TX_COMM_I2C_TRANSACTION          (0x0 << 3)
>> +#define AUX_TX_COMM_MOT                              (0x1 << 2)
>> +#define AUX_TX_COMM_WRITE                    (0x0 << 0)
>> +#define AUX_TX_COMM_READ                     (0x1 << 0)
>> +
>> +/* EXYNOS_DP_AUX_ADDR_7_0 */
>> +#define AUX_ADDR_7_0(x)                              (((x) >> 0) & 0xff)
>> +
>> +/* EXYNOS_DP_AUX_ADDR_15_8 */
>> +#define AUX_ADDR_15_8(x)                     (((x) >> 8) & 0xff)
>> +
>> +/* EXYNOS_DP_AUX_ADDR_19_16 */
>> +#define AUX_ADDR_19_16(x)                    (((x) >> 16) & 0x0f)
>> +
>> +/* EXYNOS_DP_AUX_CH_CTL_2 */
>> +#define ADDR_ONLY                            (0x1 << 1)
>> +#define AUX_EN                                       (0x1 << 0)
>> +
>> +/* EXYNOS_DP_SOC_GENERAL_CTL */
>> +#define AUDIO_MODE_SPDIF_MODE                        (0x1 << 8)
>> +#define AUDIO_MODE_MASTER_MODE                       (0x0 << 8)
>> +#define MASTER_VIDEO_INTERLACE_EN            (0x1 << 4)
>> +#define VIDEO_MASTER_CLK_SEL                 (0x1 << 2)
>> +#define VIDEO_MASTER_MODE_EN                 (0x1 << 1)
>> +#define VIDEO_MODE_MASK                              (0x1 << 0)
>> +#define VIDEO_MODE_SLAVE_MODE                        (0x1 << 0)
>> +#define VIDEO_MODE_MASTER_MODE                       (0x0 << 0)
>> +
>> +#endif /* _EXYNOS_DP_REG_H */
>> diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
>> index 1b035b2..7032ad9 100644
>> --- a/drivers/video/exynos/Kconfig
>> +++ b/drivers/video/exynos/Kconfig
>> @@ -27,11 +27,4 @@ config EXYNOS_LCD_S6E8AX0
>>         If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
>>         LCD control driver.
>>
>> -config EXYNOS_DP
>> -     bool "EXYNOS DP driver support"
>> -     depends on ARCH_EXYNOS
>> -     default n
>> -     help
>> -       This enables support for DP device.
>> -
>>  endif # EXYNOS_VIDEO
>> diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile
>> index ec7772e..b5b1bd2 100644
>> --- a/drivers/video/exynos/Makefile
>> +++ b/drivers/video/exynos/Makefile
>> @@ -5,4 +5,3 @@
>>  obj-$(CONFIG_EXYNOS_MIPI_DSI)                += exynos_mipi_dsi.o
>> exynos_mipi_dsi_common.o \
>>                                       exynos_mipi_dsi_lowlevel.o
>>  obj-$(CONFIG_EXYNOS_LCD_S6E8AX0)     += s6e8ax0.o
>> -obj-$(CONFIG_EXYNOS_DP)                      += exynos_dp_core.o
>> exynos_dp_reg.o
>> diff --git a/drivers/video/exynos/exynos_dp_core.c
>> b/drivers/video/exynos/exynos_dp_core.c
>> deleted file mode 100644
>> index 089ae22..0000000
>> --- a/drivers/video/exynos/exynos_dp_core.c
>> +++ /dev/null
>> @@ -1,1213 +0,0 @@
>> -/*
>> - * Samsung SoC DP (Display Port) interface driver.
>> - *
>> - * Copyright (C) 2012 Samsung Electronics Co., Ltd.
>> - * Author: Jingoo Han <jg1.han@samsung.com>
>> - *
>> - * 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/module.h>
>> -#include <linux/platform_device.h>
>> -#include <linux/err.h>
>> -#include <linux/clk.h>
>> -#include <linux/io.h>
>> -#include <linux/interrupt.h>
>> -#include <linux/delay.h>
>> -#include <linux/of.h>
>> -
>> -#include <video/exynos_dp.h>
>> -
>> -#include "exynos_dp_core.h"
>> -
>> -static int exynos_dp_init_dp(struct exynos_dp_device *dp)
>> -{
>> -     exynos_dp_reset(dp);
>> -
>> -     exynos_dp_swreset(dp);
>> -
>> -     exynos_dp_init_analog_param(dp);
>> -     exynos_dp_init_interrupt(dp);
>> -
>> -     /* SW defined function Normal operation */
>> -     exynos_dp_enable_sw_function(dp);
>> -
>> -     exynos_dp_config_interrupt(dp);
>> -     exynos_dp_init_analog_func(dp);
>> -
>> -     exynos_dp_init_hpd(dp);
>> -     exynos_dp_init_aux(dp);
>> -
>> -     return 0;
>> -}
>> -
>> -static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
>> -{
>> -     int timeout_loop = 0;
>> -
>> -     while (exynos_dp_get_plug_in_status(dp) != 0) {
>> -             timeout_loop++;
>> -             if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
>> -                     dev_err(dp->dev, "failed to get hpd plug status\n");
>> -                     return -ETIMEDOUT;
>> -             }
>> -             usleep_range(10, 11);
>> -     }
>> -
>> -     return 0;
>> -}
>> -
>> -static unsigned char exynos_dp_calc_edid_check_sum(unsigned char
>> *edid_data)
>> -{
>> -     int i;
>> -     unsigned char sum = 0;
>> -
>> -     for (i = 0; i < EDID_BLOCK_LENGTH; i++)
>> -             sum = sum + edid_data[i];
>> -
>> -     return sum;
>> -}
>> -
>> -static int exynos_dp_read_edid(struct exynos_dp_device *dp)
>> -{
>> -     unsigned char edid[EDID_BLOCK_LENGTH * 2];
>> -     unsigned int extend_block = 0;
>> -     unsigned char sum;
>> -     unsigned char test_vector;
>> -     int retval;
>> -
>> -     /*
>> -      * EDID device address is 0x50.
>> -      * However, if necessary, you must have set upper address
>> -      * into E-EDID in I2C device, 0x30.
>> -      */
>> -
>> -     /* Read Extension Flag, Number of 128-byte EDID extension blocks */
>> -     retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
>> -                             EDID_EXTENSION_FLAG,
>> -                             &extend_block);
>> -     if (retval)
>> -             return retval;
>> -
>> -     if (extend_block > 0) {
>> -             dev_dbg(dp->dev, "EDID data includes a single
> extension!\n");
>> -
>> -             /* Read EDID data */
>> -             retval = exynos_dp_read_bytes_from_i2c(dp,
>> I2C_EDID_DEVICE_ADDR,
>> -                                             EDID_HEADER_PATTERN,
>> -                                             EDID_BLOCK_LENGTH,
>> -                                             &edid[EDID_HEADER_PATTERN]);
>> -             if (retval != 0) {
>> -                     dev_err(dp->dev, "EDID Read failed!\n");
>> -                     return -EIO;
>> -             }
>> -             sum = exynos_dp_calc_edid_check_sum(edid);
>> -             if (sum != 0) {
>> -                     dev_err(dp->dev, "EDID bad checksum!\n");
>> -                     return -EIO;
>> -             }
>> -
>> -             /* Read additional EDID data */
>> -             retval = exynos_dp_read_bytes_from_i2c(dp,
>> -                             I2C_EDID_DEVICE_ADDR,
>> -                             EDID_BLOCK_LENGTH,
>> -                             EDID_BLOCK_LENGTH,
>> -                             &edid[EDID_BLOCK_LENGTH]);
>> -             if (retval != 0) {
>> -                     dev_err(dp->dev, "EDID Read failed!\n");
>> -                     return -EIO;
>> -             }
>> -             sum =
>> exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
>> -             if (sum != 0) {
>> -                     dev_err(dp->dev, "EDID bad checksum!\n");
>> -                     return -EIO;
>> -             }
>> -
>> -             exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
>> -                                     &test_vector);
>> -             if (test_vector & DPCD_TEST_EDID_READ) {
>> -                     exynos_dp_write_byte_to_dpcd(dp,
>> -                             DPCD_ADDR_TEST_EDID_CHECKSUM,
>> -                             edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
>> -                     exynos_dp_write_byte_to_dpcd(dp,
>> -                             DPCD_ADDR_TEST_RESPONSE,
>> -                             DPCD_TEST_EDID_CHECKSUM_WRITE);
>> -             }
>> -     } else {
>> -             dev_info(dp->dev, "EDID data does not include any
>> extensions.\n");
>> -
>> -             /* Read EDID data */
>> -             retval = exynos_dp_read_bytes_from_i2c(dp,
>> -                             I2C_EDID_DEVICE_ADDR,
>> -                             EDID_HEADER_PATTERN,
>> -                             EDID_BLOCK_LENGTH,
>> -                             &edid[EDID_HEADER_PATTERN]);
>> -             if (retval != 0) {
>> -                     dev_err(dp->dev, "EDID Read failed!\n");
>> -                     return -EIO;
>> -             }
>> -             sum = exynos_dp_calc_edid_check_sum(edid);
>> -             if (sum != 0) {
>> -                     dev_err(dp->dev, "EDID bad checksum!\n");
>> -                     return -EIO;
>> -             }
>> -
>> -             exynos_dp_read_byte_from_dpcd(dp,
>> -                     DPCD_ADDR_TEST_REQUEST,
>> -                     &test_vector);
>> -             if (test_vector & DPCD_TEST_EDID_READ) {
>> -                     exynos_dp_write_byte_to_dpcd(dp,
>> -                             DPCD_ADDR_TEST_EDID_CHECKSUM,
>> -                             edid[EDID_CHECKSUM]);
>> -                     exynos_dp_write_byte_to_dpcd(dp,
>> -                             DPCD_ADDR_TEST_RESPONSE,
>> -                             DPCD_TEST_EDID_CHECKSUM_WRITE);
>> -             }
>> -     }
>> -
>> -     dev_err(dp->dev, "EDID Read success!\n");
>> -     return 0;
>> -}
>> -
>> -static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
>> -{
>> -     u8 buf[12];
>> -     int i;
>> -     int retval;
>> -
>> -     /* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
>> -     retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
>> -                             12, buf);
>> -     if (retval)
>> -             return retval;
>> -
>> -     /* Read EDID */
>> -     for (i = 0; i < 3; i++) {
>> -             retval = exynos_dp_read_edid(dp);
>> -             if (!retval)
>> -                     break;
>> -     }
>> -
>> -     return retval;
>> -}
>> -
>> -static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device
>> *dp,
>> -                                             bool enable)
>> -{
>> -     u8 data;
>> -
>> -     exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
>> -
>> -     if (enable)
>> -             exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
>> -                     DPCD_ENHANCED_FRAME_EN |
>> -                     DPCD_LANE_COUNT_SET(data));
>> -     else
>> -             exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
>> -                     DPCD_LANE_COUNT_SET(data));
>> -}
>> -
>> -static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device
>> *dp)
>> -{
>> -     u8 data;
>> -     int retval;
>> -
>> -     exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
>> -     retval = DPCD_ENHANCED_FRAME_CAP(data);
>> -
>> -     return retval;
>> -}
>> -
>> -static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
>> -{
>> -     u8 data;
>> -
>> -     data = exynos_dp_is_enhanced_mode_available(dp);
>> -     exynos_dp_enable_rx_to_enhanced_mode(dp, data);
>> -     exynos_dp_enable_enhanced_mode(dp, data);
>> -}
>> -
>> -static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
>> -{
>> -     exynos_dp_set_training_pattern(dp, DP_NONE);
>> -
>> -     exynos_dp_write_byte_to_dpcd(dp,
>> -             DPCD_ADDR_TRAINING_PATTERN_SET,
>> -             DPCD_TRAINING_PATTERN_DISABLED);
>> -}
>> -
>> -static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device
>> *dp,
>> -                                     int pre_emphasis, int lane)
>> -{
>> -     switch (lane) {
>> -     case 0:
>> -             exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
>> -             break;
>> -     case 1:
>> -             exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
>> -             break;
>> -
>> -     case 2:
>> -             exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
>> -             break;
>> -
>> -     case 3:
>> -             exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
>> -             break;
>> -     }
>> -}
>> -
>> -static int exynos_dp_link_start(struct exynos_dp_device *dp)
>> -{
>> -     u8 buf[4];
>> -     int lane, lane_count, pll_tries, retval;
>> -
>> -     lane_count = dp->link_train.lane_count;
>> -
>> -     dp->link_train.lt_state = CLOCK_RECOVERY;
>> -     dp->link_train.eq_loop = 0;
>> -
>> -     for (lane = 0; lane < lane_count; lane++)
>> -             dp->link_train.cr_loop[lane] = 0;
>> -
>> -     /* Set link rate and count as you want to establish*/
>> -     exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
>> -     exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
>> -
>> -     /* Setup RX configuration */
>> -     buf[0] = dp->link_train.link_rate;
>> -     buf[1] = dp->link_train.lane_count;
>> -     retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
>> -                             2, buf);
>> -     if (retval)
>> -             return retval;
>> -
>> -     /* Set TX pre-emphasis to minimum */
>> -     for (lane = 0; lane < lane_count; lane++)
>> -             exynos_dp_set_lane_lane_pre_emphasis(dp,
>> -                     PRE_EMPHASIS_LEVEL_0, lane);
>> -
>> -     /* Wait for PLL lock */
>> -     pll_tries = 0;
>> -     while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
>> -             if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
>> -                     dev_err(dp->dev, "Wait for PLL lock timed out\n");
>> -                     return -ETIMEDOUT;
>> -             }
>> -
>> -             pll_tries++;
>> -             usleep_range(90, 120);
>> -     }
>> -
>> -     /* Set training pattern 1 */
>> -     exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
>> -
>> -     /* Set RX training pattern */
>> -     retval = exynos_dp_write_byte_to_dpcd(dp,
>> -                     DPCD_ADDR_TRAINING_PATTERN_SET,
>> -                     DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
>> -     if (retval)
>> -             return retval;
>> -
>> -     for (lane = 0; lane < lane_count; lane++)
>> -             buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
>> -                         DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
>> -
>> -     retval = exynos_dp_write_bytes_to_dpcd(dp,
>> DPCD_ADDR_TRAINING_LANE0_SET,
>> -                     lane_count, buf);
>> -
>> -     return retval;
>> -}
>> -
>> -static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int
>> lane)
>> -{
>> -     int shift = (lane & 1) * 4;
>> -     u8 link_value = link_status[lane>>1];
>> -
>> -     return (link_value >> shift) & 0xf;
>> -}
>> -
>> -static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
>> -{
>> -     int lane;
>> -     u8 lane_status;
>> -
>> -     for (lane = 0; lane < lane_count; lane++) {
>> -             lane_status = exynos_dp_get_lane_status(link_status, lane);
>> -             if ((lane_status & DPCD_LANE_CR_DONE) == 0)
>> -                     return -EINVAL;
>> -     }
>> -     return 0;
>> -}
>> -
>> -static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
>> -                             int lane_count)
>> -{
>> -     int lane;
>> -     u8 lane_status;
>> -
>> -     if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
>> -             return -EINVAL;
>> -
>> -     for (lane = 0; lane < lane_count; lane++) {
>> -             lane_status = exynos_dp_get_lane_status(link_status, lane);
>> -             lane_status &= DPCD_CHANNEL_EQ_BITS;
>> -             if (lane_status != DPCD_CHANNEL_EQ_BITS)
>> -                     return -EINVAL;
>> -     }
>> -
>> -     return 0;
>> -}
>> -
>> -static unsigned char exynos_dp_get_adjust_request_voltage(u8
>> adjust_request[2],
>> -                                                     int lane)
>> -{
>> -     int shift = (lane & 1) * 4;
>> -     u8 link_value = adjust_request[lane>>1];
>> -
>> -     return (link_value >> shift) & 0x3;
>> -}
>> -
>> -static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
>> -                                     u8 adjust_request[2],
>> -                                     int lane)
>> -{
>> -     int shift = (lane & 1) * 4;
>> -     u8 link_value = adjust_request[lane>>1];
>> -
>> -     return ((link_value >> shift) & 0xc) >> 2;
>> -}
>> -
>> -static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
>> -                                     u8 training_lane_set, int lane)
>> -{
>> -     switch (lane) {
>> -     case 0:
>> -             exynos_dp_set_lane0_link_training(dp, training_lane_set);
>> -             break;
>> -     case 1:
>> -             exynos_dp_set_lane1_link_training(dp, training_lane_set);
>> -             break;
>> -
>> -     case 2:
>> -             exynos_dp_set_lane2_link_training(dp, training_lane_set);
>> -             break;
>> -
>> -     case 3:
>> -             exynos_dp_set_lane3_link_training(dp, training_lane_set);
>> -             break;
>> -     }
>> -}
>> -
>> -static unsigned int exynos_dp_get_lane_link_training(
>> -                             struct exynos_dp_device *dp,
>> -                             int lane)
>> -{
>> -     u32 reg;
>> -
>> -     switch (lane) {
>> -     case 0:
>> -             reg = exynos_dp_get_lane0_link_training(dp);
>> -             break;
>> -     case 1:
>> -             reg = exynos_dp_get_lane1_link_training(dp);
>> -             break;
>> -     case 2:
>> -             reg = exynos_dp_get_lane2_link_training(dp);
>> -             break;
>> -     case 3:
>> -             reg = exynos_dp_get_lane3_link_training(dp);
>> -             break;
>> -     default:
>> -             WARN_ON(1);
>> -             return 0;
>> -     }
>> -
>> -     return reg;
>> -}
>> -
>> -static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
>> -{
>> -     exynos_dp_training_pattern_dis(dp);
>> -     exynos_dp_set_enhanced_mode(dp);
>> -
>> -     dp->link_train.lt_state = FAILED;
>> -}
>> -
>> -static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device
>> *dp,
>> -                                     u8 adjust_request[2])
>> -{
>> -     int lane, lane_count;
>> -     u8 voltage_swing, pre_emphasis, training_lane;
>> -
>> -     lane_count = dp->link_train.lane_count;
>> -     for (lane = 0; lane < lane_count; lane++) {
>> -             voltage_swing = exynos_dp_get_adjust_request_voltage(
>> -                                             adjust_request, lane);
>> -             pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
>> -                                             adjust_request, lane);
>> -             training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
>> -                             DPCD_PRE_EMPHASIS_SET(pre_emphasis);
>> -
>> -             if (voltage_swing == VOLTAGE_LEVEL_3)
>> -                     training_lane |= DPCD_MAX_SWING_REACHED;
>> -             if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
>> -                     training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
>> -
>> -             dp->link_train.training_lane[lane] = training_lane;
>> -     }
>> -}
>> -
>> -static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
>> -{
>> -     int lane, lane_count, retval;
>> -     u8 voltage_swing, pre_emphasis, training_lane;
>> -     u8 link_status[2], adjust_request[2];
>> -
>> -     usleep_range(100, 101);
>> -
>> -     lane_count = dp->link_train.lane_count;
>> -
>> -     retval =  exynos_dp_read_bytes_from_dpcd(dp,
>> -                     DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
>> -     if (retval)
>> -             return retval;
>> -
>> -     retval =  exynos_dp_read_bytes_from_dpcd(dp,
>> -                     DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2,
> adjust_request);
>> -     if (retval)
>> -             return retval;
>> -
>> -     if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
>> -             /* set training pattern 2 for EQ */
>> -             exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
>> -
>> -             retval = exynos_dp_write_byte_to_dpcd(dp,
>> -                             DPCD_ADDR_TRAINING_PATTERN_SET,
>> -                             DPCD_SCRAMBLING_DISABLED |
>> -                             DPCD_TRAINING_PATTERN_2);
>> -             if (retval)
>> -                     return retval;
>> -
>> -             dev_info(dp->dev, "Link Training Clock Recovery success\n");
>> -             dp->link_train.lt_state = EQUALIZER_TRAINING;
>> -     } else {
>> -             for (lane = 0; lane < lane_count; lane++) {
>> -                     training_lane = exynos_dp_get_lane_link_training(
>> -                                                     dp, lane);
>> -                     voltage_swing =
> exynos_dp_get_adjust_request_voltage(
>> -                                                     adjust_request,
> lane);
>> -                     pre_emphasis =
>> exynos_dp_get_adjust_request_pre_emphasis(
>> -                                                     adjust_request,
> lane);
>> -
>> -                     if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
>> -                                     voltage_swing &&
>> -                         DPCD_PRE_EMPHASIS_GET(training_lane) ==
>> -                                     pre_emphasis)
>> -                             dp->link_train.cr_loop[lane]++;
>> -
>> -                     if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
>> -                         voltage_swing == VOLTAGE_LEVEL_3 ||
>> -                         pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
>> -                             dev_err(dp->dev, "CR Max reached
> (%d,%d,%d)\n",
>> -                                     dp->link_train.cr_loop[lane],
>> -                                     voltage_swing, pre_emphasis);
>> -                             exynos_dp_reduce_link_rate(dp);
>> -                             return -EIO;
>> -                     }
>> -             }
>> -     }
>> -
>> -     exynos_dp_get_adjust_training_lane(dp, adjust_request);
>> -
>> -     for (lane = 0; lane < lane_count; lane++)
>> -             exynos_dp_set_lane_link_training(dp,
>> -                     dp->link_train.training_lane[lane], lane);
>> -
>> -     retval = exynos_dp_write_bytes_to_dpcd(dp,
>> -                     DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
>> -                     dp->link_train.training_lane);
>> -     if (retval)
>> -             return retval;
>> -
>> -     return retval;
>> -}
>> -
>> -static int exynos_dp_process_equalizer_training(struct exynos_dp_device
>> *dp)
>> -{
>> -     int lane, lane_count, retval;
>> -     u32 reg;
>> -     u8 link_align, link_status[2], adjust_request[2];
>> -
>> -     usleep_range(400, 401);
>> -
>> -     lane_count = dp->link_train.lane_count;
>> -
>> -     retval = exynos_dp_read_bytes_from_dpcd(dp,
>> -                     DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
>> -     if (retval)
>> -             return retval;
>> -
>> -     if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
>> -             exynos_dp_reduce_link_rate(dp);
>> -             return -EIO;
>> -     }
>> -
>> -     retval = exynos_dp_read_bytes_from_dpcd(dp,
>> -                     DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2,
> adjust_request);
>> -     if (retval)
>> -             return retval;
>> -
>> -     retval = exynos_dp_read_byte_from_dpcd(dp,
>> -                     DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
>> -     if (retval)
>> -             return retval;
>> -
>> -     exynos_dp_get_adjust_training_lane(dp, adjust_request);
>> -
>> -     if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count))
>> {
>> -             /* traing pattern Set to Normal */
>> -             exynos_dp_training_pattern_dis(dp);
>> -
>> -             dev_info(dp->dev, "Link Training success!\n");
>> -
>> -             exynos_dp_get_link_bandwidth(dp, &reg);
>> -             dp->link_train.link_rate = reg;
>> -             dev_dbg(dp->dev, "final bandwidth = %.2x\n",
>> -                     dp->link_train.link_rate);
>> -
>> -             exynos_dp_get_lane_count(dp, &reg);
>> -             dp->link_train.lane_count = reg;
>> -             dev_dbg(dp->dev, "final lane count = %.2x\n",
>> -                     dp->link_train.lane_count);
>> -
>> -             /* set enhanced mode if available */
>> -             exynos_dp_set_enhanced_mode(dp);
>> -             dp->link_train.lt_state = FINISHED;
>> -
>> -             return 0;
>> -     }
>> -
>> -     /* not all locked */
>> -     dp->link_train.eq_loop++;
>> -
>> -     if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
>> -             dev_err(dp->dev, "EQ Max loop\n");
>> -             exynos_dp_reduce_link_rate(dp);
>> -             return -EIO;
>> -     }
>> -
>> -     for (lane = 0; lane < lane_count; lane++)
>> -             exynos_dp_set_lane_link_training(dp,
>> -                     dp->link_train.training_lane[lane], lane);
>> -
>> -     retval = exynos_dp_write_bytes_to_dpcd(dp,
>> DPCD_ADDR_TRAINING_LANE0_SET,
>> -                     lane_count, dp->link_train.training_lane);
>> -
>> -     return retval;
>> -}
>> -
>> -static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
>> -                                     u8 *bandwidth)
>> -{
>> -     u8 data;
>> -
>> -     /*
>> -      * For DP rev.1.1, Maximum link rate of Main Link lanes
>> -      * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
>> -      */
>> -     exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
>> -     *bandwidth = data;
>> -}
>> -
>> -static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
>> -                                     u8 *lane_count)
>> -{
>> -     u8 data;
>> -
>> -     /*
>> -      * For DP rev.1.1, Maximum number of Main Link lanes
>> -      * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
>> -      */
>> -     exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
>> -     *lane_count = DPCD_MAX_LANE_COUNT(data);
>> -}
>> -
>> -static void exynos_dp_init_training(struct exynos_dp_device *dp,
>> -                     enum link_lane_count_type max_lane,
>> -                     enum link_rate_type max_rate)
>> -{
>> -     /*
>> -      * MACRO_RST must be applied after the PLL_LOCK to avoid
>> -      * the DP inter pair skew issue for at least 10 us
>> -      */
>> -     exynos_dp_reset_macro(dp);
>> -
>> -     /* Initialize by reading RX's DPCD */
>> -     exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
>> -     exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
>> -
>> -     if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
>> -        (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
>> -             dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
>> -                     dp->link_train.link_rate);
>> -             dp->link_train.link_rate = LINK_RATE_1_62GBPS;
>> -     }
>> -
>> -     if (dp->link_train.lane_count == 0) {
>> -             dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
>> -                     dp->link_train.lane_count);
>> -             dp->link_train.lane_count = (u8)LANE_COUNT1;
>> -     }
>> -
>> -     /* Setup TX lane count & rate */
>> -     if (dp->link_train.lane_count > max_lane)
>> -             dp->link_train.lane_count = max_lane;
>> -     if (dp->link_train.link_rate > max_rate)
>> -             dp->link_train.link_rate = max_rate;
>> -
>> -     /* All DP analog module power up */
>> -     exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
>> -}
>> -
>> -static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
>> -{
>> -     int retval = 0, training_finished = 0;
>> -
>> -     dp->link_train.lt_state = START;
>> -
>> -     /* Process here */
>> -     while (!retval && !training_finished) {
>> -             switch (dp->link_train.lt_state) {
>> -             case START:
>> -                     retval = exynos_dp_link_start(dp);
>> -                     if (retval)
>> -                             dev_err(dp->dev, "LT link start failed!\n");
>> -                     break;
>> -             case CLOCK_RECOVERY:
>> -                     retval = exynos_dp_process_clock_recovery(dp);
>> -                     if (retval)
>> -                             dev_err(dp->dev, "LT CR failed!\n");
>> -                     break;
>> -             case EQUALIZER_TRAINING:
>> -                     retval = exynos_dp_process_equalizer_training(dp);
>> -                     if (retval)
>> -                             dev_err(dp->dev, "LT EQ failed!\n");
>> -                     break;
>> -             case FINISHED:
>> -                     training_finished = 1;
>> -                     break;
>> -             case FAILED:
>> -                     return -EREMOTEIO;
>> -             }
>> -     }
>> -     if (retval)
>> -             dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
>> -
>> -     return retval;
>> -}
>> -
>> -static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
>> -                             u32 count,
>> -                             u32 bwtype)
>> -{
>> -     int i;
>> -     int retval;
>> -
>> -     for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
>> -             exynos_dp_init_training(dp, count, bwtype);
>> -             retval = exynos_dp_sw_link_training(dp);
>> -             if (retval == 0)
>> -                     break;
>> -
>> -             usleep_range(100, 110);
>> -     }
>> -
>> -     return retval;
>> -}
>> -
>> -static int exynos_dp_config_video(struct exynos_dp_device *dp)
>> -{
>> -     int retval = 0;
>> -     int timeout_loop = 0;
>> -     int done_count = 0;
>> -
>> -     exynos_dp_config_video_slave_mode(dp);
>> -
>> -     exynos_dp_set_video_color_format(dp);
>> -
>> -     if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
>> -             dev_err(dp->dev, "PLL is not locked yet.\n");
>> -             return -EINVAL;
>> -     }
>> -
>> -     for (;;) {
>> -             timeout_loop++;
>> -             if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
>> -                     break;
>> -             if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
>> -                     dev_err(dp->dev, "Timeout of video streamclk ok\n");
>> -                     return -ETIMEDOUT;
>> -             }
>> -
>> -             usleep_range(1, 2);
>> -     }
>> -
>> -     /* Set to use the register calculated M/N video */
>> -     exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
>> -
>> -     /* For video bist, Video timing must be generated by register */
>> -     exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
>> -
>> -     /* Disable video mute */
>> -     exynos_dp_enable_video_mute(dp, 0);
>> -
>> -     /* Configure video slave mode */
>> -     exynos_dp_enable_video_master(dp, 0);
>> -
>> -     /* Enable video */
>> -     exynos_dp_start_video(dp);
>> -
>> -     timeout_loop = 0;
>> -
>> -     for (;;) {
>> -             timeout_loop++;
>> -             if (exynos_dp_is_video_stream_on(dp) == 0) {
>> -                     done_count++;
>> -                     if (done_count > 10)
>> -                             break;
>> -             } else if (done_count) {
>> -                     done_count = 0;
>> -             }
>> -             if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
>> -                     dev_err(dp->dev, "Timeout of video streamclk ok\n");
>> -                     return -ETIMEDOUT;
>> -             }
>> -
>> -             usleep_range(1000, 1001);
>> -     }
>> -
>> -     if (retval != 0)
>> -             dev_err(dp->dev, "Video stream is not detected!\n");
>> -
>> -     return retval;
>> -}
>> -
>> -static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool
>> enable)
>> -{
>> -     u8 data;
>> -
>> -     if (enable) {
>> -             exynos_dp_enable_scrambling(dp);
>> -
>> -             exynos_dp_read_byte_from_dpcd(dp,
>> -                     DPCD_ADDR_TRAINING_PATTERN_SET,
>> -                     &data);
>> -             exynos_dp_write_byte_to_dpcd(dp,
>> -                     DPCD_ADDR_TRAINING_PATTERN_SET,
>> -                     (u8)(data & ~DPCD_SCRAMBLING_DISABLED));
>> -     } else {
>> -             exynos_dp_disable_scrambling(dp);
>> -
>> -             exynos_dp_read_byte_from_dpcd(dp,
>> -                     DPCD_ADDR_TRAINING_PATTERN_SET,
>> -                     &data);
>> -             exynos_dp_write_byte_to_dpcd(dp,
>> -                     DPCD_ADDR_TRAINING_PATTERN_SET,
>> -                     (u8)(data | DPCD_SCRAMBLING_DISABLED));
>> -     }
>> -}
>> -
>> -static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
>> -{
>> -     struct exynos_dp_device *dp = arg;
>> -
>> -     enum dp_irq_type irq_type;
>> -
>> -     irq_type = exynos_dp_get_irq_type(dp);
>> -     switch (irq_type) {
>> -     case DP_IRQ_TYPE_HP_CABLE_IN:
>> -             dev_dbg(dp->dev, "Received irq - cable in\n");
>> -             schedule_work(&dp->hotplug_work);
>> -             exynos_dp_clear_hotplug_interrupts(dp);
>> -             break;
>> -     case DP_IRQ_TYPE_HP_CABLE_OUT:
>> -             dev_dbg(dp->dev, "Received irq - cable out\n");
>> -             exynos_dp_clear_hotplug_interrupts(dp);
>> -             break;
>> -     case DP_IRQ_TYPE_HP_CHANGE:
>> -             /*
>> -              * We get these change notifications once in a while, but
>> there
>> -              * is nothing we can do with them. Just ignore it for now
> and
>> -              * only handle cable changes.
>> -              */
>> -             dev_dbg(dp->dev, "Received irq - hotplug change;
>> ignoring.\n");
>> -             exynos_dp_clear_hotplug_interrupts(dp);
>> -             break;
>> -     default:
>> -             dev_err(dp->dev, "Received irq - unknown type!\n");
>> -             break;
>> -     }
>> -     return IRQ_HANDLED;
>> -}
>> -
>> -static void exynos_dp_hotplug(struct work_struct *work)
>> -{
>> -     struct exynos_dp_device *dp;
>> -     int ret;
>> -
>> -     dp = container_of(work, struct exynos_dp_device, hotplug_work);
>> -
>> -     ret = exynos_dp_detect_hpd(dp);
>> -     if (ret) {
>> -             /* Cable has been disconnected, we're done */
>> -             return;
>> -     }
>> -
>> -     ret = exynos_dp_handle_edid(dp);
>> -     if (ret) {
>> -             dev_err(dp->dev, "unable to handle edid\n");
>> -             return;
>> -     }
>> -
>> -     ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
>> -                                     dp->video_info->link_rate);
>> -     if (ret) {
>> -             dev_err(dp->dev, "unable to do link train\n");
>> -             return;
>> -     }
>> -
>> -     exynos_dp_enable_scramble(dp, 1);
>> -     exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
>> -     exynos_dp_enable_enhanced_mode(dp, 1);
>> -
>> -     exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
>> -     exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
>> -
>> -     exynos_dp_init_video(dp);
>> -     ret = exynos_dp_config_video(dp);
>> -     if (ret)
>> -             dev_err(dp->dev, "unable to config video\n");
>> -}
>> -
>> -#ifdef CONFIG_OF
>> -static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device
>> *dev)
>> -{
>> -     struct device_node *dp_node = dev->of_node;
>> -     struct exynos_dp_platdata *pd;
>> -     struct video_info *dp_video_config;
>> -
>> -     pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
>> -     if (!pd) {
>> -             dev_err(dev, "memory allocation for pdata failed\n");
>> -             return ERR_PTR(-ENOMEM);
>> -     }
>> -     dp_video_config = devm_kzalloc(dev,
>> -                             sizeof(*dp_video_config), GFP_KERNEL);
>> -
>> -     if (!dp_video_config) {
>> -             dev_err(dev, "memory allocation for video config failed\n");
>> -             return ERR_PTR(-ENOMEM);
>> -     }
>> -     pd->video_info = dp_video_config;
>> -
>> -     dp_video_config->h_sync_polarity =
>> -             of_property_read_bool(dp_node, "hsync-active-high");
>> -
>> -     dp_video_config->v_sync_polarity =
>> -             of_property_read_bool(dp_node, "vsync-active-high");
>> -
>> -     dp_video_config->interlaced =
>> -             of_property_read_bool(dp_node, "interlaced");
>> -
>> -     if (of_property_read_u32(dp_node, "samsung,color-space",
>> -                             &dp_video_config->color_space)) {
>> -             dev_err(dev, "failed to get color-space\n");
>> -             return ERR_PTR(-EINVAL);
>> -     }
>> -
>> -     if (of_property_read_u32(dp_node, "samsung,dynamic-range",
>> -                             &dp_video_config->dynamic_range)) {
>> -             dev_err(dev, "failed to get dynamic-range\n");
>> -             return ERR_PTR(-EINVAL);
>> -     }
>> -
>> -     if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
>> -                             &dp_video_config->ycbcr_coeff)) {
>> -             dev_err(dev, "failed to get ycbcr-coeff\n");
>> -             return ERR_PTR(-EINVAL);
>> -     }
>> -
>> -     if (of_property_read_u32(dp_node, "samsung,color-depth",
>> -                             &dp_video_config->color_depth)) {
>> -             dev_err(dev, "failed to get color-depth\n");
>> -             return ERR_PTR(-EINVAL);
>> -     }
>> -
>> -     if (of_property_read_u32(dp_node, "samsung,link-rate",
>> -                             &dp_video_config->link_rate)) {
>> -             dev_err(dev, "failed to get link-rate\n");
>> -             return ERR_PTR(-EINVAL);
>> -     }
>> -
>> -     if (of_property_read_u32(dp_node, "samsung,lane-count",
>> -                             &dp_video_config->lane_count)) {
>> -             dev_err(dev, "failed to get lane-count\n");
>> -             return ERR_PTR(-EINVAL);
>> -     }
>> -
>> -     return pd;
>> -}
>> -
>> -static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
>> -{
>> -     struct device_node *dp_phy_node = of_node_get(dp->dev->of_node);
>> -     u32 phy_base;
>> -     int ret = 0;
>> -
>> -     dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
>> -     if (!dp_phy_node) {
>> -             dev_err(dp->dev, "could not find dptx-phy node\n");
>> -             return -ENODEV;
>> -     }
>> -
>> -     if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
>> -             dev_err(dp->dev, "failed to get reg for dptx-phy\n");
>> -             ret = -EINVAL;
>> -             goto err;
>> -     }
>> -
>> -     if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
>> -                             &dp->enable_mask)) {
>> -             dev_err(dp->dev, "failed to get enable-mask for
> dptx-phy\n");
>> -             ret = -EINVAL;
>> -             goto err;
>> -     }
>> -
>> -     dp->phy_addr = ioremap(phy_base, SZ_4);
>> -     if (!dp->phy_addr) {
>> -             dev_err(dp->dev, "failed to ioremap dp-phy\n");
>> -             ret = -ENOMEM;
>> -             goto err;
>> -     }
>> -
>> -err:
>> -     of_node_put(dp_phy_node);
>> -
>> -     return ret;
>> -}
>> -
>> -static void exynos_dp_phy_init(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = __raw_readl(dp->phy_addr);
>> -     reg |= dp->enable_mask;
>> -     __raw_writel(reg, dp->phy_addr);
>> -}
>> -
>> -static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = __raw_readl(dp->phy_addr);
>> -     reg &= ~(dp->enable_mask);
>> -     __raw_writel(reg, dp->phy_addr);
>> -}
>> -#else
>> -static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device
>> *dev)
>> -{
>> -     return NULL;
>> -}
>> -
>> -static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
>> -{
>> -     return -EINVAL;
>> -}
>> -
>> -static void exynos_dp_phy_init(struct exynos_dp_device *dp)
>> -{
>> -     return;
>> -}
>> -
>> -static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
>> -{
>> -     return;
>> -}
>> -#endif /* CONFIG_OF */
>> -
>> -static int exynos_dp_probe(struct platform_device *pdev)
>> -{
>> -     struct resource *res;
>> -     struct exynos_dp_device *dp;
>> -     struct exynos_dp_platdata *pdata;
>> -
>> -     int ret = 0;
>> -
>> -     dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
>> -                             GFP_KERNEL);
>> -     if (!dp) {
>> -             dev_err(&pdev->dev, "no memory for device data\n");
>> -             return -ENOMEM;
>> -     }
>> -
>> -     dp->dev = &pdev->dev;
>> -
>> -     if (pdev->dev.of_node) {
>> -             pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
>> -             if (IS_ERR(pdata))
>> -                     return PTR_ERR(pdata);
>> -
>> -             ret = exynos_dp_dt_parse_phydata(dp);
>> -             if (ret)
>> -                     return ret;
>> -     } else {
>> -             pdata = pdev->dev.platform_data;
>> -             if (!pdata) {
>> -                     dev_err(&pdev->dev, "no platform data\n");
>> -                     return -EINVAL;
>> -             }
>> -     }
>> -
>> -     dp->clock = devm_clk_get(&pdev->dev, "dp");
>> -     if (IS_ERR(dp->clock)) {
>> -             dev_err(&pdev->dev, "failed to get clock\n");
>> -             return PTR_ERR(dp->clock);
>> -     }
>> -
>> -     clk_prepare_enable(dp->clock);
>> -
>> -     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> -
>> -     dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
>> -     if (IS_ERR(dp->reg_base))
>> -             return PTR_ERR(dp->reg_base);
>> -
>> -     dp->irq = platform_get_irq(pdev, 0);
>> -     if (dp->irq == -ENXIO) {
>> -             dev_err(&pdev->dev, "failed to get irq\n");
>> -             return -ENODEV;
>> -     }
>> -
>> -     INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
>> -
>> -     dp->video_info = pdata->video_info;
>> -
>> -     if (pdev->dev.of_node) {
>> -             if (dp->phy_addr)
>> -                     exynos_dp_phy_init(dp);
>> -     } else {
>> -             if (pdata->phy_init)
>> -                     pdata->phy_init();
>> -     }
>> -
>> -     exynos_dp_init_dp(dp);
>> -
>> -     ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler,
>> 0,
>> -                             "exynos-dp", dp);
>> -     if (ret) {
>> -             dev_err(&pdev->dev, "failed to request irq\n");
>> -             return ret;
>> -     }
>> -
>> -     platform_set_drvdata(pdev, dp);
>> -
>> -     return 0;
>> -}
>> -
>> -static int exynos_dp_remove(struct platform_device *pdev)
>> -{
>> -     struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
>> -     struct exynos_dp_device *dp = platform_get_drvdata(pdev);
>> -
>> -     flush_work(&dp->hotplug_work);
>> -
>> -     if (pdev->dev.of_node) {
>> -             if (dp->phy_addr)
>> -                     exynos_dp_phy_exit(dp);
>> -     } else {
>> -             if (pdata->phy_exit)
>> -                     pdata->phy_exit();
>> -     }
>> -
>> -     clk_disable_unprepare(dp->clock);
>> -
>> -
>> -     return 0;
>> -}
>> -
>> -#ifdef CONFIG_PM_SLEEP
>> -static int exynos_dp_suspend(struct device *dev)
>> -{
>> -     struct exynos_dp_platdata *pdata = dev->platform_data;
>> -     struct exynos_dp_device *dp = dev_get_drvdata(dev);
>> -
>> -     disable_irq(dp->irq);
>> -
>> -     flush_work(&dp->hotplug_work);
>> -
>> -     if (dev->of_node) {
>> -             if (dp->phy_addr)
>> -                     exynos_dp_phy_exit(dp);
>> -     } else {
>> -             if (pdata->phy_exit)
>> -                     pdata->phy_exit();
>> -     }
>> -
>> -     clk_disable_unprepare(dp->clock);
>> -
>> -     return 0;
>> -}
>> -
>> -static int exynos_dp_resume(struct device *dev)
>> -{
>> -     struct exynos_dp_platdata *pdata = dev->platform_data;
>> -     struct exynos_dp_device *dp = dev_get_drvdata(dev);
>> -
>> -     if (dev->of_node) {
>> -             if (dp->phy_addr)
>> -                     exynos_dp_phy_init(dp);
>> -     } else {
>> -             if (pdata->phy_init)
>> -                     pdata->phy_init();
>> -     }
>> -
>> -     clk_prepare_enable(dp->clock);
>> -
>> -     exynos_dp_init_dp(dp);
>> -
>> -     enable_irq(dp->irq);
>> -
>> -     return 0;
>> -}
>> -#endif
>> -
>> -static const struct dev_pm_ops exynos_dp_pm_ops = {
>> -     SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
>> -};
>> -
>> -static const struct of_device_id exynos_dp_match[] = {
>> -     { .compatible = "samsung,exynos5-dp" },
>> -     {},
>> -};
>> -MODULE_DEVICE_TABLE(of, exynos_dp_match);
>> -
>> -static struct platform_driver exynos_dp_driver = {
>> -     .probe          = exynos_dp_probe,
>> -     .remove         = exynos_dp_remove,
>> -     .driver         = {
>> -             .name   = "exynos-dp",
>> -             .owner  = THIS_MODULE,
>> -             .pm     = &exynos_dp_pm_ops,
>> -             .of_match_table = of_match_ptr(exynos_dp_match),
>> -     },
>> -};
>> -
>> -module_platform_driver(exynos_dp_driver);
>> -
>> -MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
>> -MODULE_DESCRIPTION("Samsung SoC DP Driver");
>> -MODULE_LICENSE("GPL");
>> diff --git a/drivers/video/exynos/exynos_dp_core.h
>> b/drivers/video/exynos/exynos_dp_core.h
>> deleted file mode 100644
>> index 6c567bbf..0000000
>> --- a/drivers/video/exynos/exynos_dp_core.h
>> +++ /dev/null
>> @@ -1,210 +0,0 @@
>> -/*
>> - * Header file for Samsung DP (Display Port) interface driver.
>> - *
>> - * Copyright (C) 2012 Samsung Electronics Co., Ltd.
>> - * Author: Jingoo Han <jg1.han@samsung.com>
>> - *
>> - * 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 _EXYNOS_DP_CORE_H
>> -#define _EXYNOS_DP_CORE_H
>> -
>> -enum dp_irq_type {
>> -     DP_IRQ_TYPE_HP_CABLE_IN,
>> -     DP_IRQ_TYPE_HP_CABLE_OUT,
>> -     DP_IRQ_TYPE_HP_CHANGE,
>> -     DP_IRQ_TYPE_UNKNOWN,
>> -};
>> -
>> -struct link_train {
>> -     int eq_loop;
>> -     int cr_loop[4];
>> -
>> -     u8 link_rate;
>> -     u8 lane_count;
>> -     u8 training_lane[4];
>> -
>> -     enum link_training_state lt_state;
>> -};
>> -
>> -struct exynos_dp_device {
>> -     struct device           *dev;
>> -     struct clk              *clock;
>> -     unsigned int            irq;
>> -     void __iomem            *reg_base;
>> -     void __iomem            *phy_addr;
>> -     unsigned int            enable_mask;
>> -
>> -     struct video_info       *video_info;
>> -     struct link_train       link_train;
>> -     struct work_struct      hotplug_work;
>> -};
>> -
>> -/* exynos_dp_reg.c */
>> -void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool
>> enable);
>> -void exynos_dp_stop_video(struct exynos_dp_device *dp);
>> -void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
>> -void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
>> -void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
>> -void exynos_dp_reset(struct exynos_dp_device *dp);
>> -void exynos_dp_swreset(struct exynos_dp_device *dp);
>> -void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
>> -enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device
>> *dp);
>> -void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool
>> enable);
>> -void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
>> -                             enum analog_power_block block,
>> -                             bool enable);
>> -void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
>> -void exynos_dp_init_hpd(struct exynos_dp_device *dp);
>> -enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
>> -void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
>> -void exynos_dp_reset_aux(struct exynos_dp_device *dp);
>> -void exynos_dp_init_aux(struct exynos_dp_device *dp);
>> -int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
>> -void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
>> -int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
>> -int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
>> -                             unsigned int reg_addr,
>> -                             unsigned char data);
>> -int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
>> -                             unsigned int reg_addr,
>> -                             unsigned char *data);
>> -int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
>> -                             unsigned int reg_addr,
>> -                             unsigned int count,
>> -                             unsigned char data[]);
>> -int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
>> -                             unsigned int reg_addr,
>> -                             unsigned int count,
>> -                             unsigned char data[]);
>> -int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
>> -                             unsigned int device_addr,
>> -                             unsigned int reg_addr);
>> -int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
>> -                             unsigned int device_addr,
>> -                             unsigned int reg_addr,
>> -                             unsigned int *data);
>> -int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
>> -                             unsigned int device_addr,
>> -                             unsigned int reg_addr,
>> -                             unsigned int count,
>> -                             unsigned char edid[]);
>> -void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32
>> bwtype);
>> -void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32
>> *bwtype);
>> -void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
>> -void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
>> -void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool
>> enable);
>> -void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
>> -                              enum pattern_set pattern);
>> -void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32
>> level);
>> -void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32
>> level);
>> -void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32
>> level);
>> -void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32
>> level);
>> -void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
>> -                             u32 training_lane);
>> -void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
>> -                             u32 training_lane);
>> -void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
>> -                             u32 training_lane);
>> -void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
>> -                             u32 training_lane);
>> -u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
>> -u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
>> -u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
>> -u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
>> -void exynos_dp_reset_macro(struct exynos_dp_device *dp);
>> -void exynos_dp_init_video(struct exynos_dp_device *dp);
>> -
>> -void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
>> -int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device
> *dp);
>> -void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
>> -                     enum clock_recovery_m_value_type type,
>> -                     u32 m_value,
>> -                     u32 n_value);
>> -void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32
>> type);
>> -void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool
>> enable);
>> -void exynos_dp_start_video(struct exynos_dp_device *dp);
>> -int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
>> -void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
>> -void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
>> -void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
>> -
>> -/* I2C EDID Chip ID, Slave Address */
>> -#define I2C_EDID_DEVICE_ADDR                 0x50
>> -#define I2C_E_EDID_DEVICE_ADDR                       0x30
>> -
>> -#define EDID_BLOCK_LENGTH                    0x80
>> -#define EDID_HEADER_PATTERN                  0x00
>> -#define EDID_EXTENSION_FLAG                  0x7e
>> -#define EDID_CHECKSUM                                0x7f
>> -
>> -/* Definition for DPCD Register */
>> -#define DPCD_ADDR_DPCD_REV                   0x0000
>> -#define DPCD_ADDR_MAX_LINK_RATE                      0x0001
>> -#define DPCD_ADDR_MAX_LANE_COUNT             0x0002
>> -#define DPCD_ADDR_LINK_BW_SET                        0x0100
>> -#define DPCD_ADDR_LANE_COUNT_SET             0x0101
>> -#define DPCD_ADDR_TRAINING_PATTERN_SET               0x0102
>> -#define DPCD_ADDR_TRAINING_LANE0_SET         0x0103
>> -#define DPCD_ADDR_LANE0_1_STATUS             0x0202
>> -#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED  0x0204
>> -#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1     0x0206
>> -#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3     0x0207
>> -#define DPCD_ADDR_TEST_REQUEST                       0x0218
>> -#define DPCD_ADDR_TEST_RESPONSE                      0x0260
>> -#define DPCD_ADDR_TEST_EDID_CHECKSUM         0x0261
>> -#define DPCD_ADDR_SINK_POWER_STATE           0x0600
>> -
>> -/* DPCD_ADDR_MAX_LANE_COUNT */
>> -#define DPCD_ENHANCED_FRAME_CAP(x)           (((x) >> 7) & 0x1)
>> -#define DPCD_MAX_LANE_COUNT(x)                       ((x) & 0x1f)
>> -
>> -/* DPCD_ADDR_LANE_COUNT_SET */
>> -#define DPCD_ENHANCED_FRAME_EN                       (0x1 << 7)
>> -#define DPCD_LANE_COUNT_SET(x)                       ((x) & 0x1f)
>> -
>> -/* DPCD_ADDR_TRAINING_PATTERN_SET */
>> -#define DPCD_SCRAMBLING_DISABLED             (0x1 << 5)
>> -#define DPCD_SCRAMBLING_ENABLED                      (0x0 << 5)
>> -#define DPCD_TRAINING_PATTERN_2                      (0x2 << 0)
>> -#define DPCD_TRAINING_PATTERN_1                      (0x1 << 0)
>> -#define DPCD_TRAINING_PATTERN_DISABLED               (0x0 << 0)
>> -
>> -/* DPCD_ADDR_TRAINING_LANE0_SET */
>> -#define DPCD_MAX_PRE_EMPHASIS_REACHED                (0x1 << 5)
>> -#define DPCD_PRE_EMPHASIS_SET(x)             (((x) & 0x3) << 3)
>> -#define DPCD_PRE_EMPHASIS_GET(x)             (((x) >> 3) & 0x3)
>> -#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0    (0x0 << 3)
>> -#define DPCD_MAX_SWING_REACHED                       (0x1 << 2)
>> -#define DPCD_VOLTAGE_SWING_SET(x)            (((x) & 0x3) << 0)
>> -#define DPCD_VOLTAGE_SWING_GET(x)            (((x) >> 0) & 0x3)
>> -#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0   (0x0 << 0)
>> -
>> -/* DPCD_ADDR_LANE0_1_STATUS */
>> -#define DPCD_LANE_SYMBOL_LOCKED                      (0x1 << 2)
>> -#define DPCD_LANE_CHANNEL_EQ_DONE            (0x1 << 1)
>> -#define DPCD_LANE_CR_DONE                    (0x1 << 0)
>> -#define DPCD_CHANNEL_EQ_BITS                 (DPCD_LANE_CR_DONE|     \
>> -                                              DPCD_LANE_CHANNEL_EQ_DONE|\
>> -                                              DPCD_LANE_SYMBOL_LOCKED)
>> -
>> -/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
>> -#define DPCD_LINK_STATUS_UPDATED             (0x1 << 7)
>> -#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED  (0x1 << 6)
>> -#define DPCD_INTERLANE_ALIGN_DONE            (0x1 << 0)
>> -
>> -/* DPCD_ADDR_TEST_REQUEST */
>> -#define DPCD_TEST_EDID_READ                  (0x1 << 2)
>> -
>> -/* DPCD_ADDR_TEST_RESPONSE */
>> -#define DPCD_TEST_EDID_CHECKSUM_WRITE                (0x1 << 2)
>> -
>> -/* DPCD_ADDR_SINK_POWER_STATE */
>> -#define DPCD_SET_POWER_STATE_D0                      (0x1 << 0)
>> -#define DPCD_SET_POWER_STATE_D4                      (0x2 << 0)
>> -
>> -#endif /* _EXYNOS_DP_CORE_H */
>> diff --git a/drivers/video/exynos/exynos_dp_reg.c
>> b/drivers/video/exynos/exynos_dp_reg.c
>> deleted file mode 100644
>> index 29d9d03..0000000
>> --- a/drivers/video/exynos/exynos_dp_reg.c
>> +++ /dev/null
>> @@ -1,1245 +0,0 @@
>> -/*
>> - * Samsung DP (Display port) register interface driver.
>> - *
>> - * Copyright (C) 2012 Samsung Electronics Co., Ltd.
>> - * Author: Jingoo Han <jg1.han@samsung.com>
>> - *
>> - * 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/device.h>
>> -#include <linux/io.h>
>> -#include <linux/delay.h>
>> -
>> -#include <video/exynos_dp.h>
>> -
>> -#include "exynos_dp_core.h"
>> -#include "exynos_dp_reg.h"
>> -
>> -#define COMMON_INT_MASK_1    0
>> -#define COMMON_INT_MASK_2    0
>> -#define COMMON_INT_MASK_3    0
>> -#define COMMON_INT_MASK_4    (HOTPLUG_CHG | HPD_LOST | PLUG)
>> -#define INT_STA_MASK         INT_HPD
>> -
>> -void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool
> enable)
>> -{
>> -     u32 reg;
>> -
>> -     if (enable) {
>> -             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> -             reg |= HDCP_VIDEO_MUTE;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> -     } else {
>> -             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> -             reg &= ~HDCP_VIDEO_MUTE;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> -     }
>> -}
>> -
>> -void exynos_dp_stop_video(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> -     reg &= ~VIDEO_EN;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> -}
>> -
>> -void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
>> -{
>> -     u32 reg;
>> -
>> -     if (enable)
>> -             reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
>> -                     LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
>> -     else
>> -             reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
>> -                     LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
>> -
>> -     writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
>> -}
>> -
>> -void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = TX_TERMINAL_CTRL_50_OHM;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
>> -
>> -     reg = SEL_24M | TX_DVDD_BIT_1_0625V;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
>> -
>> -     reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
>> -
>> -     reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
>> -             TX_CUR1_2X | TX_CUR_16_MA;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
>> -
>> -     reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
>> -             CH1_AMP_400_MV | CH0_AMP_400_MV;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
>> -}
>> -
>> -void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
>> -{
>> -     /* Set interrupt pin assertion polarity as high */
>> -     writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
>> -
>> -     /* Clear pending regisers */
>> -     writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
>> -     writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
>> -     writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
>> -     writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
>> -     writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
>> -
>> -     /* 0:mask,1: unmask */
>> -     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
>> -     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
>> -     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
>> -     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
>> -     writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
>> -}
>> -
>> -void exynos_dp_reset(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     exynos_dp_stop_video(dp);
>> -     exynos_dp_enable_video_mute(dp, 0);
>> -
>> -     reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
>> -             AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
>> -             HDCP_FUNC_EN_N | SW_FUNC_EN_N;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
>> -
>> -     reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
>> -             SERDES_FIFO_FUNC_EN_N |
>> -             LS_CLK_DOMAIN_FUNC_EN_N;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> -
>> -     usleep_range(20, 30);
>> -
>> -     exynos_dp_lane_swap(dp, 0);
>> -
>> -     writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
>> -     writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
>> -     writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> -     writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> -
>> -     writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
>> -     writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
>> -
>> -     writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
>> -     writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
>> -
>> -     writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
>> -
>> -     writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
>> -
>> -     writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
>> -     writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
>> -
>> -     writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
>> -     writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
>> -
>> -     writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
>> -}
>> -
>> -void exynos_dp_swreset(struct exynos_dp_device *dp)
>> -{
>> -     writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
>> -}
>> -
>> -void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     /* 0: mask, 1: unmask */
>> -     reg = COMMON_INT_MASK_1;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
>> -
>> -     reg = COMMON_INT_MASK_2;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
>> -
>> -     reg = COMMON_INT_MASK_3;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
>> -
>> -     reg = COMMON_INT_MASK_4;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
>> -
>> -     reg = INT_STA_MASK;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
>> -}
>> -
>> -enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device
> *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
>> -     if (reg & PLL_LOCK)
>> -             return PLL_LOCKED;
>> -     else
>> -             return PLL_UNLOCKED;
>> -}
>> -
>> -void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool
>> enable)
>> -{
>> -     u32 reg;
>> -
>> -     if (enable) {
>> -             reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
>> -             reg |= DP_PLL_PD;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
>> -     } else {
>> -             reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
>> -             reg &= ~DP_PLL_PD;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
>> -     }
>> -}
>> -
>> -void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
>> -                             enum analog_power_block block,
>> -                             bool enable)
>> -{
>> -     u32 reg;
>> -
>> -     switch (block) {
>> -     case AUX_BLOCK:
>> -             if (enable) {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> -                     reg |= AUX_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             } else {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> -                     reg &= ~AUX_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             }
>> -             break;
>> -     case CH0_BLOCK:
>> -             if (enable) {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> -                     reg |= CH0_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             } else {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> -                     reg &= ~CH0_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             }
>> -             break;
>> -     case CH1_BLOCK:
>> -             if (enable) {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> -                     reg |= CH1_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             } else {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> -                     reg &= ~CH1_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             }
>> -             break;
>> -     case CH2_BLOCK:
>> -             if (enable) {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> -                     reg |= CH2_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             } else {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> -                     reg &= ~CH2_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             }
>> -             break;
>> -     case CH3_BLOCK:
>> -             if (enable) {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> -                     reg |= CH3_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             } else {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> -                     reg &= ~CH3_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             }
>> -             break;
>> -     case ANALOG_TOTAL:
>> -             if (enable) {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> -                     reg |= DP_PHY_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             } else {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
>> -                     reg &= ~DP_PHY_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             }
>> -             break;
>> -     case POWER_ALL:
>> -             if (enable) {
>> -                     reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
>> -                             CH1_PD | CH0_PD;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             } else {
>> -                     writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
>> -             }
>> -             break;
>> -     default:
>> -             break;
>> -     }
>> -}
>> -
>> -void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -     int timeout_loop = 0;
>> -
>> -     exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
>> -
>> -     reg = PLL_LOCK_CHG;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
>> -     reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
>> -     writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
>> -
>> -     /* Power up PLL */
>> -     if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
>> -             exynos_dp_set_pll_power_down(dp, 0);
>> -
>> -             while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
>> -                     timeout_loop++;
>> -                     if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
>> -                             dev_err(dp->dev, "failed to get pll lock
>> status\n");
>> -                             return;
>> -                     }
>> -                     usleep_range(10, 20);
>> -             }
>> -     }
>> -
>> -     /* Enable Serdes FIFO function and Link symbol clock domain module
>> */
>> -     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> -     reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
>> -             | AUX_FUNC_EN_N);
>> -     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> -}
>> -
>> -void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = HOTPLUG_CHG | HPD_LOST | PLUG;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
>> -
>> -     reg = INT_HPD;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
>> -}
>> -
>> -void exynos_dp_init_hpd(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     exynos_dp_clear_hotplug_interrupts(dp);
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> -     reg &= ~(F_HPD | HPD_CTRL);
>> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> -}
>> -
>> -enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     /* Parse hotplug interrupt status register */
>> -     reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
>> -
>> -     if (reg & PLUG)
>> -             return DP_IRQ_TYPE_HP_CABLE_IN;
>> -
>> -     if (reg & HPD_LOST)
>> -             return DP_IRQ_TYPE_HP_CABLE_OUT;
>> -
>> -     if (reg & HOTPLUG_CHG)
>> -             return DP_IRQ_TYPE_HP_CHANGE;
>> -
>> -     return DP_IRQ_TYPE_UNKNOWN;
>> -}
>> -
>> -void exynos_dp_reset_aux(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     /* Disable AUX channel module */
>> -     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> -     reg |= AUX_FUNC_EN_N;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> -}
>> -
>> -void exynos_dp_init_aux(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     /* Clear inerrupts related to AUX channel */
>> -     reg = RPLY_RECEIV | AUX_ERR;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
>> -
>> -     exynos_dp_reset_aux(dp);
>> -
>> -     /* Disable AUX transaction H/W retry */
>> -     reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
>> -             AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
>> -
>> -     /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
>> -     reg = DEFER_CTRL_EN | DEFER_COUNT(1);
>> -     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
>> -
>> -     /* Enable AUX channel module */
>> -     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> -     reg &= ~AUX_FUNC_EN_N;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
>> -}
>> -
>> -int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> -     if (reg & HPD_STATUS)
>> -             return 0;
>> -
>> -     return -EINVAL;
>> -}
>> -
>> -void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
>> -     reg &= ~SW_FUNC_EN_N;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
>> -}
>> -
>> -int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
>> -{
>> -     int reg;
>> -     int retval = 0;
>> -     int timeout_loop = 0;
>> -
>> -     /* Enable AUX CH operation */
>> -     reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
>> -     reg |= AUX_EN;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
>> -
>> -     /* Is AUX CH command reply received? */
>> -     reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
>> -     while (!(reg & RPLY_RECEIV)) {
>> -             timeout_loop++;
>> -             if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
>> -                     dev_err(dp->dev, "AUX CH command reply failed!\n");
>> -                     return -ETIMEDOUT;
>> -             }
>> -             reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
>> -             usleep_range(10, 11);
>> -     }
>> -
>> -     /* Clear interrupt source for AUX CH command reply */
>> -     writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
>> -
>> -     /* Clear interrupt source for AUX CH access error */
>> -     reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
>> -     if (reg & AUX_ERR) {
>> -             writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
>> -             return -EREMOTEIO;
>> -     }
>> -
>> -     /* Check AUX CH error access status */
>> -     reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
>> -     if ((reg & AUX_STATUS_MASK) != 0) {
>> -             dev_err(dp->dev, "AUX CH error happens: %d\n\n",
>> -                     reg & AUX_STATUS_MASK);
>> -             return -EREMOTEIO;
>> -     }
>> -
>> -     return retval;
>> -}
>> -
>> -int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
>> -                             unsigned int reg_addr,
>> -                             unsigned char data)
>> -{
>> -     u32 reg;
>> -     int i;
>> -     int retval;
>> -
>> -     for (i = 0; i < 3; i++) {
>> -             /* Clear AUX CH data buffer */
>> -             reg = BUF_CLR;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
>> -
>> -             /* Select DPCD device address */
>> -             reg = AUX_ADDR_7_0(reg_addr);
>> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
>> -             reg = AUX_ADDR_15_8(reg_addr);
>> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
>> -             reg = AUX_ADDR_19_16(reg_addr);
>> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
>> -
>> -             /* Write data buffer */
>> -             reg = (unsigned int)data;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
>> -
>> -             /*
>> -              * Set DisplayPort transaction and write 1 byte
>> -              * If bit 3 is 1, DisplayPort transaction.
>> -              * If Bit 3 is 0, I2C transaction.
>> -              */
>> -             reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
>> -
>> -             /* Start AUX transaction */
>> -             retval = exynos_dp_start_aux_transaction(dp);
>> -             if (retval == 0)
>> -                     break;
>> -             else
>> -                     dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
>> -                             __func__);
>> -     }
>> -
>> -     return retval;
>> -}
>> -
>> -int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
>> -                             unsigned int reg_addr,
>> -                             unsigned char *data)
>> -{
>> -     u32 reg;
>> -     int i;
>> -     int retval;
>> -
>> -     for (i = 0; i < 3; i++) {
>> -             /* Clear AUX CH data buffer */
>> -             reg = BUF_CLR;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
>> -
>> -             /* Select DPCD device address */
>> -             reg = AUX_ADDR_7_0(reg_addr);
>> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
>> -             reg = AUX_ADDR_15_8(reg_addr);
>> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
>> -             reg = AUX_ADDR_19_16(reg_addr);
>> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
>> -
>> -             /*
>> -              * Set DisplayPort transaction and read 1 byte
>> -              * If bit 3 is 1, DisplayPort transaction.
>> -              * If Bit 3 is 0, I2C transaction.
>> -              */
>> -             reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
>> -
>> -             /* Start AUX transaction */
>> -             retval = exynos_dp_start_aux_transaction(dp);
>> -             if (retval == 0)
>> -                     break;
>> -             else
>> -                     dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
>> -                             __func__);
>> -     }
>> -
>> -     /* Read data buffer */
>> -     reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
>> -     *data = (unsigned char)(reg & 0xff);
>> -
>> -     return retval;
>> -}
>> -
>> -int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
>> -                             unsigned int reg_addr,
>> -                             unsigned int count,
>> -                             unsigned char data[])
>> -{
>> -     u32 reg;
>> -     unsigned int start_offset;
>> -     unsigned int cur_data_count;
>> -     unsigned int cur_data_idx;
>> -     int i;
>> -     int retval = 0;
>> -
>> -     /* Clear AUX CH data buffer */
>> -     reg = BUF_CLR;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
>> -
>> -     start_offset = 0;
>> -     while (start_offset < count) {
>> -             /* Buffer size of AUX CH is 16 * 4bytes */
>> -             if ((count - start_offset) > 16)
>> -                     cur_data_count = 16;
>> -             else
>> -                     cur_data_count = count - start_offset;
>> -
>> -             for (i = 0; i < 3; i++) {
>> -                     /* Select DPCD device address */
>> -                     reg = AUX_ADDR_7_0(reg_addr + start_offset);
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
>> -                     reg = AUX_ADDR_15_8(reg_addr + start_offset);
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
>> -                     reg = AUX_ADDR_19_16(reg_addr + start_offset);
>> -                     writel(reg, dp->reg_base +
> EXYNOS_DP_AUX_ADDR_19_16);
>> -
>> -                     for (cur_data_idx = 0; cur_data_idx <
> cur_data_count;
>> -                          cur_data_idx++) {
>> -                             reg = data[start_offset + cur_data_idx];
>> -                             writel(reg, dp->reg_base +
> EXYNOS_DP_BUF_DATA_0
>> -                                                       + 4 *
> cur_data_idx);
>> -                     }
>> -
>> -                     /*
>> -                      * Set DisplayPort transaction and write
>> -                      * If bit 3 is 1, DisplayPort transaction.
>> -                      * If Bit 3 is 0, I2C transaction.
>> -                      */
>> -                     reg = AUX_LENGTH(cur_data_count) |
>> -                             AUX_TX_COMM_DP_TRANSACTION |
> AUX_TX_COMM_WRITE;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
>> -
>> -                     /* Start AUX transaction */
>> -                     retval = exynos_dp_start_aux_transaction(dp);
>> -                     if (retval == 0)
>> -                             break;
>> -                     else
>> -                             dev_dbg(dp->dev, "%s: Aux Transaction
> fail!\n",
>> -                                     __func__);
>> -             }
>> -
>> -             start_offset += cur_data_count;
>> -     }
>> -
>> -     return retval;
>> -}
>> -
>> -int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
>> -                             unsigned int reg_addr,
>> -                             unsigned int count,
>> -                             unsigned char data[])
>> -{
>> -     u32 reg;
>> -     unsigned int start_offset;
>> -     unsigned int cur_data_count;
>> -     unsigned int cur_data_idx;
>> -     int i;
>> -     int retval = 0;
>> -
>> -     /* Clear AUX CH data buffer */
>> -     reg = BUF_CLR;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
>> -
>> -     start_offset = 0;
>> -     while (start_offset < count) {
>> -             /* Buffer size of AUX CH is 16 * 4bytes */
>> -             if ((count - start_offset) > 16)
>> -                     cur_data_count = 16;
>> -             else
>> -                     cur_data_count = count - start_offset;
>> -
>> -             /* AUX CH Request Transaction process */
>> -             for (i = 0; i < 3; i++) {
>> -                     /* Select DPCD device address */
>> -                     reg = AUX_ADDR_7_0(reg_addr + start_offset);
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
>> -                     reg = AUX_ADDR_15_8(reg_addr + start_offset);
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
>> -                     reg = AUX_ADDR_19_16(reg_addr + start_offset);
>> -                     writel(reg, dp->reg_base +
> EXYNOS_DP_AUX_ADDR_19_16);
>> -
>> -                     /*
>> -                      * Set DisplayPort transaction and read
>> -                      * If bit 3 is 1, DisplayPort transaction.
>> -                      * If Bit 3 is 0, I2C transaction.
>> -                      */
>> -                     reg = AUX_LENGTH(cur_data_count) |
>> -                             AUX_TX_COMM_DP_TRANSACTION |
> AUX_TX_COMM_READ;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
>> -
>> -                     /* Start AUX transaction */
>> -                     retval = exynos_dp_start_aux_transaction(dp);
>> -                     if (retval == 0)
>> -                             break;
>> -                     else
>> -                             dev_dbg(dp->dev, "%s: Aux Transaction
> fail!\n",
>> -                                     __func__);
>> -             }
>> -
>> -             for (cur_data_idx = 0; cur_data_idx < cur_data_count;
>> -                 cur_data_idx++) {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
>> -                                              + 4 * cur_data_idx);
>> -                     data[start_offset + cur_data_idx] =
>> -                             (unsigned char)reg;
>> -             }
>> -
>> -             start_offset += cur_data_count;
>> -     }
>> -
>> -     return retval;
>> -}
>> -
>> -int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
>> -                             unsigned int device_addr,
>> -                             unsigned int reg_addr)
>> -{
>> -     u32 reg;
>> -     int retval;
>> -
>> -     /* Set EDID device address */
>> -     reg = device_addr;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
>> -     writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
>> -     writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
>> -
>> -     /* Set offset from base address of EDID device */
>> -     writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
>> -
>> -     /*
>> -      * Set I2C transaction and write address
>> -      * If bit 3 is 1, DisplayPort transaction.
>> -      * If Bit 3 is 0, I2C transaction.
>> -      */
>> -     reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
>> -             AUX_TX_COMM_WRITE;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
>> -
>> -     /* Start AUX transaction */
>> -     retval = exynos_dp_start_aux_transaction(dp);
>> -     if (retval != 0)
>> -             dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
>> -
>> -     return retval;
>> -}
>> -
>> -int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
>> -                             unsigned int device_addr,
>> -                             unsigned int reg_addr,
>> -                             unsigned int *data)
>> -{
>> -     u32 reg;
>> -     int i;
>> -     int retval;
>> -
>> -     for (i = 0; i < 3; i++) {
>> -             /* Clear AUX CH data buffer */
>> -             reg = BUF_CLR;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
>> -
>> -             /* Select EDID device */
>> -             retval = exynos_dp_select_i2c_device(dp, device_addr,
>> reg_addr);
>> -             if (retval != 0)
>> -                     continue;
>> -
>> -             /*
>> -              * Set I2C transaction and read data
>> -              * If bit 3 is 1, DisplayPort transaction.
>> -              * If Bit 3 is 0, I2C transaction.
>> -              */
>> -             reg = AUX_TX_COMM_I2C_TRANSACTION |
>> -                     AUX_TX_COMM_READ;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
>> -
>> -             /* Start AUX transaction */
>> -             retval = exynos_dp_start_aux_transaction(dp);
>> -             if (retval == 0)
>> -                     break;
>> -             else
>> -                     dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
>> -                             __func__);
>> -     }
>> -
>> -     /* Read data */
>> -     if (retval == 0)
>> -             *data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
>> -
>> -     return retval;
>> -}
>> -
>> -int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
>> -                             unsigned int device_addr,
>> -                             unsigned int reg_addr,
>> -                             unsigned int count,
>> -                             unsigned char edid[])
>> -{
>> -     u32 reg;
>> -     unsigned int i, j;
>> -     unsigned int cur_data_idx;
>> -     unsigned int defer = 0;
>> -     int retval = 0;
>> -
>> -     for (i = 0; i < count; i += 16) {
>> -             for (j = 0; j < 3; j++) {
>> -                     /* Clear AUX CH data buffer */
>> -                     reg = BUF_CLR;
>> -                     writel(reg, dp->reg_base +
> EXYNOS_DP_BUFFER_DATA_CTL);
>> -
>> -                     /* Set normal AUX CH command */
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
>> -                     reg &= ~ADDR_ONLY;
>> -                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
>> -
>> -                     /*
>> -                      * If Rx sends defer, Tx sends only reads
>> -                      * request without sending address
>> -                      */
>> -                     if (!defer)
>> -                             retval = exynos_dp_select_i2c_device(dp,
>> -                                             device_addr, reg_addr + i);
>> -                     else
>> -                             defer = 0;
>> -
>> -                     if (retval == 0) {
>> -                             /*
>> -                              * Set I2C transaction and write data
>> -                              * If bit 3 is 1, DisplayPort transaction.
>> -                              * If Bit 3 is 0, I2C transaction.
>> -                              */
>> -                             reg = AUX_LENGTH(16) |
>> -                                     AUX_TX_COMM_I2C_TRANSACTION |
>> -                                     AUX_TX_COMM_READ;
>> -                             writel(reg, dp->reg_base +
>> -                                     EXYNOS_DP_AUX_CH_CTL_1);
>> -
>> -                             /* Start AUX transaction */
>> -                             retval =
> exynos_dp_start_aux_transaction(dp);
>> -                             if (retval == 0)
>> -                                     break;
>> -                             else
>> -                                     dev_dbg(dp->dev,
>> -                                             "%s: Aux Transaction
> fail!\n",
>> -                                             __func__);
>> -                     }
>> -                     /* Check if Rx sends defer */
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
>> -                     if (reg == AUX_RX_COMM_AUX_DEFER ||
>> -                             reg == AUX_RX_COMM_I2C_DEFER) {
>> -                             dev_err(dp->dev, "Defer: %d\n\n", reg);
>> -                             defer = 1;
>> -                     }
>> -             }
>> -
>> -             for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
>> -                     reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
>> -                                              + 4 * cur_data_idx);
>> -                     edid[i + cur_data_idx] = (unsigned char)reg;
>> -             }
>> -     }
>> -
>> -     return retval;
>> -}
>> -
>> -void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32
> bwtype)
>> -{
>> -     u32 reg;
>> -
>> -     reg = bwtype;
>> -     if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype ==
>> LINK_RATE_1_62GBPS))
>> -             writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
>> -}
>> -
>> -void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32
>> *bwtype)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
>> -     *bwtype = reg;
>> -}
>> -
>> -void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
>> -{
>> -     u32 reg;
>> -
>> -     reg = count;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
>> -}
>> -
>> -void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
>> -     *count = reg;
>> -}
>> -
>> -void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool
>> enable)
>> -{
>> -     u32 reg;
>> -
>> -     if (enable) {
>> -             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> -             reg |= ENHANCED;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> -     } else {
>> -             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> -             reg &= ~ENHANCED;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> -     }
>> -}
>> -
>> -void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
>> -                              enum pattern_set pattern)
>> -{
>> -     u32 reg;
>> -
>> -     switch (pattern) {
>> -     case PRBS7:
>> -             reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> -             break;
>> -     case D10_2:
>> -             reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> -             break;
>> -     case TRAINING_PTN1:
>> -             reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> -             break;
>> -     case TRAINING_PTN2:
>> -             reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> -             break;
>> -     case DP_NONE:
>> -             reg = SCRAMBLING_ENABLE |
>> -                     LINK_QUAL_PATTERN_SET_DISABLE |
>> -                     SW_TRAINING_PATTERN_SET_NORMAL;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> -             break;
>> -     default:
>> -             break;
>> -     }
>> -}
>> -
>> -void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32
>> level)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
>> -     reg &= ~PRE_EMPHASIS_SET_MASK;
>> -     reg |= level << PRE_EMPHASIS_SET_SHIFT;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
>> -}
>> -
>> -void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32
>> level)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
>> -     reg &= ~PRE_EMPHASIS_SET_MASK;
>> -     reg |= level << PRE_EMPHASIS_SET_SHIFT;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
>> -}
>> -
>> -void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32
>> level)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
>> -     reg &= ~PRE_EMPHASIS_SET_MASK;
>> -     reg |= level << PRE_EMPHASIS_SET_SHIFT;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
>> -}
>> -
>> -void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32
>> level)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
>> -     reg &= ~PRE_EMPHASIS_SET_MASK;
>> -     reg |= level << PRE_EMPHASIS_SET_SHIFT;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
>> -}
>> -
>> -void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
>> -                                     u32 training_lane)
>> -{
>> -     u32 reg;
>> -
>> -     reg = training_lane;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
>> -}
>> -
>> -void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
>> -                                     u32 training_lane)
>> -{
>> -     u32 reg;
>> -
>> -     reg = training_lane;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
>> -}
>> -
>> -void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
>> -                                     u32 training_lane)
>> -{
>> -     u32 reg;
>> -
>> -     reg = training_lane;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
>> -}
>> -
>> -void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
>> -                                     u32 training_lane)
>> -{
>> -     u32 reg;
>> -
>> -     reg = training_lane;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
>> -}
>> -
>> -u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
>> -     return reg;
>> -}
>> -
>> -u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
>> -     return reg;
>> -}
>> -
>> -u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
>> -     return reg;
>> -}
>> -
>> -u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
>> -     return reg;
>> -}
>> -
>> -void exynos_dp_reset_macro(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
>> -     reg |= MACRO_RST;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
>> -
>> -     /* 10 us is the minimum reset time. */
>> -     usleep_range(10, 20);
>> -
>> -     reg &= ~MACRO_RST;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
>> -}
>> -
>> -void exynos_dp_init_video(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
>> -
>> -     reg = 0x0;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
>> -
>> -     reg = CHA_CRI(4) | CHA_CTRL;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
>> -
>> -     reg = 0x0;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> -
>> -     reg = VID_HRES_TH(2) | VID_VRES_TH(0);
>> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
>> -}
>> -
>> -void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     /* Configure the input color depth, color space, dynamic range */
>> -     reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
>> -             (dp->video_info->color_depth << IN_BPC_SHIFT) |
>> -             (dp->video_info->color_space << IN_COLOR_F_SHIFT);
>> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
>> -
>> -     /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
>> -     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
>> -     reg &= ~IN_YC_COEFFI_MASK;
>> -     if (dp->video_info->ycbcr_coeff)
>> -             reg |= IN_YC_COEFFI_ITU709;
>> -     else
>> -             reg |= IN_YC_COEFFI_ITU601;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
>> -}
>> -
>> -int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
>> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
>> -
>> -     if (!(reg & DET_STA)) {
>> -             dev_dbg(dp->dev, "Input stream clock not detected.\n");
>> -             return -EINVAL;
>> -     }
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
>> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
>> -     dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
>> -
>> -     if (reg & CHA_STA) {
>> -             dev_dbg(dp->dev, "Input stream clk is changing\n");
>> -             return -EINVAL;
>> -     }
>> -
>> -     return 0;
>> -}
>> -
>> -void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
>> -             enum clock_recovery_m_value_type type,
>> -             u32 m_value,
>> -             u32 n_value)
>> -{
>> -     u32 reg;
>> -
>> -     if (type == REGISTER_M) {
>> -             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> -             reg |= FIX_M_VID;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> -             reg = m_value & 0xff;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
>> -             reg = (m_value >> 8) & 0xff;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
>> -             reg = (m_value >> 16) & 0xff;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
>> -
>> -             reg = n_value & 0xff;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
>> -             reg = (n_value >> 8) & 0xff;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
>> -             reg = (n_value >> 16) & 0xff;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
>> -     } else  {
>> -             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> -             reg &= ~FIX_M_VID;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
>> -
>> -             writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
>> -             writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
>> -             writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
>> -     }
>> -}
>> -
>> -void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32
>> type)
>> -{
>> -     u32 reg;
>> -
>> -     if (type == VIDEO_TIMING_FROM_CAPTURE) {
>> -             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> -             reg &= ~FORMAT_SEL;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> -     } else {
>> -             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> -             reg |= FORMAT_SEL;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> -     }
>> -}
>> -
>> -void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool
>> enable)
>> -{
>> -     u32 reg;
>> -
>> -     if (enable) {
>> -             reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
>> -             reg &= ~VIDEO_MODE_MASK;
>> -             reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
>> -     } else {
>> -             reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
>> -             reg &= ~VIDEO_MODE_MASK;
>> -             reg |= VIDEO_MODE_SLAVE_MODE;
>> -             writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
>> -     }
>> -}
>> -
>> -void exynos_dp_start_video(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> -     reg |= VIDEO_EN;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
>> -}
>> -
>> -int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
>> -     if (!(reg & STRM_VALID)) {
>> -             dev_dbg(dp->dev, "Input video stream is not detected.\n");
>> -             return -EINVAL;
>> -     }
>> -
>> -     return 0;
>> -}
>> -
>> -void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
>> -     reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
>> -     reg |= MASTER_VID_FUNC_EN_N;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> -     reg &= ~INTERACE_SCAN_CFG;
>> -     reg |= (dp->video_info->interlaced << 2);
>> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> -     reg &= ~VSYNC_POLARITY_CFG;
>> -     reg |= (dp->video_info->v_sync_polarity << 1);
>> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> -     reg &= ~HSYNC_POLARITY_CFG;
>> -     reg |= (dp->video_info->h_sync_polarity << 0);
>> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
>> -
>> -     reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
>> -}
>> -
>> -void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> -     reg &= ~SCRAMBLING_DISABLE;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> -}
>> -
>> -void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
>> -{
>> -     u32 reg;
>> -
>> -     reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> -     reg |= SCRAMBLING_DISABLE;
>> -     writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
>> -}
>> diff --git a/drivers/video/exynos/exynos_dp_reg.h
>> b/drivers/video/exynos/exynos_dp_reg.h
>> deleted file mode 100644
>> index 2e9bd0e..0000000
>> --- a/drivers/video/exynos/exynos_dp_reg.h
>> +++ /dev/null
>> @@ -1,366 +0,0 @@
>> -/*
>> - * Register definition file for Samsung DP driver
>> - *
>> - * Copyright (C) 2012 Samsung Electronics Co., Ltd.
>> - * Author: Jingoo Han <jg1.han@samsung.com>
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License version 2 as
>> - * published by the Free Software Foundation.
>> - */
>> -
>> -#ifndef _EXYNOS_DP_REG_H
>> -#define _EXYNOS_DP_REG_H
>> -
>> -#define EXYNOS_DP_TX_SW_RESET                        0x14
>> -#define EXYNOS_DP_FUNC_EN_1                  0x18
>> -#define EXYNOS_DP_FUNC_EN_2                  0x1C
>> -#define EXYNOS_DP_VIDEO_CTL_1                        0x20
>> -#define EXYNOS_DP_VIDEO_CTL_2                        0x24
>> -#define EXYNOS_DP_VIDEO_CTL_3                        0x28
>> -
>> -#define EXYNOS_DP_VIDEO_CTL_8                        0x3C
>> -#define EXYNOS_DP_VIDEO_CTL_10                       0x44
>> -
>> -#define EXYNOS_DP_LANE_MAP                   0x35C
>> -
>> -#define EXYNOS_DP_ANALOG_CTL_1                       0x370
>> -#define EXYNOS_DP_ANALOG_CTL_2                       0x374
>> -#define EXYNOS_DP_ANALOG_CTL_3                       0x378
>> -#define EXYNOS_DP_PLL_FILTER_CTL_1           0x37C
>> -#define EXYNOS_DP_TX_AMP_TUNING_CTL          0x380
>> -
>> -#define EXYNOS_DP_AUX_HW_RETRY_CTL           0x390
>> -
>> -#define EXYNOS_DP_COMMON_INT_STA_1           0x3C4
>> -#define EXYNOS_DP_COMMON_INT_STA_2           0x3C8
>> -#define EXYNOS_DP_COMMON_INT_STA_3           0x3CC
>> -#define EXYNOS_DP_COMMON_INT_STA_4           0x3D0
>> -#define EXYNOS_DP_INT_STA                    0x3DC
>> -#define EXYNOS_DP_COMMON_INT_MASK_1          0x3E0
>> -#define EXYNOS_DP_COMMON_INT_MASK_2          0x3E4
>> -#define EXYNOS_DP_COMMON_INT_MASK_3          0x3E8
>> -#define EXYNOS_DP_COMMON_INT_MASK_4          0x3EC
>> -#define EXYNOS_DP_INT_STA_MASK                       0x3F8
>> -#define EXYNOS_DP_INT_CTL                    0x3FC
>> -
>> -#define EXYNOS_DP_SYS_CTL_1                  0x600
>> -#define EXYNOS_DP_SYS_CTL_2                  0x604
>> -#define EXYNOS_DP_SYS_CTL_3                  0x608
>> -#define EXYNOS_DP_SYS_CTL_4                  0x60C
>> -
>> -#define EXYNOS_DP_PKT_SEND_CTL                       0x640
>> -#define EXYNOS_DP_HDCP_CTL                   0x648
>> -
>> -#define EXYNOS_DP_LINK_BW_SET                        0x680
>> -#define EXYNOS_DP_LANE_COUNT_SET             0x684
>> -#define EXYNOS_DP_TRAINING_PTN_SET           0x688
>> -#define EXYNOS_DP_LN0_LINK_TRAINING_CTL              0x68C
>> -#define EXYNOS_DP_LN1_LINK_TRAINING_CTL              0x690
>> -#define EXYNOS_DP_LN2_LINK_TRAINING_CTL              0x694
>> -#define EXYNOS_DP_LN3_LINK_TRAINING_CTL              0x698
>> -
>> -#define EXYNOS_DP_DEBUG_CTL                  0x6C0
>> -#define EXYNOS_DP_HPD_DEGLITCH_L             0x6C4
>> -#define EXYNOS_DP_HPD_DEGLITCH_H             0x6C8
>> -#define EXYNOS_DP_LINK_DEBUG_CTL             0x6E0
>> -
>> -#define EXYNOS_DP_M_VID_0                    0x700
>> -#define EXYNOS_DP_M_VID_1                    0x704
>> -#define EXYNOS_DP_M_VID_2                    0x708
>> -#define EXYNOS_DP_N_VID_0                    0x70C
>> -#define EXYNOS_DP_N_VID_1                    0x710
>> -#define EXYNOS_DP_N_VID_2                    0x714
>> -
>> -#define EXYNOS_DP_PLL_CTL                    0x71C
>> -#define EXYNOS_DP_PHY_PD                     0x720
>> -#define EXYNOS_DP_PHY_TEST                   0x724
>> -
>> -#define EXYNOS_DP_VIDEO_FIFO_THRD            0x730
>> -#define EXYNOS_DP_AUDIO_MARGIN                       0x73C
>> -
>> -#define EXYNOS_DP_M_VID_GEN_FILTER_TH                0x764
>> -#define EXYNOS_DP_M_AUD_GEN_FILTER_TH                0x778
>> -#define EXYNOS_DP_AUX_CH_STA                 0x780
>> -#define EXYNOS_DP_AUX_CH_DEFER_CTL           0x788
>> -#define EXYNOS_DP_AUX_RX_COMM                        0x78C
>> -#define EXYNOS_DP_BUFFER_DATA_CTL            0x790
>> -#define EXYNOS_DP_AUX_CH_CTL_1                       0x794
>> -#define EXYNOS_DP_AUX_ADDR_7_0                       0x798
>> -#define EXYNOS_DP_AUX_ADDR_15_8                      0x79C
>> -#define EXYNOS_DP_AUX_ADDR_19_16             0x7A0
>> -#define EXYNOS_DP_AUX_CH_CTL_2                       0x7A4
>> -
>> -#define EXYNOS_DP_BUF_DATA_0                 0x7C0
>> -
>> -#define EXYNOS_DP_SOC_GENERAL_CTL            0x800
>> -
>> -/* EXYNOS_DP_TX_SW_RESET */
>> -#define RESET_DP_TX                          (0x1 << 0)
>> -
>> -/* EXYNOS_DP_FUNC_EN_1 */
>> -#define MASTER_VID_FUNC_EN_N                 (0x1 << 7)
>> -#define SLAVE_VID_FUNC_EN_N                  (0x1 << 5)
>> -#define AUD_FIFO_FUNC_EN_N                   (0x1 << 4)
>> -#define AUD_FUNC_EN_N                                (0x1 << 3)
>> -#define HDCP_FUNC_EN_N                               (0x1 << 2)
>> -#define CRC_FUNC_EN_N                                (0x1 << 1)
>> -#define SW_FUNC_EN_N                         (0x1 << 0)
>> -
>> -/* EXYNOS_DP_FUNC_EN_2 */
>> -#define SSC_FUNC_EN_N                                (0x1 << 7)
>> -#define AUX_FUNC_EN_N                                (0x1 << 2)
>> -#define SERDES_FIFO_FUNC_EN_N                        (0x1 << 1)
>> -#define LS_CLK_DOMAIN_FUNC_EN_N                      (0x1 << 0)
>> -
>> -/* EXYNOS_DP_VIDEO_CTL_1 */
>> -#define VIDEO_EN                             (0x1 << 7)
>> -#define HDCP_VIDEO_MUTE                              (0x1 << 6)
>> -
>> -/* EXYNOS_DP_VIDEO_CTL_1 */
>> -#define IN_D_RANGE_MASK                              (0x1 << 7)
>> -#define IN_D_RANGE_SHIFT                     (7)
>> -#define IN_D_RANGE_CEA                               (0x1 << 7)
>> -#define IN_D_RANGE_VESA                              (0x0 << 7)
>> -#define IN_BPC_MASK                          (0x7 << 4)
>> -#define IN_BPC_SHIFT                         (4)
>> -#define IN_BPC_12_BITS                               (0x3 << 4)
>> -#define IN_BPC_10_BITS                               (0x2 << 4)
>> -#define IN_BPC_8_BITS                                (0x1 << 4)
>> -#define IN_BPC_6_BITS                                (0x0 << 4)
>> -#define IN_COLOR_F_MASK                              (0x3 << 0)
>> -#define IN_COLOR_F_SHIFT                     (0)
>> -#define IN_COLOR_F_YCBCR444                  (0x2 << 0)
>> -#define IN_COLOR_F_YCBCR422                  (0x1 << 0)
>> -#define IN_COLOR_F_RGB                               (0x0 << 0)
>> -
>> -/* EXYNOS_DP_VIDEO_CTL_3 */
>> -#define IN_YC_COEFFI_MASK                    (0x1 << 7)
>> -#define IN_YC_COEFFI_SHIFT                   (7)
>> -#define IN_YC_COEFFI_ITU709                  (0x1 << 7)
>> -#define IN_YC_COEFFI_ITU601                  (0x0 << 7)
>> -#define VID_CHK_UPDATE_TYPE_MASK             (0x1 << 4)
>> -#define VID_CHK_UPDATE_TYPE_SHIFT            (4)
>> -#define VID_CHK_UPDATE_TYPE_1                        (0x1 << 4)
>> -#define VID_CHK_UPDATE_TYPE_0                        (0x0 << 4)
>> -
>> -/* EXYNOS_DP_VIDEO_CTL_8 */
>> -#define VID_HRES_TH(x)                               (((x) & 0xf) << 4)
>> -#define VID_VRES_TH(x)                               (((x) & 0xf) << 0)
>> -
>> -/* EXYNOS_DP_VIDEO_CTL_10 */
>> -#define FORMAT_SEL                           (0x1 << 4)
>> -#define INTERACE_SCAN_CFG                    (0x1 << 2)
>> -#define VSYNC_POLARITY_CFG                   (0x1 << 1)
>> -#define HSYNC_POLARITY_CFG                   (0x1 << 0)
>> -
>> -/* EXYNOS_DP_LANE_MAP */
>> -#define LANE3_MAP_LOGIC_LANE_0                       (0x0 << 6)
>> -#define LANE3_MAP_LOGIC_LANE_1                       (0x1 << 6)
>> -#define LANE3_MAP_LOGIC_LANE_2                       (0x2 << 6)
>> -#define LANE3_MAP_LOGIC_LANE_3                       (0x3 << 6)
>> -#define LANE2_MAP_LOGIC_LANE_0                       (0x0 << 4)
>> -#define LANE2_MAP_LOGIC_LANE_1                       (0x1 << 4)
>> -#define LANE2_MAP_LOGIC_LANE_2                       (0x2 << 4)
>> -#define LANE2_MAP_LOGIC_LANE_3                       (0x3 << 4)
>> -#define LANE1_MAP_LOGIC_LANE_0                       (0x0 << 2)
>> -#define LANE1_MAP_LOGIC_LANE_1                       (0x1 << 2)
>> -#define LANE1_MAP_LOGIC_LANE_2                       (0x2 << 2)
>> -#define LANE1_MAP_LOGIC_LANE_3                       (0x3 << 2)
>> -#define LANE0_MAP_LOGIC_LANE_0                       (0x0 << 0)
>> -#define LANE0_MAP_LOGIC_LANE_1                       (0x1 << 0)
>> -#define LANE0_MAP_LOGIC_LANE_2                       (0x2 << 0)
>> -#define LANE0_MAP_LOGIC_LANE_3                       (0x3 << 0)
>> -
>> -/* EXYNOS_DP_ANALOG_CTL_1 */
>> -#define TX_TERMINAL_CTRL_50_OHM                      (0x1 << 4)
>> -
>> -/* EXYNOS_DP_ANALOG_CTL_2 */
>> -#define SEL_24M                                      (0x1 << 3)
>> -#define TX_DVDD_BIT_1_0625V                  (0x4 << 0)
>> -
>> -/* EXYNOS_DP_ANALOG_CTL_3 */
>> -#define DRIVE_DVDD_BIT_1_0625V                       (0x4 << 5)
>> -#define VCO_BIT_600_MICRO                    (0x5 << 0)
>> -
>> -/* EXYNOS_DP_PLL_FILTER_CTL_1 */
>> -#define PD_RING_OSC                          (0x1 << 6)
>> -#define AUX_TERMINAL_CTRL_50_OHM             (0x2 << 4)
>> -#define TX_CUR1_2X                           (0x1 << 2)
>> -#define TX_CUR_16_MA                         (0x3 << 0)
>> -
>> -/* EXYNOS_DP_TX_AMP_TUNING_CTL */
>> -#define CH3_AMP_400_MV                               (0x0 << 24)
>> -#define CH2_AMP_400_MV                               (0x0 << 16)
>> -#define CH1_AMP_400_MV                               (0x0 << 8)
>> -#define CH0_AMP_400_MV                               (0x0 << 0)
>> -
>> -/* EXYNOS_DP_AUX_HW_RETRY_CTL */
>> -#define AUX_BIT_PERIOD_EXPECTED_DELAY(x)     (((x) & 0x7) << 8)
>> -#define AUX_HW_RETRY_INTERVAL_MASK           (0x3 << 3)
>> -#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS       (0x0 << 3)
>> -#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS       (0x1 << 3)
>> -#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS      (0x2 << 3)
>> -#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS      (0x3 << 3)
>> -#define AUX_HW_RETRY_COUNT_SEL(x)            (((x) & 0x7) << 0)
>> -
>> -/* EXYNOS_DP_COMMON_INT_STA_1 */
>> -#define VSYNC_DET                            (0x1 << 7)
>> -#define PLL_LOCK_CHG                         (0x1 << 6)
>> -#define SPDIF_ERR                            (0x1 << 5)
>> -#define SPDIF_UNSTBL                         (0x1 << 4)
>> -#define VID_FORMAT_CHG                               (0x1 << 3)
>> -#define AUD_CLK_CHG                          (0x1 << 2)
>> -#define VID_CLK_CHG                          (0x1 << 1)
>> -#define SW_INT                                       (0x1 << 0)
>> -
>> -/* EXYNOS_DP_COMMON_INT_STA_2 */
>> -#define ENC_EN_CHG                           (0x1 << 6)
>> -#define HW_BKSV_RDY                          (0x1 << 3)
>> -#define HW_SHA_DONE                          (0x1 << 2)
>> -#define HW_AUTH_STATE_CHG                    (0x1 << 1)
>> -#define HW_AUTH_DONE                         (0x1 << 0)
>> -
>> -/* EXYNOS_DP_COMMON_INT_STA_3 */
>> -#define AFIFO_UNDER                          (0x1 << 7)
>> -#define AFIFO_OVER                           (0x1 << 6)
>> -#define R0_CHK_FLAG                          (0x1 << 5)
>> -
>> -/* EXYNOS_DP_COMMON_INT_STA_4 */
>> -#define PSR_ACTIVE                           (0x1 << 7)
>> -#define PSR_INACTIVE                         (0x1 << 6)
>> -#define SPDIF_BI_PHASE_ERR                   (0x1 << 5)
>> -#define HOTPLUG_CHG                          (0x1 << 2)
>> -#define HPD_LOST                             (0x1 << 1)
>> -#define PLUG                                 (0x1 << 0)
>> -
>> -/* EXYNOS_DP_INT_STA */
>> -#define INT_HPD                                      (0x1 << 6)
>> -#define HW_TRAINING_FINISH                   (0x1 << 5)
>> -#define RPLY_RECEIV                          (0x1 << 1)
>> -#define AUX_ERR                                      (0x1 << 0)
>> -
>> -/* EXYNOS_DP_INT_CTL */
>> -#define SOFT_INT_CTRL                                (0x1 << 2)
>> -#define INT_POL1                             (0x1 << 1)
>> -#define INT_POL0                             (0x1 << 0)
>> -
>> -/* EXYNOS_DP_SYS_CTL_1 */
>> -#define DET_STA                                      (0x1 << 2)
>> -#define FORCE_DET                            (0x1 << 1)
>> -#define DET_CTRL                             (0x1 << 0)
>> -
>> -/* EXYNOS_DP_SYS_CTL_2 */
>> -#define CHA_CRI(x)                           (((x) & 0xf) << 4)
>> -#define CHA_STA                                      (0x1 << 2)
>> -#define FORCE_CHA                            (0x1 << 1)
>> -#define CHA_CTRL                             (0x1 << 0)
>> -
>> -/* EXYNOS_DP_SYS_CTL_3 */
>> -#define HPD_STATUS                           (0x1 << 6)
>> -#define F_HPD                                        (0x1 << 5)
>> -#define HPD_CTRL                             (0x1 << 4)
>> -#define HDCP_RDY                             (0x1 << 3)
>> -#define STRM_VALID                           (0x1 << 2)
>> -#define F_VALID                                      (0x1 << 1)
>> -#define VALID_CTRL                           (0x1 << 0)
>> -
>> -/* EXYNOS_DP_SYS_CTL_4 */
>> -#define FIX_M_AUD                            (0x1 << 4)
>> -#define ENHANCED                             (0x1 << 3)
>> -#define FIX_M_VID                            (0x1 << 2)
>> -#define M_VID_UPDATE_CTRL                    (0x3 << 0)
>> -
>> -/* EXYNOS_DP_TRAINING_PTN_SET */
>> -#define SCRAMBLER_TYPE                               (0x1 << 9)
>> -#define HW_LINK_TRAINING_PATTERN             (0x1 << 8)
>> -#define SCRAMBLING_DISABLE                   (0x1 << 5)
>> -#define SCRAMBLING_ENABLE                    (0x0 << 5)
>> -#define LINK_QUAL_PATTERN_SET_MASK           (0x3 << 2)
>> -#define LINK_QUAL_PATTERN_SET_PRBS7          (0x3 << 2)
>> -#define LINK_QUAL_PATTERN_SET_D10_2          (0x1 << 2)
>> -#define LINK_QUAL_PATTERN_SET_DISABLE                (0x0 << 2)
>> -#define SW_TRAINING_PATTERN_SET_MASK         (0x3 << 0)
>> -#define SW_TRAINING_PATTERN_SET_PTN2         (0x2 << 0)
>> -#define SW_TRAINING_PATTERN_SET_PTN1         (0x1 << 0)
>> -#define SW_TRAINING_PATTERN_SET_NORMAL               (0x0 << 0)
>> -
>> -/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
>> -#define PRE_EMPHASIS_SET_MASK                        (0x3 << 3)
>> -#define PRE_EMPHASIS_SET_SHIFT                       (3)
>> -
>> -/* EXYNOS_DP_DEBUG_CTL */
>> -#define PLL_LOCK                             (0x1 << 4)
>> -#define F_PLL_LOCK                           (0x1 << 3)
>> -#define PLL_LOCK_CTRL                                (0x1 << 2)
>> -#define PN_INV                                       (0x1 << 0)
>> -
>> -/* EXYNOS_DP_PLL_CTL */
>> -#define DP_PLL_PD                            (0x1 << 7)
>> -#define DP_PLL_RESET                         (0x1 << 6)
>> -#define DP_PLL_LOOP_BIT_DEFAULT                      (0x1 << 4)
>> -#define DP_PLL_REF_BIT_1_1250V                       (0x5 << 0)
>> -#define DP_PLL_REF_BIT_1_2500V                       (0x7 << 0)
>> -
>> -/* EXYNOS_DP_PHY_PD */
>> -#define DP_PHY_PD                            (0x1 << 5)
>> -#define AUX_PD                                       (0x1 << 4)
>> -#define CH3_PD                                       (0x1 << 3)
>> -#define CH2_PD                                       (0x1 << 2)
>> -#define CH1_PD                                       (0x1 << 1)
>> -#define CH0_PD                                       (0x1 << 0)
>> -
>> -/* EXYNOS_DP_PHY_TEST */
>> -#define MACRO_RST                            (0x1 << 5)
>> -#define CH1_TEST                             (0x1 << 1)
>> -#define CH0_TEST                             (0x1 << 0)
>> -
>> -/* EXYNOS_DP_AUX_CH_STA */
>> -#define AUX_BUSY                             (0x1 << 4)
>> -#define AUX_STATUS_MASK                              (0xf << 0)
>> -
>> -/* EXYNOS_DP_AUX_CH_DEFER_CTL */
>> -#define DEFER_CTRL_EN                                (0x1 << 7)
>> -#define DEFER_COUNT(x)                               (((x) & 0x7f) << 0)
>> -
>> -/* EXYNOS_DP_AUX_RX_COMM */
>> -#define AUX_RX_COMM_I2C_DEFER                        (0x2 << 2)
>> -#define AUX_RX_COMM_AUX_DEFER                        (0x2 << 0)
>> -
>> -/* EXYNOS_DP_BUFFER_DATA_CTL */
>> -#define BUF_CLR                                      (0x1 << 7)
>> -#define BUF_DATA_COUNT(x)                    (((x) & 0x1f) << 0)
>> -
>> -/* EXYNOS_DP_AUX_CH_CTL_1 */
>> -#define AUX_LENGTH(x)                                (((x - 1) & 0xf) <<
> 4)
>> -#define AUX_TX_COMM_MASK                     (0xf << 0)
>> -#define AUX_TX_COMM_DP_TRANSACTION           (0x1 << 3)
>> -#define AUX_TX_COMM_I2C_TRANSACTION          (0x0 << 3)
>> -#define AUX_TX_COMM_MOT                              (0x1 << 2)
>> -#define AUX_TX_COMM_WRITE                    (0x0 << 0)
>> -#define AUX_TX_COMM_READ                     (0x1 << 0)
>> -
>> -/* EXYNOS_DP_AUX_ADDR_7_0 */
>> -#define AUX_ADDR_7_0(x)                              (((x) >> 0) & 0xff)
>> -
>> -/* EXYNOS_DP_AUX_ADDR_15_8 */
>> -#define AUX_ADDR_15_8(x)                     (((x) >> 8) & 0xff)
>> -
>> -/* EXYNOS_DP_AUX_ADDR_19_16 */
>> -#define AUX_ADDR_19_16(x)                    (((x) >> 16) & 0x0f)
>> -
>> -/* EXYNOS_DP_AUX_CH_CTL_2 */
>> -#define ADDR_ONLY                            (0x1 << 1)
>> -#define AUX_EN                                       (0x1 << 0)
>> -
>> -/* EXYNOS_DP_SOC_GENERAL_CTL */
>> -#define AUDIO_MODE_SPDIF_MODE                        (0x1 << 8)
>> -#define AUDIO_MODE_MASTER_MODE                       (0x0 << 8)
>> -#define MASTER_VIDEO_INTERLACE_EN            (0x1 << 4)
>> -#define VIDEO_MASTER_CLK_SEL                 (0x1 << 2)
>> -#define VIDEO_MASTER_MODE_EN                 (0x1 << 1)
>> -#define VIDEO_MODE_MASK                              (0x1 << 0)
>> -#define VIDEO_MODE_SLAVE_MODE                        (0x1 << 0)
>> -#define VIDEO_MODE_MASTER_MODE                       (0x0 << 0)
>> -
>> -#endif /* _EXYNOS_DP_REG_H */
>> --
>> 1.8.4
>

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-10-31 10:30   ` Inki Dae
@ 2013-10-31 16:08     ` Sean Paul
  2013-11-01  4:20       ` Inki Dae
  0 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-10-31 16:08 UTC (permalink / raw)
  To: Inki Dae; +Cc: Stéphane Marchesin, dri-devel

On Thu, Oct 31, 2013 at 6:30 AM, Inki Dae <inki.dae@samsung.com> wrote:
>
>
>> -----Original Message-----
>> From: Sean Paul [mailto:seanpaul@chromium.org]
>> Sent: Wednesday, October 30, 2013 1:13 AM
>> To: dri-devel@lists.freedesktop.org; inki.dae@samsung.com
>> Cc: airlied@linux.ie; tomasz.figa@gmail.com; marcheu@chromium.org; Sean
>> Paul
>> Subject: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
>>
>> This patch splits display and manager from subdrv. The result is that
>> crtc functions can directly call into manager callbacks and encoder
>> functions can directly call into display callbacks. This will allow
>> us to remove the exynos_drm_hdmi shim and support mixer/hdmi & fimd/dp
>> with common code.
>>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>
>> Changes in v2:
>>       - Pass display into display_ops instead of context
>> Changes in v3:
>>       - Changed vidi args to exynos_drm_display instead of void
>>       - Moved exynos_drm_hdmi.c removal into next patch
>>
>>  drivers/gpu/drm/exynos/exynos_drm_connector.c |  50 ++---
>>  drivers/gpu/drm/exynos/exynos_drm_core.c      | 181 +++++++++++++-----
>>  drivers/gpu/drm/exynos/exynos_drm_crtc.c      | 115 +++++++++---
>>  drivers/gpu/drm/exynos/exynos_drm_crtc.h      |  20 +-
>>  drivers/gpu/drm/exynos/exynos_drm_drv.c       |  29 +--
>>  drivers/gpu/drm/exynos/exynos_drm_drv.h       | 106 +++++++----
>>  drivers/gpu/drm/exynos/exynos_drm_encoder.c   | 258
> ++++------------------
>> ----
>>  drivers/gpu/drm/exynos/exynos_drm_encoder.h   |  18 +-
>>  drivers/gpu/drm/exynos/exynos_drm_fb.c        |   4 +-
>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 161 ++++++++--------
>>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c      | 211 +++++++++------------
>>  drivers/gpu/drm/exynos/exynos_drm_hdmi.h      |   2 +
>>  drivers/gpu/drm/exynos/exynos_drm_plane.c     |  15 +-
>>  drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 129 ++++++-------
>>  14 files changed, 615 insertions(+), 684 deletions(-)
>>
>>  static int exynos_drm_create_enc_conn(struct drm_device *dev,
>> -                                     struct exynos_drm_subdrv *subdrv)
>> +                                     struct exynos_drm_display *display)
>>  {
>>       struct drm_encoder *encoder;
>>       struct drm_connector *connector;
>> +     struct exynos_drm_manager *manager;
>>       int ret;
>> +     unsigned long possible_crtcs = 0;
>>
>> -     subdrv->manager->dev = subdrv->dev;
>> +     /* Find possible crtcs for this display */
>> +     list_for_each_entry(manager, &exynos_drm_manager_list, list)
>> +             if (manager->type == display->type)
>> +                     possible_crtcs |= 1 << manager->pipe;
>>
>>       /* create and initialize a encoder for this sub driver. */
>> -     encoder = exynos_drm_encoder_create(dev, subdrv->manager,
>> -                     (1 << MAX_CRTC) - 1);
>> +     encoder = exynos_drm_encoder_create(dev, display, possible_crtcs);
>>       if (!encoder) {
>>               DRM_ERROR("failed to create encoder\n");
>>               return -EFAULT;
>>       }
>> -     subdrv->encoder = encoder;
>> +     display->encoder = encoder;
>>
>> -     if (subdrv->manager->display_ops->type == EXYNOS_DISPLAY_TYPE_LCD)
>> {
>> +     if (display->type == EXYNOS_DISPLAY_TYPE_LCD) {
>>               ret = exynos_drm_attach_lcd_bridge(dev, encoder);
>
> The lvds bridge related codes need more reviews

I think everyone agrees that there need not be a 1:1 binding to driver
relationship, so what is left to discuss?

Sean



> so I'll merge this patch
> manually excepting the lvds bridge related codes. Let's discuss lvds bridge
> later.
>
> Thanks,
> Inki Dae
>
>>               if (ret)
>>                       return 0;
>> @@ -91,7 +98,7 @@ static int exynos_drm_create_enc_conn(struct drm_device
>> *dev,
>>               goto err_destroy_encoder;
>>       }
>>
>> -     subdrv->connector = connector;
>> +     display->connector = connector;
>>
>>       return 0;
>

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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
  2013-10-31 10:46   ` Inki Dae
@ 2013-10-31 23:06       ` Jingoo Han
  2013-10-31 23:06       ` Jingoo Han
  1 sibling, 0 replies; 130+ messages in thread
From: Jingoo Han @ 2013-10-31 23:06 UTC (permalink / raw)
  To: 'Inki Dae', 'Sean Paul', dri-devel
  Cc: 'Tomi Valkeinen',
	'Jean-Christophe PLAGNIOL-VILLARD',
	linux-fbdev, linux-samsung-soc, airlied, tomasz.figa, marcheu,
	'Jingoo Han'

On Thursday, October 31, 2013 7:47 PM, Inki Dae wrote:
> 
> CCing Jingoo,
> 
> Is that ok to remove eDP driver from video/exynos? Isn't this driver really
> used by Linux framebuffer driver, s3c-fb.c?

+cc Tomi Valkeinen, Jean-Christophe PLAGNIOL-VILLARD,
     linux-fbdev list, linux-samsung-soc list

Yes, it is used by s3c-fb.c.

> 
> Of course, now s3c-fb driver is dead code because this driver doesn't
> support device tree yet but we would need more reviews and discussions about
> moving this driver into drm side. Let's watch new rules for device tree
> bindings of DRM world. So I'd not like to merge this driver yet.

's3c-fb' driver is still used for other mass products projects.
Just, device tree support patch is not yet submitted.


Sean Paul,
When moving the driver, notify related Maintainers of that driver.
Please use 'scripts/get_maintainer.pl' next time.

Best regards,
Jingoo Han


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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
@ 2013-10-31 23:06       ` Jingoo Han
  0 siblings, 0 replies; 130+ messages in thread
From: Jingoo Han @ 2013-10-31 23:06 UTC (permalink / raw)
  To: 'Inki Dae', 'Sean Paul', dri-devel
  Cc: 'Tomi Valkeinen',
	'Jean-Christophe PLAGNIOL-VILLARD',
	linux-fbdev, linux-samsung-soc, airlied, tomasz.figa, marcheu,
	'Jingoo Han'

On Thursday, October 31, 2013 7:47 PM, Inki Dae wrote:
> 
> CCing Jingoo,
> 
> Is that ok to remove eDP driver from video/exynos? Isn't this driver really
> used by Linux framebuffer driver, s3c-fb.c?

+cc Tomi Valkeinen, Jean-Christophe PLAGNIOL-VILLARD,
     linux-fbdev list, linux-samsung-soc list

Yes, it is used by s3c-fb.c.

> 
> Of course, now s3c-fb driver is dead code because this driver doesn't
> support device tree yet but we would need more reviews and discussions about
> moving this driver into drm side. Let's watch new rules for device tree
> bindings of DRM world. So I'd not like to merge this driver yet.

's3c-fb' driver is still used for other mass products projects.
Just, device tree support patch is not yet submitted.


Sean Paul,
When moving the driver, notify related Maintainers of that driver.
Please use 'scripts/get_maintainer.pl' next time.

Best regards,
Jingoo Han

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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
  2013-10-31 23:06       ` Jingoo Han
@ 2013-10-31 23:11         ` Tomasz Figa
  -1 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-10-31 23:11 UTC (permalink / raw)
  To: Jingoo Han
  Cc: 'Inki Dae', 'Sean Paul',
	dri-devel, 'Tomi Valkeinen',
	'Jean-Christophe PLAGNIOL-VILLARD',
	linux-fbdev, linux-samsung-soc, airlied, marcheu

On Friday 01 of November 2013 08:06:00 Jingoo Han wrote:
> On Thursday, October 31, 2013 7:47 PM, Inki Dae wrote:
> > CCing Jingoo,
> > 
> > Is that ok to remove eDP driver from video/exynos? Isn't this driver
> > really used by Linux framebuffer driver, s3c-fb.c?
> 
> +cc Tomi Valkeinen, Jean-Christophe PLAGNIOL-VILLARD,
>      linux-fbdev list, linux-samsung-soc list
> 
> Yes, it is used by s3c-fb.c.
> 
> > Of course, now s3c-fb driver is dead code because this driver doesn't
> > support device tree yet but we would need more reviews and discussions
> > about moving this driver into drm side. Let's watch new rules for
> > device tree bindings of DRM world. So I'd not like to merge this
> > driver yet.
> 's3c-fb' driver is still used for other mass products projects.
> Just, device tree support patch is not yet submitted.

Current in-tree users of s3c-fb drivers are s3c2443, non-DT s3c64xx and 
all s5p* SoCs. It is not used on Exynos SoCs anymore.

As for Exynos DP driver, what SoCs does it support? If only Exynos (as the 
name suggests) then there is no point in keeping it at video/exynos and 
making it a part of Exynos DRM driver seems reasonable to me.

Best regards,
Tomasz


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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
@ 2013-10-31 23:11         ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-10-31 23:11 UTC (permalink / raw)
  To: Jingoo Han
  Cc: 'Inki Dae', 'Sean Paul',
	dri-devel, 'Tomi Valkeinen',
	'Jean-Christophe PLAGNIOL-VILLARD',
	linux-fbdev, linux-samsung-soc, airlied, marcheu

On Friday 01 of November 2013 08:06:00 Jingoo Han wrote:
> On Thursday, October 31, 2013 7:47 PM, Inki Dae wrote:
> > CCing Jingoo,
> > 
> > Is that ok to remove eDP driver from video/exynos? Isn't this driver
> > really used by Linux framebuffer driver, s3c-fb.c?
> 
> +cc Tomi Valkeinen, Jean-Christophe PLAGNIOL-VILLARD,
>      linux-fbdev list, linux-samsung-soc list
> 
> Yes, it is used by s3c-fb.c.
> 
> > Of course, now s3c-fb driver is dead code because this driver doesn't
> > support device tree yet but we would need more reviews and discussions
> > about moving this driver into drm side. Let's watch new rules for
> > device tree bindings of DRM world. So I'd not like to merge this
> > driver yet.
> 's3c-fb' driver is still used for other mass products projects.
> Just, device tree support patch is not yet submitted.

Current in-tree users of s3c-fb drivers are s3c2443, non-DT s3c64xx and 
all s5p* SoCs. It is not used on Exynos SoCs anymore.

As for Exynos DP driver, what SoCs does it support? If only Exynos (as the 
name suggests) then there is no point in keeping it at video/exynos and 
making it a part of Exynos DRM driver seems reasonable to me.

Best regards,
Tomasz

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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
  2013-10-31 23:11         ` Tomasz Figa
@ 2013-10-31 23:23           ` Jingoo Han
  -1 siblings, 0 replies; 130+ messages in thread
From: Jingoo Han @ 2013-10-31 23:23 UTC (permalink / raw)
  To: 'Tomasz Figa'
  Cc: 'Inki Dae', 'Sean Paul',
	dri-devel, 'Tomi Valkeinen',
	'Jean-Christophe PLAGNIOL-VILLARD',
	linux-fbdev, linux-samsung-soc, airlied, marcheu,
	'Jingoo Han'

On Friday, November 01, 2013 8:12 AM, Tomasz Figa wrote:
> On Friday 01 of November 2013 08:06:00 Jingoo Han wrote:
> > On Thursday, October 31, 2013 7:47 PM, Inki Dae wrote:
> > > CCing Jingoo,
> > >
> > > Is that ok to remove eDP driver from video/exynos? Isn't this driver
> > > really used by Linux framebuffer driver, s3c-fb.c?
> >
> > +cc Tomi Valkeinen, Jean-Christophe PLAGNIOL-VILLARD,
> >      linux-fbdev list, linux-samsung-soc list
> >
> > Yes, it is used by s3c-fb.c.
> >
> > > Of course, now s3c-fb driver is dead code because this driver doesn't
> > > support device tree yet but we would need more reviews and discussions
> > > about moving this driver into drm side. Let's watch new rules for
> > > device tree bindings of DRM world. So I'd not like to merge this
> > > driver yet.
> > 's3c-fb' driver is still used for other mass products projects.
> > Just, device tree support patch is not yet submitted.
> 
> Current in-tree users of s3c-fb drivers are s3c2443, non-DT s3c64xx and
> all s5p* SoCs. It is not used on Exynos SoCs anymore.

Hi Tomasz Figa,

Some mass product projects using Exynos5250 and etc, use s3c-fb driver
and dp driver. Also, these projects are still using Framebuffer, not DRM.

> 
> As for Exynos DP driver, what SoCs does it support? If only Exynos (as the
> name suggests) then there is no point in keeping it at video/exynos and
> making it a part of Exynos DRM driver seems reasonable to me.

However, when considering only mainline kernel, I have no strong objection.
As you know, many Linux kernel based OS projects using Exynos, are using
DRM, not Framebuffer.

Also, if moving DP driver to DRM, MAINTAINERS entry for Exynos DP driver
should be updated, too.

Best regards,
Jingoo Han


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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
@ 2013-10-31 23:23           ` Jingoo Han
  0 siblings, 0 replies; 130+ messages in thread
From: Jingoo Han @ 2013-10-31 23:23 UTC (permalink / raw)
  To: 'Tomasz Figa'
  Cc: 'Inki Dae', 'Sean Paul',
	dri-devel, 'Tomi Valkeinen',
	'Jean-Christophe PLAGNIOL-VILLARD',
	linux-fbdev, linux-samsung-soc, airlied, marcheu,
	'Jingoo Han'

On Friday, November 01, 2013 8:12 AM, Tomasz Figa wrote:
> On Friday 01 of November 2013 08:06:00 Jingoo Han wrote:
> > On Thursday, October 31, 2013 7:47 PM, Inki Dae wrote:
> > > CCing Jingoo,
> > >
> > > Is that ok to remove eDP driver from video/exynos? Isn't this driver
> > > really used by Linux framebuffer driver, s3c-fb.c?
> >
> > +cc Tomi Valkeinen, Jean-Christophe PLAGNIOL-VILLARD,
> >      linux-fbdev list, linux-samsung-soc list
> >
> > Yes, it is used by s3c-fb.c.
> >
> > > Of course, now s3c-fb driver is dead code because this driver doesn't
> > > support device tree yet but we would need more reviews and discussions
> > > about moving this driver into drm side. Let's watch new rules for
> > > device tree bindings of DRM world. So I'd not like to merge this
> > > driver yet.
> > 's3c-fb' driver is still used for other mass products projects.
> > Just, device tree support patch is not yet submitted.
> 
> Current in-tree users of s3c-fb drivers are s3c2443, non-DT s3c64xx and
> all s5p* SoCs. It is not used on Exynos SoCs anymore.

Hi Tomasz Figa,

Some mass product projects using Exynos5250 and etc, use s3c-fb driver
and dp driver. Also, these projects are still using Framebuffer, not DRM.

> 
> As for Exynos DP driver, what SoCs does it support? If only Exynos (as the
> name suggests) then there is no point in keeping it at video/exynos and
> making it a part of Exynos DRM driver seems reasonable to me.

However, when considering only mainline kernel, I have no strong objection.
As you know, many Linux kernel based OS projects using Exynos, are using
DRM, not Framebuffer.

Also, if moving DP driver to DRM, MAINTAINERS entry for Exynos DP driver
should be updated, too.

Best regards,
Jingoo Han

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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
  2013-10-31 23:23           ` Jingoo Han
@ 2013-10-31 23:27             ` Tomasz Figa
  -1 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-10-31 23:27 UTC (permalink / raw)
  To: Jingoo Han
  Cc: 'Inki Dae', 'Sean Paul',
	dri-devel, 'Tomi Valkeinen',
	'Jean-Christophe PLAGNIOL-VILLARD',
	linux-fbdev, linux-samsung-soc, airlied, marcheu

On Friday 01 of November 2013 08:23:59 Jingoo Han wrote:
> On Friday, November 01, 2013 8:12 AM, Tomasz Figa wrote:
> > On Friday 01 of November 2013 08:06:00 Jingoo Han wrote:
> > > On Thursday, October 31, 2013 7:47 PM, Inki Dae wrote:
> > > > CCing Jingoo,
> > > > 
> > > > Is that ok to remove eDP driver from video/exynos? Isn't this
> > > > driver
> > > > really used by Linux framebuffer driver, s3c-fb.c?
> > > 
> > > +cc Tomi Valkeinen, Jean-Christophe PLAGNIOL-VILLARD,
> > > 
> > >      linux-fbdev list, linux-samsung-soc list
> > > 
> > > Yes, it is used by s3c-fb.c.
> > > 
> > > > Of course, now s3c-fb driver is dead code because this driver
> > > > doesn't
> > > > support device tree yet but we would need more reviews and
> > > > discussions
> > > > about moving this driver into drm side. Let's watch new rules for
> > > > device tree bindings of DRM world. So I'd not like to merge this
> > > > driver yet.
> > > 
> > > 's3c-fb' driver is still used for other mass products projects.
> > > Just, device tree support patch is not yet submitted.
> > 
> > Current in-tree users of s3c-fb drivers are s3c2443, non-DT s3c64xx
> > and
> > all s5p* SoCs. It is not used on Exynos SoCs anymore.
> 
> Hi Tomasz Figa,

Just Tomasz. ;)

> Some mass product projects using Exynos5250 and etc, use s3c-fb driver
> and dp driver. Also, these projects are still using Framebuffer, not
> DRM.

Well, those are based on vendor trees anyway, so do not really affect 
mainline kernel.

> > As for Exynos DP driver, what SoCs does it support? If only Exynos (as
> > the name suggests) then there is no point in keeping it at
> > video/exynos and making it a part of Exynos DRM driver seems
> > reasonable to me.
> 
> However, when considering only mainline kernel, I have no strong
> objection. As you know, many Linux kernel based OS projects using
> Exynos, are using DRM, not Framebuffer.

Generally, fbdev is strongly discouraged in any new systems and DRM is the 
way to go, so I don't think we should ever want to bring s3c-fb support 
back to Exynos platforms.

> 
> Also, if moving DP driver to DRM, MAINTAINERS entry for Exynos DP driver
> should be updated, too.

That's correct.

Best regards,
Tomasz


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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
@ 2013-10-31 23:27             ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-10-31 23:27 UTC (permalink / raw)
  To: Jingoo Han
  Cc: 'Inki Dae', 'Sean Paul',
	dri-devel, 'Tomi Valkeinen',
	'Jean-Christophe PLAGNIOL-VILLARD',
	linux-fbdev, linux-samsung-soc, airlied, marcheu

On Friday 01 of November 2013 08:23:59 Jingoo Han wrote:
> On Friday, November 01, 2013 8:12 AM, Tomasz Figa wrote:
> > On Friday 01 of November 2013 08:06:00 Jingoo Han wrote:
> > > On Thursday, October 31, 2013 7:47 PM, Inki Dae wrote:
> > > > CCing Jingoo,
> > > > 
> > > > Is that ok to remove eDP driver from video/exynos? Isn't this
> > > > driver
> > > > really used by Linux framebuffer driver, s3c-fb.c?
> > > 
> > > +cc Tomi Valkeinen, Jean-Christophe PLAGNIOL-VILLARD,
> > > 
> > >      linux-fbdev list, linux-samsung-soc list
> > > 
> > > Yes, it is used by s3c-fb.c.
> > > 
> > > > Of course, now s3c-fb driver is dead code because this driver
> > > > doesn't
> > > > support device tree yet but we would need more reviews and
> > > > discussions
> > > > about moving this driver into drm side. Let's watch new rules for
> > > > device tree bindings of DRM world. So I'd not like to merge this
> > > > driver yet.
> > > 
> > > 's3c-fb' driver is still used for other mass products projects.
> > > Just, device tree support patch is not yet submitted.
> > 
> > Current in-tree users of s3c-fb drivers are s3c2443, non-DT s3c64xx
> > and
> > all s5p* SoCs. It is not used on Exynos SoCs anymore.
> 
> Hi Tomasz Figa,

Just Tomasz. ;)

> Some mass product projects using Exynos5250 and etc, use s3c-fb driver
> and dp driver. Also, these projects are still using Framebuffer, not
> DRM.

Well, those are based on vendor trees anyway, so do not really affect 
mainline kernel.

> > As for Exynos DP driver, what SoCs does it support? If only Exynos (as
> > the name suggests) then there is no point in keeping it at
> > video/exynos and making it a part of Exynos DRM driver seems
> > reasonable to me.
> 
> However, when considering only mainline kernel, I have no strong
> objection. As you know, many Linux kernel based OS projects using
> Exynos, are using DRM, not Framebuffer.

Generally, fbdev is strongly discouraged in any new systems and DRM is the 
way to go, so I don't think we should ever want to bring s3c-fb support 
back to Exynos platforms.

> 
> Also, if moving DP driver to DRM, MAINTAINERS entry for Exynos DP driver
> should be updated, too.

That's correct.

Best regards,
Tomasz

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

* Re: [PATCH v3 01/32] drm/exynos: Remove useless slab.h include
  2013-10-29 16:12 ` [PATCH v3 01/32] drm/exynos: Remove useless slab.h include Sean Paul
  2013-10-31 10:24   ` Inki Dae
@ 2013-10-31 23:32   ` Tomasz Figa
  1 sibling, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-10-31 23:32 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean, Stéphane,

On Tuesday 29 of October 2013 12:12:47 Sean Paul wrote:
> From: Stéphane Marchesin <marcheu@chromium.org>
> 
> Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/video/exynos/exynos_dp_core.c | 1 -
>  1 file changed, 1 deletion(-)

I'm not sure if this patch should really be a part of this series.

Furthermore, is this header inclusion really useless? I believe it is the 
place where kmalloc() and friends are declared.

Best regards,
Tomasz

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

* Re: [PATCH v3 02/32] drm/exynos: Merge overlay_ops into manager_ops
  2013-10-29 16:12 ` [PATCH v3 02/32] drm/exynos: Merge overlay_ops into manager_ops Sean Paul
@ 2013-10-31 23:39   ` Tomasz Figa
  2013-11-01 19:50     ` Sean Paul
  0 siblings, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-10-31 23:39 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:12:48 Sean Paul wrote:
> This patch merges overlay_ops into manager_ops. In all cases,
> overlay_ops is implemented in the same place as manager ops, it doesn't
> serve a functional purpose, and doesn't make things more clear.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_drv.h     |  29 +--
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c |  26 +-
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c    | 363
> ++++++++++++++-------------- drivers/gpu/drm/exynos/exynos_drm_hdmi.c  
>  |  36 ++-
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c    |  29 +--
>  drivers/gpu/drm/exynos/exynos_mixer.c       |   2 -
>  6 files changed, 229 insertions(+), 256 deletions(-)
[snip]
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 868a14d..f271f22
> 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> @@ -181,185 +181,6 @@ static struct exynos_drm_display_ops
> fimd_display_ops = { .power_on = fimd_display_power_on,
>  };
> 
> -static void fimd_dpms(struct device *subdrv_dev, int mode)
> -{
> -	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
> -
> -	DRM_DEBUG_KMS("%d\n", mode);
> -
> -	mutex_lock(&ctx->lock);
> -
> -	switch (mode) {
> -	case DRM_MODE_DPMS_ON:
> -		/*
> -		 * enable fimd hardware only if suspended status.
> -		 *
> -		 * P.S. fimd_dpms function would be called at booting time 
so
> -		 * clk_enable could be called double time.
> -		 */
> -		if (ctx->suspended)
> -			pm_runtime_get_sync(subdrv_dev);
> -		break;
> -	case DRM_MODE_DPMS_STANDBY:
> -	case DRM_MODE_DPMS_SUSPEND:
> -	case DRM_MODE_DPMS_OFF:
> -		if (!ctx->suspended)
> -			pm_runtime_put_sync(subdrv_dev);
> -		break;
> -	default:
> -		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
> -		break;
> -	}
> -
> -	mutex_unlock(&ctx->lock);
> -}
[snip]
> -static void fimd_wait_for_vblank(struct device *dev)
> -{
> -	struct fimd_context *ctx = get_fimd_context(dev);
> -
> -	if (ctx->suspended)
> -		return;
> -
> -	atomic_set(&ctx->wait_vsync_event, 1);
> -
> -	/*
> -	 * wait for FIMD to signal VSYNC interrupt or return after
> -	 * timeout which is set to 50ms (refresh rate of 20).
> -	 */
> -	if (!wait_event_timeout(ctx->wait_vsync_queue,
> -				!atomic_read(&ctx->wait_vsync_event),
> -				DRM_HZ/20))
> -		DRM_DEBUG_KMS("vblank wait timed out.\n");
> -}

Do you need all the churn of moving all the functions above? I believe it 
would be enough to simply move the structure. This would greatly decrease 
the diffstat and chances of possible merge conflicts.

Otherwise the patch looks good to me and improves things indeed.

Best regards,
Tomasz

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

* Re: [PATCH v3 03/32] drm/exynos: Add an initialize function to manager and display
  2013-10-29 16:12 ` [PATCH v3 03/32] drm/exynos: Add an initialize function to manager and display Sean Paul
@ 2013-10-31 23:42   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-10-31 23:42 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

On Tuesday 29 of October 2013 12:12:49 Sean Paul wrote:
> This patch adds an initialize function to the manager and display
> operations. This allows them to keep track of drm_device in their
> local context, as well as adds an initialization hook right after
> the encoder is created.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_drv.h     |  5 +++++
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c | 21 +++++++++++++++++++++
>  2 files changed, 26 insertions(+)

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 04/32] drm/exynos: Use manager_op initialize in fimd
  2013-10-29 16:12 ` [PATCH v3 04/32] drm/exynos: Use manager_op initialize in fimd Sean Paul
@ 2013-10-31 23:49   ` Tomasz Figa
  2013-11-01 19:51     ` Sean Paul
  0 siblings, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-10-31 23:49 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:12:50 Sean Paul wrote:
> This patch implements the intitialize manager op in fimd.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 19 +++++++++++++++----
>  1 file changed, 15 insertions(+), 4 deletions(-)
[snip]
>  static void fimd_dpms(struct device *subdrv_dev, int mode)
>  {
>  	struct fimd_context *ctx = get_fimd_context(subdrv_dev);
> @@ -660,6 +671,7 @@ static void fimd_wait_for_vblank(struct device *dev)
> }
> 
>  static struct exynos_drm_manager_ops fimd_manager_ops = {
> +	.initialize = fimd_mgr_initialize,
>  	.dpms = fimd_dpms,
>  	.apply = fimd_apply,
>  	.commit = fimd_commit,
> @@ -681,7 +693,6 @@ static irqreturn_t fimd_irq_handler(int irq, void
> *dev_id) {
>  	struct fimd_context *ctx = (struct fimd_context *)dev_id;
>  	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
> -	struct drm_device *drm_dev = subdrv->drm_dev;

Apparently the driver already can have a reference to drm_device, without 
the .initialize() method being called.

I guess your change makes it somehow better, but patch description fails 
to explain this.

Best regards,
Tomasz

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

* Re: [PATCH v3 05/32] drm/exynos: hdmi: Implement initialize op for hdmi
  2013-10-29 16:12 ` [PATCH v3 05/32] drm/exynos: hdmi: Implement initialize op for hdmi Sean Paul
@ 2013-10-31 23:53   ` Tomasz Figa
  2013-11-01 19:54     ` Sean Paul
  0 siblings, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-10-31 23:53 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:12:51 Sean Paul wrote:
> This patch implements the initialize callback in the hdmi and mixer
> manager. This allows us to get rid of drm_dev in the drm_hdmi level and
> track it in the mixer and hdmi drivers. This is one of the things
> holding back the complete removal of the drm_hdmi layer.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 35
> ++++++++++++++++++++++++++------
> drivers/gpu/drm/exynos/exynos_drm_hdmi.h |  3 ++-
>  drivers/gpu/drm/exynos/exynos_hdmi.c     | 18 ++++++++++++----
>  drivers/gpu/drm/exynos/exynos_mixer.c    | 35
> +++++++++++++++++++------------- 4 files changed, 66 insertions(+), 25
> deletions(-)
[snip]
> @@ -985,8 +991,7 @@ static struct exynos_mixer_ops mixer_ops = {
> 
>  static irqreturn_t mixer_irq_handler(int irq, void *arg)
>  {
> -	struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
> -	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
> +	struct mixer_context *ctx = arg;
>  	struct mixer_resources *res = &ctx->mixer_res;
>  	u32 val, base, shadow;
> 
> @@ -995,6 +1000,9 @@ static irqreturn_t mixer_irq_handler(int irq, void
> *arg) /* read interrupt status for handling and clearing flags for
> VSYNC */ val = mixer_reg_read(res, MXR_INT_STATUS);
> 
> +	if (!ctx->drm_dev)
> +		goto out;

The patch looks fine, but I'd like you to explain me in what conditions 
can this condition evaluate to true.

Best regards,
Tomasz

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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
  2013-10-31 23:27             ` Tomasz Figa
@ 2013-10-31 23:55               ` Jingoo Han
  -1 siblings, 0 replies; 130+ messages in thread
From: Jingoo Han @ 2013-10-31 23:55 UTC (permalink / raw)
  To: 'Tomasz Figa'
  Cc: 'Inki Dae', 'Sean Paul',
	dri-devel, 'Tomi Valkeinen',
	'Jean-Christophe PLAGNIOL-VILLARD',
	linux-fbdev, linux-samsung-soc, airlied, marcheu,
	'Jingoo Han'

On Friday, November 01, 2013 8:27 AM, Tomasz Figa wrote:
> On Friday 01 of November 2013 08:23:59 Jingoo Han wrote:
> > On Friday, November 01, 2013 8:12 AM, Tomasz Figa wrote:
> > > On Friday 01 of November 2013 08:06:00 Jingoo Han wrote:
> > > > On Thursday, October 31, 2013 7:47 PM, Inki Dae wrote:
> > > > > CCing Jingoo,
> > > > >
> > > > > Is that ok to remove eDP driver from video/exynos? Isn't this
> > > > > driver
> > > > > really used by Linux framebuffer driver, s3c-fb.c?
> > > >
> > > > +cc Tomi Valkeinen, Jean-Christophe PLAGNIOL-VILLARD,
> > > >
> > > >      linux-fbdev list, linux-samsung-soc list
> > > >
> > > > Yes, it is used by s3c-fb.c.
> > > >
> > > > > Of course, now s3c-fb driver is dead code because this driver
> > > > > doesn't
> > > > > support device tree yet but we would need more reviews and
> > > > > discussions
> > > > > about moving this driver into drm side. Let's watch new rules for
> > > > > device tree bindings of DRM world. So I'd not like to merge this
> > > > > driver yet.
> > > >
> > > > 's3c-fb' driver is still used for other mass products projects.
> > > > Just, device tree support patch is not yet submitted.
> > >
> > > Current in-tree users of s3c-fb drivers are s3c2443, non-DT s3c64xx
> > > and
> > > all s5p* SoCs. It is not used on Exynos SoCs anymore.
> >
> > Hi Tomasz Figa,
> 
> Just Tomasz. ;)

Hi Tomasz, :-)

> 
> > Some mass product projects using Exynos5250 and etc, use s3c-fb driver
> > and dp driver. Also, these projects are still using Framebuffer, not
> > DRM.
> 
> Well, those are based on vendor trees anyway, so do not really affect
> mainline kernel.

OK, I see.

> 
> > > As for Exynos DP driver, what SoCs does it support? If only Exynos (as
> > > the name suggests) then there is no point in keeping it at
> > > video/exynos and making it a part of Exynos DRM driver seems
> > > reasonable to me.
> >
> > However, when considering only mainline kernel, I have no strong
> > objection. As you know, many Linux kernel based OS projects using
> > Exynos, are using DRM, not Framebuffer.
> 
> Generally, fbdev is strongly discouraged in any new systems and DRM is the
> way to go, so I don't think we should ever want to bring s3c-fb support
> back to Exynos platforms.

Yes, you're right.
Personally, I think that all Exynos platforms should go into DRM, not FB.

One more thing, then how about moving Exynos MIPI to DRM side?
Is there any plan on Exynos MIPI?

Best regards,
Jingoo Han

> 
> >
> > Also, if moving DP driver to DRM, MAINTAINERS entry for Exynos DP driver
> > should be updated, too.
> 
> That's correct.


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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
@ 2013-10-31 23:55               ` Jingoo Han
  0 siblings, 0 replies; 130+ messages in thread
From: Jingoo Han @ 2013-10-31 23:55 UTC (permalink / raw)
  To: 'Tomasz Figa'
  Cc: 'Inki Dae', 'Sean Paul',
	dri-devel, 'Tomi Valkeinen',
	'Jean-Christophe PLAGNIOL-VILLARD',
	linux-fbdev, linux-samsung-soc, airlied, marcheu,
	'Jingoo Han'

On Friday, November 01, 2013 8:27 AM, Tomasz Figa wrote:
> On Friday 01 of November 2013 08:23:59 Jingoo Han wrote:
> > On Friday, November 01, 2013 8:12 AM, Tomasz Figa wrote:
> > > On Friday 01 of November 2013 08:06:00 Jingoo Han wrote:
> > > > On Thursday, October 31, 2013 7:47 PM, Inki Dae wrote:
> > > > > CCing Jingoo,
> > > > >
> > > > > Is that ok to remove eDP driver from video/exynos? Isn't this
> > > > > driver
> > > > > really used by Linux framebuffer driver, s3c-fb.c?
> > > >
> > > > +cc Tomi Valkeinen, Jean-Christophe PLAGNIOL-VILLARD,
> > > >
> > > >      linux-fbdev list, linux-samsung-soc list
> > > >
> > > > Yes, it is used by s3c-fb.c.
> > > >
> > > > > Of course, now s3c-fb driver is dead code because this driver
> > > > > doesn't
> > > > > support device tree yet but we would need more reviews and
> > > > > discussions
> > > > > about moving this driver into drm side. Let's watch new rules for
> > > > > device tree bindings of DRM world. So I'd not like to merge this
> > > > > driver yet.
> > > >
> > > > 's3c-fb' driver is still used for other mass products projects.
> > > > Just, device tree support patch is not yet submitted.
> > >
> > > Current in-tree users of s3c-fb drivers are s3c2443, non-DT s3c64xx
> > > and
> > > all s5p* SoCs. It is not used on Exynos SoCs anymore.
> >
> > Hi Tomasz Figa,
> 
> Just Tomasz. ;)

Hi Tomasz, :-)

> 
> > Some mass product projects using Exynos5250 and etc, use s3c-fb driver
> > and dp driver. Also, these projects are still using Framebuffer, not
> > DRM.
> 
> Well, those are based on vendor trees anyway, so do not really affect
> mainline kernel.

OK, I see.

> 
> > > As for Exynos DP driver, what SoCs does it support? If only Exynos (as
> > > the name suggests) then there is no point in keeping it at
> > > video/exynos and making it a part of Exynos DRM driver seems
> > > reasonable to me.
> >
> > However, when considering only mainline kernel, I have no strong
> > objection. As you know, many Linux kernel based OS projects using
> > Exynos, are using DRM, not Framebuffer.
> 
> Generally, fbdev is strongly discouraged in any new systems and DRM is the
> way to go, so I don't think we should ever want to bring s3c-fb support
> back to Exynos platforms.

Yes, you're right.
Personally, I think that all Exynos platforms should go into DRM, not FB.

One more thing, then how about moving Exynos MIPI to DRM side?
Is there any plan on Exynos MIPI?

Best regards,
Jingoo Han

> 
> >
> > Also, if moving DP driver to DRM, MAINTAINERS entry for Exynos DP driver
> > should be updated, too.
> 
> That's correct.

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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
  2013-10-31 23:55               ` Jingoo Han
@ 2013-11-01  0:01                 ` Tomasz Figa
  -1 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-01  0:01 UTC (permalink / raw)
  To: Jingoo Han
  Cc: linux-fbdev, linux-samsung-soc, dri-devel,
	'Tomi Valkeinen',
	marcheu, 'Jean-Christophe PLAGNIOL-VILLARD'

On Friday 01 of November 2013 08:55:12 Jingoo Han wrote:
> On Friday, November 01, 2013 8:27 AM, Tomasz Figa wrote:
> > On Friday 01 of November 2013 08:23:59 Jingoo Han wrote:
> > > On Friday, November 01, 2013 8:12 AM, Tomasz Figa wrote:
> > > > On Friday 01 of November 2013 08:06:00 Jingoo Han wrote:
> > > > > On Thursday, October 31, 2013 7:47 PM, Inki Dae wrote:
> > > > > > CCing Jingoo,
> > > > > > 
> > > > > > Is that ok to remove eDP driver from video/exynos? Isn't this
> > > > > > driver
> > > > > > really used by Linux framebuffer driver, s3c-fb.c?
> > > > > 
> > > > > +cc Tomi Valkeinen, Jean-Christophe PLAGNIOL-VILLARD,
> > > > > 
> > > > >      linux-fbdev list, linux-samsung-soc list
> > > > > 
> > > > > Yes, it is used by s3c-fb.c.
> > > > > 
> > > > > > Of course, now s3c-fb driver is dead code because this driver
> > > > > > doesn't
> > > > > > support device tree yet but we would need more reviews and
> > > > > > discussions
> > > > > > about moving this driver into drm side. Let's watch new rules
> > > > > > for
> > > > > > device tree bindings of DRM world. So I'd not like to merge
> > > > > > this
> > > > > > driver yet.
> > > > > 
> > > > > 's3c-fb' driver is still used for other mass products projects.
> > > > > Just, device tree support patch is not yet submitted.
> > > > 
> > > > Current in-tree users of s3c-fb drivers are s3c2443, non-DT
> > > > s3c64xx
> > > > and
> > > > all s5p* SoCs. It is not used on Exynos SoCs anymore.
> > > 
> > > Hi Tomasz Figa,
> > 
> > Just Tomasz. ;)
> 
> Hi Tomasz, :-)
> 
> > > Some mass product projects using Exynos5250 and etc, use s3c-fb
> > > driver
> > > and dp driver. Also, these projects are still using Framebuffer, not
> > > DRM.
> > 
> > Well, those are based on vendor trees anyway, so do not really affect
> > mainline kernel.
> 
> OK, I see.
> 
> > > > As for Exynos DP driver, what SoCs does it support? If only Exynos
> > > > (as
> > > > the name suggests) then there is no point in keeping it at
> > > > video/exynos and making it a part of Exynos DRM driver seems
> > > > reasonable to me.
> > > 
> > > However, when considering only mainline kernel, I have no strong
> > > objection. As you know, many Linux kernel based OS projects using
> > > Exynos, are using DRM, not Framebuffer.
> > 
> > Generally, fbdev is strongly discouraged in any new systems and DRM is
> > the way to go, so I don't think we should ever want to bring s3c-fb
> > support back to Exynos platforms.
> 
> Yes, you're right.
> Personally, I think that all Exynos platforms should go into DRM, not
> FB.
> 
> One more thing, then how about moving Exynos MIPI to DRM side?
> Is there any plan on Exynos MIPI?

Well, it will eventually have to be moved somewhere else than it is, but I 
believe this will have to wait for Common Display Framework.

This is because the case of MIPI DSI is slightly different from 
DisplayPort, since it is not an enumerable/auto-configurable interface and 
requires dedicated panel drivers and static data provided by board 
designers (in DT for example). Handling of such things in a generic way 
will be done by CDF.

Best regards,
Tomasz


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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
@ 2013-11-01  0:01                 ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-01  0:01 UTC (permalink / raw)
  To: Jingoo Han
  Cc: linux-fbdev, linux-samsung-soc, dri-devel,
	'Tomi Valkeinen',
	marcheu, 'Jean-Christophe PLAGNIOL-VILLARD'

On Friday 01 of November 2013 08:55:12 Jingoo Han wrote:
> On Friday, November 01, 2013 8:27 AM, Tomasz Figa wrote:
> > On Friday 01 of November 2013 08:23:59 Jingoo Han wrote:
> > > On Friday, November 01, 2013 8:12 AM, Tomasz Figa wrote:
> > > > On Friday 01 of November 2013 08:06:00 Jingoo Han wrote:
> > > > > On Thursday, October 31, 2013 7:47 PM, Inki Dae wrote:
> > > > > > CCing Jingoo,
> > > > > > 
> > > > > > Is that ok to remove eDP driver from video/exynos? Isn't this
> > > > > > driver
> > > > > > really used by Linux framebuffer driver, s3c-fb.c?
> > > > > 
> > > > > +cc Tomi Valkeinen, Jean-Christophe PLAGNIOL-VILLARD,
> > > > > 
> > > > >      linux-fbdev list, linux-samsung-soc list
> > > > > 
> > > > > Yes, it is used by s3c-fb.c.
> > > > > 
> > > > > > Of course, now s3c-fb driver is dead code because this driver
> > > > > > doesn't
> > > > > > support device tree yet but we would need more reviews and
> > > > > > discussions
> > > > > > about moving this driver into drm side. Let's watch new rules
> > > > > > for
> > > > > > device tree bindings of DRM world. So I'd not like to merge
> > > > > > this
> > > > > > driver yet.
> > > > > 
> > > > > 's3c-fb' driver is still used for other mass products projects.
> > > > > Just, device tree support patch is not yet submitted.
> > > > 
> > > > Current in-tree users of s3c-fb drivers are s3c2443, non-DT
> > > > s3c64xx
> > > > and
> > > > all s5p* SoCs. It is not used on Exynos SoCs anymore.
> > > 
> > > Hi Tomasz Figa,
> > 
> > Just Tomasz. ;)
> 
> Hi Tomasz, :-)
> 
> > > Some mass product projects using Exynos5250 and etc, use s3c-fb
> > > driver
> > > and dp driver. Also, these projects are still using Framebuffer, not
> > > DRM.
> > 
> > Well, those are based on vendor trees anyway, so do not really affect
> > mainline kernel.
> 
> OK, I see.
> 
> > > > As for Exynos DP driver, what SoCs does it support? If only Exynos
> > > > (as
> > > > the name suggests) then there is no point in keeping it at
> > > > video/exynos and making it a part of Exynos DRM driver seems
> > > > reasonable to me.
> > > 
> > > However, when considering only mainline kernel, I have no strong
> > > objection. As you know, many Linux kernel based OS projects using
> > > Exynos, are using DRM, not Framebuffer.
> > 
> > Generally, fbdev is strongly discouraged in any new systems and DRM is
> > the way to go, so I don't think we should ever want to bring s3c-fb
> > support back to Exynos platforms.
> 
> Yes, you're right.
> Personally, I think that all Exynos platforms should go into DRM, not
> FB.
> 
> One more thing, then how about moving Exynos MIPI to DRM side?
> Is there any plan on Exynos MIPI?

Well, it will eventually have to be moved somewhere else than it is, but I 
believe this will have to wait for Common Display Framework.

This is because the case of MIPI DSI is slightly different from 
DisplayPort, since it is not an enumerable/auto-configurable interface and 
requires dedicated panel drivers and static data provided by board 
designers (in DT for example). Handling of such things in a generic way 
will be done by CDF.

Best regards,
Tomasz

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

* Re: [PATCH v3 06/32] drm/exynos: Pass exynos_drm_manager in manager ops instead of dev
  2013-10-29 16:12 ` [PATCH v3 06/32] drm/exynos: Pass exynos_drm_manager in manager ops instead of dev Sean Paul
@ 2013-11-01  0:19   ` Tomasz Figa
  2013-11-01 20:01     ` Sean Paul
  0 siblings, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-11-01  0:19 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:12:52 Sean Paul wrote:
> This patch changes the manager ops callbacks from accepting the subdrv
> device pointer to taking a pointer to the manager. This will allow us
> to move closer to decoupling manager/display from subdrv, and
> subsequently decoupling the crtc/plane from the encoder.

The idea of changing callbacks argument itself is fine for me, but I 
wonder if by the way we couldn't refactor the code in a way that would 
allow type checking of context structures. This would make the code a bit 
less error-prone (or maybe I'm just a bit too paranoid...).

Anyway, please see my remaining comments inline.

> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2:
> 	- Instead of passing context, pass manager
> 	- Properly assign ctx->dev in fimd driver
> Changes in v3:
> 	- Added vidi implementation
> 
>  drivers/gpu/drm/exynos/exynos_drm_connector.c |   2 +-
>  drivers/gpu/drm/exynos/exynos_drm_drv.h       |  35 ++++----
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c   |  27 +++---
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 114
> ++++++++++++++------------ drivers/gpu/drm/exynos/exynos_drm_hdmi.c    
>  |  72 ++++++++-------- drivers/gpu/drm/exynos/exynos_drm_vidi.c      |
>  83 ++++++++++--------- 6 files changed, 180 insertions(+), 153
> deletions(-)
[snip]
> @@ -182,16 +184,16 @@ static struct exynos_drm_display_ops
> fimd_display_ops = { .power_on = fimd_display_power_on,
>  };
> 
> -static void fimd_win_mode_set(struct device *dev,
> -			      struct exynos_drm_overlay *overlay)
> +static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
> +			struct exynos_drm_overlay *overlay)
>  {
> -	struct fimd_context *ctx = get_fimd_context(dev);
> +	struct fimd_context *ctx = mgr->ctx;
>  	struct fimd_win_data *win_data;
>  	int win;
>  	unsigned long offset;
> 
>  	if (!overlay) {
> -		dev_err(dev, "overlay is NULL\n");
> +		DRM_ERROR("overlay is NULL\n");

This change does not seem to be related to $subject.

>  		return;
>  	}
> 
> @@ -231,9 +233,8 @@ static void fimd_win_mode_set(struct device *dev,
>  			overlay->fb_width, overlay->crtc_width);
>  }
> 
> -static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
> +static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int
> win) {

Again not really related to $subject. Maybe this should be done in a 
preparatory patch preceeding this one? (+ same comment for several 
identical changes below)

> -	struct fimd_context *ctx = get_fimd_context(dev);
>  	struct fimd_win_data *win_data = &ctx->win_data[win];
>  	unsigned long val;
> 
[snip]
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
> b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index aebcc0e..ca0a87f
> 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
> @@ -129,11 +129,9 @@ static struct edid *drm_hdmi_get_edid(struct device
> *dev,
> 
>  	return NULL;
>  }
> -
> -static int drm_hdmi_check_mode(struct device *dev,
> +static int drm_hdmi_check_mode_ctx(struct drm_hdmi_context *ctx,
>  		struct drm_display_mode *mode)
>  {
> -	struct drm_hdmi_context *ctx = to_context(dev);
>  	int ret = 0;
> 
>  	/*
> @@ -153,6 +151,14 @@ static int drm_hdmi_check_mode(struct device *dev,
>  	return 0;
>  }
> 
> +static int drm_hdmi_check_mode(struct device *dev,
> +		struct drm_display_mode *mode)
> +{
> +	struct drm_hdmi_context *ctx = to_context(dev);
> +
> +	return drm_hdmi_check_mode_ctx(ctx, mode);
> +}
> +

nit: I don't think such wrapper is necessary.

It seems to be easy enough to get from dev to ctx, so depending on the 
amount of user of drm_hdmi_check_mode() it might be better to simply 
change them to pass ctx instead of dev.

[snip]
> @@ -403,19 +404,23 @@ static void vidi_subdrv_remove(struct drm_device
> *drm_dev, struct device *dev) /* TODO. */
>  }
> 
> -static int vidi_power_on(struct vidi_context *ctx, bool enable)
> +static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
>  {
> -	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
> -	struct device *dev = subdrv->dev;
> +	struct vidi_context *ctx = mgr->ctx;
> +
> +	DRM_DEBUG_KMS("%s\n", __FILE__);
> +
> +	if (enable != false && enable != true)
> +		return -EINVAL;

Huh? What value would you expect a bool to have if not false or true?

Anyway, this shouldn't really matter, as the check bellow assumes that 
anything non-zero is true.

> 
>  	if (enable) {
>  		ctx->suspended = false;
> 

Just for clarity, this is the check I mentioned above.

Best regards,
Tomasz

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-10-31 16:08     ` Sean Paul
@ 2013-11-01  4:20       ` Inki Dae
  0 siblings, 0 replies; 130+ messages in thread
From: Inki Dae @ 2013-11-01  4:20 UTC (permalink / raw)
  To: Sean Paul; +Cc: Stéphane Marchesin, dri-devel

2013/11/1 Sean Paul <seanpaul@chromium.org>:
> On Thu, Oct 31, 2013 at 6:30 AM, Inki Dae <inki.dae@samsung.com> wrote:
>>
>>
>>> -----Original Message-----
>>> From: Sean Paul [mailto:seanpaul@chromium.org]
>>> Sent: Wednesday, October 30, 2013 1:13 AM
>>> To: dri-devel@lists.freedesktop.org; inki.dae@samsung.com
>>> Cc: airlied@linux.ie; tomasz.figa@gmail.com; marcheu@chromium.org; Sean
>>> Paul
>>> Subject: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
>>>
>>> This patch splits display and manager from subdrv. The result is that
>>> crtc functions can directly call into manager callbacks and encoder
>>> functions can directly call into display callbacks. This will allow
>>> us to remove the exynos_drm_hdmi shim and support mixer/hdmi & fimd/dp
>>> with common code.
>>>
>>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>>> ---
>>>
>>> Changes in v2:
>>>       - Pass display into display_ops instead of context
>>> Changes in v3:
>>>       - Changed vidi args to exynos_drm_display instead of void
>>>       - Moved exynos_drm_hdmi.c removal into next patch
>>>
>>>  drivers/gpu/drm/exynos/exynos_drm_connector.c |  50 ++---
>>>  drivers/gpu/drm/exynos/exynos_drm_core.c      | 181 +++++++++++++-----
>>>  drivers/gpu/drm/exynos/exynos_drm_crtc.c      | 115 +++++++++---
>>>  drivers/gpu/drm/exynos/exynos_drm_crtc.h      |  20 +-
>>>  drivers/gpu/drm/exynos/exynos_drm_drv.c       |  29 +--
>>>  drivers/gpu/drm/exynos/exynos_drm_drv.h       | 106 +++++++----
>>>  drivers/gpu/drm/exynos/exynos_drm_encoder.c   | 258
>> ++++------------------
>>> ----
>>>  drivers/gpu/drm/exynos/exynos_drm_encoder.h   |  18 +-
>>>  drivers/gpu/drm/exynos/exynos_drm_fb.c        |   4 +-
>>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 161 ++++++++--------
>>>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c      | 211 +++++++++------------
>>>  drivers/gpu/drm/exynos/exynos_drm_hdmi.h      |   2 +
>>>  drivers/gpu/drm/exynos/exynos_drm_plane.c     |  15 +-
>>>  drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 129 ++++++-------
>>>  14 files changed, 615 insertions(+), 684 deletions(-)
>>>
>>>  static int exynos_drm_create_enc_conn(struct drm_device *dev,
>>> -                                     struct exynos_drm_subdrv *subdrv)
>>> +                                     struct exynos_drm_display *display)
>>>  {
>>>       struct drm_encoder *encoder;
>>>       struct drm_connector *connector;
>>> +     struct exynos_drm_manager *manager;
>>>       int ret;
>>> +     unsigned long possible_crtcs = 0;
>>>
>>> -     subdrv->manager->dev = subdrv->dev;
>>> +     /* Find possible crtcs for this display */
>>> +     list_for_each_entry(manager, &exynos_drm_manager_list, list)
>>> +             if (manager->type == display->type)
>>> +                     possible_crtcs |= 1 << manager->pipe;
>>>
>>>       /* create and initialize a encoder for this sub driver. */
>>> -     encoder = exynos_drm_encoder_create(dev, subdrv->manager,
>>> -                     (1 << MAX_CRTC) - 1);
>>> +     encoder = exynos_drm_encoder_create(dev, display, possible_crtcs);
>>>       if (!encoder) {
>>>               DRM_ERROR("failed to create encoder\n");
>>>               return -EFAULT;
>>>       }
>>> -     subdrv->encoder = encoder;
>>> +     display->encoder = encoder;
>>>
>>> -     if (subdrv->manager->display_ops->type == EXYNOS_DISPLAY_TYPE_LCD)
>>> {
>>> +     if (display->type == EXYNOS_DISPLAY_TYPE_LCD) {
>>>               ret = exynos_drm_attach_lcd_bridge(dev, encoder);
>>
>> The lvds bridge related codes need more reviews
>
> I think everyone agrees that there need not be a 1:1 binding to driver
> relationship, so what is left to discuss?
>

I also agree to that no 1:1 binding. But this way it's not clear to me
yet. For this, I already commented that I'll try to find a better way
to you. So know that it's not that I don't agree to this way. If there
is no any better way, then I'll merge this lvds support to top of the
re-factoring patch series. any problem?  I'd really like to focus on
the re-factoring patch series as of now. And we also have other patch
series to should be reviewed. BTW, did Dave accept that lvds driver?
This lvds driver should be placed in drivers/gpu/drm/bridge/.

Thanks,
Inki Dae

> Sean
>
>
>
>> so I'll merge this patch
>> manually excepting the lvds bridge related codes. Let's discuss lvds bridge
>> later.
>>
>> Thanks,
>> Inki Dae
>>
>>>               if (ret)
>>>                       return 0;
>>> @@ -91,7 +98,7 @@ static int exynos_drm_create_enc_conn(struct drm_device
>>> *dev,
>>>               goto err_destroy_encoder;
>>>       }
>>>
>>> -     subdrv->connector = connector;
>>> +     display->connector = connector;
>>>
>>>       return 0;
>>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 02/32] drm/exynos: Merge overlay_ops into manager_ops
  2013-10-31 23:39   ` Tomasz Figa
@ 2013-11-01 19:50     ` Sean Paul
  2013-11-01 19:55       ` Tomasz Figa
  0 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-11-01 19:50 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: dri-devel, Stéphane Marchesin

On Thu, Oct 31, 2013 at 7:39 PM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> Hi Sean,
>
> On Tuesday 29 of October 2013 12:12:48 Sean Paul wrote:
>> This patch merges overlay_ops into manager_ops. In all cases,
>> overlay_ops is implemented in the same place as manager ops, it doesn't
>> serve a functional purpose, and doesn't make things more clear.
>>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>
>> Changes in v2: None
>> Changes in v3: None
>>
>>  drivers/gpu/drm/exynos/exynos_drm_drv.h     |  29 +--
>>  drivers/gpu/drm/exynos/exynos_drm_encoder.c |  26 +-
>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c    | 363
>> ++++++++++++++-------------- drivers/gpu/drm/exynos/exynos_drm_hdmi.c
>>  |  36 ++-
>>  drivers/gpu/drm/exynos/exynos_drm_vidi.c    |  29 +--
>>  drivers/gpu/drm/exynos/exynos_mixer.c       |   2 -
>>  6 files changed, 229 insertions(+), 256 deletions(-)
> [snip]
>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>> b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 868a14d..f271f22
>> 100644
>> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>> @@ -181,185 +181,6 @@ static struct exynos_drm_display_ops
>> fimd_display_ops = { .power_on = fimd_display_power_on,
>>  };
>>
>> -static void fimd_dpms(struct device *subdrv_dev, int mode)
>> -{
>> -     struct fimd_context *ctx = get_fimd_context(subdrv_dev);
>> -
>> -     DRM_DEBUG_KMS("%d\n", mode);
>> -
>> -     mutex_lock(&ctx->lock);
>> -
>> -     switch (mode) {
>> -     case DRM_MODE_DPMS_ON:
>> -             /*
>> -              * enable fimd hardware only if suspended status.
>> -              *
>> -              * P.S. fimd_dpms function would be called at booting time
> so
>> -              * clk_enable could be called double time.
>> -              */
>> -             if (ctx->suspended)
>> -                     pm_runtime_get_sync(subdrv_dev);
>> -             break;
>> -     case DRM_MODE_DPMS_STANDBY:
>> -     case DRM_MODE_DPMS_SUSPEND:
>> -     case DRM_MODE_DPMS_OFF:
>> -             if (!ctx->suspended)
>> -                     pm_runtime_put_sync(subdrv_dev);
>> -             break;
>> -     default:
>> -             DRM_DEBUG_KMS("unspecified mode %d\n", mode);
>> -             break;
>> -     }
>> -
>> -     mutex_unlock(&ctx->lock);
>> -}
> [snip]
>> -static void fimd_wait_for_vblank(struct device *dev)
>> -{
>> -     struct fimd_context *ctx = get_fimd_context(dev);
>> -
>> -     if (ctx->suspended)
>> -             return;
>> -
>> -     atomic_set(&ctx->wait_vsync_event, 1);
>> -
>> -     /*
>> -      * wait for FIMD to signal VSYNC interrupt or return after
>> -      * timeout which is set to 50ms (refresh rate of 20).
>> -      */
>> -     if (!wait_event_timeout(ctx->wait_vsync_queue,
>> -                             !atomic_read(&ctx->wait_vsync_event),
>> -                             DRM_HZ/20))
>> -             DRM_DEBUG_KMS("vblank wait timed out.\n");
>> -}
>
> Do you need all the churn of moving all the functions above? I believe it
> would be enough to simply move the structure. This would greatly decrease
> the diffstat and chances of possible merge conflicts.
>

Hi Tomasz,
I've done as you suggest, I'll post a new version once we settle on
the other issues you brought up.

Sean

> Otherwise the patch looks good to me and improves things indeed.
>
> Best regards,
> Tomasz
>

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

* Re: [PATCH v3 04/32] drm/exynos: Use manager_op initialize in fimd
  2013-10-31 23:49   ` Tomasz Figa
@ 2013-11-01 19:51     ` Sean Paul
  2013-11-01 19:57       ` Tomasz Figa
  0 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-11-01 19:51 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: dri-devel, Stéphane Marchesin

On Thu, Oct 31, 2013 at 7:49 PM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> Hi Sean,
>
> On Tuesday 29 of October 2013 12:12:50 Sean Paul wrote:
>> This patch implements the intitialize manager op in fimd.
>>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>
>> Changes in v2: None
>> Changes in v3: None
>>
>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 19 +++++++++++++++----
>>  1 file changed, 15 insertions(+), 4 deletions(-)
> [snip]
>>  static void fimd_dpms(struct device *subdrv_dev, int mode)
>>  {
>>       struct fimd_context *ctx = get_fimd_context(subdrv_dev);
>> @@ -660,6 +671,7 @@ static void fimd_wait_for_vblank(struct device *dev)
>> }
>>
>>  static struct exynos_drm_manager_ops fimd_manager_ops = {
>> +     .initialize = fimd_mgr_initialize,
>>       .dpms = fimd_dpms,
>>       .apply = fimd_apply,
>>       .commit = fimd_commit,
>> @@ -681,7 +693,6 @@ static irqreturn_t fimd_irq_handler(int irq, void
>> *dev_id) {
>>       struct fimd_context *ctx = (struct fimd_context *)dev_id;
>>       struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
>> -     struct drm_device *drm_dev = subdrv->drm_dev;
>
> Apparently the driver already can have a reference to drm_device, without
> the .initialize() method being called.
>
> I guess your change makes it somehow better, but patch description fails
> to explain this.
>

I've updated the patch description. This change is needed to remove
all subdrv references from fimd so we can just implement manager.

Sean

> Best regards,
> Tomasz
>

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

* Re: [PATCH v3 05/32] drm/exynos: hdmi: Implement initialize op for hdmi
  2013-10-31 23:53   ` Tomasz Figa
@ 2013-11-01 19:54     ` Sean Paul
  2013-11-01 19:56       ` Tomasz Figa
  0 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-11-01 19:54 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: dri-devel, Stéphane Marchesin

On Thu, Oct 31, 2013 at 7:53 PM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> Hi Sean,
>
> On Tuesday 29 of October 2013 12:12:51 Sean Paul wrote:
>> This patch implements the initialize callback in the hdmi and mixer
>> manager. This allows us to get rid of drm_dev in the drm_hdmi level and
>> track it in the mixer and hdmi drivers. This is one of the things
>> holding back the complete removal of the drm_hdmi layer.
>>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>
>> Changes in v2: None
>> Changes in v3: None
>>
>>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 35
>> ++++++++++++++++++++++++++------
>> drivers/gpu/drm/exynos/exynos_drm_hdmi.h |  3 ++-
>>  drivers/gpu/drm/exynos/exynos_hdmi.c     | 18 ++++++++++++----
>>  drivers/gpu/drm/exynos/exynos_mixer.c    | 35
>> +++++++++++++++++++------------- 4 files changed, 66 insertions(+), 25
>> deletions(-)
> [snip]
>> @@ -985,8 +991,7 @@ static struct exynos_mixer_ops mixer_ops = {
>>
>>  static irqreturn_t mixer_irq_handler(int irq, void *arg)
>>  {
>> -     struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
>> -     struct mixer_context *ctx = drm_hdmi_ctx->ctx;
>> +     struct mixer_context *ctx = arg;
>>       struct mixer_resources *res = &ctx->mixer_res;
>>       u32 val, base, shadow;
>>
>> @@ -995,6 +1000,9 @@ static irqreturn_t mixer_irq_handler(int irq, void
>> *arg) /* read interrupt status for handling and clearing flags for
>> VSYNC */ val = mixer_reg_read(res, MXR_INT_STATUS);
>>
>> +     if (!ctx->drm_dev)
>> +             goto out;
>
> The patch looks fine, but I'd like you to explain me in what conditions
> can this condition evaluate to true.
>

This can happen if there's a mixer interrupt before the intialize()
hook is called.

Sean


> Best regards,
> Tomasz
>

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

* Re: [PATCH v3 02/32] drm/exynos: Merge overlay_ops into manager_ops
  2013-11-01 19:50     ` Sean Paul
@ 2013-11-01 19:55       ` Tomasz Figa
  2013-11-04  7:44         ` Inki Dae
  0 siblings, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-11-01 19:55 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, Stéphane Marchesin

Hi Sean,

On Friday 01 of November 2013 15:50:05 Sean Paul wrote:
> On Thu, Oct 31, 2013 at 7:39 PM, Tomasz Figa <tomasz.figa@gmail.com> 
wrote:
> > Hi Sean,
> > 
> > On Tuesday 29 of October 2013 12:12:48 Sean Paul wrote:
[snip]
> >> -static void fimd_wait_for_vblank(struct device *dev)
> >> -{
> >> -     struct fimd_context *ctx = get_fimd_context(dev);
> >> -
> >> -     if (ctx->suspended)
> >> -             return;
> >> -
> >> -     atomic_set(&ctx->wait_vsync_event, 1);
> >> -
> >> -     /*
> >> -      * wait for FIMD to signal VSYNC interrupt or return after
> >> -      * timeout which is set to 50ms (refresh rate of 20).
> >> -      */
> >> -     if (!wait_event_timeout(ctx->wait_vsync_queue,
> >> -                             !atomic_read(&ctx->wait_vsync_event),
> >> -                             DRM_HZ/20))
> >> -             DRM_DEBUG_KMS("vblank wait timed out.\n");
> >> -}
> > 
> > Do you need all the churn of moving all the functions above? I believe
> > it would be enough to simply move the structure. This would greatly
> > decrease the diffstat and chances of possible merge conflicts.
> 
> Hi Tomasz,
> I've done as you suggest,

Thanks.

> I'll post a new version once we settle on
> the other issues you brought up.

Okay.

I'm yet to review remaining patches from this series (I hope to review 
next 5-7 patches later today), as it is quite a lot of changes, so stay 
tuned for further comments. ;)

Best regards,
Tomasz

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

* Re: [PATCH v3 05/32] drm/exynos: hdmi: Implement initialize op for hdmi
  2013-11-01 19:54     ` Sean Paul
@ 2013-11-01 19:56       ` Tomasz Figa
  2013-11-01 20:08         ` Sean Paul
  0 siblings, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-11-01 19:56 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, Stéphane Marchesin

Hi Sean,

On Friday 01 of November 2013 15:54:31 Sean Paul wrote:
> On Thu, Oct 31, 2013 at 7:53 PM, Tomasz Figa <tomasz.figa@gmail.com> 
wrote:
> > Hi Sean,
> > 
> > On Tuesday 29 of October 2013 12:12:51 Sean Paul wrote:
[snip]
> >> @@ -995,6 +1000,9 @@ static irqreturn_t mixer_irq_handler(int irq,
> >> void
> >> *arg) /* read interrupt status for handling and clearing flags for
> >> VSYNC */ val = mixer_reg_read(res, MXR_INT_STATUS);
> >> 
> >> +     if (!ctx->drm_dev)
> >> +             goto out;
> > 
> > The patch looks fine, but I'd like you to explain me in what
> > conditions
> > can this condition evaluate to true.
> 
> This can happen if there's a mixer interrupt before the intialize()
> hook is called.

What about making the driver enable the interrupt (or even all the 
hardware) after this hook is called then?

Best regards,
Tomasz

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

* Re: [PATCH v3 04/32] drm/exynos: Use manager_op initialize in fimd
  2013-11-01 19:51     ` Sean Paul
@ 2013-11-01 19:57       ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-01 19:57 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, Stéphane Marchesin

On Friday 01 of November 2013 15:51:00 Sean Paul wrote:
> On Thu, Oct 31, 2013 at 7:49 PM, Tomasz Figa <tomasz.figa@gmail.com> 
wrote:
> > Hi Sean,
> > 
> > On Tuesday 29 of October 2013 12:12:50 Sean Paul wrote:
> >> This patch implements the intitialize manager op in fimd.
> >> 
> >> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> >> ---
> >> 
> >> Changes in v2: None
> >> Changes in v3: None
> >> 
> >>  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 19 +++++++++++++++----
> >>  1 file changed, 15 insertions(+), 4 deletions(-)
> > 
> > [snip]
> > 
> >>  static void fimd_dpms(struct device *subdrv_dev, int mode)
> >>  {
> >>  
> >>       struct fimd_context *ctx = get_fimd_context(subdrv_dev);
> >> 
> >> @@ -660,6 +671,7 @@ static void fimd_wait_for_vblank(struct device
> >> *dev) }
> >> 
> >>  static struct exynos_drm_manager_ops fimd_manager_ops = {
> >> 
> >> +     .initialize = fimd_mgr_initialize,
> >> 
> >>       .dpms = fimd_dpms,
> >>       .apply = fimd_apply,
> >>       .commit = fimd_commit,
> >> 
> >> @@ -681,7 +693,6 @@ static irqreturn_t fimd_irq_handler(int irq, void
> >> *dev_id) {
> >> 
> >>       struct fimd_context *ctx = (struct fimd_context *)dev_id;
> >>       struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
> >> 
> >> -     struct drm_device *drm_dev = subdrv->drm_dev;
> > 
> > Apparently the driver already can have a reference to drm_device,
> > without the .initialize() method being called.
> > 
> > I guess your change makes it somehow better, but patch description
> > fails to explain this.
> 
> I've updated the patch description. This change is needed to remove
> all subdrv references from fimd so we can just implement manager.

Fair enough. Thanks.

Best regards,
Tomasz

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

* Re: [PATCH v3 06/32] drm/exynos: Pass exynos_drm_manager in manager ops instead of dev
  2013-11-01  0:19   ` Tomasz Figa
@ 2013-11-01 20:01     ` Sean Paul
  2013-11-01 20:11       ` Tomasz Figa
  0 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-11-01 20:01 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: dri-devel, Stéphane Marchesin

On Thu, Oct 31, 2013 at 8:19 PM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> Hi Sean,
>
> On Tuesday 29 of October 2013 12:12:52 Sean Paul wrote:
>> This patch changes the manager ops callbacks from accepting the subdrv
>> device pointer to taking a pointer to the manager. This will allow us
>> to move closer to decoupling manager/display from subdrv, and
>> subsequently decoupling the crtc/plane from the encoder.
>
> The idea of changing callbacks argument itself is fine for me, but I
> wonder if by the way we couldn't refactor the code in a way that would
> allow type checking of context structures. This would make the code a bit
> less error-prone (or maybe I'm just a bit too paranoid...).
>
> Anyway, please see my remaining comments inline.
>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>
>> Changes in v2:
>>       - Instead of passing context, pass manager
>>       - Properly assign ctx->dev in fimd driver
>> Changes in v3:
>>       - Added vidi implementation
>>
>>  drivers/gpu/drm/exynos/exynos_drm_connector.c |   2 +-
>>  drivers/gpu/drm/exynos/exynos_drm_drv.h       |  35 ++++----
>>  drivers/gpu/drm/exynos/exynos_drm_encoder.c   |  27 +++---
>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 114
>> ++++++++++++++------------ drivers/gpu/drm/exynos/exynos_drm_hdmi.c
>>  |  72 ++++++++-------- drivers/gpu/drm/exynos/exynos_drm_vidi.c      |
>>  83 ++++++++++--------- 6 files changed, 180 insertions(+), 153
>> deletions(-)
> [snip]
>> @@ -182,16 +184,16 @@ static struct exynos_drm_display_ops
>> fimd_display_ops = { .power_on = fimd_display_power_on,
>>  };
>>
>> -static void fimd_win_mode_set(struct device *dev,
>> -                           struct exynos_drm_overlay *overlay)
>> +static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
>> +                     struct exynos_drm_overlay *overlay)
>>  {
>> -     struct fimd_context *ctx = get_fimd_context(dev);
>> +     struct fimd_context *ctx = mgr->ctx;
>>       struct fimd_win_data *win_data;
>>       int win;
>>       unsigned long offset;
>>
>>       if (!overlay) {
>> -             dev_err(dev, "overlay is NULL\n");
>> +             DRM_ERROR("overlay is NULL\n");
>
> This change does not seem to be related to $subject.
>

It is. fimd_win_mode_set does not take dev as an argument any longer,
as such it's undefined.

>>               return;
>>       }
>>
>> @@ -231,9 +233,8 @@ static void fimd_win_mode_set(struct device *dev,
>>                       overlay->fb_width, overlay->crtc_width);
>>  }
>>
>> -static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
>> +static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int
>> win) {
>
> Again not really related to $subject. Maybe this should be done in a
> preparatory patch preceeding this one? (+ same comment for several
> identical changes below)
>

I think it's directly related to the subject. We no longer pass dev as
an argument, so that has indirect effects on other functions.

>> -     struct fimd_context *ctx = get_fimd_context(dev);
>>       struct fimd_win_data *win_data = &ctx->win_data[win];
>>       unsigned long val;
>>
> [snip]
>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
>> b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index aebcc0e..ca0a87f
>> 100644
>> --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
>> @@ -129,11 +129,9 @@ static struct edid *drm_hdmi_get_edid(struct device
>> *dev,
>>
>>       return NULL;
>>  }
>> -
>> -static int drm_hdmi_check_mode(struct device *dev,
>> +static int drm_hdmi_check_mode_ctx(struct drm_hdmi_context *ctx,
>>               struct drm_display_mode *mode)
>>  {
>> -     struct drm_hdmi_context *ctx = to_context(dev);
>>       int ret = 0;
>>
>>       /*
>> @@ -153,6 +151,14 @@ static int drm_hdmi_check_mode(struct device *dev,
>>       return 0;
>>  }
>>
>> +static int drm_hdmi_check_mode(struct device *dev,
>> +             struct drm_display_mode *mode)
>> +{
>> +     struct drm_hdmi_context *ctx = to_context(dev);
>> +
>> +     return drm_hdmi_check_mode_ctx(ctx, mode);
>> +}
>> +
>
> nit: I don't think such wrapper is necessary.
>
> It seems to be easy enough to get from dev to ctx, so depending on the
> amount of user of drm_hdmi_check_mode() it might be better to simply
> change them to pass ctx instead of dev.
>

This is a display_op that is defined to accept dev. It's changed later
in the patchset to accept display, at which point the wrapper goes
away.

> [snip]
>> @@ -403,19 +404,23 @@ static void vidi_subdrv_remove(struct drm_device
>> *drm_dev, struct device *dev) /* TODO. */
>>  }
>>
>> -static int vidi_power_on(struct vidi_context *ctx, bool enable)
>> +static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
>>  {
>> -     struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
>> -     struct device *dev = subdrv->dev;
>> +     struct vidi_context *ctx = mgr->ctx;
>> +
>> +     DRM_DEBUG_KMS("%s\n", __FILE__);
>> +
>> +     if (enable != false && enable != true)
>> +             return -EINVAL;
>
> Huh? What value would you expect a bool to have if not false or true?
>
> Anyway, this shouldn't really matter, as the check bellow assumes that
> anything non-zero is true.
>

This is pre-existing vidi code, I just moved it.

Sean

>>
>>       if (enable) {
>>               ctx->suspended = false;
>>
>
> Just for clarity, this is the check I mentioned above.
>
> Best regards,
> Tomasz
>

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

* Re: [PATCH v3 05/32] drm/exynos: hdmi: Implement initialize op for hdmi
  2013-11-01 19:56       ` Tomasz Figa
@ 2013-11-01 20:08         ` Sean Paul
  0 siblings, 0 replies; 130+ messages in thread
From: Sean Paul @ 2013-11-01 20:08 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: dri-devel, Stéphane Marchesin

On Fri, Nov 1, 2013 at 3:56 PM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> Hi Sean,
>
> On Friday 01 of November 2013 15:54:31 Sean Paul wrote:
>> On Thu, Oct 31, 2013 at 7:53 PM, Tomasz Figa <tomasz.figa@gmail.com>
> wrote:
>> > Hi Sean,
>> >
>> > On Tuesday 29 of October 2013 12:12:51 Sean Paul wrote:
> [snip]
>> >> @@ -995,6 +1000,9 @@ static irqreturn_t mixer_irq_handler(int irq,
>> >> void
>> >> *arg) /* read interrupt status for handling and clearing flags for
>> >> VSYNC */ val = mixer_reg_read(res, MXR_INT_STATUS);
>> >>
>> >> +     if (!ctx->drm_dev)
>> >> +             goto out;
>> >
>> > The patch looks fine, but I'd like you to explain me in what
>> > conditions
>> > can this condition evaluate to true.
>>
>> This can happen if there's a mixer interrupt before the intialize()
>> hook is called.
>
> What about making the driver enable the interrupt (or even all the
> hardware) after this hook is called then?
>

Sure, I can do that. This is one of the reasons that a unified driver
model would be useful.

Sean



> Best regards,
> Tomasz
>

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

* Re: [PATCH v3 06/32] drm/exynos: Pass exynos_drm_manager in manager ops instead of dev
  2013-11-01 20:01     ` Sean Paul
@ 2013-11-01 20:11       ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-01 20:11 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, Stéphane Marchesin

On Friday 01 of November 2013 16:01:23 Sean Paul wrote:
> On Thu, Oct 31, 2013 at 8:19 PM, Tomasz Figa <tomasz.figa@gmail.com> 
wrote:
> > Hi Sean,
> > 
> > On Tuesday 29 of October 2013 12:12:52 Sean Paul wrote:
[snip]
> >> -static void fimd_win_mode_set(struct device *dev,
> >> -                           struct exynos_drm_overlay *overlay)
> >> +static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
> >> +                     struct exynos_drm_overlay *overlay)
> >> 
> >>  {
> >> 
> >> -     struct fimd_context *ctx = get_fimd_context(dev);
> >> +     struct fimd_context *ctx = mgr->ctx;
> >> 
> >>       struct fimd_win_data *win_data;
> >>       int win;
> >>       unsigned long offset;
> >>       
> >>       if (!overlay) {
> >> 
> >> -             dev_err(dev, "overlay is NULL\n");
> >> +             DRM_ERROR("overlay is NULL\n");
> > 
> > This change does not seem to be related to $subject.
> 
> It is. fimd_win_mode_set does not take dev as an argument any longer,
> as such it's undefined.

Right, I have overlooked this.

> >>               return;
> >>       
> >>       }
> >> 
> >> @@ -231,9 +233,8 @@ static void fimd_win_mode_set(struct device *dev,
> >> 
> >>                       overlay->fb_width, overlay->crtc_width);
> >>  
> >>  }
> >> 
> >> -static void fimd_win_set_pixfmt(struct device *dev, unsigned int
> >> win)
> >> +static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned
> >> int
> >> win) {
> > 
> > Again not really related to $subject. Maybe this should be done in a
> > preparatory patch preceeding this one? (+ same comment for several
> > identical changes below)
> 
> I think it's directly related to the subject. We no longer pass dev as
> an argument, so that has indirect effects on other functions.

Fine.

> >> -     struct fimd_context *ctx = get_fimd_context(dev);
> >> 
> >>       struct fimd_win_data *win_data = &ctx->win_data[win];
> >>       unsigned long val;
> > 
> > [snip]
> > 
> >> diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
> >> b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index aebcc0e..ca0a87f
> >> 100644
> >> --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
> >> +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
> >> @@ -129,11 +129,9 @@ static struct edid *drm_hdmi_get_edid(struct
> >> device *dev,
> >> 
> >>       return NULL;
> >>  
> >>  }
> >> 
> >> -
> >> -static int drm_hdmi_check_mode(struct device *dev,
> >> +static int drm_hdmi_check_mode_ctx(struct drm_hdmi_context *ctx,
> >> 
> >>               struct drm_display_mode *mode)
> >>  
> >>  {
> >> 
> >> -     struct drm_hdmi_context *ctx = to_context(dev);
> >> 
> >>       int ret = 0;
> >>       
> >>       /*
> >> 
> >> @@ -153,6 +151,14 @@ static int drm_hdmi_check_mode(struct device
> >> *dev,
> >> 
> >>       return 0;
> >>  
> >>  }
> >> 
> >> +static int drm_hdmi_check_mode(struct device *dev,
> >> +             struct drm_display_mode *mode)
> >> +{
> >> +     struct drm_hdmi_context *ctx = to_context(dev);
> >> +
> >> +     return drm_hdmi_check_mode_ctx(ctx, mode);
> >> +}
> >> +
> > 
> > nit: I don't think such wrapper is necessary.
> > 
> > It seems to be easy enough to get from dev to ctx, so depending on the
> > amount of user of drm_hdmi_check_mode() it might be better to simply
> > change them to pass ctx instead of dev.
> 
> This is a display_op that is defined to accept dev. It's changed later
> in the patchset to accept display, at which point the wrapper goes
> away.

Fair enough.

> > [snip]
> > 
> >> @@ -403,19 +404,23 @@ static void vidi_subdrv_remove(struct
> >> drm_device
> >> *drm_dev, struct device *dev) /* TODO. */
> >> 
> >>  }
> >> 
> >> -static int vidi_power_on(struct vidi_context *ctx, bool enable)
> >> +static int vidi_power_on(struct exynos_drm_manager *mgr, bool
> >> enable)
> >> 
> >>  {
> >> 
> >> -     struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
> >> -     struct device *dev = subdrv->dev;
> >> +     struct vidi_context *ctx = mgr->ctx;
> >> +
> >> +     DRM_DEBUG_KMS("%s\n", __FILE__);
> >> +
> >> +     if (enable != false && enable != true)
> >> +             return -EINVAL;
> > 
> > Huh? What value would you expect a bool to have if not false or true?
> > 
> > Anyway, this shouldn't really matter, as the check bellow assumes that
> > anything non-zero is true.
> 
> This is pre-existing vidi code, I just moved it.

I don't see the hunk removing it from another location. Are you sure?

Best regards,
Tomasz

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

* Re: [PATCH v3 02/32] drm/exynos: Merge overlay_ops into manager_ops
  2013-11-01 19:55       ` Tomasz Figa
@ 2013-11-04  7:44         ` Inki Dae
  0 siblings, 0 replies; 130+ messages in thread
From: Inki Dae @ 2013-11-04  7:44 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: Stéphane Marchesin, dri-devel

2013/11/2 Tomasz Figa <tomasz.figa@gmail.com>:
> Hi Sean,
>
> On Friday 01 of November 2013 15:50:05 Sean Paul wrote:
>> On Thu, Oct 31, 2013 at 7:39 PM, Tomasz Figa <tomasz.figa@gmail.com>
> wrote:
>> > Hi Sean,
>> >
>> > On Tuesday 29 of October 2013 12:12:48 Sean Paul wrote:
> [snip]
>> >> -static void fimd_wait_for_vblank(struct device *dev)
>> >> -{
>> >> -     struct fimd_context *ctx = get_fimd_context(dev);
>> >> -
>> >> -     if (ctx->suspended)
>> >> -             return;
>> >> -
>> >> -     atomic_set(&ctx->wait_vsync_event, 1);
>> >> -
>> >> -     /*
>> >> -      * wait for FIMD to signal VSYNC interrupt or return after
>> >> -      * timeout which is set to 50ms (refresh rate of 20).
>> >> -      */
>> >> -     if (!wait_event_timeout(ctx->wait_vsync_queue,
>> >> -                             !atomic_read(&ctx->wait_vsync_event),
>> >> -                             DRM_HZ/20))
>> >> -             DRM_DEBUG_KMS("vblank wait timed out.\n");
>> >> -}
>> >
>> > Do you need all the churn of moving all the functions above? I believe
>> > it would be enough to simply move the structure. This would greatly
>> > decrease the diffstat and chances of possible merge conflicts.
>>
>> Hi Tomasz,
>> I've done as you suggest,
>
> Thanks.
>
>> I'll post a new version once we settle on
>> the other issues you brought up.
>
> Okay.
>
> I'm yet to review remaining patches from this series (I hope to review
> next 5-7 patches later today), as it is quite a lot of changes, so stay
> tuned for further comments. ;)
>

Hi Tomasz,

Are you reviewing yet? I have looked into this patch series but I
couldn't find any big issues excepting bridge and eDP related patches
so I wanted  to merge them as is, and then fix them up later.

Do you and Sean prefer this patch series to be more reviewed? If so or
If there are quite big issues to should be fixed then I will not merge
all patch series this time so that we can have enough time for more
detailed reviews including bridge, eDP related patches, dt support to
hdmi phy config, and so on.

Thanks,
Inki Dae

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

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

* Re: [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver
  2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
                   ` (31 preceding siblings ...)
  2013-10-29 16:13 ` [PATCH v3 32/32] drm/exynos: Remove the exynos_drm_connector shim Sean Paul
@ 2013-11-07  5:48 ` Inki Dae
  2013-11-07 18:20   ` Sean Paul
  2013-11-08 21:01   ` Tomasz Figa
  32 siblings, 2 replies; 130+ messages in thread
From: Inki Dae @ 2013-11-07  5:48 UTC (permalink / raw)
  To: Sean Paul; +Cc: Stéphane Marchesin, DRI mailing list

Hi Sean,

When are you going to post your next version?  Need more time? Other
DRM drivers have been merged to drm-next except Exynos. So plz hurry
up if you want to merge this re-factoring patch series during merge
window.

Thanks,
Inki Dae


2013/10/30 Sean Paul <seanpaul@chromium.org>:
> This patchset refactors parts of the exynos driver to move it closer to a proper
> drm driver (rather than just implementing a drm layer on top of the hardware
> drivers). The hope is to get to a point where the dp/hdmi drivers can implement
> drm_connector/drm_encoder directly, and fimd/mixer can directly implement
> drm_crtc.
>
> The notable changes in this set:
>         - drm_encoder funcs no longer route through the crtc
>         - DP driver has been moved from video into the drm driver
>         - fimd no longer implements encoder callbacks
>         - exynos_drm_hdmi is removed in favor of generic manager/display
>           handling
>
> At a glance, differences between v1 and v2:
>         - Passing manager/display in callbacks instead of ctx
>         - Tacked on some dpms patches on the end to handle suspend/resume
>           through the dpms path
>
> At a glance, differences between v2 and v3:
>         - Fixed vidi issues
>         - Moved exynos_drm_hdmi.c removal to the right place
>         - Added the exynos_drm_connector removal patches on the end
>
> Sean
>
>
> Daniel Kurtz (1):
>   drm/exynos: hdmi: remove the i2c drivers and use devtree
>
> Sean Paul (30):
>   drm/exynos: Merge overlay_ops into manager_ops
>   drm/exynos: Add an initialize function to manager and display
>   drm/exynos: Use manager_op initialize in fimd
>   drm/exynos: hdmi: Implement initialize op for hdmi
>   drm/exynos: Pass exynos_drm_manager in manager ops instead of dev
>   drm/exynos: Remove apply manager callback
>   drm/exynos: Remove dpms link between encoder/connector
>   drm/exynos: Rename display_op power_on to dpms
>   drm/exynos: Don't keep dpms state in encoder
>   drm/exynos: Use unsigned long for possible_crtcs
>   drm/exynos: Split manager/display/subdrv
>   drm/exynos: Remove exynos_drm_hdmi shim
>   drm/exynos: Use drm_mode_copy to copy modes
>   drm/exynos: Disable unused crtc planes from crtc
>   drm/exynos: Add mode_set manager operation
>   drm/exynos: Implement mode_fixup manager operation
>   drm/exynos: Use mode_set to configure fimd
>   drm/exynos: Remove unused/useless fimd_context members
>   drm/exynos: Move dp driver from video/ to drm/
>   drm/exynos: Move display implementation into dp
>   ARM: dts: Move display-timings node from fimd to dp
>   drm/exynos: Implement dpms display callback in DP
>   drm/exynos: Clean up FIMD power on/off routines
>   drm/exynos: Consolidate suspend/resume in drm_drv
>   drm/exynos: Add create_connector callback
>   drm/exynos: Implement drm_connector in hdmi directly
>   drm/exynos: Implement drm_connector directly in dp driver
>   drm/exynos: Implement drm_connector directly in vidi driver
>   drm/exynos: Move lvds bridge discovery into DP driver
>   drm/exynos: Remove the exynos_drm_connector shim
>
> Stéphane Marchesin (1):
>   drm/exynos: Remove useless slab.h include
>
>  .../devicetree/bindings/video/exynos_dp.txt        |   17 +
>  .../devicetree/bindings/video/samsung-fimd.txt     |    2 +
>  arch/arm/boot/dts/exynos5250-arndale.dts           |    7 +-
>  arch/arm/boot/dts/exynos5250-smdk5250.dts          |    7 +-
>  arch/arm/boot/dts/exynos5250-snow.dts              |    7 +-
>  arch/arm/boot/dts/exynos5420-smdk5420.dts          |    7 +-
>  drivers/gpu/drm/exynos/Kconfig                     |    7 +
>  drivers/gpu/drm/exynos/Makefile                    |    7 +-
>  drivers/gpu/drm/exynos/exynos_ddc.c                |   63 -
>  drivers/gpu/drm/exynos/exynos_dp_core.c            | 1399 ++++++++++++++++++++
>  drivers/gpu/drm/exynos/exynos_dp_core.h            |  220 +++
>  drivers/gpu/drm/exynos/exynos_dp_reg.c             | 1245 +++++++++++++++++
>  drivers/gpu/drm/exynos/exynos_dp_reg.h             |  366 +++++
>  drivers/gpu/drm/exynos/exynos_drm_connector.c      |  304 -----
>  drivers/gpu/drm/exynos/exynos_drm_connector.h      |   24 -
>  drivers/gpu/drm/exynos/exynos_drm_core.c           |  233 ++--
>  drivers/gpu/drm/exynos/exynos_drm_crtc.c           |  139 +-
>  drivers/gpu/drm/exynos/exynos_drm_crtc.h           |   20 +-
>  drivers/gpu/drm/exynos/exynos_drm_drv.c            |  155 ++-
>  drivers/gpu/drm/exynos/exynos_drm_drv.h            |  154 ++-
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c        |  357 +----
>  drivers/gpu/drm/exynos/exynos_drm_encoder.h        |   18 +-
>  drivers/gpu/drm/exynos/exynos_drm_fb.c             |    4 +-
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c           |  875 ++++++------
>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c           |  439 ------
>  drivers/gpu/drm/exynos/exynos_drm_hdmi.h           |   67 -
>  drivers/gpu/drm/exynos/exynos_drm_plane.c          |   17 +-
>  drivers/gpu/drm/exynos/exynos_drm_plane.h          |    2 +-
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c           |  434 +++---
>  drivers/gpu/drm/exynos/exynos_hdmi.c               |  360 ++---
>  drivers/gpu/drm/exynos/exynos_hdmi.h               |   23 -
>  drivers/gpu/drm/exynos/exynos_hdmiphy.c            |   65 -
>  drivers/gpu/drm/exynos/exynos_mixer.c              |  280 ++--
>  drivers/gpu/drm/exynos/exynos_mixer.h              |   20 +
>  drivers/video/exynos/Kconfig                       |    7 -
>  drivers/video/exynos/Makefile                      |    1 -
>  drivers/video/exynos/exynos_dp_core.c              | 1214 -----------------
>  drivers/video/exynos/exynos_dp_core.h              |  210 ---
>  drivers/video/exynos/exynos_dp_reg.c               | 1245 -----------------
>  drivers/video/exynos/exynos_dp_reg.h               |  366 -----
>  40 files changed, 4735 insertions(+), 5652 deletions(-)
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_ddc.c
>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c
>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h
>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c
>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.h
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.c
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.h
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.c
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.h
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmi.h
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy.c
>  create mode 100644 drivers/gpu/drm/exynos/exynos_mixer.h
>  delete mode 100644 drivers/video/exynos/exynos_dp_core.c
>  delete mode 100644 drivers/video/exynos/exynos_dp_core.h
>  delete mode 100644 drivers/video/exynos/exynos_dp_reg.c
>  delete mode 100644 drivers/video/exynos/exynos_dp_reg.h
>
> --
> 1.8.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver
  2013-11-07  5:48 ` [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Inki Dae
@ 2013-11-07 18:20   ` Sean Paul
  2013-11-08 21:01   ` Tomasz Figa
  1 sibling, 0 replies; 130+ messages in thread
From: Sean Paul @ 2013-11-07 18:20 UTC (permalink / raw)
  To: Inki Dae, Tomasz Figa; +Cc: Stéphane Marchesin, DRI mailing list

On Thu, Nov 7, 2013 at 12:48 AM, Inki Dae <inki.dae@samsung.com> wrote:
> Hi Sean,
>
> When are you going to post your next version?  Need more time? Other
> DRM drivers have been merged to drm-next except Exynos. So plz hurry
> up if you want to merge this re-factoring patch series during merge
> window.
>

I was waiting on Tomasz's review to post the next version.

Sean



> Thanks,
> Inki Dae
>
>
> 2013/10/30 Sean Paul <seanpaul@chromium.org>:
>> This patchset refactors parts of the exynos driver to move it closer to a proper
>> drm driver (rather than just implementing a drm layer on top of the hardware
>> drivers). The hope is to get to a point where the dp/hdmi drivers can implement
>> drm_connector/drm_encoder directly, and fimd/mixer can directly implement
>> drm_crtc.
>>
>> The notable changes in this set:
>>         - drm_encoder funcs no longer route through the crtc
>>         - DP driver has been moved from video into the drm driver
>>         - fimd no longer implements encoder callbacks
>>         - exynos_drm_hdmi is removed in favor of generic manager/display
>>           handling
>>
>> At a glance, differences between v1 and v2:
>>         - Passing manager/display in callbacks instead of ctx
>>         - Tacked on some dpms patches on the end to handle suspend/resume
>>           through the dpms path
>>
>> At a glance, differences between v2 and v3:
>>         - Fixed vidi issues
>>         - Moved exynos_drm_hdmi.c removal to the right place
>>         - Added the exynos_drm_connector removal patches on the end
>>
>> Sean
>>
>>
>> Daniel Kurtz (1):
>>   drm/exynos: hdmi: remove the i2c drivers and use devtree
>>
>> Sean Paul (30):
>>   drm/exynos: Merge overlay_ops into manager_ops
>>   drm/exynos: Add an initialize function to manager and display
>>   drm/exynos: Use manager_op initialize in fimd
>>   drm/exynos: hdmi: Implement initialize op for hdmi
>>   drm/exynos: Pass exynos_drm_manager in manager ops instead of dev
>>   drm/exynos: Remove apply manager callback
>>   drm/exynos: Remove dpms link between encoder/connector
>>   drm/exynos: Rename display_op power_on to dpms
>>   drm/exynos: Don't keep dpms state in encoder
>>   drm/exynos: Use unsigned long for possible_crtcs
>>   drm/exynos: Split manager/display/subdrv
>>   drm/exynos: Remove exynos_drm_hdmi shim
>>   drm/exynos: Use drm_mode_copy to copy modes
>>   drm/exynos: Disable unused crtc planes from crtc
>>   drm/exynos: Add mode_set manager operation
>>   drm/exynos: Implement mode_fixup manager operation
>>   drm/exynos: Use mode_set to configure fimd
>>   drm/exynos: Remove unused/useless fimd_context members
>>   drm/exynos: Move dp driver from video/ to drm/
>>   drm/exynos: Move display implementation into dp
>>   ARM: dts: Move display-timings node from fimd to dp
>>   drm/exynos: Implement dpms display callback in DP
>>   drm/exynos: Clean up FIMD power on/off routines
>>   drm/exynos: Consolidate suspend/resume in drm_drv
>>   drm/exynos: Add create_connector callback
>>   drm/exynos: Implement drm_connector in hdmi directly
>>   drm/exynos: Implement drm_connector directly in dp driver
>>   drm/exynos: Implement drm_connector directly in vidi driver
>>   drm/exynos: Move lvds bridge discovery into DP driver
>>   drm/exynos: Remove the exynos_drm_connector shim
>>
>> Stéphane Marchesin (1):
>>   drm/exynos: Remove useless slab.h include
>>
>>  .../devicetree/bindings/video/exynos_dp.txt        |   17 +
>>  .../devicetree/bindings/video/samsung-fimd.txt     |    2 +
>>  arch/arm/boot/dts/exynos5250-arndale.dts           |    7 +-
>>  arch/arm/boot/dts/exynos5250-smdk5250.dts          |    7 +-
>>  arch/arm/boot/dts/exynos5250-snow.dts              |    7 +-
>>  arch/arm/boot/dts/exynos5420-smdk5420.dts          |    7 +-
>>  drivers/gpu/drm/exynos/Kconfig                     |    7 +
>>  drivers/gpu/drm/exynos/Makefile                    |    7 +-
>>  drivers/gpu/drm/exynos/exynos_ddc.c                |   63 -
>>  drivers/gpu/drm/exynos/exynos_dp_core.c            | 1399 ++++++++++++++++++++
>>  drivers/gpu/drm/exynos/exynos_dp_core.h            |  220 +++
>>  drivers/gpu/drm/exynos/exynos_dp_reg.c             | 1245 +++++++++++++++++
>>  drivers/gpu/drm/exynos/exynos_dp_reg.h             |  366 +++++
>>  drivers/gpu/drm/exynos/exynos_drm_connector.c      |  304 -----
>>  drivers/gpu/drm/exynos/exynos_drm_connector.h      |   24 -
>>  drivers/gpu/drm/exynos/exynos_drm_core.c           |  233 ++--
>>  drivers/gpu/drm/exynos/exynos_drm_crtc.c           |  139 +-
>>  drivers/gpu/drm/exynos/exynos_drm_crtc.h           |   20 +-
>>  drivers/gpu/drm/exynos/exynos_drm_drv.c            |  155 ++-
>>  drivers/gpu/drm/exynos/exynos_drm_drv.h            |  154 ++-
>>  drivers/gpu/drm/exynos/exynos_drm_encoder.c        |  357 +----
>>  drivers/gpu/drm/exynos/exynos_drm_encoder.h        |   18 +-
>>  drivers/gpu/drm/exynos/exynos_drm_fb.c             |    4 +-
>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c           |  875 ++++++------
>>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c           |  439 ------
>>  drivers/gpu/drm/exynos/exynos_drm_hdmi.h           |   67 -
>>  drivers/gpu/drm/exynos/exynos_drm_plane.c          |   17 +-
>>  drivers/gpu/drm/exynos/exynos_drm_plane.h          |    2 +-
>>  drivers/gpu/drm/exynos/exynos_drm_vidi.c           |  434 +++---
>>  drivers/gpu/drm/exynos/exynos_hdmi.c               |  360 ++---
>>  drivers/gpu/drm/exynos/exynos_hdmi.h               |   23 -
>>  drivers/gpu/drm/exynos/exynos_hdmiphy.c            |   65 -
>>  drivers/gpu/drm/exynos/exynos_mixer.c              |  280 ++--
>>  drivers/gpu/drm/exynos/exynos_mixer.h              |   20 +
>>  drivers/video/exynos/Kconfig                       |    7 -
>>  drivers/video/exynos/Makefile                      |    1 -
>>  drivers/video/exynos/exynos_dp_core.c              | 1214 -----------------
>>  drivers/video/exynos/exynos_dp_core.h              |  210 ---
>>  drivers/video/exynos/exynos_dp_reg.c               | 1245 -----------------
>>  drivers/video/exynos/exynos_dp_reg.h               |  366 -----
>>  40 files changed, 4735 insertions(+), 5652 deletions(-)
>>  delete mode 100644 drivers/gpu/drm/exynos/exynos_ddc.c
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.h
>>  delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.c
>>  delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.h
>>  delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.c
>>  delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.h
>>  delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmi.h
>>  delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy.c
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_mixer.h
>>  delete mode 100644 drivers/video/exynos/exynos_dp_core.c
>>  delete mode 100644 drivers/video/exynos/exynos_dp_core.h
>>  delete mode 100644 drivers/video/exynos/exynos_dp_reg.c
>>  delete mode 100644 drivers/video/exynos/exynos_dp_reg.h
>>
>> --
>> 1.8.4
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver
  2013-11-07  5:48 ` [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Inki Dae
  2013-11-07 18:20   ` Sean Paul
@ 2013-11-08 21:01   ` Tomasz Figa
  2013-11-08 21:22     ` Sean Paul
  1 sibling, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-11-08 21:01 UTC (permalink / raw)
  To: dri-devel; +Cc: Stéphane Marchesin

Hi Inki, Sean,

On Thursday 07 of November 2013 14:48:28 Inki Dae wrote:
> Hi Sean,
> 
> When are you going to post your next version?  Need more time? Other
> DRM drivers have been merged to drm-next except Exynos. So plz hurry
> up if you want to merge this re-factoring patch series during merge
> window.

Sorry for the delay, this was a quite busy week.

Anyway, I don't think we should hurry up with this series, as such big 
code refactor should be kept in linux-next for a while to receive enough 
testing (see recent breaks of OF interrupt parsing as an example of why 
having patches in linux-next is important).

So I would rather target Linux 3.14 with this series.

Best regards,
Tomasz

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

* Re: [PATCH v3 07/32] drm/exynos: Remove apply manager callback
  2013-10-29 16:12 ` [PATCH v3 07/32] drm/exynos: Remove apply manager callback Sean Paul
@ 2013-11-08 21:05   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-08 21:05 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

On Tuesday 29 of October 2013 12:12:53 Sean Paul wrote:
> This patch removes the apply() manager callback in favor of putting the
> relevant commits in the individual drivers. This will mitigate some of
> the difference between the suspend/resume path and the dpms path
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2:
> 	- This was previously in another patch, but moved since it 
warrants its
> own Changes in v3:
> 	- Removed apply() from vidi
> 
>  drivers/gpu/drm/exynos/exynos_drm_drv.h     |  2 --
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c |  6 ------
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c    | 22 +++++-----------------
> drivers/gpu/drm/exynos/exynos_drm_hdmi.c    | 17 -----------------
> drivers/gpu/drm/exynos/exynos_drm_vidi.c    |  1 -
>  drivers/gpu/drm/exynos/exynos_hdmi.c        |  1 +
>  drivers/gpu/drm/exynos/exynos_mixer.c       |  2 ++
>  7 files changed, 8 insertions(+), 43 deletions(-)

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver
  2013-11-08 21:01   ` Tomasz Figa
@ 2013-11-08 21:22     ` Sean Paul
  0 siblings, 0 replies; 130+ messages in thread
From: Sean Paul @ 2013-11-08 21:22 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: Stéphane Marchesin, dri-devel

On Fri, Nov 8, 2013 at 4:01 PM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> Hi Inki, Sean,
>
> On Thursday 07 of November 2013 14:48:28 Inki Dae wrote:
>> Hi Sean,
>>
>> When are you going to post your next version?  Need more time? Other
>> DRM drivers have been merged to drm-next except Exynos. So plz hurry
>> up if you want to merge this re-factoring patch series during merge
>> window.
>
> Sorry for the delay, this was a quite busy week.
>
> Anyway, I don't think we should hurry up with this series, as such big
> code refactor should be kept in linux-next for a while to receive enough
> testing (see recent breaks of OF interrupt parsing as an example of why
> having patches in linux-next is important).
>
> So I would rather target Linux 3.14 with this series.
>

Yeah, that's good with me.

Omitting the DP & bridge patches from the two series means we can't
reliably use mainline on the ARM chromebook anyways, so there's no
value to me in pushing to get this in 3.13.

Sean



> Best regards,
> Tomasz
>

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

* Re: [PATCH v3 08/32] drm/exynos: Remove dpms link between encoder/connector
  2013-10-29 16:12 ` [PATCH v3 08/32] drm/exynos: Remove dpms link between encoder/connector Sean Paul
@ 2013-11-08 21:45   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-08 21:45 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

On Tuesday 29 of October 2013 12:12:54 Sean Paul wrote:
> This patch removes the call from encoder dpms into connector dpms (which
> will then call back into encoder dpms through the helper function). The
> callback is likely to keep connector->dpms in the right state when
> initiating dpms from crtc or encoder, but this isn't the right way to
> do it. This patch is the first step towards rationalizing power
> management in the exynos drm driver.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2:
> 	- Split out the apply change into a new patch
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_connector.c | 42
> ++-------------------- drivers/gpu/drm/exynos/exynos_drm_connector.h | 
> 4 ---
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c   | 50
> +++------------------------ 3 files changed, 8 insertions(+), 88
> deletions(-)

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 09/32] drm/exynos: Rename display_op power_on to dpms
  2013-10-29 16:12 ` [PATCH v3 09/32] drm/exynos: Rename display_op power_on to dpms Sean Paul
@ 2013-11-08 22:09   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-08 22:09 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

On Tuesday 29 of October 2013 12:12:55 Sean Paul wrote:
> This patch renames the display_op power_on to dpms to accurately reflect
> what the function does.
> 
> The side-effect of this patch is that the new hdmi dpms callback is now
> invoked twice in the dpms path. This is safe and will be dealt with when
> the exynos_drm shim goes away.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3:
> 	- Changed vidi to dpms as well
> 
>  drivers/gpu/drm/exynos/exynos_drm_drv.h     | 4 ++--
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c | 4 ++--
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c    | 8 --------
>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c    | 8 ++++----
>  drivers/gpu/drm/exynos/exynos_drm_hdmi.h    | 3 +--
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c    | 8 --------
>  drivers/gpu/drm/exynos/exynos_hdmi.c        | 2 +-
>  7 files changed, 10 insertions(+), 27 deletions(-)

Patch description fails to mention about removing dummy callbacks from 
FIMD and ViDi drivers, but that's just a nitpick, so:

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 13/32] drm/exynos: hdmi: remove the i2c drivers and use devtree
  2013-10-29 16:12 ` [PATCH v3 13/32] drm/exynos: hdmi: remove the i2c drivers and use devtree Sean Paul
@ 2013-11-10 20:46   ` Tomasz Figa
  2013-11-11  8:44     ` Thierry Reding
  0 siblings, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-11-10 20:46 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean, Daniel,

Please see my comments inline.

On Tuesday 29 of October 2013 12:12:59 Sean Paul wrote:
> From: Daniel Kurtz <djkurtz@chromium.org>
> 
> The i2c client was previously being passed into the hdmi driver via a
> dedicated i2c driver, and then a global variable. This patch removes all
> of that and just uses the device tree to get the i2c_client. This patch
> also properly references the client so we don't lose it before we're
> done with it.
> 
> Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2:
> 	- Change include to linux/i2c.h instead of linux/of_i2c.h
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/Makefile         |  1 -
>  drivers/gpu/drm/exynos/exynos_ddc.c     | 63 --------------------------------
>  drivers/gpu/drm/exynos/exynos_hdmi.c    | 59 ++++++++++++++----------------
>  drivers/gpu/drm/exynos/exynos_hdmi.h    | 23 ------------
>  drivers/gpu/drm/exynos/exynos_hdmiphy.c | 65 ---------------------------------
>  5 files changed, 27 insertions(+), 184 deletions(-)
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_ddc.c
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmi.h
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy.c

I hope this patch does not alter the existing Exynos HDMI bindings.
This would have to be reflected in respective documentation otherwise
and of course done in a backwards compatible way.

Well, let's see...

> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
> index d35ab2a..e106309 100644
> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
[snip]
> @@ -1957,21 +1943,30 @@ static int hdmi_probe(struct platform_device *pdev)
>  	}
>  
>  	/* DDC i2c driver */
> -	if (i2c_add_driver(&ddc_driver)) {
> -		DRM_ERROR("failed to register ddc i2c driver\n");
> -		return -ENOENT;
> +	ddc_node = of_find_node_by_name(NULL, "hdmiddc");

This is wrong. You shall not reference a device tree node by its name,
except some very specific well-defined cases, such as cpus or memory
nodes.

A solution closest to yours, but correct, would be to use the same match
table as in the I2C driver you are removing and call
of_find_matching_node().

> +	if (!ddc_node) {
> +		DRM_ERROR("Failed to find ddc node in device tree\n");
> +		return -ENODEV;
> +	}
> +	hdata->ddc_port = of_find_i2c_device_by_node(ddc_node);
> +	if (!hdata->ddc_port) {
> +		DRM_ERROR("Failed to get ddc i2c client by node\n");
> +		return -ENODEV;
>  	}

In general, this looks like a better approach, without using a fake
driver. However you should check how this will play together with runtime
PM of the I2C adapter, as I'm not sure about it.

Both this comment and the comment above apply as well to the hdmiphy
handling.

Best regards,
Tomasz

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

* Re: [PATCH v3 10/32] drm/exynos: Don't keep dpms state in encoder
  2013-10-29 16:12 ` [PATCH v3 10/32] drm/exynos: Don't keep dpms state in encoder Sean Paul
@ 2013-11-10 20:47   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-10 20:47 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

On Tuesday 29 of October 2013 12:12:56 Sean Paul wrote:
> This patch removes the dpms state tracking in encoder. This
> state is at best confusing and at worst incorrect since the display
> drivers can turn on and off without propagating the value.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c | 17 -----------------
>  1 file changed, 17 deletions(-)

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 11/32] drm/exynos: Use unsigned long for possible_crtcs
  2013-10-29 16:12 ` [PATCH v3 11/32] drm/exynos: Use unsigned long for possible_crtcs Sean Paul
@ 2013-11-10 20:47   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-10 20:47 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

On Tuesday 29 of October 2013 12:12:57 Sean Paul wrote:
> Change all instances of possible_crtcs in the exynos drm driver to be
> unsigned long. This matches the type used in the drm layer.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_drv.c     | 2 +-
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c | 2 +-
>  drivers/gpu/drm/exynos/exynos_drm_encoder.h | 2 +-
>  drivers/gpu/drm/exynos/exynos_drm_plane.c   | 2 +-
>  drivers/gpu/drm/exynos/exynos_drm_plane.h   | 2 +-
>  5 files changed, 5 insertions(+), 5 deletions(-)

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-10-29 16:12 ` [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv Sean Paul
  2013-10-31 10:30   ` Inki Dae
@ 2013-11-10 21:09   ` Tomasz Figa
  2013-11-12 17:51     ` Sean Paul
  1 sibling, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-11-10 21:09 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:12:58 Sean Paul wrote:
> This patch splits display and manager from subdrv. The result is that
> crtc functions can directly call into manager callbacks and encoder
> functions can directly call into display callbacks. This will allow
> us to remove the exynos_drm_hdmi shim and support mixer/hdmi & fimd/dp
> with common code.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2:
> 	- Pass display into display_ops instead of context
> Changes in v3:
> 	- Changed vidi args to exynos_drm_display instead of void
> 	- Moved exynos_drm_hdmi.c removal into next patch
> 
>  drivers/gpu/drm/exynos/exynos_drm_connector.c |  50 ++---
>  drivers/gpu/drm/exynos/exynos_drm_core.c      | 181 +++++++++++++-----
>  drivers/gpu/drm/exynos/exynos_drm_crtc.c      | 115 +++++++++---
>  drivers/gpu/drm/exynos/exynos_drm_crtc.h      |  20 +-
>  drivers/gpu/drm/exynos/exynos_drm_drv.c       |  29 +--
>  drivers/gpu/drm/exynos/exynos_drm_drv.h       | 106 +++++++----
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c   | 258 ++++----------------------
>  drivers/gpu/drm/exynos/exynos_drm_encoder.h   |  18 +-
>  drivers/gpu/drm/exynos/exynos_drm_fb.c        |   4 +-
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 161 ++++++++--------
>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c      | 211 +++++++++------------
>  drivers/gpu/drm/exynos/exynos_drm_hdmi.h      |   2 +
>  drivers/gpu/drm/exynos/exynos_drm_plane.c     |  15 +-
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 129 ++++++-------
>  14 files changed, 615 insertions(+), 684 deletions(-)

This patch is really heavy, making it very hard to review. I wonder if it
couldn't really be split into several smaller patches...

Anyway, please see my comments below, for the points I haven't overlooked
due to the complexity of this patch.

> diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
> index 08ca4f9..e76098d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_core.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
> @@ -16,11 +16,14 @@
>  #include <drm/drmP.h>
>  #include <drm/bridge/ptn3460.h>

Huh? Including a specific bridge chip inside a generic Exynos DRM core?
I know this is not a part of this patch, but... this is _broken_.

You may want to support multiple bridge chips in Exynos DRM core and you
may also want to support PTN3460 in other DRM cores. It can't be done this
way.

This series is very nice, but the whole effect is destroyed by basing it
on top of such insanity... Please rebase it on top of something more
reasonable (preferably Inki's next branch directly).

Otherwise, this patch seems reasonable (except its size).

Best regards,
Tomasz

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

* Re: [PATCH v3 14/32] drm/exynos: Remove exynos_drm_hdmi shim
  2013-10-29 16:13 ` [PATCH v3 14/32] drm/exynos: Remove exynos_drm_hdmi shim Sean Paul
@ 2013-11-10 21:24   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-10 21:24 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:00 Sean Paul wrote:
> This patch trims exynos_drm_hdmi out of the driver. The reason it
> existed in the first place was to make up for the mixture of
> display/overlay/manager ops being spread across hdmi and mixer. With
> that code now rationalized, mixer and hdmi map directly to
> exynos_drm_crtc and exynos_drm_encoder, respectively. Since there is a
> 1:1 mapping, we no longer need this layer.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2:
> 	- hdmi/mixer ops now take display/manager instead of context
> Changes in v3:
> 	- Moved removal of exynos_drm_hdmi.c file here
> 
>  drivers/gpu/drm/exynos/Makefile          |   3 +-
>  drivers/gpu/drm/exynos/exynos_drm_drv.c  |  13 -
>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 416 -------------------------------
>  drivers/gpu/drm/exynos/exynos_drm_hdmi.h |  69 -----
>  drivers/gpu/drm/exynos/exynos_hdmi.c     | 162 +++++++-----
>  drivers/gpu/drm/exynos/exynos_mixer.c    | 204 ++++++++-------
>  drivers/gpu/drm/exynos/exynos_mixer.h    |  20 ++
>  7 files changed, 222 insertions(+), 665 deletions(-)
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.c
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.h
>  create mode 100644 drivers/gpu/drm/exynos/exynos_mixer.h
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
> index e106309..9e12fb7 100644
> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
[snip]
> +static struct exynos_drm_display hdmi_display = {
> +	.type = EXYNOS_DISPLAY_TYPE_HDMI,
> +	.ops = &hdmi_display_ops,
> +};
> +
>  static irqreturn_t hdmi_irq_thread(int irq, void *arg)
>  {
> -	struct exynos_drm_hdmi_context *ctx = arg;
> -	struct hdmi_context *hdata = ctx->ctx;
> +	struct hdmi_context *hdata = arg;
>  
>  	mutex_lock(&hdata->hdmi_mutex);
>  	hdata->hpd = gpio_get_value(hdata->hpd_gpio);
> @@ -1887,7 +1944,6 @@ static struct of_device_id hdmi_match_types[] = {
>  static int hdmi_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> -	struct exynos_drm_hdmi_context *drm_hdmi_ctx;
>  	struct hdmi_context *hdata;
>  	struct s5p_hdmi_platform_data *pdata;
>  	struct resource *res;
> @@ -1902,20 +1958,13 @@ static int hdmi_probe(struct platform_device *pdev)
>  	if (!pdata)
>  		return -EINVAL;
>  
> -	drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx), GFP_KERNEL);
> -	if (!drm_hdmi_ctx)
> -		return -ENOMEM;
> -
>  	hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
>  	if (!hdata)
>  		return -ENOMEM;
>  
>  	mutex_init(&hdata->hdmi_mutex);
>  
> -	drm_hdmi_ctx->ctx = (void *)hdata;
> -	hdata->parent_ctx = (void *)drm_hdmi_ctx;
> -
> -	platform_set_drvdata(pdev, drm_hdmi_ctx);
> +	platform_set_drvdata(pdev, &hdmi_display);

This looks like a step backwards. Originally the driver had kind of per
instance data, while now it has a single global struct, making it harder
to properly support multiple HDMI instances, what is not unlikely to show
up in future SoCs.

So instead, I would embed an exynos_drm_display struct inside struct
hdmi_context and initialize it at runtime and use it to get access to
hdata, using container_of.

> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
> index 60935c4..39aed3e 100644
> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
[snip]
> @@ -1184,21 +1190,17 @@ static struct of_device_id mixer_match_types[] = {
>  static int mixer_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> -	struct exynos_drm_hdmi_context *drm_hdmi_ctx;
>  	struct mixer_context *ctx;
>  	struct mixer_drv_data *drv;
>  	int ret;
>  
>  	dev_info(dev, "probe start\n");
>  
> -	drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx),
> -								GFP_KERNEL);
> -	if (!drm_hdmi_ctx)
> -		return -ENOMEM;
> -
> -	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
> -	if (!ctx)
> +	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
> +	if (!ctx) {
> +		DRM_ERROR("failed to alloc mixer context.\n");
>  		return -ENOMEM;
> +	}
>  
>  	mutex_init(&ctx->mixer_mutex);
>  
> @@ -1211,18 +1213,14 @@ static int mixer_probe(struct platform_device *pdev)
>  			platform_get_device_id(pdev)->driver_data;
>  	}
>  
> -	ctx->dev = dev;
> -	ctx->parent_ctx = (void *)drm_hdmi_ctx;
> -	drm_hdmi_ctx->ctx = (void *)ctx;
> +	ctx->dev = &pdev->dev;
>  	ctx->vp_enabled = drv->is_vp_enabled;
>  	ctx->mxr_ver = drv->version;
>  	DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
>  	atomic_set(&ctx->wait_vsync_event, 0);
>  
> -	platform_set_drvdata(pdev, drm_hdmi_ctx);
> -
>  	/* acquire resources: regs, irqs, clocks */
> -	ret = mixer_resources_init(drm_hdmi_ctx, pdev);
> +	ret = mixer_resources_init(ctx, pdev);
>  	if (ret) {
>  		DRM_ERROR("mixer_resources_init failed\n");
>  		goto fail;
> @@ -1230,18 +1228,16 @@ static int mixer_probe(struct platform_device *pdev)
>  
>  	if (ctx->vp_enabled) {
>  		/* acquire vp resources: regs, irqs, clocks */
> -		ret = vp_resources_init(drm_hdmi_ctx, pdev);
> +		ret = vp_resources_init(ctx, pdev);
>  		if (ret) {
>  			DRM_ERROR("vp_resources_init failed\n");
>  			goto fail;
>  		}
>  	}
>  
> -	/* attach mixer driver to common hdmi. */
> -	exynos_mixer_drv_attach(drm_hdmi_ctx);
> -
> -	/* register specific callback point to common hdmi. */
> -	exynos_mixer_ops_register(&mixer_ops);
> +	mixer_manager.ctx = ctx;
> +	platform_set_drvdata(pdev, &mixer_manager);
> +	exynos_drm_manager_register(&mixer_manager);

Ditto.

Best regards,
Tomasz

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

* Re: [PATCH v3 15/32] drm/exynos: Use drm_mode_copy to copy modes
  2013-10-29 16:13 ` [PATCH v3 15/32] drm/exynos: Use drm_mode_copy to copy modes Sean Paul
@ 2013-11-10 21:27   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-10 21:27 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:01 Sean Paul wrote:
> This patch changes the manual copying of mode to adjusted_mode in
> mode_fixup to use drm_mode_copy instead of handling things manually.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_hdmi.c | 10 +---------
>  1 file changed, 1 insertion(+), 9 deletions(-)

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 16/32] drm/exynos: Disable unused crtc planes from crtc
  2013-10-29 16:13 ` [PATCH v3 16/32] drm/exynos: Disable unused crtc planes from crtc Sean Paul
@ 2013-11-10 21:29   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-10 21:29 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

On Tuesday 29 of October 2013 12:13:02 Sean Paul wrote:
> This patch moves the code which disables unused crtc planes from the
> encoder to the crtc. Since there is a 1:1 encoder/crtc mapping in
> exynos, the only valid crtc change the pre-existing code could catch is
> disconnecting an active crtc from the encoder. Thus it is functionally
> equivalent to just disable all planes attached to a crtc when the crtc
> is disabled.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_crtc.c    | 13 +++++-
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c | 65 ++---------------------------
>  2 files changed, 15 insertions(+), 63 deletions(-)

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 17/32] drm/exynos: Add mode_set manager operation
  2013-10-29 16:13 ` [PATCH v3 17/32] drm/exynos: Add mode_set manager operation Sean Paul
@ 2013-11-10 21:31   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-10 21:31 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:03 Sean Paul wrote:
> This patch adds a mode_set callback to the manager operations which
> sets the crtc's current mode to the manager driver.

To allow/fix/improve/extend...

Patch description should say why such change is good to have.

> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 ++++
>  drivers/gpu/drm/exynos/exynos_drm_drv.h  | 3 +++
>  2 files changed, 7 insertions(+)

Otherwise the patch looks fine.

Best regards,
Tomasz

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

* Re: [PATCH v3 18/32] drm/exynos: Implement mode_fixup manager operation
  2013-10-29 16:13 ` [PATCH v3 18/32] drm/exynos: Implement mode_fixup " Sean Paul
@ 2013-11-10 21:33   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-10 21:33 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

On Tuesday 29 of October 2013 12:13:04 Sean Paul wrote:
> This patch adds a new manager callback for mode_fixup and pipes it
> through exynos_drm_crtc.

Patch description lacking explanation what this change is for.

> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_crtc.c | 7 ++++++-
>  drivers/gpu/drm/exynos/exynos_drm_drv.h  | 4 ++++
>  2 files changed, 10 insertions(+), 1 deletion(-)

Otherwise the code looks fine.

Best regards,
Tomasz

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

* Re: [PATCH v3 19/32] drm/exynos: Use mode_set to configure fimd
  2013-10-29 16:13 ` [PATCH v3 19/32] drm/exynos: Use mode_set to configure fimd Sean Paul
@ 2013-11-10 22:03   ` Tomasz Figa
  2013-11-15 13:49     ` Daniel Kurtz
  2013-11-15 13:53     ` Daniel Kurtz
  0 siblings, 2 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-10 22:03 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:05 Sean Paul wrote:
> This patch uses the mode passed into mode_set to configure fimd instead
> of directly using the panel from context. This will allow us to move
> the exynos_drm_display implementation from fimd into the DP driver
> where it belongs.

Remember that DP is not the only possible way to connect a display driven
by FIMD. You also have the direct (RGB and i80) and DSI interfaces.

Also, please see my comments inline.

> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 159 ++++++++++++++++++-------------
>  1 file changed, 91 insertions(+), 68 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> index d2b8ccb..f69d6e5 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> @@ -104,6 +104,20 @@ struct fimd_win_data {
>  	bool			resume;
>  };
>  
> +struct fimd_mode_data {
> +	unsigned		vtotal;

For consistency with rest of the code, unsigned int would prefered.

However, I'm not sure what is this struct for, since it does not store
neither raw register values (1 needs to be subtracted from them) nor
any values hard to compute at commit time (maybe except clkdiv, but still
how often commit would be called?).

> +	unsigned		vdisplay;
> +	unsigned		vsync_len;
> +	unsigned		vbpd;
> +	unsigned		vfpd;
> +	unsigned		htotal;
> +	unsigned		hdisplay;
> +	unsigned		hsync_len;
> +	unsigned		hbpd;
> +	unsigned		hfpd;
> +	u32			clkdiv;
> +};
> +
>  struct fimd_context {
>  	struct device			*dev;
>  	struct drm_device		*drm_dev;
> @@ -112,8 +126,8 @@ struct fimd_context {
>  	struct clk			*bus_clk;
>  	struct clk			*lcd_clk;
>  	void __iomem			*regs;
> +	struct fimd_mode_data		mode;
>  	struct fimd_win_data		win_data[WINDOWS_NR];
> -	unsigned int			clkdiv;
>  	unsigned int			default_win;
>  	unsigned long			irq_flags;
>  	u32				vidcon0;
> @@ -560,11 +574,56 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
>  	mutex_unlock(&ctx->lock);
>  }
>  
> +static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
> +		const struct drm_display_mode *mode)
> +{
> +	unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
> +	u32 clkdiv;
> +
> +	/* Find the clock divider value that gets us closest to ideal_clk */
> +	clkdiv = DIV_ROUND_CLOSEST(clk_get_rate(ctx->lcd_clk), ideal_clk);

This is a functional change unrelated to $subject. Before this patch,
DIV_ROUND_UP() had been used.

> +
> +	return (clkdiv < 0x100) ? clkdiv : 0xff;
> +}
> +
> +static bool fimd_mode_fixup(struct exynos_drm_manager *mgr,
> +		const struct drm_display_mode *mode,
> +		struct drm_display_mode *adjusted_mode)
> +{
> +	if (adjusted_mode->vrefresh == 0)
> +		adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE;
> +
> +	return true;
> +}
> +
> +static void fimd_mode_set(struct exynos_drm_manager *mgr,
> +		const struct drm_display_mode *in_mode)
> +{
> +	struct fimd_context *ctx = mgr->ctx;
> +	struct fimd_mode_data *mode = &ctx->mode;
> +	int hblank, vblank;
> +
> +	vblank = in_mode->crtc_vblank_end - in_mode->crtc_vblank_start;
> +	mode->vtotal = in_mode->crtc_vtotal;
> +	mode->vdisplay = in_mode->crtc_vdisplay;
> +	mode->vsync_len = in_mode->crtc_vsync_end - in_mode->crtc_vsync_start;
> +	mode->vbpd = (vblank - mode->vsync_len) / 2;
> +	mode->vfpd = vblank - mode->vsync_len - mode->vbpd;
> +
> +	hblank = in_mode->crtc_hblank_end - in_mode->crtc_hblank_start;
> +	mode->htotal = in_mode->crtc_htotal;
> +	mode->hdisplay = in_mode->crtc_hdisplay;
> +	mode->hsync_len = in_mode->crtc_hsync_end - in_mode->crtc_hsync_start;
> +	mode->hbpd = (hblank - mode->hsync_len) / 2;
> +	mode->hfpd = hblank - mode->hsync_len - mode->hbpd;
> +
> +	mode->clkdiv = fimd_calc_clkdiv(ctx, in_mode);

What about simply copying contents of in_mode to driver context
and then calculating clkdiv at commit time? You could get rid
of the fimd_mode_data struct and most of this function.

Otherwise, the patch looks fine.

Best regards,
Tomasz

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

* Re: [PATCH v3 20/32] drm/exynos: Remove unused/useless fimd_context members
  2013-10-29 16:13 ` [PATCH v3 20/32] drm/exynos: Remove unused/useless fimd_context members Sean Paul
@ 2013-11-11  1:19   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-11  1:19 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:06 Sean Paul wrote:
> This patch removes a few fimd_context members which are either entirely
> unused or unneeded.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 13 +------------
>  1 file changed, 1 insertion(+), 12 deletions(-)

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 22/32] drm/exynos: Move display implementation into dp
       [not found]   ` <1383063198-10526-23-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2013-11-11  1:53     ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-11  1:53 UTC (permalink / raw)
  To: Sean Paul
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	inki.dae-Sze3O3UU22JBDgjK7y7TUQ, airlied-cv59FeDIM0c,
	marcheu-F7+t8E8rja9g9hUCZPvPmw,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Rutland, Stephen Warren,
	Kumar Gala

Hi Sean,

[CCing devicetree ML and some DT maintainers]

On Tuesday 29 of October 2013 12:13:08 Sean Paul wrote:
> This patch moves the exynos_drm_display implementation from fimd into
> the dp driver. This will allow for tighter integration of the dp driver
> into the exynos drm driver.
> 
> Signed-off-by: Sean Paul <seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> ---
> 
> Changes in v2: None
> Changes in v3: None
> 
>  .../devicetree/bindings/video/exynos_dp.txt        |  17 +++
>  .../devicetree/bindings/video/samsung-fimd.txt     |   2 +
>  drivers/gpu/drm/exynos/exynos_dp_core.c            | 137 ++++++++++++++++-----
>  drivers/gpu/drm/exynos/exynos_dp_core.h            |   5 +
>  drivers/gpu/drm/exynos/exynos_drm_drv.c            |  14 +++
>  drivers/gpu/drm/exynos/exynos_drm_drv.h            |   1 +
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c           |  78 +++---------
>  7 files changed, 156 insertions(+), 98 deletions(-)

Technically the changes in code look fine, but how does it play with
panels connected directly to FIMD (using RGB or i80 interface)?

> diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt
> index 84f10c1..a073e15 100644
> --- a/Documentation/devicetree/bindings/video/exynos_dp.txt
> +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt
> @@ -45,6 +45,8 @@ Required properties for dp-controller:
>  	-samsung,lane-count:
>  		number of lanes supported by the panel.
>  			LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
> +	- display-timings: timings for the connected panel as described by
> +		Documentation/devicetree/bindings/video/display-timing.txt

I'm afraid this is breaking compatibility with existing device trees.
Unless we can guarantee that there are no existing devices shipped using
the old binding, we should keep compatibility with it.

Also, since this patch is changing a binding, it must go through the
devicetree ML (now on CC) and be reviewed and acked by at least one of DT
maintainers.

Of course this new binding makes more sense, but that's another story.

>  
>  Optional properties for dp-controller:
>  	-interlaced:
> @@ -83,4 +85,19 @@ Board Specific portion:
>  		samsung,color-depth = <1>;
>  		samsung,link-rate = <0x0a>;
>  		samsung,lane-count = <4>;
> +
> +		display-timings {
> +			native-mode = <&lcd_timing>;
> +			lcd_timing: 1366x768 {
> +				clock-frequency = <70589280>;
> +				hactive = <1366>;
> +				vactive = <768>;
> +				hfront-porch = <40>;
> +				hback-porch = <40>;
> +				hsync-len = <32>;
> +				vback-porch = <10>;
> +				vfront-porch = <12>;
> +				vsync-len = <6>;
> +			};
> +		};
>  	};
> diff --git a/Documentation/devicetree/bindings/video/samsung-fimd.txt b/Documentation/devicetree/bindings/video/samsung-fimd.txt
> index 778838a..fa465c3 100644
> --- a/Documentation/devicetree/bindings/video/samsung-fimd.txt
> +++ b/Documentation/devicetree/bindings/video/samsung-fimd.txt
> @@ -39,6 +39,8 @@ Required properties:
>  
>  Optional Properties:
>  - samsung,power-domain: a phandle to FIMD power domain node.
> +- samsung,invert-vden: video enable signal is inverted
> +- samsung,invert_vclk: video clock signal is inverted

s/_/-/ in property names

>  
>  Example:
>  
> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
> index 089ae22..13ea8b7 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp_core.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
[snip]
> @@ -1142,45 +1241,17 @@ static int exynos_dp_remove(struct platform_device *pdev)
>  #ifdef CONFIG_PM_SLEEP
>  static int exynos_dp_suspend(struct device *dev)
>  {
> -	struct exynos_dp_platdata *pdata = dev->platform_data;
>  	struct exynos_dp_device *dp = dev_get_drvdata(dev);
>  
> -	disable_irq(dp->irq);
> -
> -	flush_work(&dp->hotplug_work);
> -
> -	if (dev->of_node) {
> -		if (dp->phy_addr)
> -			exynos_dp_phy_exit(dp);
> -	} else {
> -		if (pdata->phy_exit)
> -			pdata->phy_exit();
> -	}
> -
> -	clk_disable_unprepare(dp->clock);
> -
> +	exynos_dp_poweroff(dp);

This change (moving this code to separate function) could be done in
a separate patch.

>  	return 0;
>  }
>  
>  static int exynos_dp_resume(struct device *dev)
>  {
> -	struct exynos_dp_platdata *pdata = dev->platform_data;
>  	struct exynos_dp_device *dp = dev_get_drvdata(dev);
>  
> -	if (dev->of_node) {
> -		if (dp->phy_addr)
> -			exynos_dp_phy_init(dp);
> -	} else {
> -		if (pdata->phy_init)
> -			pdata->phy_init();
> -	}
> -
> -	clk_prepare_enable(dp->clock);
> -
> -	exynos_dp_init_dp(dp);
> -
> -	enable_irq(dp->irq);
> -
> +	exynos_dp_poweron(dp);

Along with this one.

>  	return 0;
>  }
>  #endif
[snip]
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> index 61124ca..c6a05f6 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
[snip]
>  static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
>  			struct exynos_drm_overlay *overlay)
>  {
> @@ -611,6 +578,16 @@ static void fimd_mode_set(struct exynos_drm_manager *mgr,
>  	mode->hfpd = hblank - mode->hsync_len - mode->hbpd;
>  
>  	mode->clkdiv = fimd_calc_clkdiv(ctx, in_mode);
> +
> +	if (in_mode->flags & DRM_MODE_FLAG_NVSYNC)
> +		ctx->vidcon1 |= VIDCON1_INV_VSYNC;
> +	else
> +		ctx->vidcon1 &= ~VIDCON1_INV_VSYNC;
> +
> +	if (in_mode->flags & DRM_MODE_FLAG_NHSYNC)
> +		ctx->vidcon1 |= VIDCON1_INV_HSYNC;
> +	else
> +		ctx->vidcon1 &= ~VIDCON1_INV_HSYNC;
>  }
>  
>  static void fimd_commit(struct exynos_drm_manager *mgr)
> @@ -888,30 +865,6 @@ static int fimd_activate(struct exynos_drm_manager *mgr, bool enable)
>  	return 0;
>  }
>  
> -static int fimd_get_platform_data(struct fimd_context *ctx, struct device *dev)
> -{
> -	struct videomode *vm;
> -	int ret;
> -
> -	vm = &ctx->panel.vm;
> -	ret = of_get_videomode(dev->of_node, vm, OF_USE_NATIVE_MODE);
> -	if (ret) {
> -		DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
> -		return ret;
> -	}
> -
> -	if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW)
> -		ctx->vidcon1 |= VIDCON1_INV_VSYNC;
> -	if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW)
> -		ctx->vidcon1 |= VIDCON1_INV_HSYNC;
> -	if (vm->flags & DISPLAY_FLAGS_DE_LOW)
> -		ctx->vidcon1 |= VIDCON1_INV_VDEN;
> -	if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
> -		ctx->vidcon1 |= VIDCON1_INV_VCLK;
> -
> -	return 0;
> -}
> -
>  static int fimd_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -929,9 +882,10 @@ static int fimd_probe(struct platform_device *pdev)
>  
>  	ctx->dev = dev;
>  
> -	ret = fimd_get_platform_data(ctx, dev);
> -	if (ret)
> -		return ret;
> +	if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
> +		ctx->vidcon1 |= VIDCON1_INV_VDEN;
> +	if (of_property_read_bool(dev->of_node, "samsung,invert-vclk"))
> +		ctx->vidcon1 |= VIDCON1_INV_VCLK;

This is a step backwards. Why add separate properties, when this can be
retrieved from the display timings node?

Anyway, you can't just break compatibility with the old way, since there
might be devices shipped with DTB using it and they must be able to work
on newer kernels.

Best regards,
Tomasz

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

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

* Re: [PATCH v3 24/32] drm/exynos: Implement dpms display callback in DP
  2013-10-29 16:13 ` [PATCH v3 24/32] drm/exynos: Implement dpms display callback in DP Sean Paul
@ 2013-11-11  2:04   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-11  2:04 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:10 Sean Paul wrote:
> This patch implements the dpms display callback for the DP driver.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2:
> 	- Added to the patchset
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_dp_core.c | 173 ++++++++++++++++----------------
>  drivers/gpu/drm/exynos/exynos_dp_core.h |   1 +
>  2 files changed, 85 insertions(+), 89 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
> index 13ea8b7..476d3b0 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp_core.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
[snip]
> @@ -1190,26 +1205,17 @@ static int exynos_dp_probe(struct platform_device *pdev)
>  
>  	dp->video_info = pdata->video_info;
>  
> -	if (pdev->dev.of_node) {
> -		if (dp->phy_addr)
> -			exynos_dp_phy_init(dp);
> -	} else {
> -		if (pdata->phy_init)
> -			pdata->phy_init();
> -	}
> -
> -	exynos_dp_init_dp(dp);
> -
>  	ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
>  				"exynos-dp", dp);
>  	if (ret) {
>  		dev_err(&pdev->dev, "failed to request irq\n");
>  		return ret;
>  	}
> -
> -	platform_set_drvdata(pdev, dp);
> +	disable_irq(dp->irq);
>  
>  	exynos_dp_display.ctx = dp;
> +
> +	platform_set_drvdata(pdev, &exynos_dp_display);

This is probably more a comment to previous patch, but what about multiple
instances of display port controller? The solution would be something
I proposed in my reply to one of HDMI related patches.

Otherwise the patch looks fine.

Best regards,
Tomasz

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

* Re: [PATCH v3 25/32] drm/exynos: Clean up FIMD power on/off routines
  2013-10-29 16:13 ` [PATCH v3 25/32] drm/exynos: Clean up FIMD power on/off routines Sean Paul
  2013-10-31 10:54   ` Inki Dae
@ 2013-11-11  2:09   ` Tomasz Figa
  1 sibling, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-11  2:09 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:11 Sean Paul wrote:
> This patch separates the fimd_activate function into poweron/poweroff
> functions to be more consistent with the other drivers in exynos drm. It
> also properly cleans up after failures in poweron. The functions have
> also been shuffled around such that they are all in the same
> spot in the file and poweron/poweroff can be called from the dpms function.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2:
> 	- Added to the patchset
> Changes in v3: None
> 
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 247 +++++++++++++++++--------------
>  1 file changed, 135 insertions(+), 112 deletions(-)

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 27/32] drm/exynos: Add create_connector callback
  2013-10-29 16:13 ` [PATCH v3 27/32] drm/exynos: Add create_connector callback Sean Paul
@ 2013-11-11  2:19   ` Tomasz Figa
  2013-12-03  5:01   ` Inki Dae
  1 sibling, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-11  2:19 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

On Tuesday 29 of October 2013 12:13:13 Sean Paul wrote:
> This creates a new display hook called create_connector. The purpose is
> to allow the display driver to create its own drm_connector instead of
> using the exynos_drm_connector. This moves things closer to completely
> removing the exynos_drm_connector abstraction.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2: None
> Changes in v3:
> 	- Added to the patchset
> 
>  drivers/gpu/drm/exynos/exynos_drm_core.c | 3 +++
>  drivers/gpu/drm/exynos/exynos_drm_drv.h  | 2 ++
>  2 files changed, 5 insertions(+)

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* RE: [PATCH v3 25/32] drm/exynos: Clean up FIMD power on/off routines
       [not found]     ` <1630995.NnKzZB9Rl5@flatron>
@ 2013-11-11  4:08       ` Inki Dae
  0 siblings, 0 replies; 130+ messages in thread
From: Inki Dae @ 2013-11-11  4:08 UTC (permalink / raw)
  To: 'Tomasz Figa'; +Cc: marcheu, dri-devel



> -----Original Message-----
> From: Tomasz Figa [mailto:tomasz.figa@gmail.com]
> Sent: Monday, November 11, 2013 11:09 AM
> To: Inki Dae
> Cc: 'Sean Paul'; dri-devel@lists.freedesktop.org; airlied@linux.ie;
> marcheu@chromium.org
> Subject: Re: [PATCH v3 25/32] drm/exynos: Clean up FIMD power on/off
> routines
> 
> On Thursday 31 of October 2013 19:54:18 Inki Dae wrote:
> >
> > As I mentioned already, I'll not merge eDP related codes yet. So can you
> > rebase patche 25 through 26 to top of patch 20?
> 
> Why not? IMHO Exynos DRM is already the only way to support Exynos DP
> and it should simplify things. Of course, only if done properly and not
> breaking other things.
> 

Your late comment. I wanted to merge only the re-factoring patch series
because Sean missed CCing proper person and I was not sure that moving eDP
driver into Exynos drm is good way or not _for the moment_. So I just wanted
to have time enough about merging this patch and watch out how other
maintainers will handle the similar thing. However, s3c-fb driver wouldn't
be used anymore and Jingoo commented enough - for this, see the original
email thread - so the moving is reasonable to me.

Thanks,
Inki Dae

> Best regards,
> Tomasz

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

* Re: [PATCH v3 13/32] drm/exynos: hdmi: remove the i2c drivers and use devtree
  2013-11-10 20:46   ` Tomasz Figa
@ 2013-11-11  8:44     ` Thierry Reding
  2013-11-28 13:30       ` Tomasz Figa
  0 siblings, 1 reply; 130+ messages in thread
From: Thierry Reding @ 2013-11-11  8:44 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: marcheu, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1135 bytes --]

On Sun, Nov 10, 2013 at 09:46:02PM +0100, Tomasz Figa wrote:
[...]
> On Tuesday 29 of October 2013 12:12:59 Sean Paul wrote:
[...]
> [snip]
> > @@ -1957,21 +1943,30 @@ static int hdmi_probe(struct platform_device *pdev)
> >  	}
> >  
> >  	/* DDC i2c driver */
> > -	if (i2c_add_driver(&ddc_driver)) {
> > -		DRM_ERROR("failed to register ddc i2c driver\n");
> > -		return -ENOENT;
> > +	ddc_node = of_find_node_by_name(NULL, "hdmiddc");
> 
> This is wrong. You shall not reference a device tree node by its name,
> except some very specific well-defined cases, such as cpus or memory
> nodes.
> 
> A solution closest to yours, but correct, would be to use the same match
> table as in the I2C driver you are removing and call
> of_find_matching_node().

Isn't the correct solution to use a phandle? That might need the binding
to change in a backwards incompatible way. Then again, if something as
simple as specifying a DDC I2C bus causes the binding to change in a
backwards incompatible way then it can't have been a very good binding
in the first place, right? +1 for unstable DT bindings...

Thierry

[-- Attachment #1.2: Type: application/pgp-signature, Size: 836 bytes --]

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

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

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-10 21:09   ` Tomasz Figa
@ 2013-11-12 17:51     ` Sean Paul
  2013-11-12 18:35       ` Tomasz Figa
  0 siblings, 1 reply; 130+ messages in thread
From: Sean Paul @ 2013-11-12 17:51 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: dri-devel, Stéphane Marchesin

On Sun, Nov 10, 2013 at 4:09 PM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> Hi Sean,
>
> On Tuesday 29 of October 2013 12:12:58 Sean Paul wrote:
>> This patch splits display and manager from subdrv. The result is that
>> crtc functions can directly call into manager callbacks and encoder
>> functions can directly call into display callbacks. This will allow
>> us to remove the exynos_drm_hdmi shim and support mixer/hdmi & fimd/dp
>> with common code.
>>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>
>> Changes in v2:
>>       - Pass display into display_ops instead of context
>> Changes in v3:
>>       - Changed vidi args to exynos_drm_display instead of void
>>       - Moved exynos_drm_hdmi.c removal into next patch
>>
>>  drivers/gpu/drm/exynos/exynos_drm_connector.c |  50 ++---
>>  drivers/gpu/drm/exynos/exynos_drm_core.c      | 181 +++++++++++++-----
>>  drivers/gpu/drm/exynos/exynos_drm_crtc.c      | 115 +++++++++---
>>  drivers/gpu/drm/exynos/exynos_drm_crtc.h      |  20 +-
>>  drivers/gpu/drm/exynos/exynos_drm_drv.c       |  29 +--
>>  drivers/gpu/drm/exynos/exynos_drm_drv.h       | 106 +++++++----
>>  drivers/gpu/drm/exynos/exynos_drm_encoder.c   | 258 ++++----------------------
>>  drivers/gpu/drm/exynos/exynos_drm_encoder.h   |  18 +-
>>  drivers/gpu/drm/exynos/exynos_drm_fb.c        |   4 +-
>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 161 ++++++++--------
>>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c      | 211 +++++++++------------
>>  drivers/gpu/drm/exynos/exynos_drm_hdmi.h      |   2 +
>>  drivers/gpu/drm/exynos/exynos_drm_plane.c     |  15 +-
>>  drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 129 ++++++-------
>>  14 files changed, 615 insertions(+), 684 deletions(-)
>
> This patch is really heavy, making it very hard to review. I wonder if it
> couldn't really be split into several smaller patches...
>

I've distilled it down as much as possible. Unfortunately the
encoder/crtc were fused pretty tightly and the effects of that are
far-reaching.

> Anyway, please see my comments below, for the points I haven't overlooked
> due to the complexity of this patch.
>
>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
>> index 08ca4f9..e76098d 100644
>> --- a/drivers/gpu/drm/exynos/exynos_drm_core.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
>> @@ -16,11 +16,14 @@
>>  #include <drm/drmP.h>
>>  #include <drm/bridge/ptn3460.h>
>
> Huh? Including a specific bridge chip inside a generic Exynos DRM core?
> I know this is not a part of this patch, but... this is _broken_.
>
> You may want to support multiple bridge chips in Exynos DRM core and you
> may also want to support PTN3460 in other DRM cores. It can't be done this
> way.
>
> This series is very nice, but the whole effect is destroyed by basing it
> on top of such insanity... Please rebase it on top of something more
> reasonable (preferably Inki's next branch directly).
>

Well, that was blunt. Unfortunately, I don't know how else to do this
other than this broken, unreasonable and insane way.

This has already been discussed at length in a few other places.
Without some help from the drm layer, I don't see any other way to do
this than to enumerate the possible bridges in each drm driver.

I based the current set off the "Add some missing bits for
exynos5250-snow" series I sent up a little while ago. This set was
sent to the relevant dt people, acked by Olof, and there are no
outstanding review comments. Since it's required for me to test on
Real Hardware, I assumed this was an appropriate base.

If you think this is _broken_, unreasonable, and insane, I'd love to
hear an alternative.

Sean



> Otherwise, this patch seems reasonable (except its size).
>
> Best regards,
> Tomasz
>

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-12 17:51     ` Sean Paul
@ 2013-11-12 18:35       ` Tomasz Figa
  2013-11-26 18:00         ` Olof Johansson
  0 siblings, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-11-12 18:35 UTC (permalink / raw)
  To: Sean Paul; +Cc: Laurent Pinchart, dri-devel, Stéphane Marchesin

On Tuesday 12 of November 2013 12:51:11 Sean Paul wrote:
> On Sun, Nov 10, 2013 at 4:09 PM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> > Hi Sean,
> >
> > On Tuesday 29 of October 2013 12:12:58 Sean Paul wrote:
> >> This patch splits display and manager from subdrv. The result is that
> >> crtc functions can directly call into manager callbacks and encoder
> >> functions can directly call into display callbacks. This will allow
> >> us to remove the exynos_drm_hdmi shim and support mixer/hdmi & fimd/dp
> >> with common code.
> >>
> >> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> >> ---
> >>
> >> Changes in v2:
> >>       - Pass display into display_ops instead of context
> >> Changes in v3:
> >>       - Changed vidi args to exynos_drm_display instead of void
> >>       - Moved exynos_drm_hdmi.c removal into next patch
> >>
> >>  drivers/gpu/drm/exynos/exynos_drm_connector.c |  50 ++---
> >>  drivers/gpu/drm/exynos/exynos_drm_core.c      | 181 +++++++++++++-----
> >>  drivers/gpu/drm/exynos/exynos_drm_crtc.c      | 115 +++++++++---
> >>  drivers/gpu/drm/exynos/exynos_drm_crtc.h      |  20 +-
> >>  drivers/gpu/drm/exynos/exynos_drm_drv.c       |  29 +--
> >>  drivers/gpu/drm/exynos/exynos_drm_drv.h       | 106 +++++++----
> >>  drivers/gpu/drm/exynos/exynos_drm_encoder.c   | 258 ++++----------------------
> >>  drivers/gpu/drm/exynos/exynos_drm_encoder.h   |  18 +-
> >>  drivers/gpu/drm/exynos/exynos_drm_fb.c        |   4 +-
> >>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 161 ++++++++--------
> >>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c      | 211 +++++++++------------
> >>  drivers/gpu/drm/exynos/exynos_drm_hdmi.h      |   2 +
> >>  drivers/gpu/drm/exynos/exynos_drm_plane.c     |  15 +-
> >>  drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 129 ++++++-------
> >>  14 files changed, 615 insertions(+), 684 deletions(-)
> >
> > This patch is really heavy, making it very hard to review. I wonder if it
> > couldn't really be split into several smaller patches...
> >
> 
> I've distilled it down as much as possible. Unfortunately the
> encoder/crtc were fused pretty tightly and the effects of that are
> far-reaching.

I was afraid of this. Well, I guess nothing can be done about it then.

> 
> > Anyway, please see my comments below, for the points I haven't overlooked
> > due to the complexity of this patch.
> >
> >> diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
> >> index 08ca4f9..e76098d 100644
> >> --- a/drivers/gpu/drm/exynos/exynos_drm_core.c
> >> +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
> >> @@ -16,11 +16,14 @@
> >>  #include <drm/drmP.h>
> >>  #include <drm/bridge/ptn3460.h>
> >
> > Huh? Including a specific bridge chip inside a generic Exynos DRM core?
> > I know this is not a part of this patch, but... this is _broken_.
> >
> > You may want to support multiple bridge chips in Exynos DRM core and you
> > may also want to support PTN3460 in other DRM cores. It can't be done this
> > way.
> >
> > This series is very nice, but the whole effect is destroyed by basing it
> > on top of such insanity... Please rebase it on top of something more
> > reasonable (preferably Inki's next branch directly).
> >
> 
> Well, that was blunt. Unfortunately, I don't know how else to do this
> other than this broken, unreasonable and insane way.

Sorry, this might have been a bit too harsh, but just imagine myself doing
my regular patch review round, hoping (as usual) to see only code that is
not less than great, while suddenly stumbling upon a line of code that
I would expect at most in some vendor tree or maybe several years ago in
sources of a 2.4 kernel.

> 
> This has already been discussed at length in a few other places.
> Without some help from the drm layer, I don't see any other way to do
> this than to enumerate the possible bridges in each drm driver.
> 
> I based the current set off the "Add some missing bits for
> exynos5250-snow" series I sent up a little while ago. This set was
> sent to the relevant dt people, acked by Olof, and there are no
> outstanding review comments. Since it's required for me to test on
> Real Hardware, I assumed this was an appropriate base.
> 
> If you think this is _broken_, unreasonable, and insane, I'd love to
> hear an alternative.

Well, I should say that Laurent would probably have something to say about
this, but I understand that the really good solution need to take some
time to be developed, so...

What about at least creating a minimal, temporary abstraction layer that
would provide all you originally needed from drm/bridge/ptn3460.h, but in
a bridge chip agnostic way?

I believe we already have established Device Tree bindings for video
interfaces (used currently by V4L) and you can safely use them to bind
your video devices together. Based on this assumption, you can implement
a local parser for a subset of those bindings that is enough to achieve
everything you need - bind a bridge to a video output of the SoC.

As for your explicit need to include headers of particular bridges,
looking at your Chromium kernel sources[1] I can see that all you need
is an init routine for the bridge. A rewritten find_bridge() that would
instead take some generic cookie of a device driving a connector could
return a generic (exynos_)drm_bridge cookie that could be further used
to call functions like (exynos_)drm_bridge_init(), which would then
use the cookie to call appropriate bridge-specific init function.

Of course, as a temporary solution, this can be made Exynos-specific,
but this won't add dependencies on particular bridge chips to Exynos DRM
core.

[1] http://git.chromium.org/gitweb/?p=chromiumos/third_party/kernel-next.git;a=blob;f=drivers/gpu/drm/exynos/exynos_drm_drv.c;h=099baa836784ea5d0eff8c2189abab35a3b342c5;hb=refs/heads/chromeos-3.8

Best regards,
Tomasz

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

* Re: [PATCH v3 19/32] drm/exynos: Use mode_set to configure fimd
  2013-11-10 22:03   ` Tomasz Figa
@ 2013-11-15 13:49     ` Daniel Kurtz
  2013-11-15 13:53     ` Daniel Kurtz
  1 sibling, 0 replies; 130+ messages in thread
From: Daniel Kurtz @ 2013-11-15 13:49 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: Stéphane Marchesin, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 5384 bytes --]

Hi Sean, Tomasz,

On Mon, Nov 11, 2013 at 6:03 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:

> Hi Sean,
>
> On Tuesday 29 of October 2013 12:13:05 Sean Paul wrote:
> > This patch uses the mode passed into mode_set to configure fimd instead
> > of directly using the panel from context. This will allow us to move
> > the exynos_drm_display implementation from fimd into the DP driver
> > where it belongs.
>
> Remember that DP is not the only possible way to connect a display driven
> by FIMD. You also have the direct (RGB and i80) and DSI interfaces.
>
> Also, please see my comments inline.
>
> >
> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
> > ---
> >
> > Changes in v2: None
> > Changes in v3: None
> >
> >  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 159
> ++++++++++++++++++-------------
> >  1 file changed, 91 insertions(+), 68 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> > index d2b8ccb..f69d6e5 100644
> > --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> > +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> > @@ -104,6 +104,20 @@ struct fimd_win_data {
> >       bool                    resume;
> >  };
> >
> > +struct fimd_mode_data {
> > +     unsigned                vtotal;
>
> For consistency with rest of the code, unsigned int would prefered.
>
> However, I'm not sure what is this struct for, since it does not store
> neither raw register values (1 needs to be subtracted from them) nor
> any values hard to compute at commit time (maybe except clkdiv, but still
> how often commit would be called?).
>
> > +     unsigned                vdisplay;
> > +     unsigned                vsync_len;
> > +     unsigned                vbpd;
> > +     unsigned                vfpd;
> > +     unsigned                htotal;
> > +     unsigned                hdisplay;
> > +     unsigned                hsync_len;
> > +     unsigned                hbpd;
> > +     unsigned                hfpd;
> > +     u32                     clkdiv;
> > +};
> > +
> >  struct fimd_context {
> >       struct device                   *dev;
> >       struct drm_device               *drm_dev;
> > @@ -112,8 +126,8 @@ struct fimd_context {
> >       struct clk                      *bus_clk;
> >       struct clk                      *lcd_clk;
> >       void __iomem                    *regs;
> > +     struct fimd_mode_data           mode;
> >       struct fimd_win_data            win_data[WINDOWS_NR];
> > -     unsigned int                    clkdiv;
> >       unsigned int                    default_win;
> >       unsigned long                   irq_flags;
> >       u32                             vidcon0;
> > @@ -560,11 +574,56 @@ static void fimd_dpms(struct exynos_drm_manager
> *mgr, int mode)
> >       mutex_unlock(&ctx->lock);
> >  }
> >
> > +static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
> > +             const struct drm_display_mode *mode)
> > +{
> > +     unsigned long ideal_clk = mode->htotal * mode->vtotal *
> mode->vrefresh;
> > +     u32 clkdiv;
> > +
> > +     /* Find the clock divider value that gets us closest to ideal_clk
> */
> > +     clkdiv = DIV_ROUND_CLOSEST(clk_get_rate(ctx->lcd_clk), ideal_clk);
>
> This is a functional change unrelated to $subject. Before this patch,
> DIV_ROUND_UP() had been used.
>
> > +
> > +     return (clkdiv < 0x100) ? clkdiv : 0xff;
> > +}
> > +
> > +static bool fimd_mode_fixup(struct exynos_drm_manager *mgr,
> > +             const struct drm_display_mode *mode,
> > +             struct drm_display_mode *adjusted_mode)
> > +{
> > +     if (adjusted_mode->vrefresh == 0)
> > +             adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE;
>

The actual pixel clock will be clk_get_rate(ctx->lcd_clk) / clkdiv.
Should we also be adjusting the "clock" field of adjusted_mode here?


> > +
> > +     return true;
> > +}
> > +
> > +static void fimd_mode_set(struct exynos_drm_manager *mgr,
> > +             const struct drm_display_mode *in_mode)
> > +{
> > +     struct fimd_context *ctx = mgr->ctx;
> > +     struct fimd_mode_data *mode = &ctx->mode;
> > +     int hblank, vblank;
> > +
> > +     vblank = in_mode->crtc_vblank_end - in_mode->crtc_vblank_start;
> > +     mode->vtotal = in_mode->crtc_vtotal;
> > +     mode->vdisplay = in_mode->crtc_vdisplay;
> > +     mode->vsync_len = in_mode->crtc_vsync_end -
> in_mode->crtc_vsync_start;
> > +     mode->vbpd = (vblank - mode->vsync_len) / 2;
> > +     mode->vfpd = vblank - mode->vsync_len - mode->vbpd;
> > +
> > +     hblank = in_mode->crtc_hblank_end - in_mode->crtc_hblank_start;
> > +     mode->htotal = in_mode->crtc_htotal;
> > +     mode->hdisplay = in_mode->crtc_hdisplay;
> > +     mode->hsync_len = in_mode->crtc_hsync_end -
> in_mode->crtc_hsync_start;
> > +     mode->hbpd = (hblank - mode->hsync_len) / 2;
> > +     mode->hfpd = hblank - mode->hsync_len - mode->hbpd;
> > +
> > +     mode->clkdiv = fimd_calc_clkdiv(ctx, in_mode);
>
> What about simply copying contents of in_mode to driver context
> and then calculating clkdiv at commit time? You could get rid
> of the fimd_mode_data struct and most of this function.
>
> Otherwise, the patch looks fine.
>
> Best regards,
> Tomasz
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>

[-- Attachment #1.2: Type: text/html, Size: 7327 bytes --]

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

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

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

* Re: [PATCH v3 19/32] drm/exynos: Use mode_set to configure fimd
  2013-11-10 22:03   ` Tomasz Figa
  2013-11-15 13:49     ` Daniel Kurtz
@ 2013-11-15 13:53     ` Daniel Kurtz
  2013-11-28 22:57       ` Tomasz Figa
  2013-12-04 22:37       ` Sean Paul
  1 sibling, 2 replies; 130+ messages in thread
From: Daniel Kurtz @ 2013-11-15 13:53 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: Stéphane Marchesin, dri-devel

Hi Sean, Tomasz,

On Mon, Nov 11, 2013 at 6:03 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> Hi Sean,
>
> On Tuesday 29 of October 2013 12:13:05 Sean Paul wrote:
>> This patch uses the mode passed into mode_set to configure fimd instead
>> of directly using the panel from context. This will allow us to move
>> the exynos_drm_display implementation from fimd into the DP driver
>> where it belongs.
>
> Remember that DP is not the only possible way to connect a display driven
> by FIMD. You also have the direct (RGB and i80) and DSI interfaces.
>
> Also, please see my comments inline.
>
>>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>
>> Changes in v2: None
>> Changes in v3: None
>>
>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 159 ++++++++++++++++++-------------
>>  1 file changed, 91 insertions(+), 68 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>> index d2b8ccb..f69d6e5 100644
>> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>> @@ -104,6 +104,20 @@ struct fimd_win_data {
>>       bool                    resume;
>>  };
>>
>> +struct fimd_mode_data {
>> +     unsigned                vtotal;
>
> For consistency with rest of the code, unsigned int would prefered.
>
> However, I'm not sure what is this struct for, since it does not store
> neither raw register values (1 needs to be subtracted from them) nor
> any values hard to compute at commit time (maybe except clkdiv, but still
> how often commit would be called?).
>
>> +     unsigned                vdisplay;
>> +     unsigned                vsync_len;
>> +     unsigned                vbpd;
>> +     unsigned                vfpd;
>> +     unsigned                htotal;
>> +     unsigned                hdisplay;
>> +     unsigned                hsync_len;
>> +     unsigned                hbpd;
>> +     unsigned                hfpd;
>> +     u32                     clkdiv;
>> +};
>> +
>>  struct fimd_context {
>>       struct device                   *dev;
>>       struct drm_device               *drm_dev;
>> @@ -112,8 +126,8 @@ struct fimd_context {
>>       struct clk                      *bus_clk;
>>       struct clk                      *lcd_clk;
>>       void __iomem                    *regs;
>> +     struct fimd_mode_data           mode;
>>       struct fimd_win_data            win_data[WINDOWS_NR];
>> -     unsigned int                    clkdiv;
>>       unsigned int                    default_win;
>>       unsigned long                   irq_flags;
>>       u32                             vidcon0;
>> @@ -560,11 +574,56 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
>>       mutex_unlock(&ctx->lock);
>>  }
>>
>> +static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
>> +             const struct drm_display_mode *mode)
>> +{
>> +     unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
>> +     u32 clkdiv;
>> +
>> +     /* Find the clock divider value that gets us closest to ideal_clk */
>> +     clkdiv = DIV_ROUND_CLOSEST(clk_get_rate(ctx->lcd_clk), ideal_clk);
>
> This is a functional change unrelated to $subject. Before this patch,
> DIV_ROUND_UP() had been used.
>
>> +
>> +     return (clkdiv < 0x100) ? clkdiv : 0xff;
>> +}
>> +
>> +static bool fimd_mode_fixup(struct exynos_drm_manager *mgr,
>> +             const struct drm_display_mode *mode,
>> +             struct drm_display_mode *adjusted_mode)
>> +{
>> +     if (adjusted_mode->vrefresh == 0)
>> +             adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE;

The actual pixel clock will be clk_get_rate(ctx->lcd_clk) / clkdiv.
Should we also be adjusting the "clock" field of adjusted_mode here?

>> +
>> +     return true;
>> +}
>> +
>> +static void fimd_mode_set(struct exynos_drm_manager *mgr,
>> +             const struct drm_display_mode *in_mode)
>> +{
>> +     struct fimd_context *ctx = mgr->ctx;
>> +     struct fimd_mode_data *mode = &ctx->mode;
>> +     int hblank, vblank;
>> +
>> +     vblank = in_mode->crtc_vblank_end - in_mode->crtc_vblank_start;
>> +     mode->vtotal = in_mode->crtc_vtotal;
>> +     mode->vdisplay = in_mode->crtc_vdisplay;
>> +     mode->vsync_len = in_mode->crtc_vsync_end - in_mode->crtc_vsync_start;
>> +     mode->vbpd = (vblank - mode->vsync_len) / 2;
>> +     mode->vfpd = vblank - mode->vsync_len - mode->vbpd;
>> +
>> +     hblank = in_mode->crtc_hblank_end - in_mode->crtc_hblank_start;
>> +     mode->htotal = in_mode->crtc_htotal;
>> +     mode->hdisplay = in_mode->crtc_hdisplay;
>> +     mode->hsync_len = in_mode->crtc_hsync_end - in_mode->crtc_hsync_start;
>> +     mode->hbpd = (hblank - mode->hsync_len) / 2;
>> +     mode->hfpd = hblank - mode->hsync_len - mode->hbpd;
>> +
>> +     mode->clkdiv = fimd_calc_clkdiv(ctx, in_mode);
>
> What about simply copying contents of in_mode to driver context
> and then calculating clkdiv at commit time? You could get rid
> of the fimd_mode_data struct and most of this function.
>
> Otherwise, the patch looks fine.
>
> Best regards,
> Tomasz
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-12 18:35       ` Tomasz Figa
@ 2013-11-26 18:00         ` Olof Johansson
  2013-11-27 10:04           ` Thierry Reding
  2013-11-28 23:04           ` Tomasz Figa
  0 siblings, 2 replies; 130+ messages in thread
From: Olof Johansson @ 2013-11-26 18:00 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: Stéphane Marchesin, Laurent Pinchart, dri-devel

On Tue, Nov 12, 2013 at 10:35 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> On Tuesday 12 of November 2013 12:51:11 Sean Paul wrote:
>> On Sun, Nov 10, 2013 at 4:09 PM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
>> > Hi Sean,
>> >
>> > On Tuesday 29 of October 2013 12:12:58 Sean Paul wrote:
>> >> This patch splits display and manager from subdrv. The result is that
>> >> crtc functions can directly call into manager callbacks and encoder
>> >> functions can directly call into display callbacks. This will allow
>> >> us to remove the exynos_drm_hdmi shim and support mixer/hdmi & fimd/dp
>> >> with common code.
>> >>
>> >> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> >> ---
>> >>
>> >> Changes in v2:
>> >>       - Pass display into display_ops instead of context
>> >> Changes in v3:
>> >>       - Changed vidi args to exynos_drm_display instead of void
>> >>       - Moved exynos_drm_hdmi.c removal into next patch
>> >>
>> >>  drivers/gpu/drm/exynos/exynos_drm_connector.c |  50 ++---
>> >>  drivers/gpu/drm/exynos/exynos_drm_core.c      | 181 +++++++++++++-----
>> >>  drivers/gpu/drm/exynos/exynos_drm_crtc.c      | 115 +++++++++---
>> >>  drivers/gpu/drm/exynos/exynos_drm_crtc.h      |  20 +-
>> >>  drivers/gpu/drm/exynos/exynos_drm_drv.c       |  29 +--
>> >>  drivers/gpu/drm/exynos/exynos_drm_drv.h       | 106 +++++++----
>> >>  drivers/gpu/drm/exynos/exynos_drm_encoder.c   | 258 ++++----------------------
>> >>  drivers/gpu/drm/exynos/exynos_drm_encoder.h   |  18 +-
>> >>  drivers/gpu/drm/exynos/exynos_drm_fb.c        |   4 +-
>> >>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 161 ++++++++--------
>> >>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c      | 211 +++++++++------------
>> >>  drivers/gpu/drm/exynos/exynos_drm_hdmi.h      |   2 +
>> >>  drivers/gpu/drm/exynos/exynos_drm_plane.c     |  15 +-
>> >>  drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 129 ++++++-------
>> >>  14 files changed, 615 insertions(+), 684 deletions(-)
>> >
>> > This patch is really heavy, making it very hard to review. I wonder if it
>> > couldn't really be split into several smaller patches...
>> >
>>
>> I've distilled it down as much as possible. Unfortunately the
>> encoder/crtc were fused pretty tightly and the effects of that are
>> far-reaching.
>
> I was afraid of this. Well, I guess nothing can be done about it then.
>
>>
>> > Anyway, please see my comments below, for the points I haven't overlooked
>> > due to the complexity of this patch.
>> >
>> >> diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
>> >> index 08ca4f9..e76098d 100644
>> >> --- a/drivers/gpu/drm/exynos/exynos_drm_core.c
>> >> +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
>> >> @@ -16,11 +16,14 @@
>> >>  #include <drm/drmP.h>
>> >>  #include <drm/bridge/ptn3460.h>
>> >
>> > Huh? Including a specific bridge chip inside a generic Exynos DRM core?
>> > I know this is not a part of this patch, but... this is _broken_.
>> >
>> > You may want to support multiple bridge chips in Exynos DRM core and you
>> > may also want to support PTN3460 in other DRM cores. It can't be done this
>> > way.
>> >
>> > This series is very nice, but the whole effect is destroyed by basing it
>> > on top of such insanity... Please rebase it on top of something more
>> > reasonable (preferably Inki's next branch directly).
>> >
>>
>> Well, that was blunt. Unfortunately, I don't know how else to do this
>> other than this broken, unreasonable and insane way.
>
> Sorry, this might have been a bit too harsh, but just imagine myself doing
> my regular patch review round, hoping (as usual) to see only code that is
> not less than great, while suddenly stumbling upon a line of code that
> I would expect at most in some vendor tree or maybe several years ago in
> sources of a 2.4 kernel.

More like code written in the same style as x86 DRM stuff, where
they're not used to overabstracting things from day one to make things
generic instead of supporting the only known chip combination to date.


>> This has already been discussed at length in a few other places.
>> Without some help from the drm layer, I don't see any other way to do
>> this than to enumerate the possible bridges in each drm driver.
>>
>> I based the current set off the "Add some missing bits for
>> exynos5250-snow" series I sent up a little while ago. This set was
>> sent to the relevant dt people, acked by Olof, and there are no
>> outstanding review comments. Since it's required for me to test on
>> Real Hardware, I assumed this was an appropriate base.
>>
>> If you think this is _broken_, unreasonable, and insane, I'd love to
>> hear an alternative.
>
> Well, I should say that Laurent would probably have something to say about
> this, but I understand that the really good solution need to take some
> time to be developed, so...
>
> What about at least creating a minimal, temporary abstraction layer that
> would provide all you originally needed from drm/bridge/ptn3460.h, but in
> a bridge chip agnostic way?
>
> I believe we already have established Device Tree bindings for video
> interfaces (used currently by V4L) and you can safely use them to bind
> your video devices together. Based on this assumption, you can implement
> a local parser for a subset of those bindings that is enough to achieve
> everything you need - bind a bridge to a video output of the SoC.
>
> As for your explicit need to include headers of particular bridges,
> looking at your Chromium kernel sources[1] I can see that all you need
> is an init routine for the bridge. A rewritten find_bridge() that would
> instead take some generic cookie of a device driving a connector could
> return a generic (exynos_)drm_bridge cookie that could be further used
> to call functions like (exynos_)drm_bridge_init(), which would then
> use the cookie to call appropriate bridge-specific init function.
>
> Of course, as a temporary solution, this can be made Exynos-specific,
> but this won't add dependencies on particular bridge chips to Exynos DRM
> core.

On the other hand, there's a chance more abstraction than that is
needed when the second or third chip is added. Until then, there's
little point in doing premature work on abstracting too much of it
out. I'd rather see the code go in sooner and iterate in the tree.


-Olof

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-26 18:00         ` Olof Johansson
@ 2013-11-27 10:04           ` Thierry Reding
  2013-11-28 23:04           ` Tomasz Figa
  1 sibling, 0 replies; 130+ messages in thread
From: Thierry Reding @ 2013-11-27 10:04 UTC (permalink / raw)
  To: Olof Johansson; +Cc: Stéphane Marchesin, dri-devel, Laurent Pinchart


[-- Attachment #1.1: Type: text/plain, Size: 577 bytes --]

On Tue, Nov 26, 2013 at 10:00:13AM -0800, Olof Johansson wrote:
[...]
> More like code written in the same style as x86 DRM stuff, where
> they're not used to overabstracting things from day one to make things
> generic instead of supporting the only known chip combination to date.
[...]
> On the other hand, there's a chance more abstraction than that is
> needed when the second or third chip is added. Until then, there's
> little point in doing premature work on abstracting too much of it
> out. I'd rather see the code go in sooner and iterate in the tree.

+1

Thierry

[-- Attachment #1.2: Type: application/pgp-signature, Size: 836 bytes --]

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

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

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

* Re: [PATCH v3 13/32] drm/exynos: hdmi: remove the i2c drivers and use devtree
  2013-11-11  8:44     ` Thierry Reding
@ 2013-11-28 13:30       ` Tomasz Figa
  2013-11-29 10:24         ` Thierry Reding
  0 siblings, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-11-28 13:30 UTC (permalink / raw)
  To: dri-devel; +Cc: marcheu

On Monday 11 of November 2013 09:44:27 Thierry Reding wrote:
> On Sun, Nov 10, 2013 at 09:46:02PM +0100, Tomasz Figa wrote:
> [...]
> > On Tuesday 29 of October 2013 12:12:59 Sean Paul wrote:
> [...]
> > [snip]
> > > @@ -1957,21 +1943,30 @@ static int hdmi_probe(struct platform_device *pdev)
> > >  	}
> > >  
> > >  	/* DDC i2c driver */
> > > -	if (i2c_add_driver(&ddc_driver)) {
> > > -		DRM_ERROR("failed to register ddc i2c driver\n");
> > > -		return -ENOENT;
> > > +	ddc_node = of_find_node_by_name(NULL, "hdmiddc");
> > 
> > This is wrong. You shall not reference a device tree node by its name,
> > except some very specific well-defined cases, such as cpus or memory
> > nodes.
> > 
> > A solution closest to yours, but correct, would be to use the same match
> > table as in the I2C driver you are removing and call
> > of_find_matching_node().
> 
> Isn't the correct solution to use a phandle? That might need the binding
> to change in a backwards incompatible way.

Yes, phandle is an even better option as it can point you precisely to the
node you are interested in, but this will be incompatible, meaning that
you would have to support both variants anyway.

> Then again, if something as
> simple as specifying a DDC I2C bus causes the binding to change in a
> backwards incompatible way then it can't have been a very good binding
> in the first place, right? +1 for unstable DT bindings...

Well, some of already existing bindings should have been definitely marked
unstable, as they haven't been thought and reviewed well enough, if at all
(especially reviewed, as we only started seriously reviewing DT bindings
not so long ago).

Honestly, I'm not quite sure about this binding in particular, especially
how much it would be a problem if we broke compatibility. I mean, how much
tied to old DTBs are existing boards using this binding. The affected
boards are:
 - exynos5250-snow,
 - exynos5250-arndale,
 - exynos5250-smdk5250,
 - exynos5420-smdk5420.
The last three are most likely to be used only with DTB appended, so
I don't think that anyone would complain. However I'm not sure about the
first one, which is supposed to be a Chromebook if I'm not mistaken.

Best regards,
Tomasz

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

* Re: [PATCH v3 19/32] drm/exynos: Use mode_set to configure fimd
  2013-11-15 13:53     ` Daniel Kurtz
@ 2013-11-28 22:57       ` Tomasz Figa
  2013-12-04 22:37       ` Sean Paul
  1 sibling, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-28 22:57 UTC (permalink / raw)
  To: Daniel Kurtz; +Cc: Stéphane Marchesin, dri-devel

On Friday 15 of November 2013 21:53:16 Daniel Kurtz wrote:
> Hi Sean, Tomasz,
> 
> On Mon, Nov 11, 2013 at 6:03 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> > Hi Sean,
> >
> > On Tuesday 29 of October 2013 12:13:05 Sean Paul wrote:
> >> This patch uses the mode passed into mode_set to configure fimd instead
> >> of directly using the panel from context. This will allow us to move
> >> the exynos_drm_display implementation from fimd into the DP driver
> >> where it belongs.
> >
> > Remember that DP is not the only possible way to connect a display driven
> > by FIMD. You also have the direct (RGB and i80) and DSI interfaces.
> >
> > Also, please see my comments inline.
> >
> >>
> >> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> >> ---
> >>
> >> Changes in v2: None
> >> Changes in v3: None
> >>
> >>  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 159 ++++++++++++++++++-------------
> >>  1 file changed, 91 insertions(+), 68 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> >> index d2b8ccb..f69d6e5 100644
> >> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> >> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> >> @@ -104,6 +104,20 @@ struct fimd_win_data {
> >>       bool                    resume;
> >>  };
> >>
> >> +struct fimd_mode_data {
> >> +     unsigned                vtotal;
> >
> > For consistency with rest of the code, unsigned int would prefered.
> >
> > However, I'm not sure what is this struct for, since it does not store
> > neither raw register values (1 needs to be subtracted from them) nor
> > any values hard to compute at commit time (maybe except clkdiv, but still
> > how often commit would be called?).
> >
> >> +     unsigned                vdisplay;
> >> +     unsigned                vsync_len;
> >> +     unsigned                vbpd;
> >> +     unsigned                vfpd;
> >> +     unsigned                htotal;
> >> +     unsigned                hdisplay;
> >> +     unsigned                hsync_len;
> >> +     unsigned                hbpd;
> >> +     unsigned                hfpd;
> >> +     u32                     clkdiv;
> >> +};
> >> +
> >>  struct fimd_context {
> >>       struct device                   *dev;
> >>       struct drm_device               *drm_dev;
> >> @@ -112,8 +126,8 @@ struct fimd_context {
> >>       struct clk                      *bus_clk;
> >>       struct clk                      *lcd_clk;
> >>       void __iomem                    *regs;
> >> +     struct fimd_mode_data           mode;
> >>       struct fimd_win_data            win_data[WINDOWS_NR];
> >> -     unsigned int                    clkdiv;
> >>       unsigned int                    default_win;
> >>       unsigned long                   irq_flags;
> >>       u32                             vidcon0;
> >> @@ -560,11 +574,56 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
> >>       mutex_unlock(&ctx->lock);
> >>  }
> >>
> >> +static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
> >> +             const struct drm_display_mode *mode)
> >> +{
> >> +     unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
> >> +     u32 clkdiv;
> >> +
> >> +     /* Find the clock divider value that gets us closest to ideal_clk */
> >> +     clkdiv = DIV_ROUND_CLOSEST(clk_get_rate(ctx->lcd_clk), ideal_clk);
> >
> > This is a functional change unrelated to $subject. Before this patch,
> > DIV_ROUND_UP() had been used.
> >
> >> +
> >> +     return (clkdiv < 0x100) ? clkdiv : 0xff;
> >> +}
> >> +
> >> +static bool fimd_mode_fixup(struct exynos_drm_manager *mgr,
> >> +             const struct drm_display_mode *mode,
> >> +             struct drm_display_mode *adjusted_mode)
> >> +{
> >> +     if (adjusted_mode->vrefresh == 0)
> >> +             adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE;
> 
> The actual pixel clock will be clk_get_rate(ctx->lcd_clk) / clkdiv.
> Should we also be adjusting the "clock" field of adjusted_mode here?

Not sure how the pixel clock in adjusted_mode is used elsewhere, but at
least for the sake of consistency, it might be good idea to adjust it
indeed.

Best regards,
Tomasz

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-26 18:00         ` Olof Johansson
  2013-11-27 10:04           ` Thierry Reding
@ 2013-11-28 23:04           ` Tomasz Figa
  2013-11-29  7:52             ` Daniel Vetter
  2013-11-29 10:16             ` Thierry Reding
  1 sibling, 2 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-28 23:04 UTC (permalink / raw)
  To: Olof Johansson; +Cc: Stéphane Marchesin, Laurent Pinchart, dri-devel

On Tuesday 26 of November 2013 10:00:13 Olof Johansson wrote:
> On Tue, Nov 12, 2013 at 10:35 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> > On Tuesday 12 of November 2013 12:51:11 Sean Paul wrote:
> >> On Sun, Nov 10, 2013 at 4:09 PM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> >> > Hi Sean,
> >> >
> >> > On Tuesday 29 of October 2013 12:12:58 Sean Paul wrote:
> >> >> This patch splits display and manager from subdrv. The result is that
> >> >> crtc functions can directly call into manager callbacks and encoder
> >> >> functions can directly call into display callbacks. This will allow
> >> >> us to remove the exynos_drm_hdmi shim and support mixer/hdmi & fimd/dp
> >> >> with common code.
> >> >>
> >> >> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> >> >> ---
> >> >>
> >> >> Changes in v2:
> >> >>       - Pass display into display_ops instead of context
> >> >> Changes in v3:
> >> >>       - Changed vidi args to exynos_drm_display instead of void
> >> >>       - Moved exynos_drm_hdmi.c removal into next patch
> >> >>
> >> >>  drivers/gpu/drm/exynos/exynos_drm_connector.c |  50 ++---
> >> >>  drivers/gpu/drm/exynos/exynos_drm_core.c      | 181 +++++++++++++-----
> >> >>  drivers/gpu/drm/exynos/exynos_drm_crtc.c      | 115 +++++++++---
> >> >>  drivers/gpu/drm/exynos/exynos_drm_crtc.h      |  20 +-
> >> >>  drivers/gpu/drm/exynos/exynos_drm_drv.c       |  29 +--
> >> >>  drivers/gpu/drm/exynos/exynos_drm_drv.h       | 106 +++++++----
> >> >>  drivers/gpu/drm/exynos/exynos_drm_encoder.c   | 258 ++++----------------------
> >> >>  drivers/gpu/drm/exynos/exynos_drm_encoder.h   |  18 +-
> >> >>  drivers/gpu/drm/exynos/exynos_drm_fb.c        |   4 +-
> >> >>  drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 161 ++++++++--------
> >> >>  drivers/gpu/drm/exynos/exynos_drm_hdmi.c      | 211 +++++++++------------
> >> >>  drivers/gpu/drm/exynos/exynos_drm_hdmi.h      |   2 +
> >> >>  drivers/gpu/drm/exynos/exynos_drm_plane.c     |  15 +-
> >> >>  drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 129 ++++++-------
> >> >>  14 files changed, 615 insertions(+), 684 deletions(-)
> >> >
> >> > This patch is really heavy, making it very hard to review. I wonder if it
> >> > couldn't really be split into several smaller patches...
> >> >
> >>
> >> I've distilled it down as much as possible. Unfortunately the
> >> encoder/crtc were fused pretty tightly and the effects of that are
> >> far-reaching.
> >
> > I was afraid of this. Well, I guess nothing can be done about it then.
> >
> >>
> >> > Anyway, please see my comments below, for the points I haven't overlooked
> >> > due to the complexity of this patch.
> >> >
> >> >> diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
> >> >> index 08ca4f9..e76098d 100644
> >> >> --- a/drivers/gpu/drm/exynos/exynos_drm_core.c
> >> >> +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
> >> >> @@ -16,11 +16,14 @@
> >> >>  #include <drm/drmP.h>
> >> >>  #include <drm/bridge/ptn3460.h>
> >> >
> >> > Huh? Including a specific bridge chip inside a generic Exynos DRM core?
> >> > I know this is not a part of this patch, but... this is _broken_.
> >> >
> >> > You may want to support multiple bridge chips in Exynos DRM core and you
> >> > may also want to support PTN3460 in other DRM cores. It can't be done this
> >> > way.
> >> >
> >> > This series is very nice, but the whole effect is destroyed by basing it
> >> > on top of such insanity... Please rebase it on top of something more
> >> > reasonable (preferably Inki's next branch directly).
> >> >
> >>
> >> Well, that was blunt. Unfortunately, I don't know how else to do this
> >> other than this broken, unreasonable and insane way.
> >
> > Sorry, this might have been a bit too harsh, but just imagine myself doing
> > my regular patch review round, hoping (as usual) to see only code that is
> > not less than great, while suddenly stumbling upon a line of code that
> > I would expect at most in some vendor tree or maybe several years ago in
> > sources of a 2.4 kernel.
> 
> More like code written in the same style as x86 DRM stuff, where
> they're not used to overabstracting things from day one to make things
> generic instead of supporting the only known chip combination to date.

No, not really. They don't have any modularity on x86. Just a graphics
card with everything on it, so they can freely do such things, as they
don't have to account for all we need to account for on ARM platforms.

Also, I wouldn't call making a driver usable and useful for more than
just one fixed platform "overabstracting"...

> 
> 
> >> This has already been discussed at length in a few other places.
> >> Without some help from the drm layer, I don't see any other way to do
> >> this than to enumerate the possible bridges in each drm driver.
> >>
> >> I based the current set off the "Add some missing bits for
> >> exynos5250-snow" series I sent up a little while ago. This set was
> >> sent to the relevant dt people, acked by Olof, and there are no
> >> outstanding review comments. Since it's required for me to test on
> >> Real Hardware, I assumed this was an appropriate base.
> >>
> >> If you think this is _broken_, unreasonable, and insane, I'd love to
> >> hear an alternative.
> >
> > Well, I should say that Laurent would probably have something to say about
> > this, but I understand that the really good solution need to take some
> > time to be developed, so...
> >
> > What about at least creating a minimal, temporary abstraction layer that
> > would provide all you originally needed from drm/bridge/ptn3460.h, but in
> > a bridge chip agnostic way?
> >
> > I believe we already have established Device Tree bindings for video
> > interfaces (used currently by V4L) and you can safely use them to bind
> > your video devices together. Based on this assumption, you can implement
> > a local parser for a subset of those bindings that is enough to achieve
> > everything you need - bind a bridge to a video output of the SoC.
> >
> > As for your explicit need to include headers of particular bridges,
> > looking at your Chromium kernel sources[1] I can see that all you need
> > is an init routine for the bridge. A rewritten find_bridge() that would
> > instead take some generic cookie of a device driving a connector could
> > return a generic (exynos_)drm_bridge cookie that could be further used
> > to call functions like (exynos_)drm_bridge_init(), which would then
> > use the cookie to call appropriate bridge-specific init function.
> >
> > Of course, as a temporary solution, this can be made Exynos-specific,
> > but this won't add dependencies on particular bridge chips to Exynos DRM
> > core.
> 
> On the other hand, there's a chance more abstraction than that is
> needed when the second or third chip is added. Until then, there's
> little point in doing premature work on abstracting too much of it
> out. I'd rather see the code go in sooner and iterate in the tree.

First of all, this is heavily Chromebook specific and that's not the only
Exynos-based platform using Exynos DRM. In fact, before conversion to DT,
we had full support for parallel and DSI displays on several Exynos4 based
boards.

I really regret that we allowed for such regression back then, but now
the only thing we can do about it is to at least not make a step backwards
with this and make DRM bridge something useful (or at least usable).

Best regards,
Tomasz

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-28 23:04           ` Tomasz Figa
@ 2013-11-29  7:52             ` Daniel Vetter
  2013-11-29  9:10               ` Tomasz Figa
  2013-11-29 10:16             ` Thierry Reding
  1 sibling, 1 reply; 130+ messages in thread
From: Daniel Vetter @ 2013-11-29  7:52 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: Stéphane Marchesin, Laurent Pinchart, dri-devel

On Fri, Nov 29, 2013 at 12:04:04AM +0100, Tomasz Figa wrote:
> On Tuesday 26 of November 2013 10:00:13 Olof Johansson wrote:
> > More like code written in the same style as x86 DRM stuff, where
> > they're not used to overabstracting things from day one to make things
> > generic instead of supporting the only known chip combination to date.
> 
> No, not really. They don't have any modularity on x86. Just a graphics
> card with everything on it, so they can freely do such things, as they
> don't have to account for all we need to account for on ARM platforms.

I guess you didn't bother looking at x86 drivers then ... in i915 we have
different blocks spanning 7 major hw iterations, reused in funny (and
overlapping) ways. We have clock trees, nested power domains, interrupt
controllers and forwarders, different coherency domains, off-chip
functiosn in the PCH, the full shebang.

In the code itself we have piles of vtables for the different parts of the
chip, mmio base offsets (since hw engineers just love to move things
around) and otherwise neatly abstracted helpers for different parts of the
chip to be able to reuse things across generations.

The _only_ difference I see compared to an arm soc is that this entire
madness is neatly wrapped up into a fake pci device. And some of the
really remote mmio ranges are windowed into general hodgepodge mmio
register bar so that we don't have to hunt it down on different pci
devices. But occasionally we do even that.

So as per the discussion at KS about soc gfx drivers where all the ip
blocks come from the same vendor I really don't see why arm drivers need
to be so much different than more traditional x86 drivers. Since nowadays
(at least with intel) that means we _are_ talking about an soc.

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-29  7:52             ` Daniel Vetter
@ 2013-11-29  9:10               ` Tomasz Figa
  2013-11-29 10:25                 ` Daniel Vetter
  2013-11-29 14:13                 ` Rob Clark
  0 siblings, 2 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-29  9:10 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Stéphane Marchesin, Laurent Pinchart, dri-devel

On Friday 29 of November 2013 08:52:22 Daniel Vetter wrote:
> On Fri, Nov 29, 2013 at 12:04:04AM +0100, Tomasz Figa wrote:
> > On Tuesday 26 of November 2013 10:00:13 Olof Johansson wrote:
> > > More like code written in the same style as x86 DRM stuff, where
> > > they're not used to overabstracting things from day one to make things
> > > generic instead of supporting the only known chip combination to date.
> > 
> > No, not really. They don't have any modularity on x86. Just a graphics
> > card with everything on it, so they can freely do such things, as they
> > don't have to account for all we need to account for on ARM platforms.
> 
> I guess you didn't bother looking at x86 drivers then ... in i915 we have
> different blocks spanning 7 major hw iterations, reused in funny (and
> overlapping) ways. We have clock trees, nested power domains, interrupt
> controllers and forwarders, different coherency domains, off-chip
> functiosn in the PCH, the full shebang.
> 
> In the code itself we have piles of vtables for the different parts of the
> chip, mmio base offsets (since hw engineers just love to move things
> around) and otherwise neatly abstracted helpers for different parts of the
> chip to be able to reuse things across generations.
> 
> The _only_ difference I see compared to an arm soc is that this entire
> madness is neatly wrapped up into a fake pci device. And some of the
> really remote mmio ranges are windowed into general hodgepodge mmio
> register bar so that we don't have to hunt it down on different pci
> devices. But occasionally we do even that.
> 
> So as per the discussion at KS about soc gfx drivers where all the ip
> blocks come from the same vendor I really don't see why arm drivers need
> to be so much different than more traditional x86 drivers. Since nowadays
> (at least with intel) that means we _are_ talking about an soc.

I would mostly agree with you if we were discussing SoC-internal
components here. Mostly, because the ARM world is more complex and you
can see the same IP across completely different SoCs from different
vendors.

However, the topic here is about external devices, outside the SoC, such
as different kind of bridges, like the PTN3460 eDP to LVDS bridge, which
are likely to be reused across different platforms. Similar thing is with
using different bridges on different boards using the same SoC platform.
I don't think having an abstraction here would be any overabstraction at
all. Anything less would be a huge "underabstraction" in fact.

Best regards,
Tomasz

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-28 23:04           ` Tomasz Figa
  2013-11-29  7:52             ` Daniel Vetter
@ 2013-11-29 10:16             ` Thierry Reding
  1 sibling, 0 replies; 130+ messages in thread
From: Thierry Reding @ 2013-11-29 10:16 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: Stéphane Marchesin, Laurent Pinchart, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 3024 bytes --]

On Fri, Nov 29, 2013 at 12:04:04AM +0100, Tomasz Figa wrote:
> On Tuesday 26 of November 2013 10:00:13 Olof Johansson wrote:
> > On Tue, Nov 12, 2013 at 10:35 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
[...]
> > > Sorry, this might have been a bit too harsh, but just imagine myself doing
> > > my regular patch review round, hoping (as usual) to see only code that is
> > > not less than great, while suddenly stumbling upon a line of code that
> > > I would expect at most in some vendor tree or maybe several years ago in
> > > sources of a 2.4 kernel.
> > 
> > More like code written in the same style as x86 DRM stuff, where
> > they're not used to overabstracting things from day one to make things
> > generic instead of supporting the only known chip combination to date.
> 
> No, not really. They don't have any modularity on x86. Just a graphics
> card with everything on it, so they can freely do such things, as they
> don't have to account for all we need to account for on ARM platforms.

I don't think there's such a clear difference. A particular GPU on x86
is equally modular as a specific GPU on an ARM SoC. The problem is that
on x86 there's much less mix-and-matching going on.

So theoretically they do need to account for the same craziness. That's
not done, however, because there's no need for it. It doesn't happen in
practice.

> Also, I wouldn't call making a driver usable and useful for more than
> just one fixed platform "overabstracting"...

It is if there's never more than the single fixed platform. Since none
of us can predict the future I think it's entirely reasonable if we do
concentrate on solving the problems that we have now. It doesn't mean
that we should write code in a way that makes future enhancements
unnecessarily difficult, but I very much prefer to see code merged that
supports one specific use-case that we have now rather than working on
the code for years on end in an attempt to make it generic enough to
support everything that the future can possibly hold.

Chances are pretty good that we won't be able to predict one specific
use-case and then rewrite everything anyway. Linux has been pretty
successful so far in a large part because it has evolved organically.
We're not doing ourselves any good by requiring everything to be perfect
from the beginning.

We all know what a disaster DT has been and still is. It makes it very
difficult to get new features supported because we now have a component
that we can no longer change at will and that cannot evolve organically
anymore. That impedes progress.

For this particular issue no DT is involved. There's no need for ABI
stability because it's just in-tree code and we can change it to our
heart's content. We can refactor things when an actual need arises. By
then chances are pretty good we'll have a much better understanding of
what exactly we need and therefore we can come up with a much better
solution than at this point in time.

Thierry

[-- Attachment #1.2: Type: application/pgp-signature, Size: 836 bytes --]

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

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

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

* Re: [PATCH v3 13/32] drm/exynos: hdmi: remove the i2c drivers and use devtree
  2013-11-28 13:30       ` Tomasz Figa
@ 2013-11-29 10:24         ` Thierry Reding
  2013-12-03  0:37           ` Olof Johansson
  0 siblings, 1 reply; 130+ messages in thread
From: Thierry Reding @ 2013-11-29 10:24 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: marcheu, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 3092 bytes --]

On Thu, Nov 28, 2013 at 02:30:24PM +0100, Tomasz Figa wrote:
> On Monday 11 of November 2013 09:44:27 Thierry Reding wrote:
> > On Sun, Nov 10, 2013 at 09:46:02PM +0100, Tomasz Figa wrote:
> > [...]
> > > On Tuesday 29 of October 2013 12:12:59 Sean Paul wrote:
> > [...]
> > > [snip]
> > > > @@ -1957,21 +1943,30 @@ static int hdmi_probe(struct platform_device *pdev)
> > > >  	}
> > > >  
> > > >  	/* DDC i2c driver */
> > > > -	if (i2c_add_driver(&ddc_driver)) {
> > > > -		DRM_ERROR("failed to register ddc i2c driver\n");
> > > > -		return -ENOENT;
> > > > +	ddc_node = of_find_node_by_name(NULL, "hdmiddc");
> > > 
> > > This is wrong. You shall not reference a device tree node by its name,
> > > except some very specific well-defined cases, such as cpus or memory
> > > nodes.
> > > 
> > > A solution closest to yours, but correct, would be to use the same match
> > > table as in the I2C driver you are removing and call
> > > of_find_matching_node().
> > 
> > Isn't the correct solution to use a phandle? That might need the binding
> > to change in a backwards incompatible way.
> 
> Yes, phandle is an even better option as it can point you precisely to the
> node you are interested in, but this will be incompatible, meaning that
> you would have to support both variants anyway.

Oh come on. If a phandle is the right way to do it, then we should just
do it. Will it really be so difficult to carry code for both variants?
If nothing else it will at least set a good example and reduce the risk
of people doing the same mistakes over and over again.

Adding the right binding also gives you a way to start deprecating the
wrong one and eventually remove it. The longer you wait, the more people
will start to use the existing, broken binding and removing it will only
become more difficult over time.

> > Then again, if something as
> > simple as specifying a DDC I2C bus causes the binding to change in a
> > backwards incompatible way then it can't have been a very good binding
> > in the first place, right? +1 for unstable DT bindings...
> 
> Well, some of already existing bindings should have been definitely marked
> unstable, as they haven't been thought and reviewed well enough, if at all
> (especially reviewed, as we only started seriously reviewing DT bindings
> not so long ago).
> 
> Honestly, I'm not quite sure about this binding in particular, especially
> how much it would be a problem if we broke compatibility. I mean, how much
> tied to old DTBs are existing boards using this binding. The affected
> boards are:
>  - exynos5250-snow,
>  - exynos5250-arndale,
>  - exynos5250-smdk5250,
>  - exynos5420-smdk5420.
> The last three are most likely to be used only with DTB appended, so
> I don't think that anyone would complain. However I'm not sure about the
> first one, which is supposed to be a Chromebook if I'm not mistaken.

Well, if it's a Chromebook it likely doesn't ship with a completely
mainline kernel. That frees it from the stability requirements, doesn't
it?

Thierry

[-- Attachment #1.2: Type: application/pgp-signature, Size: 836 bytes --]

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

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

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-29  9:10               ` Tomasz Figa
@ 2013-11-29 10:25                 ` Daniel Vetter
  2013-11-29 14:13                 ` Rob Clark
  1 sibling, 0 replies; 130+ messages in thread
From: Daniel Vetter @ 2013-11-29 10:25 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: Stéphane Marchesin, Laurent Pinchart, dri-devel

On Fri, Nov 29, 2013 at 10:10 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> I would mostly agree with you if we were discussing SoC-internal
> components here. Mostly, because the ARM world is more complex and you
> can see the same IP across completely different SoCs from different
> vendors.

Yeah, hence the restriction to IP blocks from the same vendor. Heck we
have external IP blocks in our gpus, too. It's just that the driver to
make that one work is in no shape for upstreaming :( So even for that
case of smashing a random decode engine into your gpu we've seen this
on intel. And I'd guess the radeon uvd block is a similarly alien
piece (although at least not shared anywhere else iirc).

> However, the topic here is about external devices, outside the SoC, such
> as different kind of bridges, like the PTN3460 eDP to LVDS bridge, which
> are likely to be reused across different platforms. Similar thing is with
> using different bridges on different boards using the same SoC platform.
> I don't think having an abstraction here would be any overabstraction at
> all. Anything less would be a huge "underabstraction" in fact.

Hm, I've thought Sean's rework was mostly about the driver core and
not so much about off-chip blocks. But I admit to not have read
through all the details of this thread, so please forgive me my
ignorance ;-)

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-29  9:10               ` Tomasz Figa
  2013-11-29 10:25                 ` Daniel Vetter
@ 2013-11-29 14:13                 ` Rob Clark
  2013-11-29 17:05                   ` Tomasz Figa
  1 sibling, 1 reply; 130+ messages in thread
From: Rob Clark @ 2013-11-29 14:13 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: Stéphane Marchesin, dri-devel, Laurent Pinchart

On Fri, Nov 29, 2013 at 4:10 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> I would mostly agree with you if we were discussing SoC-internal
> components here. Mostly, because the ARM world is more complex and you
> can see the same IP across completely different SoCs from different
> vendors.
>
> However, the topic here is about external devices, outside the SoC, such
> as different kind of bridges, like the PTN3460 eDP to LVDS bridge, which
> are likely to be reused across different platforms. Similar thing is with
> using different bridges on different boards using the same SoC platform.
> I don't think having an abstraction here would be any overabstraction at
> all. Anything less would be a huge "underabstraction" in fact.


I think no one is arguing that we don't eventually need some better
abstraction.  But as long as it is one-bridge and one-user, if the
patches otherwise have merit, add functionality that was missing
before and don't regress, then lack of infrastructure to match up
bridge and driver isn't something I will care about too much yet.
Things are allowed to be in-progress.  A missing abstraction for a 1:1
relationship is fine.

Now as we start getting a few more bridge devices and users, then I'll
start blocking patches until some sort of generic bridge loader is
sorted out.

BR,
-R

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

* Re: [PATCH v3 26/32] drm/exynos: Consolidate suspend/resume in drm_drv
  2013-10-29 16:13 ` [PATCH v3 26/32] drm/exynos: Consolidate suspend/resume in drm_drv Sean Paul
@ 2013-11-29 14:58   ` Tomasz Figa
  2013-12-19 16:48   ` Inki Dae
  1 sibling, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-29 14:58 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:12 Sean Paul wrote:
> This patch removes all of the suspend/resume logic from the individual
> drivers and consolidates it in drm_drv. This consolidation reduces the
> number of functions which enable/disable the hardware to just one -- the
> dpms callback. This ensures that we always power up/down in a consistent
> manner.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v2:
> 	- Added to the patchset
> Changes in v3:
> 	- Made appropriate changes to vidi as well (removed pm_ops)
> 
>  drivers/gpu/drm/exynos/exynos_drm_drv.c  |  97 +++++++++++++++++++++++++
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c |  91 ++++-------------------
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c | 119 +++++++++++++------------------
>  drivers/gpu/drm/exynos/exynos_hdmi.c     |  82 +--------------------
>  drivers/gpu/drm/exynos/exynos_mixer.c    |  75 ++++---------------
>  5 files changed, 176 insertions(+), 288 deletions(-)
[snip]
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> index ba12916..208e013 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> @@ -741,6 +741,8 @@ static int fimd_poweron(struct exynos_drm_manager *mgr)
>  
>  	ctx->suspended = false;
>  
> +	pm_runtime_get_sync(ctx->dev);
> +
>  	ret = clk_prepare_enable(ctx->bus_clk);
>  	if (ret < 0) {
>  		DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
> @@ -794,32 +796,24 @@ static int fimd_poweroff(struct exynos_drm_manager *mgr)
>  	clk_disable_unprepare(ctx->lcd_clk);
>  	clk_disable_unprepare(ctx->bus_clk);
>  
> +	pm_runtime_put_sync(ctx->dev);
> +
>  	ctx->suspended = true;
>  	return 0;
>  }
[snip]
> @@ -950,8 +944,14 @@ static int fimd_probe(struct platform_device *pdev)
>  	fimd_manager.ctx = ctx;
>  	exynos_drm_manager_register(&fimd_manager);
>  
> +	/*
> +	 * We need to runtime pm to enable/disable sysmmu since it is a child of
> +	 * this driver. Ideally, this would hang off the drm driver's runtime
> +	 * operations, but we're not quite there yet.

You also need runtime PM to control state of power domains. I don't think
we should be going away of runtime PM API. Instead DPMS callbacks could
simply call pm_runtime_get_sync/put() whenever the hardware is supposed
to go up or down, just as done above in fimd_poweron/off(). This would
allow any platform-specific PM logic placed outside of DRM subsystem (such
as power domains and IOMMU) to operate.

> +	 *
> +	 * Tracked in crbug.com/264312
> +	 */
>  	pm_runtime_enable(dev);
> -	pm_runtime_get_sync(dev);
>  
>  	for (win = 0; win < WINDOWS_NR; win++)
>  		fimd_clear_win(ctx, win);
[snip]
> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
> index 2c127b9..c6561fe 100644
> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
[snip]
> @@ -2030,8 +2024,6 @@ static int hdmi_probe(struct platform_device *pdev)
>  	hdmi_display.ctx = hdata;
>  	exynos_drm_display_register(&hdmi_display);
>  
> -	pm_runtime_enable(dev);
> -

That's plain wrong. You need runtime PM to enable LCD power domain in
which the HDMI is placed.

>  	return 0;
>  
>  err_hdmiphy:
> @@ -2047,88 +2039,18 @@ static int hdmi_remove(struct platform_device *pdev)
>  	struct exynos_drm_display *display = get_hdmi_display(dev);
>  	struct hdmi_context *hdata = display->ctx;
>  
> -	pm_runtime_disable(dev);
> -
>  	put_device(&hdata->hdmiphy_port->dev);
>  	put_device(&hdata->ddc_port->dev);
>  
>  	return 0;
>  }
[snip]
> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
> index 39aed3e..985391d 100644
> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
[snip]
> @@ -1239,6 +1239,13 @@ static int mixer_probe(struct platform_device *pdev)
>  	platform_set_drvdata(pdev, &mixer_manager);
>  	exynos_drm_manager_register(&mixer_manager);
>  
> +	/*
> +	 * We need to runtime pm to enable/disable sysmmu since it is a child of
> +	 * this driver. Ideally, this would hang off the drm driver's runtime
> +	 * operations, but we're not quite there yet.

Same comment as for FIMD and HDMI.

Best regards,
Tomasz

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

* Re: [PATCH v3 28/32] drm/exynos: Implement drm_connector in hdmi directly
  2013-10-29 16:13 ` [PATCH v3 28/32] drm/exynos: Implement drm_connector in hdmi directly Sean Paul
@ 2013-11-29 15:58   ` Tomasz Figa
  2013-12-02  9:46     ` Thierry Reding
  0 siblings, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-11-29 15:58 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:14 Sean Paul wrote:
> This patch implements drm_connector in the hdmi driver directly, instead
> of using exynos_drm_connector.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v3:
> 	- Added to the patchset
> 
>  drivers/gpu/drm/exynos/exynos_hdmi.c | 126 +++++++++++++++++++++++------------
>  1 file changed, 85 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
> index c6561fe..b063610 100644
> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
> @@ -43,9 +43,8 @@
>  #include <linux/gpio.h>
>  #include <media/s5p_hdmi.h>
>  
> -#define MAX_WIDTH		1920
> -#define MAX_HEIGHT		1080

Hmm, you are removing these values, but they don't seem to be redefined
in any way anywhere below. Are you removing some of the video mode checks?

>  #define get_hdmi_display(dev)	platform_get_drvdata(to_platform_device(dev))
> +#define ctx_from_connector(c)	container_of(c, struct hdmi_context, connector)
>  
>  /* AVI header and aspect ratio */
>  #define HDMI_AVI_VERSION		0x02
[snip]
> @@ -811,11 +816,60 @@ static int hdmi_check_mode(struct exynos_drm_display *display,
>  
>  	ret = mixer_check_mode(mode);
>  	if (ret)
> -		return ret;
> +		return MODE_BAD;

Is there a need to define custom return values, instead of returning 0 or
a standard error code depending on whether the mode is correct?

Best regards,
Tomasz

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

* Re: [PATCH v3 29/32] drm/exynos: Implement drm_connector directly in dp driver
  2013-10-29 16:13 ` [PATCH v3 29/32] drm/exynos: Implement drm_connector directly in dp driver Sean Paul
@ 2013-11-29 16:04   ` Tomasz Figa
  2013-12-03  4:45   ` Inki Dae
  1 sibling, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-29 16:04 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:15 Sean Paul wrote:
> This patch implements drm_connector directly in the dp driver, this will
> allow us to move away from the exynos_drm_connector layer.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v3:
> 	- Added to the patchset
> 
>  drivers/gpu/drm/exynos/exynos_dp_core.c | 99 ++++++++++++++++++++++++++++++---
>  drivers/gpu/drm/exynos/exynos_dp_core.h |  4 ++
>  2 files changed, 94 insertions(+), 9 deletions(-)

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 30/32] drm/exynos: Implement drm_connector directly in vidi driver
  2013-10-29 16:13 ` [PATCH v3 30/32] drm/exynos: Implement drm_connector directly in vidi driver Sean Paul
@ 2013-11-29 16:13   ` Tomasz Figa
  2013-12-03  4:47   ` Inki Dae
  1 sibling, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-29 16:13 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:16 Sean Paul wrote:
> This patch implements drm_connector directly in the vidi
> driver, this will allow us to move away from the exynos_drm_connector
> layer.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v3:
> 	- Added to the patchset
> 
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c | 163 ++++++++++++++++++++-----------
>  1 file changed, 107 insertions(+), 56 deletions(-)

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 32/32] drm/exynos: Remove the exynos_drm_connector shim
  2013-10-29 16:13 ` [PATCH v3 32/32] drm/exynos: Remove the exynos_drm_connector shim Sean Paul
@ 2013-11-29 16:14   ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-29 16:14 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:18 Sean Paul wrote:
> This path removes the exynos_drm_connector code since it was just
> passing hooks through display_ops. The individual device drivers are now
> responsible for implementing drm_connector directly.
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v3:
> 	- Added to the patchset
> 
>  drivers/gpu/drm/exynos/Makefile               |   2 +-
>  drivers/gpu/drm/exynos/exynos_drm_connector.c | 258 --------------------------
>  drivers/gpu/drm/exynos/exynos_drm_connector.h |  20 --
>  drivers/gpu/drm/exynos/exynos_drm_core.c      |  18 +-
>  drivers/gpu/drm/exynos/exynos_drm_drv.h       |  11 --
>  drivers/gpu/drm/exynos/exynos_drm_encoder.c   |   1 -
>  6 files changed, 4 insertions(+), 306 deletions(-)
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.c
>  delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.h

Reviewed-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

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

* Re: [PATCH v3 31/32] drm/exynos: Move lvds bridge discovery into DP driver
  2013-10-29 16:13 ` [PATCH v3 31/32] drm/exynos: Move lvds bridge discovery into DP driver Sean Paul
@ 2013-11-29 16:55   ` Tomasz Figa
  2013-11-30  5:18     ` Inki Dae
  0 siblings, 1 reply; 130+ messages in thread
From: Tomasz Figa @ 2013-11-29 16:55 UTC (permalink / raw)
  To: Sean Paul; +Cc: dri-devel, marcheu

Hi Sean,

On Tuesday 29 of October 2013 12:13:17 Sean Paul wrote:
> This patch moves the lvds bridge discovery and connector pre-emption
> code from exynos common code into the dp driver (since the bridge is
> only applicable for dp).
> 
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> 
> Changes in v3:
> 	- Added to the patchset
> 
>  drivers/gpu/drm/exynos/exynos_dp_core.c  | 41 ++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/exynos/exynos_drm_core.c | 41 --------------------------------
>  2 files changed, 41 insertions(+), 41 deletions(-)
> 

Well, DRM bridge infrastructure is useful for more than just DP. Currently
there are several platforms that could use it with DSI as well, e.g.
Trats, Trats2, Arndale. With a simple abstraction worth of one or at most
two days of work, we could get something that would cover much more than
just a single Chromebook.

Best regards,
Tomasz

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-29 14:13                 ` Rob Clark
@ 2013-11-29 17:05                   ` Tomasz Figa
  2013-11-29 18:35                     ` Rob Clark
  2013-12-03 21:38                     ` Sean Paul
  0 siblings, 2 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-29 17:05 UTC (permalink / raw)
  To: dri-devel; +Cc: Stéphane Marchesin, Laurent Pinchart

On Friday 29 of November 2013 09:13:19 Rob Clark wrote:
> On Fri, Nov 29, 2013 at 4:10 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> > I would mostly agree with you if we were discussing SoC-internal
> > components here. Mostly, because the ARM world is more complex and you
> > can see the same IP across completely different SoCs from different
> > vendors.
> >
> > However, the topic here is about external devices, outside the SoC, such
> > as different kind of bridges, like the PTN3460 eDP to LVDS bridge, which
> > are likely to be reused across different platforms. Similar thing is with
> > using different bridges on different boards using the same SoC platform.
> > I don't think having an abstraction here would be any overabstraction at
> > all. Anything less would be a huge "underabstraction" in fact.
> 
> 
> I think no one is arguing that we don't eventually need some better
> abstraction.  But as long as it is one-bridge and one-user, if the
> patches otherwise have merit, add functionality that was missing
> before and don't regress, then lack of infrastructure to match up
> bridge and driver isn't something I will care about too much yet.
> Things are allowed to be in-progress.  A missing abstraction for a 1:1
> relationship is fine.

This is not just one-bridge, one-user. This is about users of Exynos DRM
we already have in-tree, such as Trats, Trats2 or Arndale, that the DRM
bridge infrastructure could be used on and finally allowing to have
display support on them. Of course you could merge this as is and
then let someone else completely rewrite it (most likely in the same
release cycle), but since it's not really much more work, I don't
think there is any sense.

Moreover, let's stick to modern kernel driver coding standards. I don't
think that "I want this patchset merged so badly" is really a good excuse
to get around it. After all, there would be no GKH's staging tree, if
nobody cared about quality in mainline.

Best regards,
Tomasz

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-29 17:05                   ` Tomasz Figa
@ 2013-11-29 18:35                     ` Rob Clark
  2013-11-30  5:25                       ` Inki Dae
  2013-12-03 21:38                     ` Sean Paul
  1 sibling, 1 reply; 130+ messages in thread
From: Rob Clark @ 2013-11-29 18:35 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: Stéphane Marchesin, dri-devel, Laurent Pinchart

On Fri, Nov 29, 2013 at 12:05 PM, Tomasz Figa <t.figa@samsung.com> wrote:
> On Friday 29 of November 2013 09:13:19 Rob Clark wrote:
>> On Fri, Nov 29, 2013 at 4:10 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
>> > I would mostly agree with you if we were discussing SoC-internal
>> > components here. Mostly, because the ARM world is more complex and you
>> > can see the same IP across completely different SoCs from different
>> > vendors.
>> >
>> > However, the topic here is about external devices, outside the SoC, such
>> > as different kind of bridges, like the PTN3460 eDP to LVDS bridge, which
>> > are likely to be reused across different platforms. Similar thing is with
>> > using different bridges on different boards using the same SoC platform.
>> > I don't think having an abstraction here would be any overabstraction at
>> > all. Anything less would be a huge "underabstraction" in fact.
>>
>>
>> I think no one is arguing that we don't eventually need some better
>> abstraction.  But as long as it is one-bridge and one-user, if the
>> patches otherwise have merit, add functionality that was missing
>> before and don't regress, then lack of infrastructure to match up
>> bridge and driver isn't something I will care about too much yet.
>> Things are allowed to be in-progress.  A missing abstraction for a 1:1
>> relationship is fine.
>
> This is not just one-bridge, one-user. This is about users of Exynos DRM
> we already have in-tree, such as Trats, Trats2 or Arndale, that the DRM
> bridge infrastructure could be used on and finally allowing to have
> display support on them. Of course you could merge this as is and
> then let someone else completely rewrite it (most likely in the same
> release cycle), but since it's not really much more work, I don't
> think there is any sense.

well, I'm not quite sure where I there is a pending complete
re-write..  it looks like the hard ptn3460 dependency is just a few
lines in one function.  Otherwise I'd agree with you.

(and even the patch that touches the code calling ptn3460_init() is
just moving it around from what I see)

> Moreover, let's stick to modern kernel driver coding standards. I don't
> think that "I want this patchset merged so badly" is really a good excuse
> to get around it. After all, there would be no GKH's staging tree, if
> nobody cared about quality in mainline.

And with my quality hat on, I could say that I'm not too fond of
unused (or 1:1 client to user) abstractions.  That is something that
should be introduced as we merge our 2nd or 3rd bridge.

BR,
-R

> Best regards,
> Tomasz
>

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

* Re: [PATCH v3 31/32] drm/exynos: Move lvds bridge discovery into DP driver
  2013-11-29 16:55   ` Tomasz Figa
@ 2013-11-30  5:18     ` Inki Dae
  2013-11-30 12:27       ` Tomasz Figa
  0 siblings, 1 reply; 130+ messages in thread
From: Inki Dae @ 2013-11-30  5:18 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: marcheu, dri-devel

Hi Tomasz,

Thanks for review,


2013/11/30 Tomasz Figa <t.figa@samsung.com>:
> Hi Sean,
>
> On Tuesday 29 of October 2013 12:13:17 Sean Paul wrote:
>> This patch moves the lvds bridge discovery and connector pre-emption
>> code from exynos common code into the dp driver (since the bridge is
>> only applicable for dp).
>>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>
>> Changes in v3:
>>       - Added to the patchset
>>
>>  drivers/gpu/drm/exynos/exynos_dp_core.c  | 41 ++++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/exynos/exynos_drm_core.c | 41 --------------------------------
>>  2 files changed, 41 insertions(+), 41 deletions(-)
>>
>
> Well, DRM bridge infrastructure is useful for more than just DP. Currently
> there are several platforms that could use it with DSI as well, e.g.

In case that some board with DSI bus needs this LVDS bridge, the
bridge type would be MIPI-DSI to LVDS Display bridge. So I think
moving this lvds stuff into eDP driver is reasonable becasue the
normal DSI bus cannot use this LVDS bridge, and this bridge (eDP to
LVDS) would be for eDP bus. BTW, Sean, why not implementing this lvds
codes to eDP driver without previous related patch? that seems
unnecessary work.

> Trats, Trats2, Arndale. With a simple abstraction worth of one or at most
> two days of work, we could get something that would cover much more than
> just a single Chromebook.

I also thought a better way is to use simple abstraction layer. But
the abstraction layer I thought was the case that lvds binding is done
in this lvds driver itself so drm connector should call some bridge
related functions of the abstraction layer. But it seems that other
maintainers don't agree to this way. :(

Anyway, we can say the use of lvds bridge is dependent on board but
actually, the use of lvds bridge would be more dependent on bus device
or lcd panel attached to the board. So my opinion is to bind dt in the
bus or lcd panel drivers that need lvds bridge. If dt binding of lvds
bridge cannot be done itself, Sean's way is reasonable to me except
the unnecessary patch.

Thanks,
Inki Dae

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

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-29 18:35                     ` Rob Clark
@ 2013-11-30  5:25                       ` Inki Dae
  0 siblings, 0 replies; 130+ messages in thread
From: Inki Dae @ 2013-11-30  5:25 UTC (permalink / raw)
  To: Rob Clark; +Cc: Stéphane Marchesin, Laurent Pinchart, dri-devel

Hi all,

How about moving this discussion to other related email thread,
"[PATCH v3 31/32] drm/exynos: Move lvds bridge discovery into DP
driver"? lvds related codes have already been removed from this patch
and moved into eDP bus driver. It would be more good to make a
dicussion about actual codes.

Thanks,
Inki Dae

2013/11/30 Rob Clark <robdclark@gmail.com>:
> On Fri, Nov 29, 2013 at 12:05 PM, Tomasz Figa <t.figa@samsung.com> wrote:
>> On Friday 29 of November 2013 09:13:19 Rob Clark wrote:
>>> On Fri, Nov 29, 2013 at 4:10 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
>>> > I would mostly agree with you if we were discussing SoC-internal
>>> > components here. Mostly, because the ARM world is more complex and you
>>> > can see the same IP across completely different SoCs from different
>>> > vendors.
>>> >
>>> > However, the topic here is about external devices, outside the SoC, such
>>> > as different kind of bridges, like the PTN3460 eDP to LVDS bridge, which
>>> > are likely to be reused across different platforms. Similar thing is with
>>> > using different bridges on different boards using the same SoC platform.
>>> > I don't think having an abstraction here would be any overabstraction at
>>> > all. Anything less would be a huge "underabstraction" in fact.
>>>
>>>
>>> I think no one is arguing that we don't eventually need some better
>>> abstraction.  But as long as it is one-bridge and one-user, if the
>>> patches otherwise have merit, add functionality that was missing
>>> before and don't regress, then lack of infrastructure to match up
>>> bridge and driver isn't something I will care about too much yet.
>>> Things are allowed to be in-progress.  A missing abstraction for a 1:1
>>> relationship is fine.
>>
>> This is not just one-bridge, one-user. This is about users of Exynos DRM
>> we already have in-tree, such as Trats, Trats2 or Arndale, that the DRM
>> bridge infrastructure could be used on and finally allowing to have
>> display support on them. Of course you could merge this as is and
>> then let someone else completely rewrite it (most likely in the same
>> release cycle), but since it's not really much more work, I don't
>> think there is any sense.
>
> well, I'm not quite sure where I there is a pending complete
> re-write..  it looks like the hard ptn3460 dependency is just a few
> lines in one function.  Otherwise I'd agree with you.
>
> (and even the patch that touches the code calling ptn3460_init() is
> just moving it around from what I see)
>
>> Moreover, let's stick to modern kernel driver coding standards. I don't
>> think that "I want this patchset merged so badly" is really a good excuse
>> to get around it. After all, there would be no GKH's staging tree, if
>> nobody cared about quality in mainline.
>
> And with my quality hat on, I could say that I'm not too fond of
> unused (or 1:1 client to user) abstractions.  That is something that
> should be introduced as we merge our 2nd or 3rd bridge.
>
> BR,
> -R
>
>> Best regards,
>> Tomasz
>>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 31/32] drm/exynos: Move lvds bridge discovery into DP driver
  2013-11-30  5:18     ` Inki Dae
@ 2013-11-30 12:27       ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-11-30 12:27 UTC (permalink / raw)
  To: dri-devel; +Cc: marcheu

Hi Inki,

On Saturday 30 of November 2013 14:18:08 Inki Dae wrote:
> Hi Tomasz,
> 
> Thanks for review,

You're welcome.

> 
> 2013/11/30 Tomasz Figa <t.figa@samsung.com>:
> > Hi Sean,
> >
> > On Tuesday 29 of October 2013 12:13:17 Sean Paul wrote:
> >> This patch moves the lvds bridge discovery and connector pre-emption
> >> code from exynos common code into the dp driver (since the bridge is
> >> only applicable for dp).
> >>
> >> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> >> ---
> >>
> >> Changes in v3:
> >>       - Added to the patchset
> >>
> >>  drivers/gpu/drm/exynos/exynos_dp_core.c  | 41 ++++++++++++++++++++++++++++++++
> >>  drivers/gpu/drm/exynos/exynos_drm_core.c | 41 --------------------------------
> >>  2 files changed, 41 insertions(+), 41 deletions(-)
> >>
> >
> > Well, DRM bridge infrastructure is useful for more than just DP. Currently
> > there are several platforms that could use it with DSI as well, e.g.
> 
> In case that some board with DSI bus needs this LVDS bridge, the
> bridge type would be MIPI-DSI to LVDS Display bridge. So I think
> moving this lvds stuff into eDP driver is reasonable becasue the
> normal DSI bus cannot use this LVDS bridge, and this bridge (eDP to
> LVDS) would be for eDP bus. BTW, Sean, why not implementing this lvds
> codes to eDP driver without previous related patch? that seems
> unnecessary work.

I don't mean this particular bridge chip, but rather the bridge binding
infrastructure. Anyway, having such hacks just in the DP driver is
better than in Exynos DRM core and since we don't use DP on our platforms
it doesn't bother me that much. So, if you really insist, I'm okay with
this, just place all the bridge related code in this driver already, as
Inki suggests.

> 
> > Trats, Trats2, Arndale. With a simple abstraction worth of one or at most
> > two days of work, we could get something that would cover much more than
> > just a single Chromebook.
> 
> I also thought a better way is to use simple abstraction layer. But
> the abstraction layer I thought was the case that lvds binding is done
> in this lvds driver itself so drm connector should call some bridge
> related functions of the abstraction layer. But it seems that other
> maintainers don't agree to this way. :(
> 
> Anyway, we can say the use of lvds bridge is dependent on board but
> actually, the use of lvds bridge would be more dependent on bus device
> or lcd panel attached to the board. So my opinion is to bind dt in the
> bus or lcd panel drivers that need lvds bridge. If dt binding of lvds
> bridge cannot be done itself, Sean's way is reasonable to me except
> the unnecessary patch.

Well, I don't see why DT bindings couldn't be made for this. We already
have bindings for video-interfaces (the so called v4l2 bindings), bindings
for the LVDS bridge itself would be mostly device-specific, although we
even already have bindings for display timings.

Anyway, if even DRM people don't care, why should I? Just do what you want
as long as it doesn't break other hardware.

Best regards,
Tomasz

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

* Re: [PATCH v3 28/32] drm/exynos: Implement drm_connector in hdmi directly
  2013-11-29 15:58   ` Tomasz Figa
@ 2013-12-02  9:46     ` Thierry Reding
  2013-12-02  9:54       ` Tomasz Figa
  0 siblings, 1 reply; 130+ messages in thread
From: Thierry Reding @ 2013-12-02  9:46 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: marcheu, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1020 bytes --]

On Fri, Nov 29, 2013 at 04:58:46PM +0100, Tomasz Figa wrote:
> On Tuesday 29 of October 2013 12:13:14 Sean Paul wrote:
[...]
> > diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
[...]
> > @@ -811,11 +816,60 @@ static int hdmi_check_mode(struct exynos_drm_display *display,
> >  
> >  	ret = mixer_check_mode(mode);
> >  	if (ret)
> > -		return ret;
> > +		return MODE_BAD;
> 
> Is there a need to define custom return values, instead of returning 0 or
> a standard error code depending on whether the mode is correct?

That's not a custom return value. It's one of the values in the
drm_mode_status enumeration (include/drm/drm_crtc.h). They are used to
transport more meaning than one of the standard error codes. In this
case one could argue that MODE_BAD doesn't transport very much meaning,
though, and I think it would be more useful to modify mixer_check_mode()
to return a specific MODE_* value rather than one of the standard error
codes.

Thierry

[-- Attachment #1.2: Type: application/pgp-signature, Size: 836 bytes --]

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

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

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

* Re: [PATCH v3 28/32] drm/exynos: Implement drm_connector in hdmi directly
  2013-12-02  9:46     ` Thierry Reding
@ 2013-12-02  9:54       ` Tomasz Figa
  0 siblings, 0 replies; 130+ messages in thread
From: Tomasz Figa @ 2013-12-02  9:54 UTC (permalink / raw)
  To: dri-devel; +Cc: marcheu

On Monday 02 of December 2013 10:46:37 Thierry Reding wrote:
> On Fri, Nov 29, 2013 at 04:58:46PM +0100, Tomasz Figa wrote:
> > On Tuesday 29 of October 2013 12:13:14 Sean Paul wrote:
> [...]
> > > diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
> [...]
> > > @@ -811,11 +816,60 @@ static int hdmi_check_mode(struct exynos_drm_display *display,
> > >  
> > >  	ret = mixer_check_mode(mode);
> > >  	if (ret)
> > > -		return ret;
> > > +		return MODE_BAD;
> > 
> > Is there a need to define custom return values, instead of returning 0 or
> > a standard error code depending on whether the mode is correct?
> 
> That's not a custom return value. It's one of the values in the
> drm_mode_status enumeration (include/drm/drm_crtc.h). They are used to
> transport more meaning than one of the standard error codes.

OK. Strange thing is that LXR doesn't index them.

> In this
> case one could argue that MODE_BAD doesn't transport very much meaning,
> though, and I think it would be more useful to modify mixer_check_mode()
> to return a specific MODE_* value rather than one of the standard error
> codes.

Right.

Best regards,
Tomasz

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

* Re: [PATCH v3 13/32] drm/exynos: hdmi: remove the i2c drivers and use devtree
  2013-11-29 10:24         ` Thierry Reding
@ 2013-12-03  0:37           ` Olof Johansson
  0 siblings, 0 replies; 130+ messages in thread
From: Olof Johansson @ 2013-12-03  0:37 UTC (permalink / raw)
  To: Thierry Reding; +Cc: Stéphane Marchesin, DRI mailing list

On Fri, Nov 29, 2013 at 2:24 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Thu, Nov 28, 2013 at 02:30:24PM +0100, Tomasz Figa wrote:
>> On Monday 11 of November 2013 09:44:27 Thierry Reding wrote:
>> > On Sun, Nov 10, 2013 at 09:46:02PM +0100, Tomasz Figa wrote:
>> > [...]
>> > > On Tuesday 29 of October 2013 12:12:59 Sean Paul wrote:
>> > [...]
>> > > [snip]
>> > > > @@ -1957,21 +1943,30 @@ static int hdmi_probe(struct platform_device *pdev)
>> > > >         }
>> > > >
>> > > >         /* DDC i2c driver */
>> > > > -       if (i2c_add_driver(&ddc_driver)) {
>> > > > -               DRM_ERROR("failed to register ddc i2c driver\n");
>> > > > -               return -ENOENT;
>> > > > +       ddc_node = of_find_node_by_name(NULL, "hdmiddc");
>> > >
>> > > This is wrong. You shall not reference a device tree node by its name,
>> > > except some very specific well-defined cases, such as cpus or memory
>> > > nodes.
>> > >
>> > > A solution closest to yours, but correct, would be to use the same match
>> > > table as in the I2C driver you are removing and call
>> > > of_find_matching_node().
>> >
>> > Isn't the correct solution to use a phandle? That might need the binding
>> > to change in a backwards incompatible way.
>>
>> Yes, phandle is an even better option as it can point you precisely to the
>> node you are interested in, but this will be incompatible, meaning that
>> you would have to support both variants anyway.
>
> Oh come on. If a phandle is the right way to do it, then we should just
> do it. Will it really be so difficult to carry code for both variants?
> If nothing else it will at least set a good example and reduce the risk
> of people doing the same mistakes over and over again.
>
> Adding the right binding also gives you a way to start deprecating the
> wrong one and eventually remove it. The longer you wait, the more people
> will start to use the existing, broken binding and removing it will only
> become more difficult over time.
>
>> > Then again, if something as
>> > simple as specifying a DDC I2C bus causes the binding to change in a
>> > backwards incompatible way then it can't have been a very good binding
>> > in the first place, right? +1 for unstable DT bindings...
>>
>> Well, some of already existing bindings should have been definitely marked
>> unstable, as they haven't been thought and reviewed well enough, if at all
>> (especially reviewed, as we only started seriously reviewing DT bindings
>> not so long ago).
>>
>> Honestly, I'm not quite sure about this binding in particular, especially
>> how much it would be a problem if we broke compatibility. I mean, how much
>> tied to old DTBs are existing boards using this binding. The affected
>> boards are:
>>  - exynos5250-snow,
>>  - exynos5250-arndale,
>>  - exynos5250-smdk5250,
>>  - exynos5420-smdk5420.
>> The last three are most likely to be used only with DTB appended, so
>> I don't think that anyone would complain. However I'm not sure about the
>> first one, which is supposed to be a Chromebook if I'm not mistaken.
>
> Well, if it's a Chromebook it likely doesn't ship with a completely
> mainline kernel. That frees it from the stability requirements, doesn't
> it?

Correct, there are absolutely no stability requirements between
mainline and the chromium.org kernel.


-Olof

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

* Re: [PATCH v3 29/32] drm/exynos: Implement drm_connector directly in dp driver
  2013-10-29 16:13 ` [PATCH v3 29/32] drm/exynos: Implement drm_connector directly in dp driver Sean Paul
  2013-11-29 16:04   ` Tomasz Figa
@ 2013-12-03  4:45   ` Inki Dae
  2013-12-04  6:46     ` Inki Dae
  1 sibling, 1 reply; 130+ messages in thread
From: Inki Dae @ 2013-12-03  4:45 UTC (permalink / raw)
  To: Sean Paul; +Cc: Stéphane Marchesin, DRI mailing list

Hi Sean,


2013/10/30 Sean Paul <seanpaul@chromium.org>:
> This patch implements drm_connector directly in the dp driver, this will
> allow us to move away from the exynos_drm_connector layer.
>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
>
> Changes in v3:
>         - Added to the patchset
>
>  drivers/gpu/drm/exynos/exynos_dp_core.c | 99 ++++++++++++++++++++++++++++++---
>  drivers/gpu/drm/exynos/exynos_dp_core.h |  4 ++
>  2 files changed, 94 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
> index 476d3b0..139ea15 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp_core.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
> @@ -22,10 +22,15 @@
>  #include <video/of_videomode.h>
>
>  #include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
>
>  #include "exynos_drm_drv.h"
>  #include "exynos_dp_core.h"
>
> +#define ctx_from_connector(c)  container_of(c, struct exynos_dp_device, \
> +                                       connector)
> +
>  static int exynos_dp_init_dp(struct exynos_dp_device *dp)
>  {
>         exynos_dp_reset(dp);
> @@ -896,21 +901,98 @@ static void exynos_dp_hotplug(struct work_struct *work)
>                 dev_err(dp->dev, "unable to config video\n");
>  }
>
> -static bool exynos_dp_display_is_connected(struct exynos_drm_display *display)
> +static enum drm_connector_status exynos_dp_detect(
> +                               struct drm_connector *connector, bool force)
>  {
> -       return true;
> +       return connector_status_connected;

No, eDP can be hot-plugged. Check if lcd panel is connected or not,
and if connected then return connector_status_connected else
connector_status_disconnected. See the interrupt handler.

>  }
>
> -static void *exynos_dp_get_panel(struct exynos_drm_display *display)
> +static void exynos_dp_connector_destroy(struct drm_connector *connector)
>  {
> -       struct exynos_dp_device *dp = display->ctx;
> +}
> +
> +static struct drm_connector_funcs exynos_dp_connector_funcs = {
> +       .dpms = drm_helper_connector_dpms,
> +       .fill_modes = drm_helper_probe_single_connector_modes,
> +       .detect = exynos_dp_detect,
> +       .destroy = exynos_dp_connector_destroy,
> +};
> +
> +static int exynos_dp_get_modes(struct drm_connector *connector)
> +{
> +       struct exynos_dp_device *dp = ctx_from_connector(connector);
> +       struct drm_display_mode *mode;
> +
> +       mode = drm_mode_create(connector->dev);
> +       if (!mode) {
> +               DRM_ERROR("failed to create a new display mode.\n");
> +               return 0;
> +       }
>
> -       return &dp->panel;
> +       drm_display_mode_from_videomode(&dp->panel.vm, mode);
> +       mode->width_mm = dp->panel.width_mm;
> +       mode->height_mm = dp->panel.height_mm;
> +       connector->display_info.width_mm = mode->width_mm;
> +       connector->display_info.height_mm = mode->height_mm;
> +
> +       mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
> +       drm_mode_set_name(mode);
> +       drm_mode_probed_add(connector, mode);
> +
> +       return 1;
>  }
>
> -static int exynos_dp_check_mode(struct exynos_drm_display *display,
> +static int exynos_dp_mode_valid(struct drm_connector *connector,
>                         struct drm_display_mode *mode)
>  {
> +       return MODE_OK;
> +}
> +
> +static struct drm_encoder *exynos_dp_best_encoder(
> +                       struct drm_connector *connector)
> +{
> +       struct exynos_dp_device *dp = ctx_from_connector(connector);
> +
> +       return dp->encoder;

eDP context doesn't need a encoder as its member. And you can get best
encoder through connector->encoder.

> +}
> +
> +static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = {
> +       .get_modes = exynos_dp_get_modes,
> +       .mode_valid = exynos_dp_mode_valid,
> +       .best_encoder = exynos_dp_best_encoder,
> +};
> +
> +static int exynos_dp_initialize(struct exynos_drm_display *display,
> +                               struct drm_device *drm_dev)
> +{
> +       struct exynos_dp_device *dp = display->ctx;
> +
> +       dp->drm_dev = drm_dev;
> +
> +       return 0;
> +}
> +
> +static int exynos_dp_create_connector(struct exynos_drm_display *display,
> +                               struct drm_encoder *encoder)
> +{
> +       struct exynos_dp_device *dp = display->ctx;
> +       struct drm_connector *connector = &dp->connector;
> +       int ret;
> +
> +       dp->encoder = encoder;

Unnecessary line, Add connector->encoder = encoder instead.

> +       connector->polled = DRM_CONNECTOR_POLL_HPD;
> +
> +       ret = drm_connector_init(dp->drm_dev, connector,
> +                       &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP);
> +       if (ret) {
> +               DRM_ERROR("Failed to initialize connector with drm\n");
> +               return ret;
> +       }
> +
> +       drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs);
> +       drm_sysfs_connector_add(connector);
> +       drm_mode_connector_attach_encoder(connector, encoder);
> +
>         return 0;
>  }
>
> @@ -986,9 +1068,8 @@ static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
>  }
>
>  static struct exynos_drm_display_ops exynos_dp_display_ops = {
> -       .is_connected = exynos_dp_display_is_connected,
> -       .get_panel = exynos_dp_get_panel,
> -       .check_mode = exynos_dp_check_mode,
> +       .initialize = exynos_dp_initialize,
> +       .create_connector = exynos_dp_create_connector,
>         .dpms = exynos_dp_dpms,
>  };
>
> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h
> index 0c67c19..da3fa7e 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp_core.h
> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
> @@ -13,6 +13,7 @@
>  #ifndef _EXYNOS_DP_CORE_H
>  #define _EXYNOS_DP_CORE_H
>
> +#include <drm/drm_crtc.h>
>  #include <drm/exynos_drm.h>
>  #include <video/exynos_dp.h>
>
> @@ -36,6 +37,9 @@ struct link_train {
>
>  struct exynos_dp_device {
>         struct device           *dev;
> +       struct drm_device       *drm_dev;
> +       struct drm_connector    connector;
> +       struct drm_encoder      *encoder;

I don't see why eDP context needs encoder pointer.

>         struct clk              *clock;
>         unsigned int            irq;
>         void __iomem            *reg_base;
> --
> 1.8.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 30/32] drm/exynos: Implement drm_connector directly in vidi driver
  2013-10-29 16:13 ` [PATCH v3 30/32] drm/exynos: Implement drm_connector directly in vidi driver Sean Paul
  2013-11-29 16:13   ` Tomasz Figa
@ 2013-12-03  4:47   ` Inki Dae
  2013-12-04  6:47     ` Inki Dae
  1 sibling, 1 reply; 130+ messages in thread
From: Inki Dae @ 2013-12-03  4:47 UTC (permalink / raw)
  To: Sean Paul; +Cc: Stéphane Marchesin, DRI mailing list

2013/10/30 Sean Paul <seanpaul@chromium.org>:
> This patch implements drm_connector directly in the vidi
> driver, this will allow us to move away from the exynos_drm_connector
> layer.
>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
>
> Changes in v3:
>         - Added to the patchset
>
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c | 163 ++++++++++++++++++++-----------
>  1 file changed, 107 insertions(+), 56 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> index 7d79b6c..5104431 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> @@ -29,6 +29,8 @@
>  #define WINDOWS_NR             3
>
>  #define get_vidi_mgr(dev)      platform_get_drvdata(to_platform_device(dev))
> +#define ctx_from_connector(c)  container_of(c, struct vidi_context, \
> +                                       connector)
>
>  struct vidi_win_data {
>         unsigned int            offset_x;
> @@ -47,6 +49,8 @@ struct vidi_win_data {
>  struct vidi_context {
>         struct drm_device               *drm_dev;
>         struct drm_crtc                 *crtc;
> +       struct drm_encoder              *encoder;

Unnecessary member.

> +       struct drm_connector            connector;
>         struct vidi_win_data            win_data[WINDOWS_NR];
>         struct edid                     *raw_edid;
>         unsigned int                    clkdiv;
> @@ -86,62 +90,6 @@ static const char fake_edid_info[] = {
>         0x00, 0x00, 0x00, 0x06
>  };
>
> -static bool vidi_display_is_connected(struct exynos_drm_display *display)
> -{
> -       struct vidi_context *ctx = display->ctx;
> -
> -       /*
> -        * connection request would come from user side
> -        * to do hotplug through specific ioctl.
> -        */
> -       return ctx->connected ? true : false;
> -}
> -
> -static struct edid *vidi_get_edid(struct exynos_drm_display *display,
> -                       struct drm_connector *connector)
> -{
> -       struct vidi_context *ctx = display->ctx;
> -       struct edid *edid;
> -       int edid_len;
> -
> -       /*
> -        * the edid data comes from user side and it would be set
> -        * to ctx->raw_edid through specific ioctl.
> -        */
> -       if (!ctx->raw_edid) {
> -               DRM_DEBUG_KMS("raw_edid is null.\n");
> -               return ERR_PTR(-EFAULT);
> -       }
> -
> -       edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
> -       edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
> -       if (!edid) {
> -               DRM_DEBUG_KMS("failed to allocate edid\n");
> -               return ERR_PTR(-ENOMEM);
> -       }
> -
> -       return edid;
> -}
> -
> -static int vidi_check_mode(struct exynos_drm_display *display,
> -                       struct drm_display_mode *mode)
> -{
> -       /* TODO. */
> -
> -       return 0;
> -}
> -
> -static struct exynos_drm_display_ops vidi_display_ops = {
> -       .is_connected = vidi_display_is_connected,
> -       .get_edid = vidi_get_edid,
> -       .check_mode = vidi_check_mode,
> -};
> -
> -static struct exynos_drm_display vidi_display = {
> -       .type = EXYNOS_DISPLAY_TYPE_VIDI,
> -       .ops = &vidi_display_ops,
> -};
> -
>  static void vidi_apply(struct exynos_drm_manager *mgr)
>  {
>         struct vidi_context *ctx = mgr->ctx;
> @@ -536,6 +484,109 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
>         return 0;
>  }
>
> +static enum drm_connector_status vidi_detect(struct drm_connector *connector,
> +                       bool force)
> +{
> +       struct vidi_context *ctx = ctx_from_connector(connector);
> +
> +       /*
> +        * connection request would come from user side
> +        * to do hotplug through specific ioctl.
> +        */
> +       return ctx->connected ? connector_status_connected :
> +                       connector_status_disconnected;
> +}
> +
> +static void vidi_connector_destroy(struct drm_connector *connector)
> +{
> +}
> +
> +static struct drm_connector_funcs vidi_connector_funcs = {
> +       .dpms = drm_helper_connector_dpms,
> +       .fill_modes = drm_helper_probe_single_connector_modes,
> +       .detect = vidi_detect,
> +       .destroy = vidi_connector_destroy,
> +};
> +
> +static int vidi_get_modes(struct drm_connector *connector)
> +{
> +       struct vidi_context *ctx = ctx_from_connector(connector);
> +       struct edid *edid;
> +       int edid_len;
> +
> +       /*
> +        * the edid data comes from user side and it would be set
> +        * to ctx->raw_edid through specific ioctl.
> +        */
> +       if (!ctx->raw_edid) {
> +               DRM_DEBUG_KMS("raw_edid is null.\n");
> +               return -EFAULT;
> +       }
> +
> +       edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
> +       edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
> +       if (!edid) {
> +               DRM_DEBUG_KMS("failed to allocate edid\n");
> +               return -ENOMEM;
> +       }
> +
> +       drm_mode_connector_update_edid_property(connector, edid);
> +
> +       return drm_add_edid_modes(connector, edid);
> +}
> +
> +static int vidi_mode_valid(struct drm_connector *connector,
> +                       struct drm_display_mode *mode)
> +{
> +       return MODE_OK;
> +}
> +
> +static struct drm_encoder *vidi_best_encoder(struct drm_connector *connector)
> +{
> +       struct vidi_context *ctx = ctx_from_connector(connector);
> +
> +       return ctx->encoder;

Just return connector->encoder.

> +}
> +
> +static struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
> +       .get_modes = vidi_get_modes,
> +       .mode_valid = vidi_mode_valid,
> +       .best_encoder = vidi_best_encoder,
> +};
> +
> +static int vidi_create_connector(struct exynos_drm_display *display,
> +                               struct drm_encoder *encoder)
> +{
> +       struct vidi_context *ctx = display->ctx;
> +       struct drm_connector *connector = &ctx->connector;
> +       int ret;
> +
> +       ctx->encoder = encoder;

Add connector->encoder = encoder instead.

> +       connector->polled = DRM_CONNECTOR_POLL_HPD;
> +
> +       ret = drm_connector_init(ctx->drm_dev, connector,
> +                       &vidi_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
> +       if (ret) {
> +               DRM_ERROR("Failed to initialize connector with drm\n");
> +               return ret;
> +       }
> +
> +       drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
> +       drm_sysfs_connector_add(connector);
> +       drm_mode_connector_attach_encoder(connector, encoder);
> +
> +       return 0;
> +}
> +
> +static struct exynos_drm_display_ops vidi_display_ops = {
> +       .create_connector = vidi_create_connector,
> +};
> +
> +static struct exynos_drm_display vidi_display = {
> +       .type = EXYNOS_DISPLAY_TYPE_VIDI,
> +       .ops = &vidi_display_ops,
> +};
> +
>  static int vidi_probe(struct platform_device *pdev)
>  {
>         struct device *dev = &pdev->dev;
> --
> 1.8.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 27/32] drm/exynos: Add create_connector callback
  2013-10-29 16:13 ` [PATCH v3 27/32] drm/exynos: Add create_connector callback Sean Paul
  2013-11-11  2:19   ` Tomasz Figa
@ 2013-12-03  5:01   ` Inki Dae
  1 sibling, 0 replies; 130+ messages in thread
From: Inki Dae @ 2013-12-03  5:01 UTC (permalink / raw)
  To: Sean Paul; +Cc: Stéphane Marchesin, DRI mailing list

2013/10/30 Sean Paul <seanpaul@chromium.org>:
> This creates a new display hook called create_connector. The purpose is
> to allow the display driver to create its own drm_connector instead of
> using the exynos_drm_connector. This moves things closer to completely
> removing the exynos_drm_connector abstraction.
>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
>
> Changes in v2: None
> Changes in v3:
>         - Added to the patchset
>
>  drivers/gpu/drm/exynos/exynos_drm_core.c | 3 +++
>  drivers/gpu/drm/exynos/exynos_drm_drv.h  | 2 ++
>  2 files changed, 5 insertions(+)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
> index e76098d..1a60f5a 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_core.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
> @@ -87,6 +87,9 @@ static int exynos_drm_create_enc_conn(struct drm_device *dev,
>                         return 0;
>         }
>
> +       if (display->ops->create_connector)
> +               return display->ops->create_connector(display, encoder);

There would be display->connector = connector below. But
create_connector callback of connector drivers doesn't set a new
connector to display->connector. So if you return here, this code has
no consistency.  I think we can remove below codes for creating a new
connector. If connector drivers have create_connector callback, the
below codes wouldn't be needed anymore.

> +
>         /*
>          * create and initialize a connector for this sub driver and
>          * attach the encoder created above to the connector.
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> index f3e18d1..db6a3b2 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> @@ -139,6 +139,8 @@ struct exynos_drm_display;
>  struct exynos_drm_display_ops {
>         int (*initialize)(struct exynos_drm_display *display,
>                                 struct drm_device *drm_dev);
> +       int (*create_connector)(struct exynos_drm_display *display,
> +                               struct drm_encoder *encoder);
>         void (*remove)(struct exynos_drm_display *display);
>         bool (*is_connected)(struct exynos_drm_display *display);
>         void (*get_max_resol)(struct exynos_drm_display *display,
> --
> 1.8.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv
  2013-11-29 17:05                   ` Tomasz Figa
  2013-11-29 18:35                     ` Rob Clark
@ 2013-12-03 21:38                     ` Sean Paul
  1 sibling, 0 replies; 130+ messages in thread
From: Sean Paul @ 2013-12-03 21:38 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: Stéphane Marchesin, Laurent Pinchart, dri-devel

On Fri, Nov 29, 2013 at 12:05 PM, Tomasz Figa <t.figa@samsung.com> wrote:
> On Friday 29 of November 2013 09:13:19 Rob Clark wrote:
>> On Fri, Nov 29, 2013 at 4:10 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
>> > I would mostly agree with you if we were discussing SoC-internal
>> > components here. Mostly, because the ARM world is more complex and you
>> > can see the same IP across completely different SoCs from different
>> > vendors.
>> >
>> > However, the topic here is about external devices, outside the SoC, such
>> > as different kind of bridges, like the PTN3460 eDP to LVDS bridge, which
>> > are likely to be reused across different platforms. Similar thing is with
>> > using different bridges on different boards using the same SoC platform.
>> > I don't think having an abstraction here would be any overabstraction at
>> > all. Anything less would be a huge "underabstraction" in fact.
>>
>>
>> I think no one is arguing that we don't eventually need some better
>> abstraction.  But as long as it is one-bridge and one-user, if the
>> patches otherwise have merit, add functionality that was missing
>> before and don't regress, then lack of infrastructure to match up
>> bridge and driver isn't something I will care about too much yet.
>> Things are allowed to be in-progress.  A missing abstraction for a 1:1
>> relationship is fine.
>
> This is not just one-bridge, one-user. This is about users of Exynos DRM
> we already have in-tree, such as Trats, Trats2 or Arndale, that the DRM
> bridge infrastructure could be used on and finally allowing to have
> display support on them. Of course you could merge this as is and
> then let someone else completely rewrite it (most likely in the same
> release cycle), but since it's not really much more work, I don't
> think there is any sense.
>
> Moreover, let's stick to modern kernel driver coding standards. I don't
> think that "I want this patchset merged so badly" is really a good excuse
> to get around it. After all, there would be no GKH's staging tree, if
> nobody cared about quality in mainline.
>

I don't see how this change makes the code quality any worse, it's a
noop on boards without the bridge.

I proposed a general solution in v2, to which Laurent said he was
working on a patch. I didn't feel the need to do anything more general
here since it would be more work to rip it out later.

I am happy to pick up this work, however:
- I don't want to step on Laurent's toes
- It's probably more useful to have a general framework with 2 or more
bridges, so I don't think it should be a blocker on the ptn stuff

Sean



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

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

* Re: [PATCH v3 29/32] drm/exynos: Implement drm_connector directly in dp driver
  2013-12-03  4:45   ` Inki Dae
@ 2013-12-04  6:46     ` Inki Dae
  0 siblings, 0 replies; 130+ messages in thread
From: Inki Dae @ 2013-12-04  6:46 UTC (permalink / raw)
  To: Sean Paul; +Cc: Stéphane Marchesin, DRI mailing list

2013/12/3 Inki Dae <inki.dae@samsung.com>:
> Hi Sean,
>
>
> 2013/10/30 Sean Paul <seanpaul@chromium.org>:
>> This patch implements drm_connector directly in the dp driver, this will
>> allow us to move away from the exynos_drm_connector layer.
>>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>
>> Changes in v3:
>>         - Added to the patchset
>>
>>  drivers/gpu/drm/exynos/exynos_dp_core.c | 99 ++++++++++++++++++++++++++++++---
>>  drivers/gpu/drm/exynos/exynos_dp_core.h |  4 ++
>>  2 files changed, 94 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
>> index 476d3b0..139ea15 100644
>> --- a/drivers/gpu/drm/exynos/exynos_dp_core.c
>> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
>> @@ -22,10 +22,15 @@
>>  #include <video/of_videomode.h>
>>
>>  #include <drm/drmP.h>
>> +#include <drm/drm_crtc.h>
>> +#include <drm/drm_crtc_helper.h>
>>
>>  #include "exynos_drm_drv.h"
>>  #include "exynos_dp_core.h"
>>
>> +#define ctx_from_connector(c)  container_of(c, struct exynos_dp_device, \
>> +                                       connector)
>> +
>>  static int exynos_dp_init_dp(struct exynos_dp_device *dp)
>>  {
>>         exynos_dp_reset(dp);
>> @@ -896,21 +901,98 @@ static void exynos_dp_hotplug(struct work_struct *work)
>>                 dev_err(dp->dev, "unable to config video\n");
>>  }
>>
>> -static bool exynos_dp_display_is_connected(struct exynos_drm_display *display)
>> +static enum drm_connector_status exynos_dp_detect(
>> +                               struct drm_connector *connector, bool force)
>>  {
>> -       return true;
>> +       return connector_status_connected;
>
> No, eDP can be hot-plugged. Check if lcd panel is connected or not,
> and if connected then return connector_status_connected else
> connector_status_disconnected. See the interrupt handler.
>
>>  }
>>
>> -static void *exynos_dp_get_panel(struct exynos_drm_display *display)
>> +static void exynos_dp_connector_destroy(struct drm_connector *connector)
>>  {
>> -       struct exynos_dp_device *dp = display->ctx;
>> +}
>> +
>> +static struct drm_connector_funcs exynos_dp_connector_funcs = {
>> +       .dpms = drm_helper_connector_dpms,
>> +       .fill_modes = drm_helper_probe_single_connector_modes,
>> +       .detect = exynos_dp_detect,
>> +       .destroy = exynos_dp_connector_destroy,
>> +};
>> +
>> +static int exynos_dp_get_modes(struct drm_connector *connector)
>> +{
>> +       struct exynos_dp_device *dp = ctx_from_connector(connector);
>> +       struct drm_display_mode *mode;
>> +
>> +       mode = drm_mode_create(connector->dev);
>> +       if (!mode) {
>> +               DRM_ERROR("failed to create a new display mode.\n");
>> +               return 0;
>> +       }
>>
>> -       return &dp->panel;
>> +       drm_display_mode_from_videomode(&dp->panel.vm, mode);
>> +       mode->width_mm = dp->panel.width_mm;
>> +       mode->height_mm = dp->panel.height_mm;
>> +       connector->display_info.width_mm = mode->width_mm;
>> +       connector->display_info.height_mm = mode->height_mm;
>> +
>> +       mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
>> +       drm_mode_set_name(mode);
>> +       drm_mode_probed_add(connector, mode);
>> +
>> +       return 1;
>>  }
>>
>> -static int exynos_dp_check_mode(struct exynos_drm_display *display,
>> +static int exynos_dp_mode_valid(struct drm_connector *connector,
>>                         struct drm_display_mode *mode)
>>  {
>> +       return MODE_OK;
>> +}
>> +
>> +static struct drm_encoder *exynos_dp_best_encoder(
>> +                       struct drm_connector *connector)
>> +{
>> +       struct exynos_dp_device *dp = ctx_from_connector(connector);
>> +
>> +       return dp->encoder;
>
> eDP context doesn't need a encoder as its member. And you can get best
> encoder through connector->encoder.
>

Ah~ when drm is closed, connector->encoder could be NULL so it is
needed to connect again.

Sorry.


>> +}
>> +
>> +static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = {
>> +       .get_modes = exynos_dp_get_modes,
>> +       .mode_valid = exynos_dp_mode_valid,
>> +       .best_encoder = exynos_dp_best_encoder,
>> +};
>> +
>> +static int exynos_dp_initialize(struct exynos_drm_display *display,
>> +                               struct drm_device *drm_dev)
>> +{
>> +       struct exynos_dp_device *dp = display->ctx;
>> +
>> +       dp->drm_dev = drm_dev;
>> +
>> +       return 0;
>> +}
>> +
>> +static int exynos_dp_create_connector(struct exynos_drm_display *display,
>> +                               struct drm_encoder *encoder)
>> +{
>> +       struct exynos_dp_device *dp = display->ctx;
>> +       struct drm_connector *connector = &dp->connector;
>> +       int ret;
>> +
>> +       dp->encoder = encoder;
>
> Unnecessary line, Add connector->encoder = encoder instead.

Ignore it.

>
>> +       connector->polled = DRM_CONNECTOR_POLL_HPD;
>> +
>> +       ret = drm_connector_init(dp->drm_dev, connector,
>> +                       &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP);
>> +       if (ret) {
>> +               DRM_ERROR("Failed to initialize connector with drm\n");
>> +               return ret;
>> +       }
>> +
>> +       drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs);
>> +       drm_sysfs_connector_add(connector);
>> +       drm_mode_connector_attach_encoder(connector, encoder);
>> +
>>         return 0;
>>  }
>>
>> @@ -986,9 +1068,8 @@ static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
>>  }
>>
>>  static struct exynos_drm_display_ops exynos_dp_display_ops = {
>> -       .is_connected = exynos_dp_display_is_connected,
>> -       .get_panel = exynos_dp_get_panel,
>> -       .check_mode = exynos_dp_check_mode,
>> +       .initialize = exynos_dp_initialize,
>> +       .create_connector = exynos_dp_create_connector,
>>         .dpms = exynos_dp_dpms,
>>  };
>>
>> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h
>> index 0c67c19..da3fa7e 100644
>> --- a/drivers/gpu/drm/exynos/exynos_dp_core.h
>> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
>> @@ -13,6 +13,7 @@
>>  #ifndef _EXYNOS_DP_CORE_H
>>  #define _EXYNOS_DP_CORE_H
>>
>> +#include <drm/drm_crtc.h>
>>  #include <drm/exynos_drm.h>
>>  #include <video/exynos_dp.h>
>>
>> @@ -36,6 +37,9 @@ struct link_train {
>>
>>  struct exynos_dp_device {
>>         struct device           *dev;
>> +       struct drm_device       *drm_dev;
>> +       struct drm_connector    connector;
>> +       struct drm_encoder      *encoder;
>
> I don't see why eDP context needs encoder pointer.

Ignore it.

>
>>         struct clk              *clock;
>>         unsigned int            irq;
>>         void __iomem            *reg_base;
>> --
>> 1.8.4
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 30/32] drm/exynos: Implement drm_connector directly in vidi driver
  2013-12-03  4:47   ` Inki Dae
@ 2013-12-04  6:47     ` Inki Dae
  0 siblings, 0 replies; 130+ messages in thread
From: Inki Dae @ 2013-12-04  6:47 UTC (permalink / raw)
  To: Sean Paul; +Cc: Stéphane Marchesin, DRI mailing list

Sorry, there was my missing point. Ignore the below my comments.

Thanks,
Inki Dae


2013/12/3 Inki Dae <inki.dae@samsung.com>:
> 2013/10/30 Sean Paul <seanpaul@chromium.org>:
>> This patch implements drm_connector directly in the vidi
>> driver, this will allow us to move away from the exynos_drm_connector
>> layer.
>>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>
>> Changes in v3:
>>         - Added to the patchset
>>
>>  drivers/gpu/drm/exynos/exynos_drm_vidi.c | 163 ++++++++++++++++++++-----------
>>  1 file changed, 107 insertions(+), 56 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>> index 7d79b6c..5104431 100644
>> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
>> @@ -29,6 +29,8 @@
>>  #define WINDOWS_NR             3
>>
>>  #define get_vidi_mgr(dev)      platform_get_drvdata(to_platform_device(dev))
>> +#define ctx_from_connector(c)  container_of(c, struct vidi_context, \
>> +                                       connector)
>>
>>  struct vidi_win_data {
>>         unsigned int            offset_x;
>> @@ -47,6 +49,8 @@ struct vidi_win_data {
>>  struct vidi_context {
>>         struct drm_device               *drm_dev;
>>         struct drm_crtc                 *crtc;
>> +       struct drm_encoder              *encoder;
>
> Unnecessary member.
>
>> +       struct drm_connector            connector;
>>         struct vidi_win_data            win_data[WINDOWS_NR];
>>         struct edid                     *raw_edid;
>>         unsigned int                    clkdiv;
>> @@ -86,62 +90,6 @@ static const char fake_edid_info[] = {
>>         0x00, 0x00, 0x00, 0x06
>>  };
>>
>> -static bool vidi_display_is_connected(struct exynos_drm_display *display)
>> -{
>> -       struct vidi_context *ctx = display->ctx;
>> -
>> -       /*
>> -        * connection request would come from user side
>> -        * to do hotplug through specific ioctl.
>> -        */
>> -       return ctx->connected ? true : false;
>> -}
>> -
>> -static struct edid *vidi_get_edid(struct exynos_drm_display *display,
>> -                       struct drm_connector *connector)
>> -{
>> -       struct vidi_context *ctx = display->ctx;
>> -       struct edid *edid;
>> -       int edid_len;
>> -
>> -       /*
>> -        * the edid data comes from user side and it would be set
>> -        * to ctx->raw_edid through specific ioctl.
>> -        */
>> -       if (!ctx->raw_edid) {
>> -               DRM_DEBUG_KMS("raw_edid is null.\n");
>> -               return ERR_PTR(-EFAULT);
>> -       }
>> -
>> -       edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
>> -       edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
>> -       if (!edid) {
>> -               DRM_DEBUG_KMS("failed to allocate edid\n");
>> -               return ERR_PTR(-ENOMEM);
>> -       }
>> -
>> -       return edid;
>> -}
>> -
>> -static int vidi_check_mode(struct exynos_drm_display *display,
>> -                       struct drm_display_mode *mode)
>> -{
>> -       /* TODO. */
>> -
>> -       return 0;
>> -}
>> -
>> -static struct exynos_drm_display_ops vidi_display_ops = {
>> -       .is_connected = vidi_display_is_connected,
>> -       .get_edid = vidi_get_edid,
>> -       .check_mode = vidi_check_mode,
>> -};
>> -
>> -static struct exynos_drm_display vidi_display = {
>> -       .type = EXYNOS_DISPLAY_TYPE_VIDI,
>> -       .ops = &vidi_display_ops,
>> -};
>> -
>>  static void vidi_apply(struct exynos_drm_manager *mgr)
>>  {
>>         struct vidi_context *ctx = mgr->ctx;
>> @@ -536,6 +484,109 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
>>         return 0;
>>  }
>>
>> +static enum drm_connector_status vidi_detect(struct drm_connector *connector,
>> +                       bool force)
>> +{
>> +       struct vidi_context *ctx = ctx_from_connector(connector);
>> +
>> +       /*
>> +        * connection request would come from user side
>> +        * to do hotplug through specific ioctl.
>> +        */
>> +       return ctx->connected ? connector_status_connected :
>> +                       connector_status_disconnected;
>> +}
>> +
>> +static void vidi_connector_destroy(struct drm_connector *connector)
>> +{
>> +}
>> +
>> +static struct drm_connector_funcs vidi_connector_funcs = {
>> +       .dpms = drm_helper_connector_dpms,
>> +       .fill_modes = drm_helper_probe_single_connector_modes,
>> +       .detect = vidi_detect,
>> +       .destroy = vidi_connector_destroy,
>> +};
>> +
>> +static int vidi_get_modes(struct drm_connector *connector)
>> +{
>> +       struct vidi_context *ctx = ctx_from_connector(connector);
>> +       struct edid *edid;
>> +       int edid_len;
>> +
>> +       /*
>> +        * the edid data comes from user side and it would be set
>> +        * to ctx->raw_edid through specific ioctl.
>> +        */
>> +       if (!ctx->raw_edid) {
>> +               DRM_DEBUG_KMS("raw_edid is null.\n");
>> +               return -EFAULT;
>> +       }
>> +
>> +       edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
>> +       edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
>> +       if (!edid) {
>> +               DRM_DEBUG_KMS("failed to allocate edid\n");
>> +               return -ENOMEM;
>> +       }
>> +
>> +       drm_mode_connector_update_edid_property(connector, edid);
>> +
>> +       return drm_add_edid_modes(connector, edid);
>> +}
>> +
>> +static int vidi_mode_valid(struct drm_connector *connector,
>> +                       struct drm_display_mode *mode)
>> +{
>> +       return MODE_OK;
>> +}
>> +
>> +static struct drm_encoder *vidi_best_encoder(struct drm_connector *connector)
>> +{
>> +       struct vidi_context *ctx = ctx_from_connector(connector);
>> +
>> +       return ctx->encoder;
>
> Just return connector->encoder.
>
>> +}
>> +
>> +static struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
>> +       .get_modes = vidi_get_modes,
>> +       .mode_valid = vidi_mode_valid,
>> +       .best_encoder = vidi_best_encoder,
>> +};
>> +
>> +static int vidi_create_connector(struct exynos_drm_display *display,
>> +                               struct drm_encoder *encoder)
>> +{
>> +       struct vidi_context *ctx = display->ctx;
>> +       struct drm_connector *connector = &ctx->connector;
>> +       int ret;
>> +
>> +       ctx->encoder = encoder;
>
> Add connector->encoder = encoder instead.
>
>> +       connector->polled = DRM_CONNECTOR_POLL_HPD;
>> +
>> +       ret = drm_connector_init(ctx->drm_dev, connector,
>> +                       &vidi_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
>> +       if (ret) {
>> +               DRM_ERROR("Failed to initialize connector with drm\n");
>> +               return ret;
>> +       }
>> +
>> +       drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
>> +       drm_sysfs_connector_add(connector);
>> +       drm_mode_connector_attach_encoder(connector, encoder);
>> +
>> +       return 0;
>> +}
>> +
>> +static struct exynos_drm_display_ops vidi_display_ops = {
>> +       .create_connector = vidi_create_connector,
>> +};
>> +
>> +static struct exynos_drm_display vidi_display = {
>> +       .type = EXYNOS_DISPLAY_TYPE_VIDI,
>> +       .ops = &vidi_display_ops,
>> +};
>> +
>>  static int vidi_probe(struct platform_device *pdev)
>>  {
>>         struct device *dev = &pdev->dev;
>> --
>> 1.8.4
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 19/32] drm/exynos: Use mode_set to configure fimd
  2013-11-15 13:53     ` Daniel Kurtz
  2013-11-28 22:57       ` Tomasz Figa
@ 2013-12-04 22:37       ` Sean Paul
  1 sibling, 0 replies; 130+ messages in thread
From: Sean Paul @ 2013-12-04 22:37 UTC (permalink / raw)
  To: Daniel Kurtz; +Cc: Stéphane Marchesin, dri-devel

On Fri, Nov 15, 2013 at 8:53 AM, Daniel Kurtz <djkurtz@chromium.org> wrote:
> Hi Sean, Tomasz,
>
> On Mon, Nov 11, 2013 at 6:03 AM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
>> Hi Sean,
>>
>> On Tuesday 29 of October 2013 12:13:05 Sean Paul wrote:
>>> This patch uses the mode passed into mode_set to configure fimd instead
>>> of directly using the panel from context. This will allow us to move
>>> the exynos_drm_display implementation from fimd into the DP driver
>>> where it belongs.
>>
>> Remember that DP is not the only possible way to connect a display driven
>> by FIMD. You also have the direct (RGB and i80) and DSI interfaces.
>>
>> Also, please see my comments inline.
>>
>>>
>>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>>> ---
>>>
>>> Changes in v2: None
>>> Changes in v3: None
>>>
>>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 159 ++++++++++++++++++-------------
>>>  1 file changed, 91 insertions(+), 68 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>>> index d2b8ccb..f69d6e5 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
>>> @@ -104,6 +104,20 @@ struct fimd_win_data {
>>>       bool                    resume;
>>>  };
>>>
>>> +struct fimd_mode_data {
>>> +     unsigned                vtotal;
>>
>> For consistency with rest of the code, unsigned int would prefered.
>>
>> However, I'm not sure what is this struct for, since it does not store
>> neither raw register values (1 needs to be subtracted from them) nor
>> any values hard to compute at commit time (maybe except clkdiv, but still
>> how often commit would be called?).
>>
>>> +     unsigned                vdisplay;
>>> +     unsigned                vsync_len;
>>> +     unsigned                vbpd;
>>> +     unsigned                vfpd;
>>> +     unsigned                htotal;
>>> +     unsigned                hdisplay;
>>> +     unsigned                hsync_len;
>>> +     unsigned                hbpd;
>>> +     unsigned                hfpd;
>>> +     u32                     clkdiv;
>>> +};
>>> +
>>>  struct fimd_context {
>>>       struct device                   *dev;
>>>       struct drm_device               *drm_dev;
>>> @@ -112,8 +126,8 @@ struct fimd_context {
>>>       struct clk                      *bus_clk;
>>>       struct clk                      *lcd_clk;
>>>       void __iomem                    *regs;
>>> +     struct fimd_mode_data           mode;
>>>       struct fimd_win_data            win_data[WINDOWS_NR];
>>> -     unsigned int                    clkdiv;
>>>       unsigned int                    default_win;
>>>       unsigned long                   irq_flags;
>>>       u32                             vidcon0;
>>> @@ -560,11 +574,56 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
>>>       mutex_unlock(&ctx->lock);
>>>  }
>>>
>>> +static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
>>> +             const struct drm_display_mode *mode)
>>> +{
>>> +     unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
>>> +     u32 clkdiv;
>>> +
>>> +     /* Find the clock divider value that gets us closest to ideal_clk */
>>> +     clkdiv = DIV_ROUND_CLOSEST(clk_get_rate(ctx->lcd_clk), ideal_clk);
>>
>> This is a functional change unrelated to $subject. Before this patch,
>> DIV_ROUND_UP() had been used.
>>
>>> +
>>> +     return (clkdiv < 0x100) ? clkdiv : 0xff;
>>> +}
>>> +
>>> +static bool fimd_mode_fixup(struct exynos_drm_manager *mgr,
>>> +             const struct drm_display_mode *mode,
>>> +             struct drm_display_mode *adjusted_mode)
>>> +{
>>> +     if (adjusted_mode->vrefresh == 0)
>>> +             adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE;
>
> The actual pixel clock will be clk_get_rate(ctx->lcd_clk) / clkdiv.
> Should we also be adjusting the "clock" field of adjusted_mode here?
>

Seems like we'll need the patchset you just merged in the chromium
tree to fix the mismatch between userspace/kernel (to avoid the
multiple modesets on boot). I don't think it'll make any functional
difference, maybe you can post that as a followup?

>>> +
>>> +     return true;
>>> +}
>>> +
>>> +static void fimd_mode_set(struct exynos_drm_manager *mgr,
>>> +             const struct drm_display_mode *in_mode)
>>> +{
>>> +     struct fimd_context *ctx = mgr->ctx;
>>> +     struct fimd_mode_data *mode = &ctx->mode;
>>> +     int hblank, vblank;
>>> +
>>> +     vblank = in_mode->crtc_vblank_end - in_mode->crtc_vblank_start;
>>> +     mode->vtotal = in_mode->crtc_vtotal;
>>> +     mode->vdisplay = in_mode->crtc_vdisplay;
>>> +     mode->vsync_len = in_mode->crtc_vsync_end - in_mode->crtc_vsync_start;
>>> +     mode->vbpd = (vblank - mode->vsync_len) / 2;
>>> +     mode->vfpd = vblank - mode->vsync_len - mode->vbpd;
>>> +
>>> +     hblank = in_mode->crtc_hblank_end - in_mode->crtc_hblank_start;
>>> +     mode->htotal = in_mode->crtc_htotal;
>>> +     mode->hdisplay = in_mode->crtc_hdisplay;
>>> +     mode->hsync_len = in_mode->crtc_hsync_end - in_mode->crtc_hsync_start;
>>> +     mode->hbpd = (hblank - mode->hsync_len) / 2;
>>> +     mode->hfpd = hblank - mode->hsync_len - mode->hbpd;
>>> +
>>> +     mode->clkdiv = fimd_calc_clkdiv(ctx, in_mode);
>>
>> What about simply copying contents of in_mode to driver context
>> and then calculating clkdiv at commit time? You could get rid
>> of the fimd_mode_data struct and most of this function.
>>

That makes sense, and I originally had it this way, but changed it in
response to some review feedback. The reason it was changed was to
avoid recomputing things every flip, however that seems like a
chromium-specific hack, so I'll change it back.

Sean


>> Otherwise, the patch looks fine.
>>
>> Best regards,
>> Tomasz
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/
       [not found]   ` <3513711.0qTZKxmOZX@flatron>
@ 2013-12-04 23:07     ` Sean Paul
  0 siblings, 0 replies; 130+ messages in thread
From: Sean Paul @ 2013-12-04 23:07 UTC (permalink / raw)
  To: Tomasz Figa; +Cc: dri-devel, Stéphane Marchesin

On Sun, Nov 10, 2013 at 8:32 PM, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> On Tuesday 29 of October 2013 12:13:07 Sean Paul wrote:
>> This patch moves the code from video/ to drm/
>
> Again, rationale should be mentioned in patch description.
>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>
>> Changes in v2: None
>> Changes in v3: None
>>
>>  drivers/gpu/drm/exynos/Kconfig          |    7 +
>>  drivers/gpu/drm/exynos/Makefile         |    1 +
>>  drivers/gpu/drm/exynos/exynos_dp_core.c | 1213 ++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/exynos/exynos_dp_core.h |  210 ++++++
>>  drivers/gpu/drm/exynos/exynos_dp_reg.c  | 1245 +++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/exynos/exynos_dp_reg.h  |  366 +++++++++
>>  drivers/video/exynos/Kconfig            |    7 -
>>  drivers/video/exynos/Makefile           |    1 -
>>  drivers/video/exynos/exynos_dp_core.c   | 1213 ------------------------------
>>  drivers/video/exynos/exynos_dp_core.h   |  210 ------
>>  drivers/video/exynos/exynos_dp_reg.c    | 1245 -------------------------------
>>  drivers/video/exynos/exynos_dp_reg.h    |  366 ---------
>>  12 files changed, 3042 insertions(+), 3042 deletions(-)
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c
>>  create mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.h
>>  delete mode 100644 drivers/video/exynos/exynos_dp_core.c
>>  delete mode 100644 drivers/video/exynos/exynos_dp_core.h
>>  delete mode 100644 drivers/video/exynos/exynos_dp_reg.c
>>  delete mode 100644 drivers/video/exynos/exynos_dp_reg.h
>>
>> diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
>> index 45b6ef5..3ace74f 100644
>> --- a/drivers/gpu/drm/exynos/Kconfig
>> +++ b/drivers/gpu/drm/exynos/Kconfig
>> @@ -30,6 +30,13 @@ config DRM_EXYNOS_FIMD
>>       help
>>         Choose this option if you want to use Exynos FIMD for DRM.
>>
>> +config DRM_EXYNOS_DP
>
> I would keep the symbol name as it was, so configs used by people remain
> valid.
>

I don't really want to do that. All of the other configs are named
DRM_EXYNOS_BLAH, DP should follow this convention. There are a few
ways around this:

1) Make DRM_EXYNOS_DP default to on if DRM_EXYNOS is selected
2) Make a shadow EXYNOS_DP config that selects DRM_EXYNOS_DP

Either of those work for you?

> Also, don't you need some kind of dependency on DRM_EXYNOS?
>

Yep, will do.

Sean


> Otherwise this patch is fine.
>
> Best regards,
> Tomasz
>

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

* Re: [PATCH v3 26/32] drm/exynos: Consolidate suspend/resume in drm_drv
  2013-10-29 16:13 ` [PATCH v3 26/32] drm/exynos: Consolidate suspend/resume in drm_drv Sean Paul
  2013-11-29 14:58   ` Tomasz Figa
@ 2013-12-19 16:48   ` Inki Dae
  1 sibling, 0 replies; 130+ messages in thread
From: Inki Dae @ 2013-12-19 16:48 UTC (permalink / raw)
  To: Sean Paul; +Cc: Stéphane Marchesin, DRI mailing list

Hi,

Below is my comments.

Thanks for your contributions,
Inki Dae

2013/10/30 Sean Paul <seanpaul@chromium.org>:
> This patch removes all of the suspend/resume logic from the individual
> drivers and consolidates it in drm_drv. This consolidation reduces the
> number of functions which enable/disable the hardware to just one -- the
> dpms callback. This ensures that we always power up/down in a consistent
> manner.
>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
>
> Changes in v2:
>         - Added to the patchset
> Changes in v3:
>         - Made appropriate changes to vidi as well (removed pm_ops)
>
>  drivers/gpu/drm/exynos/exynos_drm_drv.c  |  97 +++++++++++++++++++++++++
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c |  91 ++++-------------------
>  drivers/gpu/drm/exynos/exynos_drm_vidi.c | 119 +++++++++++++------------------
>  drivers/gpu/drm/exynos/exynos_hdmi.c     |  82 +--------------------
>  drivers/gpu/drm/exynos/exynos_mixer.c    |  75 ++++---------------
>  5 files changed, 176 insertions(+), 288 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> index 03caa3a..91d6863 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> @@ -11,6 +11,7 @@
>   * option) any later version.
>   */
>
> +#include <linux/pm_runtime.h>

Remove above include because it doesn't need runtime pm support. For
this, see the below comments.

>  #include <drm/drmP.h>
>  #include <drm/drm_crtc_helper.h>
>
> @@ -51,6 +52,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
>                 return -ENOMEM;
>
>         INIT_LIST_HEAD(&private->pageflip_event_list);
> +       dev_set_drvdata(dev->dev, dev);
>         dev->dev_private = (void *)private;
>
>         /*
> @@ -155,6 +157,41 @@ static int exynos_drm_unload(struct drm_device *dev)
>         return 0;
>  }
>
> +static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state)
> +{
> +       struct drm_connector *connector;
> +
> +       drm_modeset_lock_all(dev);
> +       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +               int old_dpms = connector->dpms;
> +
> +               if (connector->funcs->dpms)
> +                       connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
> +
> +               /* Set the old mode back to the connector for resume */
> +               connector->dpms = old_dpms;

Could you tell me why you want back to old state? I think
connector->dpms should have DRM_MODE_DPMS_OFF after the above
connector's dpms callback is called, not previous state.

> +       }
> +       drm_modeset_unlock_all(dev);
> +
> +       return 0;
> +}
> +
> +static int exynos_drm_resume(struct drm_device *dev)
> +{
> +       struct drm_connector *connector;
> +
> +       drm_modeset_lock_all(dev);
> +       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +               if (connector->funcs->dpms)
> +                       connector->funcs->dpms(connector, connector->dpms);

Just DRM_MODE_DPMS_ON instead of connector->dpms. Is there any reason
to send connector->dpms as a argument?

> +       }
> +
> +       drm_helper_resume_force_mode(dev);
> +       drm_modeset_unlock_all(dev);
> +
> +       return 0;
> +}
> +
>  static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
>  {
>         struct drm_exynos_file_private *file_priv;
> @@ -262,6 +299,8 @@ static struct drm_driver exynos_drm_driver = {
>                                         DRIVER_GEM | DRIVER_PRIME,
>         .load                   = exynos_drm_load,
>         .unload                 = exynos_drm_unload,
> +       .suspend                = exynos_drm_suspend,
> +       .resume                 = exynos_drm_resume,
>         .open                   = exynos_drm_open,
>         .preclose               = exynos_drm_preclose,
>         .lastclose              = exynos_drm_lastclose,
> @@ -293,6 +332,9 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
>  {
>         pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
>
> +       pm_runtime_enable(&pdev->dev);
> +       pm_runtime_get_sync(&pdev->dev);

It seems that this exynos_drm_drv module doesn't need to support
runtime pm, and it's enough for each sub driver supports the runtime
pm .

Above pm_runtime_get_sync call wouldn't do what you expect because
crtc, encoder and connector of each sub driver aren't created yet at
this moment. And crtc and connector devices will be enabled by dpms
callback of each drivers when load() is called:
drm_fb_helper_initial_config function in exynos_drm_fbdev_init(). So
it would be enough for exynos_drm_drv module considers only
suspend-to-ram.

> +
>         return drm_platform_init(&exynos_drm_driver, pdev);
>  }
>
> @@ -303,12 +345,67 @@ static int exynos_drm_platform_remove(struct platform_device *pdev)
>         return 0;
>  }
>
> +#ifdef CONFIG_PM_SLEEP
> +static int exynos_drm_sys_suspend(struct device *dev)
> +{
> +       struct drm_device *drm_dev = dev_get_drvdata(dev);
> +       pm_message_t message;
> +
> +       if (pm_runtime_suspended(dev))
> +               return 0;

Unnecessary codes.

> +
> +       message.event = PM_EVENT_SUSPEND;
> +       return exynos_drm_suspend(drm_dev, message);
> +}
> +
> +static int exynos_drm_sys_resume(struct device *dev)
> +{
> +       struct drm_device *drm_dev = dev_get_drvdata(dev);
> +
> +       if (pm_runtime_suspended(dev))
> +               return 0;

Unnecessary codes.

> +
> +       return exynos_drm_resume(drm_dev);
> +}
> +#endif
> +
> +#ifdef CONFIG_PM_RUNTIME
> +static int exynos_drm_runtime_suspend(struct device *dev)
> +{
> +       struct drm_device *drm_dev = dev_get_drvdata(dev);
> +       pm_message_t message;
> +
> +       if (pm_runtime_suspended(dev))
> +               return 0;
> +
> +       message.event = PM_EVENT_SUSPEND;
> +       return exynos_drm_suspend(drm_dev, message);
> +}
> +
> +static int exynos_drm_runtime_resume(struct device *dev)
> +{
> +       struct drm_device *drm_dev = dev_get_drvdata(dev);
> +
> +       if (!pm_runtime_suspended(dev))
> +               return 0;
> +
> +       return exynos_drm_resume(drm_dev);
> +}
> +#endif
> +
> +static const struct dev_pm_ops exynos_drm_pm_ops = {
> +       SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_sys_suspend, exynos_drm_sys_resume)
> +       SET_RUNTIME_PM_OPS(exynos_drm_runtime_suspend,
> +                       exynos_drm_runtime_resume, NULL)
> +};

Wouldn't need above all runtime pm related codes.

> +
>  static struct platform_driver exynos_drm_platform_driver = {
>         .probe          = exynos_drm_platform_probe,
>         .remove         = exynos_drm_platform_remove,
>         .driver         = {
>                 .owner  = THIS_MODULE,
>                 .name   = "exynos-drm",
> +               .pm     = &exynos_drm_pm_ops,
>         },
>  };
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> index ba12916..208e013 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> @@ -741,6 +741,8 @@ static int fimd_poweron(struct exynos_drm_manager *mgr)
>
>         ctx->suspended = false;
>
> +       pm_runtime_get_sync(ctx->dev);
> +
>         ret = clk_prepare_enable(ctx->bus_clk);
>         if (ret < 0) {
>                 DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
> @@ -794,32 +796,24 @@ static int fimd_poweroff(struct exynos_drm_manager *mgr)
>         clk_disable_unprepare(ctx->lcd_clk);
>         clk_disable_unprepare(ctx->bus_clk);
>
> +       pm_runtime_put_sync(ctx->dev);
> +
>         ctx->suspended = true;
>         return 0;
>  }
>
>  static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
>  {
> -       struct fimd_context *ctx = mgr->ctx;
> -
>         DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
>
>         switch (mode) {
>         case DRM_MODE_DPMS_ON:
> -               /*
> -                * enable fimd hardware only if suspended status.
> -                *
> -                * P.S. fimd_dpms function would be called at booting time so
> -                * clk_enable could be called double time.
> -                */
> -               if (ctx->suspended)
> -                       pm_runtime_get_sync(ctx->dev);
> +               fimd_poweron(mgr);
>                 break;
>         case DRM_MODE_DPMS_STANDBY:
>         case DRM_MODE_DPMS_SUSPEND:
>         case DRM_MODE_DPMS_OFF:
> -               if (!ctx->suspended)
> -                       pm_runtime_put_sync(ctx->dev);
> +               fimd_poweroff(mgr);
>                 break;
>         default:
>                 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
> @@ -950,8 +944,14 @@ static int fimd_probe(struct platform_device *pdev)
>         fimd_manager.ctx = ctx;
>         exynos_drm_manager_register(&fimd_manager);
>
> +       /*
> +        * We need to runtime pm to enable/disable sysmmu since it is a child of
> +        * this driver. Ideally, this would hang off the drm driver's runtime
> +        * operations, but we're not quite there yet.
> +        *
> +        * Tracked in crbug.com/264312
> +        */
>         pm_runtime_enable(dev);
> -       pm_runtime_get_sync(dev);
>
>         for (win = 0; win < WINDOWS_NR; win++)
>                 fimd_clear_win(ctx, win);
> @@ -961,84 +961,23 @@ static int fimd_probe(struct platform_device *pdev)
>
>  static int fimd_remove(struct platform_device *pdev)
>  {
> -       struct device *dev = &pdev->dev;
>         struct exynos_drm_manager *mgr = platform_get_drvdata(pdev);
> -       struct fimd_context *ctx = mgr->ctx;
>
>         exynos_drm_manager_unregister(&fimd_manager);
>
> -       if (ctx->suspended)
> -               goto out;
> -
> -       pm_runtime_set_suspended(dev);
> -       pm_runtime_put_sync(dev);
> +       fimd_dpms(mgr, DRM_MODE_DPMS_OFF);
>
> -out:
> -       pm_runtime_disable(dev);
> +       pm_runtime_disable(&pdev->dev);
>
>         return 0;
>  }
>
> -#ifdef CONFIG_PM_SLEEP
> -static int fimd_suspend(struct device *dev)
> -{
> -       struct exynos_drm_manager *mgr = get_fimd_manager(dev);
> -
> -       /*
> -        * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
> -        * called here, an error would be returned by that interface
> -        * because the usage_count of pm runtime is more than 1.
> -        */
> -       if (!pm_runtime_suspended(dev))
> -               return fimd_poweroff(mgr);
> -
> -       return 0;
> -}
> -
> -static int fimd_resume(struct device *dev)
> -{
> -       struct exynos_drm_manager *mgr = get_fimd_manager(dev);
> -
> -       /*
> -        * if entered to sleep when lcd panel was on, the usage_count
> -        * of pm runtime would still be 1 so in this case, fimd driver
> -        * should be on directly not drawing on pm runtime interface.
> -        */
> -       if (pm_runtime_suspended(dev))
> -               return 0;
> -
> -       return fimd_poweron(mgr);
> -}
> -#endif
> -
> -#ifdef CONFIG_PM_RUNTIME
> -static int fimd_runtime_suspend(struct device *dev)
> -{
> -       struct exynos_drm_manager *mgr = get_fimd_manager(dev);
> -
> -       return fimd_poweroff(mgr);
> -}
> -
> -static int fimd_runtime_resume(struct device *dev)
> -{
> -       struct exynos_drm_manager *mgr = get_fimd_manager(dev);
> -
> -       return fimd_poweron(mgr);
> -}
> -#endif
> -
> -static const struct dev_pm_ops fimd_pm_ops = {
> -       SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
> -       SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
> -};
> -
>  struct platform_driver fimd_driver = {
>         .probe          = fimd_probe,
>         .remove         = fimd_remove,
>         .driver         = {
>                 .name   = "exynos4-fb",
>                 .owner  = THIS_MODULE,
> -               .pm     = &fimd_pm_ops,
>                 .of_match_table = fimd_driver_dt_match,
>         },
>  };
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> index 90dacaf..7d79b6c 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
> @@ -142,31 +142,6 @@ static struct exynos_drm_display vidi_display = {
>         .ops = &vidi_display_ops,
>  };
>
> -static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
> -{
> -       struct vidi_context *ctx = mgr->ctx;
> -
> -       DRM_DEBUG_KMS("%d\n", mode);
> -
> -       mutex_lock(&ctx->lock);
> -
> -       switch (mode) {
> -       case DRM_MODE_DPMS_ON:
> -               /* TODO. */
> -               break;
> -       case DRM_MODE_DPMS_STANDBY:
> -       case DRM_MODE_DPMS_SUSPEND:
> -       case DRM_MODE_DPMS_OFF:
> -               /* TODO. */
> -               break;
> -       default:
> -               DRM_DEBUG_KMS("unspecified mode %d\n", mode);
> -               break;
> -       }
> -
> -       mutex_unlock(&ctx->lock);
> -}
> -
>  static void vidi_apply(struct exynos_drm_manager *mgr)
>  {
>         struct vidi_context *ctx = mgr->ctx;
> @@ -321,6 +296,55 @@ static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
>         /* TODO. */
>  }
>
> +static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
> +{
> +       struct vidi_context *ctx = mgr->ctx;
> +
> +       DRM_DEBUG_KMS("%s\n", __FILE__);
> +
> +       if (enable != false && enable != true)
> +               return -EINVAL;
> +
> +       if (enable) {
> +               ctx->suspended = false;
> +
> +               /* if vblank was enabled status, enable it again. */
> +               if (test_and_clear_bit(0, &ctx->irq_flags))
> +                       vidi_enable_vblank(mgr);
> +
> +               vidi_apply(mgr);
> +       } else {
> +               ctx->suspended = true;
> +       }
> +
> +       return 0;
> +}
> +
> +static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
> +{
> +       struct vidi_context *ctx = mgr->ctx;
> +
> +       DRM_DEBUG_KMS("%d\n", mode);
> +
> +       mutex_lock(&ctx->lock);
> +
> +       switch (mode) {
> +       case DRM_MODE_DPMS_ON:
> +               vidi_power_on(mgr, true);
> +               break;
> +       case DRM_MODE_DPMS_STANDBY:
> +       case DRM_MODE_DPMS_SUSPEND:
> +       case DRM_MODE_DPMS_OFF:
> +               vidi_power_on(mgr, false);
> +               break;
> +       default:
> +               DRM_DEBUG_KMS("unspecified mode %d\n", mode);
> +               break;
> +       }
> +
> +       mutex_unlock(&ctx->lock);
> +}
> +
>  static int vidi_mgr_initialize(struct exynos_drm_manager *mgr,
>                         struct drm_device *drm_dev, int pipe)
>  {
> @@ -392,30 +416,6 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
>         exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
>  }
>
> -static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
> -{
> -       struct vidi_context *ctx = mgr->ctx;
> -
> -       DRM_DEBUG_KMS("%s\n", __FILE__);
> -
> -       if (enable != false && enable != true)
> -               return -EINVAL;
> -
> -       if (enable) {
> -               ctx->suspended = false;
> -
> -               /* if vblank was enabled status, enable it again. */
> -               if (test_and_clear_bit(0, &ctx->irq_flags))
> -                       vidi_enable_vblank(mgr);
> -
> -               vidi_apply(mgr);
> -       } else {
> -               ctx->suspended = true;
> -       }
> -
> -       return 0;
> -}
> -
>  static int vidi_show_connection(struct device *dev,
>                                 struct device_attribute *attr, char *buf)
>  {
> @@ -582,32 +582,11 @@ static int vidi_remove(struct platform_device *pdev)
>         return 0;
>  }
>
> -#ifdef CONFIG_PM_SLEEP
> -static int vidi_suspend(struct device *dev)
> -{
> -       struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
> -
> -       return vidi_power_on(mgr, false);
> -}
> -
> -static int vidi_resume(struct device *dev)
> -{
> -       struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
> -
> -       return vidi_power_on(mgr, true);
> -}
> -#endif
> -
> -static const struct dev_pm_ops vidi_pm_ops = {
> -       SET_SYSTEM_SLEEP_PM_OPS(vidi_suspend, vidi_resume)
> -};
> -
>  struct platform_driver vidi_driver = {
>         .probe          = vidi_probe,
>         .remove         = vidi_remove,
>         .driver         = {
>                 .name   = "exynos-drm-vidi",
>                 .owner  = THIS_MODULE,
> -               .pm     = &vidi_pm_ops,
>         },
>  };
> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
> index 2c127b9..c6561fe 100644
> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
> @@ -28,7 +28,6 @@
>  #include <linux/interrupt.h>
>  #include <linux/irq.h>
>  #include <linux/delay.h>
> -#include <linux/pm_runtime.h>
>  #include <linux/clk.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/io.h>
> @@ -1770,7 +1769,6 @@ static void hdmi_poweroff(struct exynos_drm_display *display)
>         regulator_bulk_disable(res->regul_count, res->regul_bulk);
>
>         mutex_lock(&hdata->hdmi_mutex);
> -
>         hdata->powered = false;
>
>  out:
> @@ -1779,20 +1777,16 @@ out:
>
>  static void hdmi_dpms(struct exynos_drm_display *display, int mode)
>  {
> -       struct hdmi_context *hdata = display->ctx;
> -
>         DRM_DEBUG_KMS("mode %d\n", mode);
>
>         switch (mode) {
>         case DRM_MODE_DPMS_ON:
> -               if (pm_runtime_suspended(hdata->dev))
> -                       pm_runtime_get_sync(hdata->dev);
> +               hdmi_poweron(display);
>                 break;
>         case DRM_MODE_DPMS_STANDBY:
>         case DRM_MODE_DPMS_SUSPEND:
>         case DRM_MODE_DPMS_OFF:
> -               if (!pm_runtime_suspended(hdata->dev))
> -                       pm_runtime_put_sync(hdata->dev);
> +               hdmi_poweroff(display);
>                 break;
>         default:
>                 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
> @@ -2030,8 +2024,6 @@ static int hdmi_probe(struct platform_device *pdev)
>         hdmi_display.ctx = hdata;
>         exynos_drm_display_register(&hdmi_display);
>
> -       pm_runtime_enable(dev);
> -
>         return 0;
>
>  err_hdmiphy:
> @@ -2047,88 +2039,18 @@ static int hdmi_remove(struct platform_device *pdev)
>         struct exynos_drm_display *display = get_hdmi_display(dev);
>         struct hdmi_context *hdata = display->ctx;
>
> -       pm_runtime_disable(dev);
> -
>         put_device(&hdata->hdmiphy_port->dev);
>         put_device(&hdata->ddc_port->dev);
>
>         return 0;
>  }
>
> -#ifdef CONFIG_PM_SLEEP
> -static int hdmi_suspend(struct device *dev)
> -{
> -       struct exynos_drm_display *display = get_hdmi_display(dev);
> -       struct hdmi_context *hdata = display->ctx;
> -
> -       disable_irq(hdata->irq);
> -
> -       hdata->hpd = false;
> -       if (hdata->drm_dev)
> -               drm_helper_hpd_irq_event(hdata->drm_dev);
> -
> -       if (pm_runtime_suspended(dev)) {
> -               DRM_DEBUG_KMS("Already suspended\n");
> -               return 0;
> -       }
> -
> -       hdmi_poweroff(display);
> -
> -       return 0;
> -}
> -
> -static int hdmi_resume(struct device *dev)
> -{
> -       struct exynos_drm_display *display = get_hdmi_display(dev);
> -       struct hdmi_context *hdata = display->ctx;
> -
> -       hdata->hpd = gpio_get_value(hdata->hpd_gpio);
> -
> -       enable_irq(hdata->irq);
> -
> -       if (!pm_runtime_suspended(dev)) {
> -               DRM_DEBUG_KMS("Already resumed\n");
> -               return 0;
> -       }
> -
> -       hdmi_poweron(display);
> -
> -       return 0;
> -}
> -#endif
> -
> -#ifdef CONFIG_PM_RUNTIME
> -static int hdmi_runtime_suspend(struct device *dev)
> -{
> -       struct exynos_drm_display *display = get_hdmi_display(dev);
> -
> -       hdmi_poweroff(display);
> -
> -       return 0;
> -}
> -
> -static int hdmi_runtime_resume(struct device *dev)
> -{
> -       struct exynos_drm_display *display = get_hdmi_display(dev);
> -
> -       hdmi_poweron(display);
> -
> -       return 0;
> -}
> -#endif
> -
> -static const struct dev_pm_ops hdmi_pm_ops = {
> -       SET_SYSTEM_SLEEP_PM_OPS(hdmi_suspend, hdmi_resume)
> -       SET_RUNTIME_PM_OPS(hdmi_runtime_suspend, hdmi_runtime_resume, NULL)
> -};
> -
>  struct platform_driver hdmi_driver = {
>         .probe          = hdmi_probe,
>         .remove         = hdmi_remove,
>         .driver         = {
>                 .name   = "exynos-hdmi",
>                 .owner  = THIS_MODULE,
> -               .pm     = &hdmi_pm_ops,
>                 .of_match_table = hdmi_match_types,
>         },
>  };
> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
> index 39aed3e..985391d 100644
> --- a/drivers/gpu/drm/exynos/exynos_mixer.c
> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c
> @@ -902,6 +902,8 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
>         ctx->powered = true;
>         mutex_unlock(&ctx->mixer_mutex);
>
> +       pm_runtime_get_sync(ctx->dev);
> +
>         clk_prepare_enable(res->mixer);
>         if (ctx->vp_enabled) {
>                 clk_prepare_enable(res->vp);
> @@ -934,6 +936,8 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
>                 clk_disable_unprepare(res->sclk_mixer);
>         }
>
> +       pm_runtime_put_sync(ctx->dev);
> +
>         mutex_lock(&ctx->mixer_mutex);
>         ctx->powered = false;
>
> @@ -943,18 +947,14 @@ out:
>
>  static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
>  {
> -       struct mixer_context *mixer_ctx = mgr->ctx;
> -
>         switch (mode) {
>         case DRM_MODE_DPMS_ON:
> -               if (pm_runtime_suspended(mixer_ctx->dev))
> -                       pm_runtime_get_sync(mixer_ctx->dev);
> +               mixer_poweron(mgr);
>                 break;
>         case DRM_MODE_DPMS_STANDBY:
>         case DRM_MODE_DPMS_SUSPEND:
>         case DRM_MODE_DPMS_OFF:
> -               if (!pm_runtime_suspended(mixer_ctx->dev))
> -                       pm_runtime_put_sync(mixer_ctx->dev);
> +               mixer_poweroff(mgr);
>                 break;
>         default:
>                 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
> @@ -1239,6 +1239,13 @@ static int mixer_probe(struct platform_device *pdev)
>         platform_set_drvdata(pdev, &mixer_manager);
>         exynos_drm_manager_register(&mixer_manager);
>
> +       /*
> +        * We need to runtime pm to enable/disable sysmmu since it is a child of
> +        * this driver. Ideally, this would hang off the drm driver's runtime
> +        * operations, but we're not quite there yet.
> +        *
> +        * Tracked in crbug.com/264312
> +        */
>         pm_runtime_enable(dev);
>
>         return 0;
> @@ -1258,66 +1265,10 @@ static int mixer_remove(struct platform_device *pdev)
>         return 0;
>  }
>
> -#ifdef CONFIG_PM_SLEEP
> -static int mixer_suspend(struct device *dev)
> -{
> -       struct exynos_drm_manager *mgr = get_mixer_manager(dev);
> -
> -       if (pm_runtime_suspended(dev)) {
> -               DRM_DEBUG_KMS("Already suspended\n");
> -               return 0;
> -       }
> -
> -       mixer_poweroff(mgr);
> -
> -       return 0;
> -}
> -
> -static int mixer_resume(struct device *dev)
> -{
> -       struct exynos_drm_manager *mgr = get_mixer_manager(dev);
> -
> -       if (!pm_runtime_suspended(dev)) {
> -               DRM_DEBUG_KMS("Already resumed\n");
> -               return 0;
> -       }
> -
> -       mixer_poweron(mgr);
> -
> -       return 0;
> -}
> -#endif
> -
> -#ifdef CONFIG_PM_RUNTIME
> -static int mixer_runtime_suspend(struct device *dev)
> -{
> -       struct exynos_drm_manager *mgr = get_mixer_manager(dev);
> -
> -       mixer_poweroff(mgr);
> -
> -       return 0;
> -}
> -
> -static int mixer_runtime_resume(struct device *dev)
> -{
> -       struct exynos_drm_manager *mgr = get_mixer_manager(dev);
> -
> -       mixer_poweron(mgr);
> -
> -       return 0;
> -}
> -#endif
> -
> -static const struct dev_pm_ops mixer_pm_ops = {
> -       SET_SYSTEM_SLEEP_PM_OPS(mixer_suspend, mixer_resume)
> -       SET_RUNTIME_PM_OPS(mixer_runtime_suspend, mixer_runtime_resume, NULL)
> -};
> -
>  struct platform_driver mixer_driver = {
>         .driver = {
>                 .name = "exynos-mixer",
>                 .owner = THIS_MODULE,
> -               .pm = &mixer_pm_ops,
>                 .of_match_table = mixer_match_types,
>         },
>         .probe = mixer_probe,
> --
> 1.8.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2013-12-19 16:48 UTC | newest]

Thread overview: 130+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-29 16:12 [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Sean Paul
2013-10-29 16:12 ` [PATCH v3 01/32] drm/exynos: Remove useless slab.h include Sean Paul
2013-10-31 10:24   ` Inki Dae
2013-10-31 23:32   ` Tomasz Figa
2013-10-29 16:12 ` [PATCH v3 02/32] drm/exynos: Merge overlay_ops into manager_ops Sean Paul
2013-10-31 23:39   ` Tomasz Figa
2013-11-01 19:50     ` Sean Paul
2013-11-01 19:55       ` Tomasz Figa
2013-11-04  7:44         ` Inki Dae
2013-10-29 16:12 ` [PATCH v3 03/32] drm/exynos: Add an initialize function to manager and display Sean Paul
2013-10-31 23:42   ` Tomasz Figa
2013-10-29 16:12 ` [PATCH v3 04/32] drm/exynos: Use manager_op initialize in fimd Sean Paul
2013-10-31 23:49   ` Tomasz Figa
2013-11-01 19:51     ` Sean Paul
2013-11-01 19:57       ` Tomasz Figa
2013-10-29 16:12 ` [PATCH v3 05/32] drm/exynos: hdmi: Implement initialize op for hdmi Sean Paul
2013-10-31 23:53   ` Tomasz Figa
2013-11-01 19:54     ` Sean Paul
2013-11-01 19:56       ` Tomasz Figa
2013-11-01 20:08         ` Sean Paul
2013-10-29 16:12 ` [PATCH v3 06/32] drm/exynos: Pass exynos_drm_manager in manager ops instead of dev Sean Paul
2013-11-01  0:19   ` Tomasz Figa
2013-11-01 20:01     ` Sean Paul
2013-11-01 20:11       ` Tomasz Figa
2013-10-29 16:12 ` [PATCH v3 07/32] drm/exynos: Remove apply manager callback Sean Paul
2013-11-08 21:05   ` Tomasz Figa
2013-10-29 16:12 ` [PATCH v3 08/32] drm/exynos: Remove dpms link between encoder/connector Sean Paul
2013-11-08 21:45   ` Tomasz Figa
2013-10-29 16:12 ` [PATCH v3 09/32] drm/exynos: Rename display_op power_on to dpms Sean Paul
2013-11-08 22:09   ` Tomasz Figa
2013-10-29 16:12 ` [PATCH v3 10/32] drm/exynos: Don't keep dpms state in encoder Sean Paul
2013-11-10 20:47   ` Tomasz Figa
2013-10-29 16:12 ` [PATCH v3 11/32] drm/exynos: Use unsigned long for possible_crtcs Sean Paul
2013-11-10 20:47   ` Tomasz Figa
2013-10-29 16:12 ` [PATCH v3 12/32] drm/exynos: Split manager/display/subdrv Sean Paul
2013-10-31 10:30   ` Inki Dae
2013-10-31 16:08     ` Sean Paul
2013-11-01  4:20       ` Inki Dae
2013-11-10 21:09   ` Tomasz Figa
2013-11-12 17:51     ` Sean Paul
2013-11-12 18:35       ` Tomasz Figa
2013-11-26 18:00         ` Olof Johansson
2013-11-27 10:04           ` Thierry Reding
2013-11-28 23:04           ` Tomasz Figa
2013-11-29  7:52             ` Daniel Vetter
2013-11-29  9:10               ` Tomasz Figa
2013-11-29 10:25                 ` Daniel Vetter
2013-11-29 14:13                 ` Rob Clark
2013-11-29 17:05                   ` Tomasz Figa
2013-11-29 18:35                     ` Rob Clark
2013-11-30  5:25                       ` Inki Dae
2013-12-03 21:38                     ` Sean Paul
2013-11-29 10:16             ` Thierry Reding
2013-10-29 16:12 ` [PATCH v3 13/32] drm/exynos: hdmi: remove the i2c drivers and use devtree Sean Paul
2013-11-10 20:46   ` Tomasz Figa
2013-11-11  8:44     ` Thierry Reding
2013-11-28 13:30       ` Tomasz Figa
2013-11-29 10:24         ` Thierry Reding
2013-12-03  0:37           ` Olof Johansson
2013-10-29 16:13 ` [PATCH v3 14/32] drm/exynos: Remove exynos_drm_hdmi shim Sean Paul
2013-11-10 21:24   ` Tomasz Figa
2013-10-29 16:13 ` [PATCH v3 15/32] drm/exynos: Use drm_mode_copy to copy modes Sean Paul
2013-11-10 21:27   ` Tomasz Figa
2013-10-29 16:13 ` [PATCH v3 16/32] drm/exynos: Disable unused crtc planes from crtc Sean Paul
2013-11-10 21:29   ` Tomasz Figa
2013-10-29 16:13 ` [PATCH v3 17/32] drm/exynos: Add mode_set manager operation Sean Paul
2013-11-10 21:31   ` Tomasz Figa
2013-10-29 16:13 ` [PATCH v3 18/32] drm/exynos: Implement mode_fixup " Sean Paul
2013-11-10 21:33   ` Tomasz Figa
2013-10-29 16:13 ` [PATCH v3 19/32] drm/exynos: Use mode_set to configure fimd Sean Paul
2013-11-10 22:03   ` Tomasz Figa
2013-11-15 13:49     ` Daniel Kurtz
2013-11-15 13:53     ` Daniel Kurtz
2013-11-28 22:57       ` Tomasz Figa
2013-12-04 22:37       ` Sean Paul
2013-10-29 16:13 ` [PATCH v3 20/32] drm/exynos: Remove unused/useless fimd_context members Sean Paul
2013-11-11  1:19   ` Tomasz Figa
2013-10-29 16:13 ` [PATCH v3 21/32] drm/exynos: Move dp driver from video/ to drm/ Sean Paul
2013-10-31 10:46   ` Inki Dae
2013-10-31 16:05     ` Sean Paul
2013-10-31 23:06     ` Jingoo Han
2013-10-31 23:06       ` Jingoo Han
2013-10-31 23:11       ` Tomasz Figa
2013-10-31 23:11         ` Tomasz Figa
2013-10-31 23:23         ` Jingoo Han
2013-10-31 23:23           ` Jingoo Han
2013-10-31 23:27           ` Tomasz Figa
2013-10-31 23:27             ` Tomasz Figa
2013-10-31 23:55             ` Jingoo Han
2013-10-31 23:55               ` Jingoo Han
2013-11-01  0:01               ` Tomasz Figa
2013-11-01  0:01                 ` Tomasz Figa
     [not found]   ` <3513711.0qTZKxmOZX@flatron>
2013-12-04 23:07     ` Sean Paul
2013-10-29 16:13 ` [PATCH v3 22/32] drm/exynos: Move display implementation into dp Sean Paul
     [not found]   ` <1383063198-10526-23-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2013-11-11  1:53     ` Tomasz Figa
2013-10-29 16:13 ` [PATCH v3 23/32] ARM: dts: Move display-timings node from fimd to dp Sean Paul
2013-10-29 16:13 ` [PATCH v3 24/32] drm/exynos: Implement dpms display callback in DP Sean Paul
2013-11-11  2:04   ` Tomasz Figa
2013-10-29 16:13 ` [PATCH v3 25/32] drm/exynos: Clean up FIMD power on/off routines Sean Paul
2013-10-31 10:54   ` Inki Dae
     [not found]     ` <1630995.NnKzZB9Rl5@flatron>
2013-11-11  4:08       ` Inki Dae
2013-11-11  2:09   ` Tomasz Figa
2013-10-29 16:13 ` [PATCH v3 26/32] drm/exynos: Consolidate suspend/resume in drm_drv Sean Paul
2013-11-29 14:58   ` Tomasz Figa
2013-12-19 16:48   ` Inki Dae
2013-10-29 16:13 ` [PATCH v3 27/32] drm/exynos: Add create_connector callback Sean Paul
2013-11-11  2:19   ` Tomasz Figa
2013-12-03  5:01   ` Inki Dae
2013-10-29 16:13 ` [PATCH v3 28/32] drm/exynos: Implement drm_connector in hdmi directly Sean Paul
2013-11-29 15:58   ` Tomasz Figa
2013-12-02  9:46     ` Thierry Reding
2013-12-02  9:54       ` Tomasz Figa
2013-10-29 16:13 ` [PATCH v3 29/32] drm/exynos: Implement drm_connector directly in dp driver Sean Paul
2013-11-29 16:04   ` Tomasz Figa
2013-12-03  4:45   ` Inki Dae
2013-12-04  6:46     ` Inki Dae
2013-10-29 16:13 ` [PATCH v3 30/32] drm/exynos: Implement drm_connector directly in vidi driver Sean Paul
2013-11-29 16:13   ` Tomasz Figa
2013-12-03  4:47   ` Inki Dae
2013-12-04  6:47     ` Inki Dae
2013-10-29 16:13 ` [PATCH v3 31/32] drm/exynos: Move lvds bridge discovery into DP driver Sean Paul
2013-11-29 16:55   ` Tomasz Figa
2013-11-30  5:18     ` Inki Dae
2013-11-30 12:27       ` Tomasz Figa
2013-10-29 16:13 ` [PATCH v3 32/32] drm/exynos: Remove the exynos_drm_connector shim Sean Paul
2013-11-29 16:14   ` Tomasz Figa
2013-11-07  5:48 ` [PATCH v3 00/32] drm/exynos: Refactor parts of the exynos driver Inki Dae
2013-11-07 18:20   ` Sean Paul
2013-11-08 21:01   ` Tomasz Figa
2013-11-08 21:22     ` Sean Paul

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.