]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/exynos/exynos_hdmi.c
drm/exynos/hdmi: remove hdmi_v13_conf struct
[karo-tx-linux.git] / drivers / gpu / drm / exynos / exynos_hdmi.c
index 99e286489031c4a2931565823e0158428548aef2..60663ad9891ff06cc25c67c06d804dae6b47c2c7 100644 (file)
@@ -22,7 +22,6 @@
 #include "regs-hdmi.h"
 
 #include <linux/kernel.h>
-#include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
@@ -33,8 +32,8 @@
 #include <linux/clk.h>
 #include <linux/regulator/consumer.h>
 #include <linux/io.h>
-#include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/hdmi.h>
 #include <linux/component.h>
@@ -48,7 +47,6 @@
 #include "exynos_mixer.h"
 
 #include <linux/gpio.h>
-#include <media/s5p_hdmi.h>
 
 #define ctx_from_connector(c)  container_of(c, struct hdmi_context, connector)
 
@@ -109,19 +107,6 @@ struct hdmi_tg_regs {
        u8 tg_3d[1];
 };
 
-struct hdmi_v13_core_regs {
-       u8 h_blank[2];
-       u8 v_blank[3];
-       u8 h_v_line[3];
-       u8 vsync_pol[1];
-       u8 int_pro_mode[1];
-       u8 v_blank_f[3];
-       u8 h_sync_gen[3];
-       u8 v_sync_gen1[3];
-       u8 v_sync_gen2[3];
-       u8 v_sync_gen3[3];
-};
-
 struct hdmi_v14_core_regs {
        u8 h_blank[2];
        u8 v2_blank[2];
@@ -161,36 +146,19 @@ struct hdmi_v14_core_regs {
        u8 vact_space_6[2];
 };
 
-struct hdmi_v13_conf {
-       struct hdmi_v13_core_regs core;
-       struct hdmi_tg_regs tg;
-};
-
 struct hdmi_v14_conf {
        struct hdmi_v14_core_regs core;
        struct hdmi_tg_regs tg;
 };
 
-struct hdmi_conf_regs {
-       int pixel_clock;
-       int cea_video_id;
-       enum hdmi_picture_aspect aspect_ratio;
-       union {
-               struct hdmi_v13_conf v13_conf;
-               struct hdmi_v14_conf v14_conf;
-       } conf;
-};
-
 struct hdmi_context {
        struct exynos_drm_display       display;
        struct device                   *dev;
        struct drm_device               *drm_dev;
        struct drm_connector            connector;
        struct drm_encoder              *encoder;
-       bool                            hpd;
        bool                            powered;
        bool                            dvi_mode;
-       struct mutex                    hdmi_mutex;
 
        void __iomem                    *regs;
        int                             irq;
@@ -201,17 +169,16 @@ struct hdmi_context {
 
        /* current hdmiphy conf regs */
        struct drm_display_mode         current_mode;
-       struct hdmi_conf_regs           mode_conf;
+       u8                              cea_video_id;
+       struct hdmi_v14_conf            mode_conf;
 
        struct hdmi_resources           res;
+       const struct hdmi_driver_data   *drv_data;
 
        int                             hpd_gpio;
        void __iomem                    *regs_hdmiphy;
-       const struct hdmiphy_config             *phy_confs;
-       unsigned int                    phy_conf_count;
 
        struct regmap                   *pmureg;
-       enum hdmi_type                  type;
 };
 
 static inline struct hdmi_context *display_to_hdmi(struct exynos_drm_display *d)
@@ -624,6 +591,16 @@ static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
        writeb(value, hdata->regs + reg_id);
 }
 
+static inline void hdmi_reg_writev(struct hdmi_context *hdata, u32 reg_id,
+                                  int bytes, u32 val)
+{
+       while (--bytes >= 0) {
+               writeb(val & 0xff, hdata->regs + reg_id);
+               val >>= 8;
+               reg_id += 4;
+       }
+}
+
 static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
                                 u32 reg_id, u32 value, u32 mask)
 {
@@ -930,7 +907,7 @@ static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
 
 static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
 {
-       if (hdata->type == HDMI_TYPE13)
+       if (hdata->drv_data->type == HDMI_TYPE13)
                hdmi_v13_regs_dump(hdata, prefix);
        else
                hdmi_v14_regs_dump(hdata, prefix);
@@ -957,7 +934,7 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
        u32 hdr_sum;
        u8 chksum;
        u32 mod;
-       u32 vic;
+       u8 ar;
 
        mod = hdmi_reg_read(hdata, HDMI_MODE_SEL);
        if (hdata->dvi_mode) {
@@ -988,27 +965,22 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
                 * Set the aspect ratio as per the mode, mentioned in
                 * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard
                 */
-               switch (hdata->mode_conf.aspect_ratio) {
+               ar = hdata->current_mode.picture_aspect_ratio;
+               switch (ar) {
                case HDMI_PICTURE_ASPECT_4_3:
-                       hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
-                                       hdata->mode_conf.aspect_ratio |
-                                       AVI_4_3_CENTER_RATIO);
+                       ar |= AVI_4_3_CENTER_RATIO;
                        break;
                case HDMI_PICTURE_ASPECT_16_9:
-                       hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
-                                       hdata->mode_conf.aspect_ratio |
-                                       AVI_16_9_CENTER_RATIO);
+                       ar |= AVI_16_9_CENTER_RATIO;
                        break;
                case HDMI_PICTURE_ASPECT_NONE:
                default:
-                       hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
-                                       hdata->mode_conf.aspect_ratio |
-                                       AVI_SAME_AS_PIC_ASPECT_RATIO);
+                       ar |= AVI_SAME_AS_PIC_ASPECT_RATIO;
                        break;
                }
+               hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), ar);
 
-               vic = hdata->mode_conf.cea_video_id;
-               hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
+               hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), hdata->cea_video_id);
 
                chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
                                        infoframe->any.length, hdr_sum);
@@ -1038,10 +1010,10 @@ static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
 {
        struct hdmi_context *hdata = ctx_from_connector(connector);
 
-       hdata->hpd = gpio_get_value(hdata->hpd_gpio);
+       if (gpio_get_value(hdata->hpd_gpio))
+               return connector_status_connected;
 
-       return hdata->hpd ? connector_status_connected :
-                       connector_status_disconnected;
+       return connector_status_disconnected;
 }
 
 static void hdmi_connector_destroy(struct drm_connector *connector)
@@ -1064,6 +1036,7 @@ static int hdmi_get_modes(struct drm_connector *connector)
 {
        struct hdmi_context *hdata = ctx_from_connector(connector);
        struct edid *edid;
+       int ret;
 
        if (!hdata->ddc_adpt)
                return -ENODEV;
@@ -1079,15 +1052,19 @@ static int hdmi_get_modes(struct drm_connector *connector)
 
        drm_mode_connector_update_edid_property(connector, edid);
 
-       return drm_add_edid_modes(connector, edid);
+       ret = drm_add_edid_modes(connector, edid);
+
+       kfree(edid);
+
+       return ret;
 }
 
 static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
 {
        int i;
 
-       for (i = 0; i < hdata->phy_conf_count; i++)
-               if (hdata->phy_confs[i].pixel_clock == pixel_clock)
+       for (i = 0; i < hdata->drv_data->phy_conf_count; i++)
+               if (hdata->drv_data->phy_confs[i].pixel_clock == pixel_clock)
                        return i;
 
        DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
@@ -1252,7 +1229,7 @@ static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
        hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
        hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
 
-       if (hdata->type == HDMI_TYPE13)
+       if (hdata->drv_data->type == HDMI_TYPE13)
                hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
        else
                hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
@@ -1386,7 +1363,7 @@ static void hdmi_conf_init(struct hdmi_context *hdata)
                                HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
        }
 
-       if (hdata->type == HDMI_TYPE13) {
+       if (hdata->drv_data->type == HDMI_TYPE13) {
                /* choose bluescreen (fecal) color */
                hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
                hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
@@ -1419,66 +1396,94 @@ static void hdmi_conf_init(struct hdmi_context *hdata)
 
 static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
 {
-       const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
-       const struct hdmi_v13_core_regs *core =
-               &hdata->mode_conf.conf.v13_conf.core;
+       struct drm_display_mode *m = &hdata->current_mode;
+       unsigned int val;
        int tries;
 
-       /* setting core registers */
-       hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
-       hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
-       hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
-       hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
-       hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
-       hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
-       hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
-       hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
-       hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
-       hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
-       hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
+       hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
+       hdmi_reg_writev(hdata, HDMI_V13_H_V_LINE_0, 3,
+                       (m->htotal << 12) | m->vtotal);
+
+       val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
+       hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1, val);
+
+       val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
+       hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1, val);
+
+       val = (m->hsync_start - m->hdisplay - 2);
+       val |= ((m->hsync_end - m->hdisplay - 2) << 10);
+       val |= ((m->flags & DRM_MODE_FLAG_NHSYNC)  ? 1 : 0)<<20;
+       hdmi_reg_writev(hdata, HDMI_V13_H_SYNC_GEN_0, 3, val);
+
+       /*
+        * Quirk requirement for exynos HDMI IP design,
+        * 2 pixels less than the actual calculation for hsync_start
+        * and end.
+        */
+
+       /* Following values & calculations differ for different type of modes */
+       if (m->flags & DRM_MODE_FLAG_INTERLACE) {
+               /* Interlaced Mode */
+               val = ((m->vsync_end - m->vdisplay) / 2);
+               val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
+               hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
+
+               val = m->vtotal / 2;
+               val |= ((m->vtotal - m->vdisplay) / 2) << 11;
+               hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
+
+               val = (m->vtotal +
+                       ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
+               val |= m->vtotal << 11;
+               hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, val);
+
+               val = ((m->vtotal / 2) + 7);
+               val |= ((m->vtotal / 2) + 2) << 12;
+               hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, val);
+
+               val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
+               val |= ((m->htotal / 2) +
+                       (m->hsync_start - m->hdisplay)) << 12;
+               hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, val);
+
+               hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
+                               (m->vtotal - m->vdisplay) / 2);
+               hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2);
+
+               hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x249);
+       } else {
+               /* Progressive Mode */
+
+               val = m->vtotal;
+               val |= (m->vtotal - m->vdisplay) << 11;
+               hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
+
+               hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, 0);
+
+               val = (m->vsync_end - m->vdisplay);
+               val |= ((m->vsync_start - m->vdisplay) << 12);
+               hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
+
+               hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, 0x1001);
+               hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, 0x1001);
+               hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
+                               m->vtotal - m->vdisplay);
+               hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
+               hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x248);
+       }
+
        /* Timing generator registers */
-       hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
-       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
-       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
+       hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
+       hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
+       hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
+       hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
+       hdmi_reg_writev(hdata, HDMI_TG_VSYNC_L, 2, 0x1);
+       hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2, 0x233);
+       hdmi_reg_writev(hdata, HDMI_TG_FIELD_CHG_L, 2, 0x233);
+       hdmi_reg_writev(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, 2, 0x1);
+       hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2, 0x233);
+       hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1);
+       hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2, 0x233);
 
        /* waiting for HDMIPHY's PLL to get to steady state */
        for (tries = 100; tries; --tries) {
@@ -1503,9 +1508,8 @@ static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
 
 static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
 {
-       const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
-       const struct hdmi_v14_core_regs *core =
-               &hdata->mode_conf.conf.v14_conf.core;
+       const struct hdmi_tg_regs *tg = &hdata->mode_conf.tg;
+       const struct hdmi_v14_core_regs *core = &hdata->mode_conf.core;
        int tries;
 
        /* setting core registers */
@@ -1665,7 +1669,7 @@ static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
 
 static void hdmi_mode_apply(struct hdmi_context *hdata)
 {
-       if (hdata->type == HDMI_TYPE13)
+       if (hdata->drv_data->type == HDMI_TYPE13)
                hdmi_v13_mode_apply(hdata);
        else
                hdmi_v14_mode_apply(hdata);
@@ -1683,7 +1687,7 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)
        hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE,
                                HDMI_PHY_ENABLE_MODE_SET);
 
-       if (hdata->type == HDMI_TYPE13)
+       if (hdata->drv_data->type == HDMI_TYPE13)
                reg = HDMI_V13_PHY_RSTOUT;
        else
                reg = HDMI_PHY_RSTOUT;
@@ -1697,7 +1701,7 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)
 
 static void hdmiphy_poweron(struct hdmi_context *hdata)
 {
-       if (hdata->type != HDMI_TYPE14)
+       if (hdata->drv_data->type != HDMI_TYPE14)
                return;
 
        DRM_DEBUG_KMS("\n");
@@ -1717,7 +1721,7 @@ static void hdmiphy_poweron(struct hdmi_context *hdata)
 
 static void hdmiphy_poweroff(struct hdmi_context *hdata)
 {
-       if (hdata->type != HDMI_TYPE14)
+       if (hdata->drv_data->type != HDMI_TYPE14)
                return;
 
        DRM_DEBUG_KMS("\n");
@@ -1743,13 +1747,14 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata)
        int i;
 
        /* pixel clock */
-       i = hdmi_find_phy_conf(hdata, hdata->mode_conf.pixel_clock);
+       i = hdmi_find_phy_conf(hdata, hdata->current_mode.clock * 1000);
        if (i < 0) {
                DRM_ERROR("failed to find hdmiphy conf\n");
                return;
        }
 
-       ret = hdmiphy_reg_write_buf(hdata, 0, hdata->phy_confs[i].conf, 32);
+       ret = hdmiphy_reg_write_buf(hdata, 0,
+                       hdata->drv_data->phy_confs[i].conf, 32);
        if (ret) {
                DRM_ERROR("failed to configure hdmiphy\n");
                return;
@@ -1771,10 +1776,8 @@ static void hdmi_conf_apply(struct hdmi_context *hdata)
        hdmiphy_conf_reset(hdata);
        hdmiphy_conf_apply(hdata);
 
-       mutex_lock(&hdata->hdmi_mutex);
        hdmi_start(hdata, false);
        hdmi_conf_init(hdata);
-       mutex_unlock(&hdata->hdmi_mutex);
 
        hdmi_audio_init(hdata);
 
@@ -1793,114 +1796,11 @@ static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value)
                reg_pair[i] = (value >> (8 * i)) & 0xff;
 }
 
-static void hdmi_v13_mode_set(struct hdmi_context *hdata,
-                       struct drm_display_mode *m)
-{
-       struct hdmi_v13_core_regs *core = &hdata->mode_conf.conf.v13_conf.core;
-       struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
-       unsigned int val;
-
-       hdata->mode_conf.cea_video_id =
-               drm_match_cea_mode((struct drm_display_mode *)m);
-       hdata->mode_conf.pixel_clock = m->clock * 1000;
-       hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
-
-       hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
-       hdmi_set_reg(core->h_v_line, 3, (m->htotal << 12) | m->vtotal);
-
-       val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
-       hdmi_set_reg(core->vsync_pol, 1, val);
-
-       val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
-       hdmi_set_reg(core->int_pro_mode, 1, val);
-
-       val = (m->hsync_start - m->hdisplay - 2);
-       val |= ((m->hsync_end - m->hdisplay - 2) << 10);
-       val |= ((m->flags & DRM_MODE_FLAG_NHSYNC)  ? 1 : 0)<<20;
-       hdmi_set_reg(core->h_sync_gen, 3, val);
-
-       /*
-        * Quirk requirement for exynos HDMI IP design,
-        * 2 pixels less than the actual calculation for hsync_start
-        * and end.
-        */
-
-       /* Following values & calculations differ for different type of modes */
-       if (m->flags & DRM_MODE_FLAG_INTERLACE) {
-               /* Interlaced Mode */
-               val = ((m->vsync_end - m->vdisplay) / 2);
-               val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
-               hdmi_set_reg(core->v_sync_gen1, 3, val);
-
-               val = m->vtotal / 2;
-               val |= ((m->vtotal - m->vdisplay) / 2) << 11;
-               hdmi_set_reg(core->v_blank, 3, val);
-
-               val = (m->vtotal +
-                       ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
-               val |= m->vtotal << 11;
-               hdmi_set_reg(core->v_blank_f, 3, val);
-
-               val = ((m->vtotal / 2) + 7);
-               val |= ((m->vtotal / 2) + 2) << 12;
-               hdmi_set_reg(core->v_sync_gen2, 3, val);
-
-               val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
-               val |= ((m->htotal / 2) +
-                       (m->hsync_start - m->hdisplay)) << 12;
-               hdmi_set_reg(core->v_sync_gen3, 3, val);
-
-               hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
-               hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
-
-               hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
-       } else {
-               /* Progressive Mode */
-
-               val = m->vtotal;
-               val |= (m->vtotal - m->vdisplay) << 11;
-               hdmi_set_reg(core->v_blank, 3, val);
-
-               hdmi_set_reg(core->v_blank_f, 3, 0);
-
-               val = (m->vsync_end - m->vdisplay);
-               val |= ((m->vsync_start - m->vdisplay) << 12);
-               hdmi_set_reg(core->v_sync_gen1, 3, val);
-
-               hdmi_set_reg(core->v_sync_gen2, 3, 0x1001);/* Reset value  */
-               hdmi_set_reg(core->v_sync_gen3, 3, 0x1001);/* Reset value  */
-               hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
-               hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
-               hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
-       }
-
-       /* Timing generator registers */
-       hdmi_set_reg(tg->cmd, 1, 0x0);
-       hdmi_set_reg(tg->h_fsz, 2, m->htotal);
-       hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
-       hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
-       hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
-       hdmi_set_reg(tg->vsync, 2, 0x1);
-       hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
-       hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
-       hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
-       hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
-       hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
-       hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
-       hdmi_set_reg(tg->tg_3d, 1, 0x0); /* Not used */
-}
-
 static void hdmi_v14_mode_set(struct hdmi_context *hdata,
                        struct drm_display_mode *m)
 {
-       struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
-       struct hdmi_v14_core_regs *core =
-               &hdata->mode_conf.conf.v14_conf.core;
-
-       hdata->mode_conf.cea_video_id =
-               drm_match_cea_mode((struct drm_display_mode *)m);
-       hdata->mode_conf.pixel_clock = m->clock * 1000;
-       hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
+       struct hdmi_tg_regs *tg = &hdata->mode_conf.tg;
+       struct hdmi_v14_core_regs *core = &hdata->mode_conf.core;
 
        hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
        hdmi_set_reg(core->v_line, 2, m->vtotal);
@@ -2016,9 +1916,9 @@ static void hdmi_mode_set(struct exynos_drm_display *display,
        /* preserve mode information for later use. */
        drm_mode_copy(&hdata->current_mode, mode);
 
-       if (hdata->type == HDMI_TYPE13)
-               hdmi_v13_mode_set(hdata, mode);
-       else
+       hdata->cea_video_id = drm_match_cea_mode(mode);
+
+       if (hdata->drv_data->type == HDMI_TYPE14)
                hdmi_v14_mode_set(hdata, mode);
 }
 
@@ -2026,12 +1926,8 @@ static void hdmi_commit(struct exynos_drm_display *display)
 {
        struct hdmi_context *hdata = display_to_hdmi(display);
 
-       mutex_lock(&hdata->hdmi_mutex);
-       if (!hdata->powered) {
-               mutex_unlock(&hdata->hdmi_mutex);
+       if (!hdata->powered)
                return;
-       }
-       mutex_unlock(&hdata->hdmi_mutex);
 
        hdmi_conf_apply(hdata);
 }
@@ -2040,16 +1936,11 @@ static void hdmi_poweron(struct hdmi_context *hdata)
 {
        struct hdmi_resources *res = &hdata->res;
 
-       mutex_lock(&hdata->hdmi_mutex);
-       if (hdata->powered) {
-               mutex_unlock(&hdata->hdmi_mutex);
+       if (hdata->powered)
                return;
-       }
 
        hdata->powered = true;
 
-       mutex_unlock(&hdata->hdmi_mutex);
-
        pm_runtime_get_sync(hdata->dev);
 
        if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
@@ -2070,10 +1961,8 @@ static void hdmi_poweroff(struct hdmi_context *hdata)
 {
        struct hdmi_resources *res = &hdata->res;
 
-       mutex_lock(&hdata->hdmi_mutex);
        if (!hdata->powered)
-               goto out;
-       mutex_unlock(&hdata->hdmi_mutex);
+               return;
 
        /* HDMI System Disable */
        hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN);
@@ -2093,11 +1982,7 @@ static void hdmi_poweroff(struct hdmi_context *hdata)
 
        pm_runtime_put_sync(hdata->dev);
 
-       mutex_lock(&hdata->hdmi_mutex);
        hdata->powered = false;
-
-out:
-       mutex_unlock(&hdata->hdmi_mutex);
 }
 
 static void hdmi_dpms(struct exynos_drm_display *display, int mode)
@@ -2152,10 +2037,6 @@ static void hdmi_hotplug_work_func(struct work_struct *work)
 
        hdata = container_of(work, struct hdmi_context, hotplug_work.work);
 
-       mutex_lock(&hdata->hdmi_mutex);
-       hdata->hpd = gpio_get_value(hdata->hpd_gpio);
-       mutex_unlock(&hdata->hdmi_mutex);
-
        if (hdata->drm_dev)
                drm_helper_hpd_irq_event(hdata->drm_dev);
 }
@@ -2254,30 +2135,6 @@ fail:
        return ret;
 }
 
-static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
-                                       (struct device *dev)
-{
-       struct device_node *np = dev->of_node;
-       struct s5p_hdmi_platform_data *pd;
-       u32 value;
-
-       pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-       if (!pd)
-               goto err_data;
-
-       if (!of_find_property(np, "hpd-gpio", &value)) {
-               DRM_ERROR("no hpd gpio property found\n");
-               goto err_data;
-       }
-
-       pd->hpd_gpio = of_get_named_gpio(np, "hpd-gpio", 0);
-
-       return pd;
-
-err_data:
-       return NULL;
-}
-
 static struct of_device_id hdmi_match_types[] = {
        {
                .compatible = "samsung,exynos5-hdmi",
@@ -2338,43 +2195,32 @@ static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev)
 static int hdmi_probe(struct platform_device *pdev)
 {
        struct device_node *ddc_node, *phy_node;
-       struct s5p_hdmi_platform_data *pdata;
-       struct hdmi_driver_data *drv_data;
        const struct of_device_id *match;
        struct device *dev = &pdev->dev;
        struct hdmi_context *hdata;
        struct resource *res;
        int ret;
 
-       if (!dev->of_node)
-               return -ENODEV;
-
-       pdata = drm_hdmi_dt_parse_pdata(dev);
-       if (!pdata)
-               return -EINVAL;
-
        hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
        if (!hdata)
                return -ENOMEM;
 
+       match = of_match_device(hdmi_match_types, dev);
+       if (!match)
+               return -ENODEV;
+
+       hdata->drv_data = match->data;
        hdata->display.type = EXYNOS_DISPLAY_TYPE_HDMI;
        hdata->display.ops = &hdmi_display_ops;
 
-       mutex_init(&hdata->hdmi_mutex);
-
        platform_set_drvdata(pdev, hdata);
 
-       match = of_match_node(hdmi_match_types, dev->of_node);
-       if (!match)
-               return -ENODEV;
-
-       drv_data = (struct hdmi_driver_data *)match->data;
-       hdata->type = drv_data->type;
-       hdata->phy_confs = drv_data->phy_confs;
-       hdata->phy_conf_count = drv_data->phy_conf_count;
-
-       hdata->hpd_gpio = pdata->hpd_gpio;
        hdata->dev = dev;
+       hdata->hpd_gpio = of_get_named_gpio(dev->of_node, "hpd-gpio", 0);
+       if (hdata->hpd_gpio < 0) {
+               DRM_ERROR("cannot get hpd gpio property\n");
+               return hdata->hpd_gpio;
+       }
 
        ret = hdmi_resources_init(hdata);
        if (ret) {
@@ -2426,7 +2272,7 @@ out_get_ddc_adpt:
        }
 
 out_get_phy_port:
-       if (drv_data->is_apb_phy) {
+       if (hdata->drv_data->is_apb_phy) {
                hdata->regs_hdmiphy = of_iomap(phy_node, 0);
                if (!hdata->regs_hdmiphy) {
                        DRM_ERROR("failed to ioremap hdmi phy\n");
@@ -2449,8 +2295,6 @@ out_get_phy_port:
                goto err_hdmiphy;
        }
 
-       hdata->hpd = gpio_get_value(hdata->hpd_gpio);
-
        INIT_DELAYED_WORK(&hdata->hotplug_work, hdmi_hotplug_work_func);
 
        ret = devm_request_threaded_irq(dev, hdata->irq, NULL,