#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/hdmi.h>
+#include <linux/mfd/syscon.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 
 #include "inno_hdmi.h"
 
+#define HIWORD_UPDATE(val, mask)       ((val) | (mask) << 16)
+
 #define INNO_HDMI_MIN_TMDS_CLOCK  25000000U
 
+#define RK3036_GRF_SOC_CON2    0x148
+#define RK3036_HDMI_PHSYNC     BIT(4)
+#define RK3036_HDMI_PVSYNC     BIT(5)
+
+enum inno_hdmi_dev_type {
+       RK3036_HDMI,
+       RK3128_HDMI,
+};
+
 struct inno_hdmi_phy_config {
        unsigned long pixelclock;
        u8 pre_emphasis;
 };
 
 struct inno_hdmi_variant {
+       enum inno_hdmi_dev_type dev_type;
        struct inno_hdmi_phy_config *phy_configs;
        struct inno_hdmi_phy_config *default_phy_config;
 };
        struct clk *pclk;
        struct clk *refclk;
        void __iomem *regs;
+       struct regmap *grf;
 
        struct drm_connector    connector;
        struct rockchip_encoder encoder;
 static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
                                         struct drm_display_mode *mode)
 {
-       int value;
+       int value, psync;
+
+       if (hdmi->variant->dev_type == RK3036_HDMI) {
+               psync = mode->flags & DRM_MODE_FLAG_PHSYNC ? RK3036_HDMI_PHSYNC : 0;
+               value = HIWORD_UPDATE(psync, RK3036_HDMI_PHSYNC);
+               psync = mode->flags & DRM_MODE_FLAG_PVSYNC ? RK3036_HDMI_PVSYNC : 0;
+               value |= HIWORD_UPDATE(psync, RK3036_HDMI_PVSYNC);
+               regmap_write(hdmi->grf, RK3036_GRF_SOC_CON2, value);
+       }
 
        /* Set detail external video timing polarity and interlace mode */
        value = v_EXTERANL_VIDEO(1);
                goto err_disable_pclk;
        }
 
+       if (hdmi->variant->dev_type == RK3036_HDMI) {
+               hdmi->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
+               if (IS_ERR(hdmi->grf)) {
+                       ret = dev_err_probe(dev, PTR_ERR(hdmi->grf),
+                                           "Unable to get rockchip,grf\n");
+                       goto err_disable_clk;
+               }
+       }
+
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                ret = irq;
 }
 
 static const struct inno_hdmi_variant rk3036_inno_hdmi_variant = {
+       .dev_type = RK3036_HDMI,
        .phy_configs = rk3036_hdmi_phy_configs,
        .default_phy_config = &rk3036_hdmi_phy_configs[1],
 };
 
 static const struct inno_hdmi_variant rk3128_inno_hdmi_variant = {
+       .dev_type = RK3128_HDMI,
        .phy_configs = rk3128_hdmi_phy_configs,
        .default_phy_config = &rk3128_hdmi_phy_configs[1],
 };