diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3399.h b/arch/arm/include/asm/arch-rockchip/grf_rk3399.h
index eda99560ed3039c8769e9f68ab6ef0b1c56b6931..8d21eb7bee7230a45d122a9916e977a665ac7ea0 100644
--- a/arch/arm/include/asm/arch-rockchip/grf_rk3399.h
+++ b/arch/arm/include/asm/arch-rockchip/grf_rk3399.h
@@ -534,6 +534,9 @@ enum {
 	GRF_DSI0_VOP_SEL_MASK   = 1 << GRF_DSI0_VOP_SEL_SHIFT,
 	GRF_DSI0_VOP_SEL_B      = 0,
 	GRF_DSI0_VOP_SEL_L      = 1,
+	GRF_RK3399_HDMI_VOP_SEL_MASK = 1 << 6,
+	GRF_RK3399_HDMI_VOP_SEL_B = 0 << 6,
+	GRF_RK3399_HDMI_VOP_SEL_L = 1 << 6,
 
 	/* GRF_SOC_CON22 */
 	GRF_DPHY_TX0_RXMODE_SHIFT = 0,
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 65d0ed64b8f76ac95c13d09424fecbd4a92f8317..872dc0f6534a67549f7555a4ff8612b9ef6097bd 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399_vop.o
 obj-$(CONFIG_DISPLAY_ROCKCHIP_EDP) += rk_edp.o
 obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
 obj-hdmi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_hdmi.o
+obj-hdmi-$(CONFIG_ROCKCHIP_RK3399) += rk3399_hdmi.o
 obj-$(CONFIG_DISPLAY_ROCKCHIP_HDMI) += rk_hdmi.o $(obj-hdmi-y)
 obj-$(CONFIG_DISPLAY_ROCKCHIP_MIPI) += rk_mipi.o
 endif
diff --git a/drivers/video/rockchip/rk3399_hdmi.c b/drivers/video/rockchip/rk3399_hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..b1e50974f65079b2e911665dbde8deb3c991f953
--- /dev/null
+++ b/drivers/video/rockchip/rk3399_hdmi.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <display.h>
+#include <dm.h>
+#include <dw_hdmi.h>
+#include <edid.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/grf_rk3399.h>
+#include <power/regulator.h>
+#include "rk_hdmi.h"
+
+static int rk3399_hdmi_enable(struct udevice *dev, int panel_bpp,
+			      const struct display_timing *edid)
+{
+	struct rk_hdmi_priv *priv = dev_get_priv(dev);
+	struct display_plat *uc_plat = dev_get_uclass_platdata(dev);
+	int vop_id = uc_plat->source_id;
+	struct rk3399_grf_regs *grf = priv->grf;
+
+	/* select the hdmi encoder input data from our source_id */
+	rk_clrsetreg(&grf->soc_con20, GRF_RK3399_HDMI_VOP_SEL_MASK,
+		     (vop_id == 1) ? GRF_RK3399_HDMI_VOP_SEL_L : 0);
+
+	return dw_hdmi_enable(&priv->hdmi, edid);
+}
+
+static int rk3399_hdmi_ofdata_to_platdata(struct udevice *dev)
+{
+	struct rk_hdmi_priv *priv = dev_get_priv(dev);
+	struct dw_hdmi *hdmi = &priv->hdmi;
+
+	hdmi->i2c_clk_high = 0x7a;
+	hdmi->i2c_clk_low = 0x8d;
+
+	return rk_hdmi_ofdata_to_platdata(dev);
+}
+
+static const char * const rk3399_regulator_names[] = {
+	"vcc1v8_hdmi",
+	"vcc0v9_hdmi"
+};
+
+static int rk3399_hdmi_probe(struct udevice *dev)
+{
+	/* Enable regulators required for HDMI */
+	rk_hdmi_probe_regulators(dev, rk3399_regulator_names,
+				 ARRAY_SIZE(rk3399_regulator_names));
+
+	return rk_hdmi_probe(dev);
+}
+
+static const struct dm_display_ops rk3399_hdmi_ops = {
+	.read_edid = rk_hdmi_read_edid,
+	.enable = rk3399_hdmi_enable,
+};
+
+static const struct udevice_id rk3399_hdmi_ids[] = {
+	{ .compatible = "rockchip,rk3399-dw-hdmi" },
+	{ }
+};
+
+U_BOOT_DRIVER(rk3399_hdmi_rockchip) = {
+	.name = "rk3399_hdmi_rockchip",
+	.id = UCLASS_DISPLAY,
+	.of_match = rk3399_hdmi_ids,
+	.ops = &rk3399_hdmi_ops,
+	.ofdata_to_platdata = rk3399_hdmi_ofdata_to_platdata,
+	.probe = rk3399_hdmi_probe,
+	.priv_auto_alloc_size = sizeof(struct rk_hdmi_priv),
+};