diff --git a/plat/rockchip/rk3399/drivers/dp/cdn_dp.c b/plat/rockchip/rk3399/drivers/dp/cdn_dp.c
new file mode 100644
index 0000000000000000000000000000000000000000..d0e5986107b7f26776a41c1501184f43bf83d576
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/dp/cdn_dp.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cdn_dp.h>
+#include <smcc.h>
+#include <stdlib.h>
+#include <string.h>
+
+__asm__(
+	".pushsection .text.hdcp_handler, \"ax\", %progbits\n"
+	".global hdcp_handler\n"
+	".balign 4\n"
+	"hdcp_handler:\n"
+	".incbin \"" __XSTRING(HDCPFW) "\"\n"
+	".type hdcp_handler, %function\n"
+	".size hdcp_handler, .- hdcp_handler\n"
+	".popsection\n"
+);
+
+static uint64_t *hdcp_key_pdata;
+static struct cdn_dp_hdcp_key_1x key;
+
+int hdcp_handler(struct cdn_dp_hdcp_key_1x *key);
+
+uint64_t dp_hdcp_ctrl(uint64_t type)
+{
+	switch (type) {
+	case HDCP_KEY_DATA_START_TRANSFER:
+		memset(&key, 0x00, sizeof(key));
+		hdcp_key_pdata = (uint64_t *)&key;
+		return 0;
+	case HDCP_KEY_DATA_START_DECRYPT:
+		if (hdcp_key_pdata == (uint64_t *)(&key + 1))
+			return hdcp_handler(&key);
+		else
+			return PSCI_E_INVALID_PARAMS;
+	default:
+		return SMC_UNK;
+	}
+}
+
+uint64_t dp_hdcp_store_key(uint64_t x1,
+			   uint64_t x2,
+			   uint64_t x3,
+			   uint64_t x4,
+			   uint64_t x5,
+			   uint64_t x6)
+{
+	if (hdcp_key_pdata < (uint64_t *)&key ||
+		hdcp_key_pdata + 6 > (uint64_t *)(&key + 1))
+		return PSCI_E_INVALID_PARAMS;
+
+	hdcp_key_pdata[0] = x1;
+	hdcp_key_pdata[1] = x2;
+	hdcp_key_pdata[2] = x3;
+	hdcp_key_pdata[3] = x4;
+	hdcp_key_pdata[4] = x5;
+	hdcp_key_pdata[5] = x6;
+	hdcp_key_pdata += 6;
+
+	return 0;
+}
diff --git a/plat/rockchip/rk3399/drivers/dp/cdn_dp.h b/plat/rockchip/rk3399/drivers/dp/cdn_dp.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b9a108431443bf5290b15692483c5cea4cc89a7
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/dp/cdn_dp.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SOC_ROCKCHIP_RK3399_DP_H__
+#define __SOC_ROCKCHIP_RK3399_DP_H__
+#include <plat_private.h>
+
+enum {
+	CDN_DP_HDCP_1X_KSV_LEN = 5,
+	CDN_DP_HDCP_KSV_LEN = 8,
+	CDN_DP_HDCP_RESERVED_LEN = 10,
+	CDN_DP_HDCP_UID_LEN = 16,
+	CDN_DP_HDCP_SHA_LEN = 20,
+	CDN_DP_HDCP_DPK_LEN = 280,
+	CDN_DP_HDCP_1X_KEYS_LEN	= 285,
+	CDN_DP_HDCP_KEY_LEN = 326,
+};
+
+struct cdn_dp_hdcp_key_1x {
+	uint8_t ksv[CDN_DP_HDCP_KSV_LEN];
+	uint8_t device_key[CDN_DP_HDCP_DPK_LEN];
+	uint8_t sha1[CDN_DP_HDCP_SHA_LEN];
+	uint8_t uid[CDN_DP_HDCP_UID_LEN];
+	uint16_t seed;
+	uint8_t reserved[CDN_DP_HDCP_RESERVED_LEN];
+};
+
+#define HDCP_KEY_DATA_START_TRANSFER	0
+#define HDCP_KEY_DATA_START_DECRYPT	1
+#define HDCP_KEY_1X_STORE_DATA_ALIGN_SIZE	(6 * 64) / 8
+
+/* Checks the cdn_dp_hdcp_key_1x must be aligned on 6 x 64-bit word boundary */
+CASSERT(sizeof(struct cdn_dp_hdcp_key_1x) % HDCP_KEY_1X_STORE_DATA_ALIGN_SIZE, \
+	assert_hdcp_key_1x_store_data_align_size_mismatch);
+
+uint64_t dp_hdcp_ctrl(uint64_t type);
+
+uint64_t dp_hdcp_store_key(uint64_t x1,
+			   uint64_t x2,
+			   uint64_t x3,
+			   uint64_t x4,
+			   uint64_t x5,
+			   uint64_t x6);
+#endif
diff --git a/plat/rockchip/rk3399/drivers/dp/hdcp.bin b/plat/rockchip/rk3399/drivers/dp/hdcp.bin
new file mode 100644
index 0000000000000000000000000000000000000000..28db923669fe63812c25f016753df10558334fee
Binary files /dev/null and b/plat/rockchip/rk3399/drivers/dp/hdcp.bin differ
diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c
index 77b7c3ed1ba0d8c12037a1f6d7af36ff05a57d9b..1a016042f27d0ddefa2a0fb112d2a4c5400180ec 100644
--- a/plat/rockchip/rk3399/plat_sip_calls.c
+++ b/plat/rockchip/rk3399/plat_sip_calls.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <cdn_dp.h>
 #include <debug.h>
 #include <mmio.h>
 #include <plat_sip_calls.h>
@@ -22,6 +23,9 @@
 #define DRAM_SET_PARAM		0x07
 #define DRAM_SET_ODT_PD		0x08
 
+#define RK_SIP_HDCP_CONTROL	0x82000009
+#define RK_SIP_HDCP_KEY_DATA64	0xC200000A
+
 uint32_t ddr_smc_handler(uint64_t arg0, uint64_t arg1,
 			 uint64_t id, uint64_t arg2)
 {
@@ -51,9 +55,17 @@ uint64_t rockchip_plat_sip_handler(uint32_t smc_fid,
 				   void *handle,
 				   uint64_t flags)
 {
+	uint64_t x5, x6;
+
 	switch (smc_fid) {
 	case RK_SIP_DDR_CFG:
 		SMC_RET1(handle, ddr_smc_handler(x1, x2, x3, x4));
+	case RK_SIP_HDCP_CONTROL:
+		SMC_RET1(handle, dp_hdcp_ctrl(x1));
+	case RK_SIP_HDCP_KEY_DATA64:
+		x5 = read_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X5);
+		x6 = read_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X6);
+		SMC_RET1(handle, dp_hdcp_store_key(x1, x2, x3, x4, x5, x6));
 	default:
 		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
 		SMC_RET1(handle, SMC_UNK);
diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
index 61071243080fb64a30d74357d6acd7382ff6ed23..85cca1b6b462c70886c121c1ce981caa5e32b1a1 100644
--- a/plat/rockchip/rk3399/platform.mk
+++ b/plat/rockchip/rk3399/platform.mk
@@ -18,6 +18,7 @@ PLAT_INCLUDES		:=	-I${RK_PLAT_COMMON}/			\
 				-I${RK_PLAT_SOC}/drivers/secure/	\
 				-I${RK_PLAT_SOC}/drivers/soc/		\
 				-I${RK_PLAT_SOC}/drivers/dram/		\
+				-I${RK_PLAT_SOC}/drivers/dp/		\
 				-I${RK_PLAT_SOC}/include/		\
 				-I${RK_PLAT_SOC}/include/shared/	\
 
@@ -49,6 +50,7 @@ BL31_SOURCES	+=	${RK_GIC_SOURCES}				\
 			${RK_PLAT_COMMON}/aarch64/platform_common.c	\
 			${RK_PLAT_COMMON}/rockchip_sip_svc.c		\
 			${RK_PLAT_SOC}/plat_sip_calls.c			\
+			${RK_PLAT_SOC}/drivers/dp/cdn_dp.c		\
 			${RK_PLAT_SOC}/drivers/gpio/rk3399_gpio.c	\
 			${RK_PLAT_SOC}/drivers/pmu/pmu.c		\
 			${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c		\
@@ -75,11 +77,17 @@ BUILD_M0		:=	${BUILD_PLAT}/m0
 RK3399M0FW=${BUILD_M0}/${PLAT_M0}.bin
 $(eval $(call add_define,RK3399M0FW))
 
+HDCPFW=${RK_PLAT_SOC}/drivers/dp/hdcp.bin
+$(eval $(call add_define,HDCPFW))
+
 # CCACHE_EXTRAFILES is needed because ccache doesn't handle .incbin
 export CCACHE_EXTRAFILES
 ${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW)
 ${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c: $(RK3399M0FW)
 
+${BUILD_PLAT}/bl31/cdn_dp.o: CCACHE_EXTRAFILES=$(HDCPFW)
+${RK_PLAT_SOC}/drivers/dp/cdn_dp.c: $(HDCPFW)
+
 $(eval $(call MAKE_PREREQ_DIR,${BUILD_M0},))
 .PHONY: $(RK3399M0FW)
 $(RK3399M0FW): | ${BUILD_M0}