<div dir="ltr">Hi Rahul,<br><div class="gmail_extra"><br><br><div class="gmail_quote">2013/4/26 Rahul Sharma <span dir="ltr"><<a href="mailto:rahul.sharma@samsung.com" target="_blank">rahul.sharma@samsung.com</a>></span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im HOEnZb">Right now hdmiphy operations and configs are kept inside hdmi driver. hdmiphy<br>
related code is tightly coupled with hdmi ip driver. Physicaly they are<br>
different devices and should be instantiated independently.<br>
<br>
In terms of versions/mapping/configurations Hdmi and hdmiphy are independent<br>
of each other. It seems logical to isolate them and maintained independently.<br>
<br>
</div><div class="HOEnZb"><div class="h5">v2:<br>
1) Moved hdmi subsystem registration to drm-common-hdmi.<br>
2) removed __func__ as DRM_DEBUG_KMS print it by default.<br>
3) removed devname from "hdmiphy" clock as it needs to be accessed by hdmi<br>
and hdmiphy driver.<br>
<br></div></div></blockquote><div><br></div><div>Please separate this patch into 1), 2) and 3) and make it based on exynos-drm-next.<br><br></div><div>Thanks,<br></div><div>Inki Dae<br></div><div><br><br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5">
This implementations is tested for:<br>
1) Resolutions supported by exynos4 and 5 hdmi.<br>
2) Runtime PM and S2R scenarions for exynos5.<br>
<br>
This patch is dependent on the patch, posted at<br>
<a href="http://www.mail-archive.com/dri-devel@lists.freedesktop.org/msg34861.html" target="_blank">http://www.mail-archive.com/dri-devel@lists.freedesktop.org/msg34861.html</a><br>
<br>
Signed-off-by: Rahul Sharma <<a href="mailto:rahul.sharma@samsung.com">rahul.sharma@samsung.com</a>><br>
---<br>
It is based on exynos-drm-next branch at<br>
git://<a href="http://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git" target="_blank">git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git</a><br>
<br>
 arch/arm/mach-exynos/clock-exynos5.c     |    1 -<br>
 drivers/gpu/drm/exynos/exynos_drm_drv.c  |   25 +-<br>
 drivers/gpu/drm/exynos/exynos_drm_drv.h  |   14 +-<br>
 drivers/gpu/drm/exynos/exynos_drm_hdmi.c |  109 +++++-<br>
 drivers/gpu/drm/exynos/exynos_drm_hdmi.h |   20 +<br>
 drivers/gpu/drm/exynos/exynos_hdmi.c     |  372 ++-----------------<br>
 drivers/gpu/drm/exynos/exynos_hdmi.h     |    1 -<br>
 drivers/gpu/drm/exynos/exynos_hdmiphy.c  |  585 +++++++++++++++++++++++++++++-<br>
 drivers/gpu/drm/exynos/regs-hdmiphy.h    |   61 ++++<br>
 9 files changed, 783 insertions(+), 405 deletions(-)<br>
 create mode 100644 drivers/gpu/drm/exynos/regs-hdmiphy.h<br>
<br>
diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c<br>
index b0ea31f..4f39027 100644<br>
--- a/arch/arm/mach-exynos/clock-exynos5.c<br>
+++ b/arch/arm/mach-exynos/clock-exynos5.c<br>
@@ -690,7 +690,6 @@ static struct clk exynos5_init_clocks_off[] = {<br>
                .ctrlbit        = (1 << 6),<br>
        }, {<br>
                .name           = "hdmiphy",<br>
-               .devname        = "exynos5-hdmi",<br>
                .enable         = exynos5_clk_hdmiphy_ctrl,<br>
                .ctrlbit        = (1 << 0),<br>
        }, {<br>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c<br>
index 3da5c2d..2ec8ab1 100644<br>
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c<br>
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c<br>
@@ -331,19 +331,9 @@ static int __init exynos_drm_init(void)<br>
 #endif<br>
<br>
 #ifdef CONFIG_DRM_EXYNOS_HDMI<br>
-       ret = platform_driver_register(&hdmi_driver);<br>
+       ret = exynos_common_hdmi_register();<br>
        if (ret < 0)<br>
                goto out_hdmi;<br>
-       ret = platform_driver_register(&mixer_driver);<br>
-       if (ret < 0)<br>
-               goto out_mixer;<br>
-       ret = platform_driver_register(&exynos_drm_common_hdmi_driver);<br>
-       if (ret < 0)<br>
-               goto out_common_hdmi;<br>
-<br>
-       ret = exynos_platform_device_hdmi_register();<br>
-       if (ret < 0)<br>
-               goto out_common_hdmi_dev;<br>
 #endif<br>
<br>
 #ifdef CONFIG_DRM_EXYNOS_VIDI<br>
@@ -430,13 +420,7 @@ out_vidi:<br>
 #endif<br>
<br>
 #ifdef CONFIG_DRM_EXYNOS_HDMI<br>
-       exynos_platform_device_hdmi_unregister();<br>
-out_common_hdmi_dev:<br>
-       platform_driver_unregister(&exynos_drm_common_hdmi_driver);<br>
-out_common_hdmi:<br>
-       platform_driver_unregister(&mixer_driver);<br>
-out_mixer:<br>
-       platform_driver_unregister(&hdmi_driver);<br>
+       exynos_common_hdmi_unregister();<br>
 out_hdmi:<br>
 #endif<br>
<br>
@@ -476,10 +460,7 @@ static void __exit exynos_drm_exit(void)<br>
 #endif<br>
<br>
 #ifdef CONFIG_DRM_EXYNOS_HDMI<br>
-       exynos_platform_device_hdmi_unregister();<br>
-       platform_driver_unregister(&exynos_drm_common_hdmi_driver);<br>
-       platform_driver_unregister(&mixer_driver);<br>
-       platform_driver_unregister(&hdmi_driver);<br>
+       exynos_common_hdmi_unregister();<br>
 #endif<br>
<br>
 #ifdef CONFIG_DRM_EXYNOS_VIDI<br>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h<br>
index 4606fac..7e6d070 100644<br>
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h<br>
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h<br>
@@ -319,20 +319,18 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file);<br>
 void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file);<br>
<br>
 /*<br>
- * this function registers exynos drm hdmi platform device. It ensures only one<br>
- * instance of the device is created.<br>
+ * this function registers exynos drm hdmi platform driver and singleton<br>
+ * device. It also registers subdrivers like mixer, hdmi and hdmiphy.<br>
  */<br>
-extern int exynos_platform_device_hdmi_register(void);<br>
+extern int exynos_common_hdmi_register(void);<br>
<br>
 /*<br>
- * this function unregisters exynos drm hdmi platform device if it exists.<br>
+ * this function unregisters exynos drm hdmi platform driver and device,<br>
+ * subdrivers for mixer, hdmi and hdmiphy.<br>
  */<br>
-void exynos_platform_device_hdmi_unregister(void);<br>
+void exynos_common_hdmi_unregister(void);<br>
<br>
 extern struct platform_driver fimd_driver;<br>
-extern struct platform_driver hdmi_driver;<br>
-extern struct platform_driver mixer_driver;<br>
-extern struct platform_driver exynos_drm_common_hdmi_driver;<br>
 extern struct platform_driver vidi_driver;<br>
 extern struct platform_driver g2d_driver;<br>
 extern struct platform_driver fimc_driver;<br>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c<br>
index 5285509..fe66029 100644<br>
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c<br>
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c<br>
@@ -32,40 +32,88 @@<br>
 /* platform device pointer for common drm hdmi device. */<br>
 static struct platform_device *exynos_drm_hdmi_pdev;<br>
<br>
-/* Common hdmi subdrv needs to access the hdmi and mixer though context.<br>
-* These should be initialied by the repective drivers */<br>
+/* Common hdmi subdrv needs to access the hdmi, hdmiphy and mixer though<br>
+*  context. These should be initialied by the repective drivers */<br>
+static struct exynos_drm_hdmi_context *hdmiphy_ctx;<br>
 static struct exynos_drm_hdmi_context *hdmi_ctx;<br>
 static struct exynos_drm_hdmi_context *mixer_ctx;<br>
<br>
 /* these callback points shoud be set by specific drivers. */<br>
+static struct exynos_hdmiphy_ops *hdmiphy_ops;<br>
 static struct exynos_hdmi_ops *hdmi_ops;<br>
 static struct exynos_mixer_ops *mixer_ops;<br>
<br>
+struct platform_driver exynos_drm_common_hdmi_driver;<br>
+<br>
 struct drm_hdmi_context {<br>
        struct exynos_drm_subdrv        subdrv;<br>
+       struct exynos_drm_hdmi_context  *hdmiphy_ctx;<br>
        struct exynos_drm_hdmi_context  *hdmi_ctx;<br>
        struct exynos_drm_hdmi_context  *mixer_ctx;<br>
<br>
        bool    enabled[MIXER_WIN_NR];<br>
 };<br>
<br>
-int exynos_platform_device_hdmi_register(void)<br>
+int exynos_common_hdmi_register(void)<br>
 {<br>
+       int ret;<br>
+<br>
        if (exynos_drm_hdmi_pdev)<br>
                return -EEXIST;<br>
<br>
+       ret = exynos_hdmiphy_driver_register();<br>
+       if (ret < 0)<br>
+               goto out_hdmiphy;<br>
+<br>
+       ret = platform_driver_register(&hdmi_driver);<br>
+       if (ret < 0)<br>
+               goto out_hdmi;<br>
+<br>
+       ret = platform_driver_register(&mixer_driver);<br>
+       if (ret < 0)<br>
+               goto out_mixer;<br>
+<br>
+       ret = platform_driver_register(&exynos_drm_common_hdmi_driver);<br>
+       if (ret < 0)<br>
+               goto out_common_hdmi;<br>
+<br>
        exynos_drm_hdmi_pdev = platform_device_register_simple(<br>
                        "exynos-drm-hdmi", -1, NULL, 0);<br>
-       if (IS_ERR_OR_NULL(exynos_drm_hdmi_pdev))<br>
-               return PTR_ERR(exynos_drm_hdmi_pdev);<br>
+       if (IS_ERR_OR_NULL(exynos_drm_hdmi_pdev)) {<br>
+               ret = PTR_ERR(exynos_drm_hdmi_pdev);<br>
+               goto out_common_hdmi_dev;<br>
+       }<br>
<br>
        return 0;<br>
+<br>
+out_common_hdmi_dev:<br>
+       platform_driver_unregister(&exynos_drm_common_hdmi_driver);<br>
+out_common_hdmi:<br>
+       platform_driver_unregister(&mixer_driver);<br>
+out_mixer:<br>
+       platform_driver_unregister(&hdmi_driver);<br>
+out_hdmi:<br>
+       exynos_hdmiphy_driver_unregister();<br>
+out_hdmiphy:<br>
+       return ret;<br>
 }<br>
<br>
-void exynos_platform_device_hdmi_unregister(void)<br>
+void exynos_common_hdmi_unregister(void)<br>
 {<br>
-       if (exynos_drm_hdmi_pdev)<br>
-               platform_device_unregister(exynos_drm_hdmi_pdev);<br>
+       if (!exynos_drm_hdmi_pdev)<br>
+               return;<br>
+<br>
+       platform_device_unregister(exynos_drm_hdmi_pdev);<br>
+       platform_driver_unregister(&exynos_drm_common_hdmi_driver);<br>
+       platform_driver_unregister(&mixer_driver);<br>
+       platform_driver_unregister(&hdmi_driver);<br>
+       exynos_hdmiphy_driver_unregister();<br>
+}<br>
+<br>
+void exynos_hdmiphy_drv_attach(struct exynos_drm_hdmi_context *ctx)<br>
+{<br>
+       if (ctx)<br>
+               hdmiphy_ctx = ctx;<br>
 }<br>
<br>
 void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx)<br>
@@ -80,6 +128,14 @@ void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx)<br>
                mixer_ctx = ctx;<br>
 }<br>
<br>
+void exynos_hdmiphy_ops_register(struct exynos_hdmiphy_ops *ops)<br>
+{<br>
+       DRM_DEBUG_KMS("%s\n", __FILE__);<br>
+<br>
+       if (ops)<br>
+               hdmiphy_ops = ops;<br>
+}<br>
+<br>
 void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)<br>
 {<br>
        DRM_DEBUG_KMS("%s\n", __FILE__);<br>
@@ -121,7 +177,7 @@ static struct edid *drm_hdmi_get_edid(struct device *dev,<br>
        return NULL;<br>
 }<br>
<br>
-static int drm_hdmi_check_timing(struct device *dev, void *timing)<br>
+static int drm_hdmi_check_timing(struct device *dev, void *mode)<br>
 {<br>
        struct drm_hdmi_context *ctx = to_context(dev);<br>
        int ret = 0;<br>
@@ -129,18 +185,24 @@ static int drm_hdmi_check_timing(struct device *dev, void *timing)<br>
        DRM_DEBUG_KMS("%s\n", __FILE__);<br>
<br>
        /*<br>
-       * Both, mixer and hdmi should be able to handle the requested mode.<br>
-       * If any of the two fails, return mode as BAD.<br>
+       * Mixer, hdmi and hdmiphy should be able to handle the requested mode.<br>
+       * If any of the them fails, return mode as BAD.<br>
        */<br>
<br>
        if (mixer_ops && mixer_ops->check_timing)<br>
-               ret = mixer_ops->check_timing(ctx->mixer_ctx->ctx, timing);<br>
+               ret = mixer_ops->check_timing(ctx->mixer_ctx->ctx, mode);<br>
<br>
        if (ret)<br>
                return ret;<br>
<br>
        if (hdmi_ops && hdmi_ops->check_timing)<br>
-               return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing);<br>
+               ret = hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, mode);<br>
+<br>
+       if (ret)<br>
+               return ret;<br>
+<br>
+       if (hdmiphy_ops && hdmiphy_ops->check_timing)<br>
+               return hdmiphy_ops->check_timing(ctx->hdmiphy_ctx->ctx, mode);<br>
<br>
        return 0;<br>
 }<br>
@@ -254,6 +316,9 @@ static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)<br>
<br>
        if (hdmi_ops && hdmi_ops->mode_set)<br>
                hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);<br>
+<br>
+       if (hdmiphy_ops && hdmiphy_ops->mode_set)<br>
+               hdmiphy_ops->mode_set(ctx->hdmiphy_ctx->ctx, mode);<br>
 }<br>
<br>
 static void drm_hdmi_get_max_resol(struct device *subdrv_dev,<br>
@@ -273,6 +338,15 @@ static void drm_hdmi_commit(struct device *subdrv_dev)<br>
<br>
        DRM_DEBUG_KMS("%s\n", __FILE__);<br>
<br>
+       if (hdmiphy_ops && hdmiphy_ops->prepare)<br>
+               hdmiphy_ops->prepare(ctx->hdmiphy_ctx->ctx);<br>
+<br>
+       if (hdmi_ops && hdmi_ops->prepare)<br>
+               hdmi_ops->prepare(ctx->hdmi_ctx->ctx);<br>
+<br>
+       if (hdmiphy_ops && hdmiphy_ops->config_apply)<br>
+               hdmiphy_ops->config_apply(ctx->hdmiphy_ctx->ctx);<br>
+<br>
        if (hdmi_ops && hdmi_ops->commit)<br>
                hdmi_ops->commit(ctx->hdmi_ctx->ctx);<br>
 }<br>
@@ -288,6 +362,9 @@ static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)<br>
<br>
        if (hdmi_ops && hdmi_ops->dpms)<br>
                hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);<br>
+<br>
+       if (hdmiphy_ops && hdmiphy_ops->dpms)<br>
+               hdmiphy_ops->dpms(ctx->hdmiphy_ctx->ctx, mode);<br>
 }<br>
<br>
 static void drm_hdmi_apply(struct device *subdrv_dev)<br>
@@ -393,6 +470,11 @@ static int hdmi_subdrv_probe(struct drm_device *drm_dev,<br>
                return -EFAULT;<br>
        }<br>
<br>
+       if (!hdmiphy_ctx) {<br>
+               DRM_ERROR("hdmiphy context not initialized.\n");<br>
+               return -EFAULT;<br>
+       }<br>
+<br>
        if (!mixer_ctx) {<br>
                DRM_ERROR("mixer context not initialized.\n");<br>
                return -EFAULT;<br>
@@ -406,6 +488,7 @@ static int hdmi_subdrv_probe(struct drm_device *drm_dev,<br>
        }<br>
<br>
        ctx->hdmi_ctx = hdmi_ctx;<br>
+       ctx->hdmiphy_ctx = hdmiphy_ctx;<br>
        ctx->mixer_ctx = mixer_ctx;<br>
<br>
        ctx->hdmi_ctx->drm_dev = drm_dev;<br>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h<br>
index fd2ff9f..249db11 100644<br>
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h<br>
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h<br>
@@ -39,10 +39,19 @@ struct exynos_hdmi_ops {<br>
        void (*mode_set)(void *ctx, struct drm_display_mode *mode);<br>
        void (*get_max_resol)(void *ctx, unsigned int *width,<br>
                                unsigned int *height);<br>
+       void (*prepare)(void *ctx);<br>
        void (*commit)(void *ctx);<br>
        void (*dpms)(void *ctx, int mode);<br>
 };<br>
<br>
+struct exynos_hdmiphy_ops {<br>
+       int (*check_timing)(void *ctx, struct drm_display_mode *mode);<br>
+       void (*mode_set)(void *ctx, struct drm_display_mode *mode);<br>
+       void (*prepare)(void *ctx);<br>
+       int (*config_apply)(void *ctx);<br>
+       void (*dpms)(void *ctx, int mode);<br>
+};<br>
+<br>
 struct exynos_mixer_ops {<br>
        /* manager */<br>
        int (*iommu_on)(void *ctx, bool enable);<br>
@@ -60,8 +69,19 @@ struct exynos_mixer_ops {<br>
        int (*check_timing)(void *ctx, struct drm_display_mode *mode);<br>
 };<br>
<br>
+extern struct platform_driver hdmi_driver;<br>
+extern struct platform_driver mixer_driver;<br>
+<br>
+/*<br>
+ * these functions registers/unregisters exynos drm hdmiphy driver.<br>
+ */<br>
+extern int exynos_hdmiphy_driver_register(void);<br>
+extern void exynos_hdmiphy_driver_unregister(void);<br>
+<br>
+void exynos_hdmiphy_drv_attach(struct exynos_drm_hdmi_context *ctx);<br>
 void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx);<br>
 void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx);<br>
+void exynos_hdmiphy_ops_register(struct exynos_hdmiphy_ops *ops);<br>
 void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops);<br>
 void exynos_mixer_ops_register(struct exynos_mixer_ops *ops);<br>
 #endif<br>
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c<br>
index 81382ce..b5cb1fc 100644<br>
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c<br>
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c<br>
@@ -171,7 +171,6 @@ struct hdmi_v14_conf {<br>
 };<br>
<br>
 struct hdmi_conf_regs {<br>
-       int pixel_clock;<br>
        int cea_video_id;<br>
        union {<br>
                struct hdmi_v13_conf v13_conf;<br>
@@ -192,7 +191,6 @@ struct hdmi_context {<br>
        int                             irq;<br>
<br>
        struct i2c_client               *ddc_port;<br>
-       struct i2c_client               *hdmiphy_port;<br>
<br>
        /* current hdmiphy conf regs */<br>
        struct hdmi_conf_regs           mode_conf;<br>
@@ -204,180 +202,6 @@ struct hdmi_context {<br>
        enum hdmi_type                  type;<br>
 };<br>
<br>
-struct hdmiphy_config {<br>
-       int pixel_clock;<br>
-       u8 conf[32];<br>
-};<br>
-<br>
-/* list of phy config settings */<br>
-static const struct hdmiphy_config hdmiphy_v13_configs[] = {<br>
-       {<br>
-               .pixel_clock = 27000000,<br>
-               .conf = {<br>
-                       0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,<br>
-                       0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,<br>
-                       0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,<br>
-                       0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 27027000,<br>
-               .conf = {<br>
-                       0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,<br>
-                       0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,<br>
-                       0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,<br>
-                       0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 74176000,<br>
-               .conf = {<br>
-                       0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,<br>
-                       0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,<br>
-                       0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,<br>
-                       0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 74250000,<br>
-               .conf = {<br>
-                       0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,<br>
-                       0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,<br>
-                       0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,<br>
-                       0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 148500000,<br>
-               .conf = {<br>
-                       0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,<br>
-                       0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,<br>
-                       0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,<br>
-                       0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,<br>
-               },<br>
-       },<br>
-};<br>
-<br>
-static const struct hdmiphy_config hdmiphy_v14_configs[] = {<br>
-       {<br>
-               .pixel_clock = 25200000,<br>
-               .conf = {<br>
-                       0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08,<br>
-                       0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 27000000,<br>
-               .conf = {<br>
-                       0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20,<br>
-                       0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 27027000,<br>
-               .conf = {<br>
-                       0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,<br>
-                       0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 36000000,<br>
-               .conf = {<br>
-                       0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08,<br>
-                       0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 40000000,<br>
-               .conf = {<br>
-                       0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08,<br>
-                       0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 65000000,<br>
-               .conf = {<br>
-                       0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08,<br>
-                       0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 74176000,<br>
-               .conf = {<br>
-                       0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,<br>
-                       0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 74250000,<br>
-               .conf = {<br>
-                       0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,<br>
-                       0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 83500000,<br>
-               .conf = {<br>
-                       0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08,<br>
-                       0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 106500000,<br>
-               .conf = {<br>
-                       0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,<br>
-                       0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 108000000,<br>
-               .conf = {<br>
-                       0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08,<br>
-                       0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 146250000,<br>
-               .conf = {<br>
-                       0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,<br>
-                       0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,<br>
-               },<br>
-       },<br>
-       {<br>
-               .pixel_clock = 148500000,<br>
-               .conf = {<br>
-                       0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,<br>
-                       0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,<br>
-                       0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
-                       0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,<br>
-               },<br>
-       },<br>
-};<br>
-<br>
 struct hdmi_infoframe {<br>
        enum HDMI_PACKET_TYPE type;<br>
        u8 ver;<br>
@@ -772,46 +596,6 @@ static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)<br>
        return raw_edid;<br>
 }<br>
<br>
-static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)<br>
-{<br>
-       const struct hdmiphy_config *confs;<br>
-       int count, i;<br>
-<br>
-       DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);<br>
-<br>
-       if (hdata->type == HDMI_TYPE13) {<br>
-               confs = hdmiphy_v13_configs;<br>
-               count = ARRAY_SIZE(hdmiphy_v13_configs);<br>
-       } else if (hdata->type == HDMI_TYPE14) {<br>
-               confs = hdmiphy_v14_configs;<br>
-               count = ARRAY_SIZE(hdmiphy_v14_configs);<br>
-       } else<br>
-               return -EINVAL;<br>
-<br>
-       for (i = 0; i < count; i++)<br>
-               if (confs[i].pixel_clock == pixel_clock)<br>
-                       return i;<br>
-<br>
-       DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);<br>
-       return -EINVAL;<br>
-}<br>
-<br>
-static int hdmi_check_timing(void *ctx, struct drm_display_mode *mode)<br>
-{<br>
-       struct hdmi_context *hdata = ctx;<br>
-       int ret;<br>
-<br>
-       DRM_DEBUG_KMS("%s : xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",<br>
-               __func__, mode->hdisplay, mode->vdisplay,<br>
-               mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :<br>
-               false, mode->clock * 1000);<br>
-<br>
-       ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);<br>
-       if (ret < 0)<br>
-               return ret;<br>
-       return 0;<br>
-}<br>
-<br>
 static void hdmi_set_acr(u32 freq, u8 *acr)<br>
 {<br>
        u32 n, cts;<br>
@@ -1307,20 +1091,12 @@ static void hdmi_timing_apply(struct hdmi_context *hdata)<br>
<br>
 static void hdmiphy_conf_reset(struct hdmi_context *hdata)<br>
 {<br>
-       u8 buffer[2];<br>
        u32 reg;<br>
<br>
        clk_disable(hdata->res.sclk_hdmi);<br>
        clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel);<br>
        clk_enable(hdata->res.sclk_hdmi);<br>
<br>
-       /* operation mode */<br>
-       buffer[0] = 0x1f;<br>
-       buffer[1] = 0x00;<br>
-<br>
-       if (hdata->hdmiphy_port)<br>
-               i2c_master_send(hdata->hdmiphy_port, buffer, 2);<br>
-<br>
        if (hdata->type == HDMI_TYPE13)<br>
                reg = HDMI_V13_PHY_RSTOUT;<br>
        else<br>
@@ -1333,102 +1109,6 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)<br>
        usleep_range(10000, 12000);<br>
 }<br>
<br>
-static void hdmiphy_poweron(struct hdmi_context *hdata)<br>
-{<br>
-       DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);<br>
-<br>
-       if (hdata->type == HDMI_TYPE14)<br>
-               hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0,<br>
-                       HDMI_PHY_POWER_OFF_EN);<br>
-}<br>
-<br>
-static void hdmiphy_poweroff(struct hdmi_context *hdata)<br>
-{<br>
-       DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);<br>
-<br>
-       if (hdata->type == HDMI_TYPE14)<br>
-               hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0,<br>
-                       HDMI_PHY_POWER_OFF_EN);<br>
-}<br>
-<br>
-static void hdmiphy_conf_apply(struct hdmi_context *hdata)<br>
-{<br>
-       const u8 *hdmiphy_data;<br>
-       u8 buffer[32];<br>
-       u8 operation[2];<br>
-       u8 read_buffer[32] = {0, };<br>
-       int ret;<br>
-       int i;<br>
-<br>
-       if (!hdata->hdmiphy_port) {<br>
-               DRM_ERROR("hdmiphy is not attached\n");<br>
-               return;<br>
-       }<br>
-<br>
-       /* pixel clock */<br>
-       i = hdmi_find_phy_conf(hdata, hdata->mode_conf.pixel_clock);<br>
-       if (i < 0) {<br>
-               DRM_ERROR("failed to find hdmiphy conf\n");<br>
-               return;<br>
-       }<br>
-<br>
-       if (hdata->type == HDMI_TYPE13) {<br>
-               hdmiphy_data = hdmiphy_v13_configs[i].conf;<br>
-       } else {<br>
-               hdmiphy_data = hdmiphy_v14_configs[i].conf;<br>
-       }<br>
-<br>
-       memcpy(buffer, hdmiphy_data, 32);<br>
-       ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);<br>
-       if (ret != 32) {<br>
-               DRM_ERROR("failed to configure HDMIPHY via I2C\n");<br>
-               return;<br>
-       }<br>
-<br>
-       usleep_range(10000, 12000);<br>
-<br>
-       /* operation mode */<br>
-       operation[0] = 0x1f;<br>
-       operation[1] = 0x80;<br>
-<br>
-       ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);<br>
-       if (ret != 2) {<br>
-               DRM_ERROR("failed to enable hdmiphy\n");<br>
-               return;<br>
-       }<br>
-<br>
-       ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);<br>
-       if (ret < 0) {<br>
-               DRM_ERROR("failed to read hdmiphy config\n");<br>
-               return;<br>
-       }<br>
-<br>
-       for (i = 0; i < ret; i++)<br>
-               DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "<br>
-                       "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);<br>
-}<br>
-<br>
-static void hdmi_conf_apply(struct hdmi_context *hdata)<br>
-{<br>
-       DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);<br>
-<br>
-       hdmiphy_conf_reset(hdata);<br>
-       hdmiphy_conf_apply(hdata);<br>
-<br>
-       mutex_lock(&hdata->hdmi_mutex);<br>
-       hdmi_conf_reset(hdata);<br>
-       hdmi_conf_init(hdata);<br>
-       mutex_unlock(&hdata->hdmi_mutex);<br>
-<br>
-       hdmi_audio_init(hdata);<br>
-<br>
-       /* setting core registers */<br>
-       hdmi_timing_apply(hdata);<br>
-       hdmi_audio_control(hdata, true);<br>
-<br>
-       hdmi_regs_dump(hdata, "start");<br>
-}<br>
-<br>
 static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value)<br>
 {<br>
        int i;<br>
@@ -1446,7 +1126,6 @@ static void hdmi_v13_mode_set(struct hdmi_context *hdata,<br>
<br>
        hdata->mode_conf.cea_video_id =<br>
                drm_match_cea_mode((struct drm_display_mode *)m);<br>
-       hdata->mode_conf.pixel_clock = m->clock * 1000;<br>
<br>
        hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);<br>
        hdmi_set_reg(core->h_v_line, 3, (m->htotal << 12) | m->vtotal);<br>
@@ -1542,7 +1221,6 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,<br>
<br>
        hdata->mode_conf.cea_video_id =<br>
                drm_match_cea_mode((struct drm_display_mode *)m);<br>
-       hdata->mode_conf.pixel_clock = m->clock * 1000;<br>
<br>
        hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);<br>
        hdmi_set_reg(core->v_line, 2, m->vtotal);<br>
@@ -1668,6 +1346,14 @@ static void hdmi_get_max_resol(void *ctx, unsigned int *width,<br>
        *height = MAX_HEIGHT;<br>
 }<br>
<br>
+static void hdmi_commit_prepare(void *ctx)<br>
+{<br>
+       struct hdmi_context *hdata = ctx;<br>
+       DRM_DEBUG_KMS("[%d]\n", __LINE__);<br>
+<br>
+       hdmiphy_conf_reset(hdata);<br>
+}<br>
+<br>
 static void hdmi_commit(void *ctx)<br>
 {<br>
        struct hdmi_context *hdata = ctx;<br>
@@ -1679,9 +1365,18 @@ static void hdmi_commit(void *ctx)<br>
                mutex_unlock(&hdata->hdmi_mutex);<br>
                return;<br>
        }<br>
+<br>
+       hdmi_conf_reset(hdata);<br>
+       hdmi_conf_init(hdata);<br>
        mutex_unlock(&hdata->hdmi_mutex);<br>
<br>
-       hdmi_conf_apply(hdata);<br>
+       hdmi_audio_init(hdata);<br>
+<br>
+       /* setting core registers */<br>
+       hdmi_timing_apply(hdata);<br>
+       hdmi_audio_control(hdata, true);<br>
+<br>
+       hdmi_regs_dump(hdata, "start");<br>
 }<br>
<br>
 static void hdmi_poweron(struct hdmi_context *hdata)<br>
@@ -1704,8 +1399,6 @@ static void hdmi_poweron(struct hdmi_context *hdata)<br>
        clk_enable(res->hdmiphy);<br>
        clk_enable(res->hdmi);<br>
        clk_enable(res->sclk_hdmi);<br>
-<br>
-       hdmiphy_poweron(hdata);<br>
 }<br>
<br>
 static void hdmi_poweroff(struct hdmi_context *hdata)<br>
@@ -1724,7 +1417,6 @@ static void hdmi_poweroff(struct hdmi_context *hdata)<br>
         * its reset state seems to meet the condition.<br>
         */<br>
        hdmiphy_conf_reset(hdata);<br>
-       hdmiphy_poweroff(hdata);<br>
<br>
        clk_disable(res->sclk_hdmi);<br>
        clk_disable(res->hdmi);<br>
@@ -1766,11 +1458,11 @@ static struct exynos_hdmi_ops hdmi_ops = {<br>
        /* display */<br>
        .is_connected   = hdmi_is_connected,<br>
        .get_edid       = hdmi_get_edid,<br>
-       .check_timing   = hdmi_check_timing,<br>
<br>
        /* manager */<br>
        .mode_set       = hdmi_mode_set,<br>
        .get_max_resol  = hdmi_get_max_resol,<br>
+       .prepare        = hdmi_commit_prepare,<br>
        .commit         = hdmi_commit,<br>
        .dpms           = hdmi_dpms,<br>
 };<br>
@@ -1858,7 +1550,7 @@ fail:<br>
        return -ENODEV;<br>
 }<br>
<br>
-static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;<br>
+static struct i2c_client *hdmi_ddc;<br>
<br>
 void hdmi_attach_ddc_client(struct i2c_client *ddc)<br>
 {<br>
@@ -1866,12 +1558,6 @@ void hdmi_attach_ddc_client(struct i2c_client *ddc)<br>
                hdmi_ddc = ddc;<br>
 }<br>
<br>
-void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)<br>
-{<br>
-       if (hdmiphy)<br>
-               hdmi_hdmiphy = hdmiphy;<br>
-}<br>
-<br>
 #ifdef CONFIG_OF<br>
 static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata<br>
                                        (struct device *dev)<br>
@@ -2029,20 +1715,11 @@ static int hdmi_probe(struct platform_device *pdev)<br>
<br>
        hdata->ddc_port = hdmi_ddc;<br>
<br>
-       /* hdmiphy i2c driver */<br>
-       if (i2c_add_driver(&hdmiphy_driver)) {<br>
-               DRM_ERROR("failed to register hdmiphy i2c driver\n");<br>
-               ret = -ENOENT;<br>
-               goto err_ddc;<br>
-       }<br>
-<br>
-       hdata->hdmiphy_port = hdmi_hdmiphy;<br>
-<br>
        hdata->irq = gpio_to_irq(hdata->hpd_gpio);<br>
        if (hdata->irq < 0) {<br>
                DRM_ERROR("failed to get GPIO irq\n");<br>
                ret = hdata->irq;<br>
-               goto err_hdmiphy;<br>
+               goto err_ddc;<br>
        }<br>
<br>
        hdata->hpd = gpio_get_value(hdata->hpd_gpio);<br>
@@ -2053,7 +1730,7 @@ static int hdmi_probe(struct platform_device *pdev)<br>
                        "hdmi", drm_hdmi_ctx);<br>
        if (ret) {<br>
                DRM_ERROR("failed to register hdmi interrupt\n");<br>
-               goto err_hdmiphy;<br>
+               goto err_ddc;<br>
        }<br>
<br>
        /* Attach HDMI Driver to common hdmi. */<br>
@@ -2066,8 +1743,6 @@ static int hdmi_probe(struct platform_device *pdev)<br>
<br>
        return 0;<br>
<br>
-err_hdmiphy:<br>
-       i2c_del_driver(&hdmiphy_driver);<br>
 err_ddc:<br>
        i2c_del_driver(&ddc_driver);<br>
        return ret;<br>
@@ -2085,9 +1760,6 @@ static int hdmi_remove(struct platform_device *pdev)<br>
<br>
        free_irq(hdata->irq, hdata);<br>
<br>
-<br>
-       /* hdmiphy i2c driver */<br>
-       i2c_del_driver(&hdmiphy_driver);<br>
        /* DDC i2c driver */<br>
        i2c_del_driver(&ddc_driver);<br>
<br>
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.h b/drivers/gpu/drm/exynos/exynos_hdmi.h<br>
index 0ddf395..6595d7b 100644<br>
--- a/drivers/gpu/drm/exynos/exynos_hdmi.h<br>
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.h<br>
@@ -15,7 +15,6 @@<br>
 #define _EXYNOS_HDMI_H_<br>
<br>
 void hdmi_attach_ddc_client(struct i2c_client *ddc);<br>
-void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy);<br>
<br>
 extern struct i2c_driver hdmiphy_driver;<br>
 extern struct i2c_driver ddc_driver;<br>
diff --git a/drivers/gpu/drm/exynos/exynos_hdmiphy.c b/drivers/gpu/drm/exynos/exynos_hdmiphy.c<br>
index ea49d13..de7cdfd 100644<br>
--- a/drivers/gpu/drm/exynos/exynos_hdmiphy.c<br>
+++ b/drivers/gpu/drm/exynos/exynos_hdmiphy.c<br>
@@ -16,33 +16,438 @@<br>
 #include <linux/kernel.h><br>
 #include <linux/i2c.h><br>
 #include <linux/module.h><br>
+#include <linux/pm_runtime.h><br>
+#include <linux/clk.h><br>
<br>
 #include "exynos_drm_drv.h"<br>
+#include "exynos_drm_hdmi.h"<br>
 #include "exynos_hdmi.h"<br>
<br>
+#include "regs-hdmiphy.h"<br>
<br>
-static int hdmiphy_probe(struct i2c_client *client,<br>
-       const struct i2c_device_id *id)<br>
+#define HDMIPHY_REG_COUNT              (32)<br>
+<br>
+enum hdmiphy_type {<br>
+       HDMIPHY_EXYNOS4210,<br>
+       HDMIPHY_EXYNOS4212,<br>
+};<br>
+<br>
+struct hdmiphy_context {<br>
+       struct device           *dev;<br>
+       bool                    powered;<br>
+       void                    *parent_ctx;<br>
+       enum hdmiphy_type               type;<br>
+       const struct hdmiphy_config     *conf;<br>
+       struct clk              *hdmiphy;<br>
+};<br>
+<br>
+struct hdmiphy_config {<br>
+       int pixel_clock;<br>
+       u8 conf[HDMIPHY_REG_COUNT];<br>
+};<br>
+<br>
+/* list of all required phy config settings */<br>
+static const struct hdmiphy_config hdmiphy_4212_configs[] = {<br>
+       {<br>
+               .pixel_clock = 25200000,<br>
+               .conf = {<br>
+                       0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08,<br>
+                       0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 27000000,<br>
+               .conf = {<br>
+                       0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20,<br>
+                       0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 27027000,<br>
+               .conf = {<br>
+                       0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,<br>
+                       0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 36000000,<br>
+               .conf = {<br>
+                       0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08,<br>
+                       0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 40000000,<br>
+               .conf = {<br>
+                       0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08,<br>
+                       0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 65000000,<br>
+               .conf = {<br>
+                       0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08,<br>
+                       0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 74176000,<br>
+               .conf = {<br>
+                       0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,<br>
+                       0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 74250000,<br>
+               .conf = {<br>
+                       0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,<br>
+                       0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 83500000,<br>
+               .conf = {<br>
+                       0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08,<br>
+                       0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 106500000,<br>
+               .conf = {<br>
+                       0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,<br>
+                       0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 108000000,<br>
+               .conf = {<br>
+                       0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08,<br>
+                       0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 146250000,<br>
+               .conf = {<br>
+                       0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,<br>
+                       0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 148500000,<br>
+               .conf = {<br>
+                       0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,<br>
+                       0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,<br>
+                       0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,<br>
+                       0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,<br>
+               },<br>
+       },<br>
+};<br>
+<br>
+static const struct hdmiphy_config hdmiphy_4210_configs[] = {<br>
+       {<br>
+               .pixel_clock = 27000000,<br>
+               .conf = {<br>
+                       0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,<br>
+                       0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,<br>
+                       0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,<br>
+                       0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 27027000,<br>
+               .conf = {<br>
+                       0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,<br>
+                       0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,<br>
+                       0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,<br>
+                       0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 74176000,<br>
+               .conf = {<br>
+                       0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,<br>
+                       0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,<br>
+                       0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,<br>
+                       0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 74250000,<br>
+               .conf = {<br>
+                       0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,<br>
+                       0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,<br>
+                       0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,<br>
+                       0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,<br>
+               },<br>
+       },<br>
+       {<br>
+               .pixel_clock = 148500000,<br>
+               .conf = {<br>
+                       0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,<br>
+                       0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,<br>
+                       0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,<br>
+                       0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,<br>
+               },<br>
+       },<br>
+};<br>
+<br>
+static const struct hdmiphy_config *hdmiphy_find_conf(void *ctx,<br>
+                       const struct drm_display_mode *mode)<br>
+{<br>
+       struct hdmiphy_context *hdata = ctx;<br>
+       const struct hdmiphy_config *confs;<br>
+       int count, i;<br>
+<br>
+       switch (hdata->type) {<br>
+       case HDMIPHY_EXYNOS4212:<br>
+               confs = hdmiphy_4212_configs;<br>
+               count = ARRAY_SIZE(hdmiphy_4212_configs);<br>
+               break;<br>
+       case HDMIPHY_EXYNOS4210:<br>
+               confs = hdmiphy_4210_configs;<br>
+               count = ARRAY_SIZE(hdmiphy_4210_configs);<br>
+               break;<br>
+       default:<br>
+               DRM_ERROR("failed to find HDMIPHY type\n");<br>
+               return NULL;<br>
+       }<br>
+<br>
+       for (i = 0; i < count; i++)<br>
+               if (confs[i].pixel_clock == (mode->clock * 1000))<br>
+                       return &confs[i];<br>
+<br>
+       return NULL;<br>
+}<br>
+<br>
+static int hdmiphy_check_timing(void *ctx, struct drm_display_mode *mode)<br>
 {<br>
-       hdmi_attach_hdmiphy_client(client);<br>
+       const struct hdmiphy_config *conf;<br>
+       DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",<br>
+               mode->hdisplay, mode->vdisplay,<br>
+               mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE)<br>
+               ? true : false, mode->clock * 1000);<br>
<br>
-       dev_info(&client->adapter->dev, "attached s5p_hdmiphy "<br>
-               "into i2c adapter successfully\n");<br>
+       conf = hdmiphy_find_conf(ctx, mode);<br>
+       if (!conf) {<br>
+               DRM_DEBUG_KMS("Display Mode is not supported.\n");<br>
+               return -EINVAL;<br>
+       }<br>
<br>
        return 0;<br>
 }<br>
<br>
-static int hdmiphy_remove(struct i2c_client *client)<br>
+static void hdmiphy_mode_set(void *ctx, struct drm_display_mode *mode)<br>
+{<br>
+       struct hdmiphy_context *hdata = ctx;<br>
+<br>
+       DRM_DEBUG_KMS("[%d]\n", __LINE__);<br>
+<br>
+       hdata->conf = hdmiphy_find_conf(ctx, mode);<br>
+}<br>
+<br>
+static void hdmiphy_config_prepare(void *ctx)<br>
+{<br>
+       struct hdmiphy_context *hdata = ctx;<br>
+       const struct i2c_client *client = to_i2c_client(hdata->dev);<br>
+       u8 buffer[2];<br>
+<br>
+       DRM_DEBUG_KMS("[%d]\n", __LINE__);<br>
+<br>
+       /* operation mode */<br>
+       buffer[0] = HDMIPHY_MODE_SET_DONE;<br>
+       buffer[1] = 0x00;<br>
+<br>
+       if (client)<br>
+               i2c_master_send(client, buffer, 2);<br>
+}<br>
+<br>
+static int hdmiphy_config_apply(void *ctx)<br>
 {<br>
-       dev_info(&client->adapter->dev, "detached s5p_hdmiphy "<br>
-               "from i2c adapter successfully\n");<br>
+       struct hdmiphy_context *hdata = ctx;<br>
+       struct i2c_client *client = to_i2c_client(hdata->dev);<br>
+       const u8 *hdmiphy_data;<br>
+       u8 buffer[HDMIPHY_REG_COUNT];<br>
+       u8 operation[2];<br>
+       u8 read_buffer[HDMIPHY_REG_COUNT] = {0, };<br>
+       int ret;<br>
+       int i;<br>
+<br>
+       DRM_DEBUG_KMS("[%d]\n", __LINE__);<br>
+<br>
+       /* pixel clock */<br>
+       if (hdata->conf && client)<br>
+               hdmiphy_data = hdata->conf->conf;<br>
+       else<br>
+               return -EINVAL;<br>
+<br>
+       memcpy(buffer, hdmiphy_data, HDMIPHY_REG_COUNT);<br>
+<br>
+       ret = i2c_master_send(client, buffer, HDMIPHY_REG_COUNT);<br>
+       if (ret != HDMIPHY_REG_COUNT) {<br>
+               DRM_ERROR("failed to configure HDMIPHY via I2C\n");<br>
+               return ret;<br>
+       }<br>
+<br>
+       usleep_range(10000, 12000);<br>
+<br>
+       /* operation mode */<br>
+       operation[0] = HDMIPHY_MODE_SET_DONE;<br>
+       operation[1] = HDMIPHY_MODE_EN;<br>
+<br>
+       ret = i2c_master_send(client, operation, 2);<br>
+       if (ret != 2) {<br>
+               DRM_ERROR("failed to enable hdmiphy\n");<br>
+               return ret;<br>
+       }<br>
+<br>
+       ret = i2c_master_recv(client, read_buffer, HDMIPHY_REG_COUNT);<br>
+       if (ret < 0) {<br>
+               DRM_ERROR("failed to read hdmiphy config\n");<br>
+               return ret;<br>
+       }<br>
+<br>
+       for (i = 0; i < ret; i++)<br>
+               DRM_DEBUG_KMS("hdmiphy[0x%02x] wr[0x%02x], rd[0x%02x]\n",<br>
+                               i, buffer[i], read_buffer[i]);<br>
+       return 0;<br>
+}<br>
+<br>
+static void hdmiphy_dpms(void *ctx, int mode)<br>
+{<br>
+       struct hdmiphy_context *hdata = ctx;<br>
+<br>
+       DRM_DEBUG_KMS("[%d] mode %d\n", __LINE__, mode);<br>
+<br>
+       switch (mode) {<br>
+       case DRM_MODE_DPMS_ON:<br>
+               if (pm_runtime_suspended(hdata->dev))<br>
+                       pm_runtime_get_sync(hdata->dev);<br>
+               break;<br>
+       case DRM_MODE_DPMS_STANDBY:<br>
+       case DRM_MODE_DPMS_SUSPEND:<br>
+       case DRM_MODE_DPMS_OFF:<br>
+               if (!pm_runtime_suspended(hdata->dev))<br>
+                       pm_runtime_put_sync(hdata->dev);<br>
+               break;<br>
+       default:<br>
+               DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);<br>
+               break;<br>
+       }<br>
+}<br>
+<br>
+static int hdmiphy_update_bits(struct i2c_client *client, u8 *reg_cache,<br>
+                              u8 reg, u8 mask, u8 val)<br>
+{<br>
+       int ret;<br>
+       u8 buffer[2];<br>
+<br>
+       buffer[0] = reg;<br>
+       buffer[1] = (reg_cache[reg] & ~mask) | (val & mask);<br>
+       reg_cache[reg] = buffer[1];<br>
+<br>
+       ret = i2c_master_send(client, buffer, 2);<br>
+       if (ret != 2)<br>
+               return -EIO;<br>
<br>
        return 0;<br>
 }<br>
<br>
+static int hdmiphy_4412_turn_on(struct i2c_client *client, bool on)<br>
+{<br>
+       u8 reg_cache[HDMIPHY_REG_COUNT] = { 0 };<br>
+       u8 buffer[2];<br>
+       int ret;<br>
+<br>
+       DRM_DEBUG_KMS("hdmiphy is %s\n", on ? "on" : "off");<br>
+<br>
+       /* Cache all hdmi-phy registers to make the code below faster */<br>
+       buffer[0] = 0x0;<br>
+       ret = i2c_master_send(client, buffer, 1);<br>
+       if (ret != 1) {<br>
+               ret = -EIO;<br>
+               goto exit;<br>
+       }<br>
+       ret = i2c_master_recv(client, reg_cache, HDMIPHY_REG_COUNT);<br>
+       if (ret != HDMIPHY_REG_COUNT) {<br>
+               ret = -EIO;<br>
+               goto exit;<br>
+       }<br>
+<br>
+       /* Change to/from configuration from/to operation mode */<br>
+       ret = hdmiphy_update_bits(client, reg_cache, HDMIPHY_MODE_SET_DONE,<br>
+                               HDMIPHY_MODE_EN, on ? ~0 : 0);<br>
+       if (ret)<br>
+               goto exit;<br>
+<br>
+       /*<br>
+        * Turn off "oscpad" if !on; it turns on again in<br>
+        * during phy-configuration.<br>
+        */<br>
+       if (!on)<br>
+               ret = hdmiphy_update_bits(client, reg_cache,<br>
+                       HDMIPHY_4212_OSC_PAD_CON, HDMIPHY_OSC_PAD_EN, 0);<br>
+               if (ret)<br>
+                       goto exit;<br>
+<br>
+       /* Disable powerdown if on; enable if !on */<br>
+       ret = hdmiphy_update_bits(client, reg_cache, HDMIPHY_4212_PD_CON,<br>
+                       HDMIPHY_PDEN, on ? 0 : ~0);<br>
+       if (ret)<br>
+               goto exit;<br>
+       ret = hdmiphy_update_bits(client, reg_cache, HDMIPHY_4212_PD_CON,<br>
+                       HDMIPHY_PD_ALL, on ? 0 : ~0);<br>
+       if (ret)<br>
+               goto exit;<br>
+<br>
+       /* Disable pixel clock generator block if !on */<br>
+       if (!on)<br>
+               ret = hdmiphy_update_bits(client, reg_cache,<br>
+                       HDMIPHY_4212_PCG_CON, HDMIPHY_PCG_RESET_EN, 0);<br>
+               if (ret)<br>
+                       goto exit;<br>
+<br>
+exit:<br>
+       /* Don't expect any errors so just do a single warn */<br>
+       WARN_ON(ret);<br>
+<br>
+       return ret;<br>
+}<br>
+<br>
+static struct exynos_hdmiphy_ops hdmiphy_ops = {<br>
+       .check_timing   = hdmiphy_check_timing,<br>
+       .mode_set               = hdmiphy_mode_set,<br>
+       .prepare                = hdmiphy_config_prepare,<br>
+       .config_apply   = hdmiphy_config_apply,<br>
+       .dpms           = hdmiphy_dpms,<br>
+};<br>
+<br>
 static const struct i2c_device_id hdmiphy_id[] = {<br>
-       { "s5p_hdmiphy", 0 },<br>
-       { "exynos5-hdmiphy", 0 },<br>
+       { "s5p_hdmiphy", HDMIPHY_EXYNOS4210 },<br>
+       { "exynos5-hdmiphy", HDMIPHY_EXYNOS4212 },<br>
        { },<br>
 };<br>
<br>
@@ -50,21 +455,181 @@ static const struct i2c_device_id hdmiphy_id[] = {<br>
 static struct of_device_id hdmiphy_match_types[] = {<br>
        {<br>
                .compatible = "samsung,exynos5-hdmiphy",<br>
+               .data   = (void *)HDMIPHY_EXYNOS4212,<br>
        }, {<br>
                /* end node */<br>
        }<br>
 };<br>
 #endif<br>
<br>
+static int hdmiphy_probe(struct i2c_client *client,<br>
+       const struct i2c_device_id *id)<br>
+{<br>
+       struct device *dev = &client->dev;<br>
+       struct hdmiphy_context *hdata;<br>
+       struct exynos_drm_hdmi_context *drm_hdmi_ctx;<br>
+<br>
+       DRM_DEBUG_KMS("[%d]\n", __LINE__);<br>
+<br>
+       drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx),<br>
+                                       GFP_KERNEL);<br>
+       if (!drm_hdmi_ctx) {<br>
+               DRM_ERROR("failed to allocate common hdmi context.\n");<br>
+               return -ENOMEM;<br>
+       }<br>
+<br>
+       hdata = devm_kzalloc(dev, sizeof(*hdata), GFP_KERNEL);<br>
+       if (!hdata) {<br>
+               DRM_ERROR("failed to allocate hdmiphy context.\n");<br>
+               return -ENOMEM;<br>
+       }<br>
+<br>
+       if (dev->of_node) {<br>
+               const struct of_device_id *match;<br>
+               match = of_match_node(of_match_ptr(hdmiphy_match_types),<br>
+                                       dev->of_node);<br>
+               if (match == NULL)<br>
+                       return -ENODEV;<br>
+               hdata->type = (enum hdmiphy_type)match->data;<br>
+       } else {<br>
+               hdata->type = (enum hdmiphy_type)id->driver_data;<br>
+       }<br>
+<br>
+       drm_hdmi_ctx->ctx = (void *)hdata;<br>
+       hdata->parent_ctx = (void *)drm_hdmi_ctx;<br>
+       hdata->dev = dev;<br>
+<br>
+       hdata->hdmiphy = devm_clk_get(dev, "hdmiphy");<br>
+       if (IS_ERR_OR_NULL(hdata->hdmiphy)) {<br>
+               DRM_ERROR("failed to get clock 'hdmiphy'\n");<br>
+               return PTR_ERR(hdata->hdmiphy);<br>
+       }<br>
+<br>
+       i2c_set_clientdata(client, hdata);<br>
+<br>
+       /* Attach HDMI-PHY Driver to common hdmi. */<br>
+       exynos_hdmiphy_drv_attach(drm_hdmi_ctx);<br>
+<br>
+       /* register specific callbacks to common hdmi. */<br>
+       exynos_hdmiphy_ops_register(&hdmiphy_ops);<br>
+<br>
+       pm_runtime_enable(dev);<br>
+<br>
+       dev_info(&client->adapter->dev,<br>
+               "attached s5p_hdmiphy into i2c adapter successfully\n");<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
+static int hdmiphy_remove(struct i2c_client *client)<br>
+{<br>
+       dev_info(&client->adapter->dev,<br>
+               "detached s5p_hdmiphy from i2c adapter successfully\n");<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
+static void hdmiphy_poweroff(struct device *dev)<br>
+{<br>
+       struct i2c_client *client = to_i2c_client(dev);<br>
+       struct hdmiphy_context *hdata = i2c_get_clientdata(client);<br>
+<br>
+       DRM_DEBUG_KMS("[%d]\n", __LINE__);<br>
+<br>
+       if (hdata->type == HDMIPHY_EXYNOS4212)<br>
+               hdmiphy_4412_turn_on(client, 0);<br>
+<br>
+       clk_disable(hdata->hdmiphy);<br>
+}<br>
+<br>
+static void hdmiphy_poweron(struct device *dev)<br>
+{<br>
+       struct i2c_client *client = to_i2c_client(dev);<br>
+       struct hdmiphy_context *hdata = i2c_get_clientdata(client);<br>
+<br>
+       DRM_DEBUG_KMS("[%d]\n", __LINE__);<br>
+<br>
+       clk_enable(hdata->hdmiphy);<br>
+<br>
+       if (hdata->type == HDMIPHY_EXYNOS4212)<br>
+               hdmiphy_4412_turn_on(client, 1);<br>
+}<br>
+<br>
+#ifdef CONFIG_PM_SLEEP<br>
+static int hdmiphy_suspend(struct device *dev)<br>
+{<br>
+       DRM_DEBUG_KMS("[%d]\n", __LINE__);<br>
+<br>
+       if (pm_runtime_suspended(dev)) {<br>
+               DRM_DEBUG_KMS("already runtime-suspended.\n");<br>
+               return 0;<br>
+       }<br>
+<br>
+       hdmiphy_poweroff(dev);<br>
+       return 0;<br>
+}<br>
+<br>
+static int hdmiphy_resume(struct device *dev)<br>
+{<br>
+       DRM_DEBUG_KMS("[%d]\n", __LINE__);<br>
+<br>
+       if (pm_runtime_suspended(dev)) {<br>
+               /* dpms callback should resume the mixer. */<br>
+               DRM_DEBUG_KMS("already runtime-suspended.\n");<br>
+               return 0;<br>
+       }<br>
+<br>
+       hdmiphy_poweron(dev);<br>
+       return 0;<br>
+}<br>
+#endif<br>
+<br>
+<br>
+#ifdef CONFIG_PM_RUNTIME<br>
+static int hdmiphy_runtime_suspend(struct device *dev)<br>
+{<br>
+       DRM_DEBUG_KMS("[%d]\n", __LINE__);<br>
+<br>
+       hdmiphy_poweroff(dev);<br>
+       return 0;<br>
+}<br>
+<br>
+static int hdmiphy_runtime_resume(struct device *dev)<br>
+{<br>
+       DRM_DEBUG_KMS("[%d]\n", __LINE__);<br>
+<br>
+       hdmiphy_poweron(dev);<br>
+       return 0;<br>
+}<br>
+#endif<br>
+<br>
+static const struct dev_pm_ops hdmiphy_pm_ops = {<br>
+       SET_SYSTEM_SLEEP_PM_OPS(hdmiphy_suspend, hdmiphy_resume)<br>
+       SET_RUNTIME_PM_OPS(hdmiphy_runtime_suspend,<br>
+               hdmiphy_runtime_resume, NULL)<br>
+};<br>
+<br>
 struct i2c_driver hdmiphy_driver = {<br>
        .driver = {<br>
                .name   = "exynos-hdmiphy",<br>
                .owner  = THIS_MODULE,<br>
                .of_match_table = of_match_ptr(hdmiphy_match_types),<br>
+               .pm     = &hdmiphy_pm_ops,<br>
        },<br>
        .id_table = hdmiphy_id,<br>
        .probe          = hdmiphy_probe,<br>
        .remove         = hdmiphy_remove,<br>
        .command                = NULL,<br>
 };<br>
+<br>
+extern int exynos_hdmiphy_driver_register(void)<br>
+{<br>
+       return i2c_add_driver(&hdmiphy_driver);<br>
+}<br>
+<br>
+extern void exynos_hdmiphy_driver_unregister(void)<br>
+{<br>
+       i2c_del_driver(&hdmiphy_driver);<br>
+}<br>
+<br>
 EXPORT_SYMBOL(hdmiphy_driver);<br>
diff --git a/drivers/gpu/drm/exynos/regs-hdmiphy.h b/drivers/gpu/drm/exynos/regs-hdmiphy.h<br>
new file mode 100644<br>
index 0000000..1bb0860<br>
--- /dev/null<br>
+++ b/drivers/gpu/drm/exynos/regs-hdmiphy.h<br>
@@ -0,0 +1,61 @@<br>
+/*<br>
+ *<br>
+ *  regs-hdmiphy.h<br>
+ *<br>
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.<br>
+ * <a href="http://www.samsung.com/" target="_blank">http://www.samsung.com/</a><br>
+ *<br>
+ * HDMI-PHY register header file for Samsung TVOUT driver<br>
+ *<br>
+ * This program is free software; you can redistribute it and/or modify<br>
+ * it under the terms of the GNU General Public License version 2 as<br>
+ * published by the Free Software Foundation.<br>
+*/<br>
+<br>
+#ifndef SAMSUNG_REGS_HDMIPHY_H<br>
+#define SAMSUNG_REGS_HDMIPHY_H<br>
+<br>
+/*<br>
+ * Register part<br>
+*/<br>
+<br>
+/* HDMI PHY Version Common */<br>
+#define HDMIPHY_MODE_SET_DONE          (0x1f)<br>
+<br>
+/* HDMI PHY Version 4212 */<br>
+#define HDMIPHY_4212_PCG_CON           (0x04)<br>
+#define HDMIPHY_4212_OSC_PAD_CON       (0x0b)<br>
+#define HDMIPHY_4212_PD_CON            (0x1d)<br>
+<br>
+/*<br>
+ * Bit definition part<br>
+ */<br>
+<br>
+/* HDMIPHY_MODE_SET_DONE */<br>
+#define HDMIPHY_MODE_EN                (1 << 7)<br>
+<br>
+/* HDMIPHY_4212_PCG_CON */<br>
+#define HDMIPHY_PCG_RESET_EN           (1 << 3)<br>
+<br>
+/* HDMIPHY_4212_OSC_PAD_CON */<br>
+#define HDMIPHY_OSC_PAD_EN             (3 << 6)<br>
+<br>
+/* HDMIPHY_4212_PD_CON */<br>
+#define HDMIPHY_PDEN                   (1 << 7)<br>
+<br>
+#define HDMIPHY_PLL_PD                 (1 << 6)<br>
+#define HDMIPHY_CLKSER_PD              (1 << 5)<br>
+#define HDMIPHY_CLKDRV_PD              (1 << 4)<br>
+<br>
+#define HDMIPHY_DRV_PD                 (1 << 2)<br>
+#define HDMIPHY_SER_PD                 (1 << 1)<br>
+#define HDMIPHY_ICLK_PD                (1 << 0)<br>
+<br>
+#define HDMIPHY_PD_ALL                 (HDMIPHY_PLL_PD |\<br>
+                                       HDMIPHY_CLKSER_PD |\<br>
+                                       HDMIPHY_CLKDRV_PD|\<br>
+                                       HDMIPHY_DRV_PD|\<br>
+                                       HDMIPHY_SER_PD|\<br>
+                                       HDMIPHY_ICLK_PD)<br>
+<br>
+#endif /* SAMSUNG_REGS_HDMIPHY_H */<br>
--<br>
1.7.10.4<br>
<br>
--<br>
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in<br>
the body of a message to <a href="mailto:majordomo@vger.kernel.org">majordomo@vger.kernel.org</a><br>
More majordomo info at  <a href="http://vger.kernel.org/majordomo-info.html" target="_blank">http://vger.kernel.org/majordomo-info.html</a><br>
</div></div></blockquote></div><br></div></div>