#include "rockchip_drm_drv.h"
 #include "rockchip_drm_vop.h"
 
-#define GRF_SOC_CON6                    0x025c
-#define HDMI_SEL_VOP_LIT                (1 << 4)
+#define RK3288_GRF_SOC_CON6            0x025C
+#define RK3288_HDMI_LCDC_SEL           BIT(4)
+#define RK3399_GRF_SOC_CON20           0x6250
+#define RK3399_HDMI_LCDC_SEL           BIT(6)
+
+#define HIWORD_UPDATE(val, mask)       (val | (mask) << 16)
+
+/**
+ * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips
+ * @lcdsel_grf_reg: grf register offset of lcdc select
+ * @lcdsel_big: reg value of selecting vop big for HDMI
+ * @lcdsel_lit: reg value of selecting vop little for HDMI
+ */
+struct rockchip_hdmi_chip_data {
+       u32     lcdsel_grf_reg;
+       u32     lcdsel_big;
+       u32     lcdsel_lit;
+};
 
 struct rockchip_hdmi {
        struct device *dev;
        struct regmap *regmap;
        struct drm_encoder encoder;
+       const struct rockchip_hdmi_chip_data *chip_data;
 };
 
 #define to_rockchip_hdmi(x)    container_of(x, struct rockchip_hdmi, x)
 {
        struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
        u32 val;
-       int mux;
+       int ret;
 
-       mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder);
-       if (mux)
-               val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16);
+       ret = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder);
+       if (ret)
+               val = hdmi->chip_data->lcdsel_lit;
        else
-               val = HDMI_SEL_VOP_LIT << 16;
+               val = hdmi->chip_data->lcdsel_big;
+
+       ret = regmap_write(hdmi->regmap, hdmi->chip_data->lcdsel_grf_reg, val);
+       if (ret != 0)
+               dev_err(hdmi->dev, "Could not write to GRF: %d\n", ret);
 
-       regmap_write(hdmi->regmap, GRF_SOC_CON6, val);
        dev_dbg(hdmi->dev, "vop %s output to hdmi\n",
-               (mux) ? "LIT" : "BIG");
+               ret ? "LIT" : "BIG");
 }
 
 static int
        .atomic_check = dw_hdmi_rockchip_encoder_atomic_check,
 };
 
-static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = {
+static struct rockchip_hdmi_chip_data rk3288_chip_data = {
+       .lcdsel_grf_reg = RK3288_GRF_SOC_CON6,
+       .lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL),
+       .lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL),
+};
+
+static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = {
+       .mode_valid = dw_hdmi_rockchip_mode_valid,
+       .mpll_cfg   = rockchip_mpll_cfg,
+       .cur_ctr    = rockchip_cur_ctr,
+       .phy_config = rockchip_phy_config,
+       .phy_data = &rk3288_chip_data,
+};
+
+static struct rockchip_hdmi_chip_data rk3399_chip_data = {
+       .lcdsel_grf_reg = RK3399_GRF_SOC_CON20,
+       .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL),
+       .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL),
+};
+
+static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
        .mode_valid = dw_hdmi_rockchip_mode_valid,
        .mpll_cfg   = rockchip_mpll_cfg,
        .cur_ctr    = rockchip_cur_ctr,
        .phy_config = rockchip_phy_config,
+       .phy_data = &rk3399_chip_data,
 };
 
 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
        { .compatible = "rockchip,rk3288-dw-hdmi",
-         .data = &rockchip_hdmi_drv_data
+         .data = &rk3288_hdmi_drv_data
+       },
+       { .compatible = "rockchip,rk3399-dw-hdmi",
+         .data = &rk3399_hdmi_drv_data
        },
        {},
 };
        match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node);
        plat_data = match->data;
        hdmi->dev = &pdev->dev;
+       hdmi->chip_data = plat_data->phy_data;
        encoder = &hdmi->encoder;
 
        encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);