summary refs log tree commit diff
path: root/drivers/gpu/drm/msm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm')
-rw-r--r--drivers/gpu/drm/msm/Kconfig7
-rw-r--r--drivers/gpu/drm/msm/Makefile5
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx.xml.h6
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx.xml.h168
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c15
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx.xml.h420
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx_gpu.c3
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_common.xml.h6
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c12
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c34
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h9
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h31
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c43
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.h61
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.xml.h163
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c120
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c79
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_phy.c315
-rw-r--r--drivers/gpu/drm/msm/dsi/mmss_cc.xml.h12
-rw-r--r--drivers/gpu/drm/msm/dsi/pll/dsi_pll.c164
-rw-r--r--drivers/gpu/drm/msm/dsi/pll/dsi_pll.h89
-rw-r--r--drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c652
-rw-r--r--drivers/gpu/drm/msm/dsi/sfpb.xml.h12
-rw-r--r--drivers/gpu/drm/msm/edp/edp.xml.h101
-rw-r--r--drivers/gpu/drm/msm/edp/edp_aux.c12
-rw-r--r--drivers/gpu/drm/msm/edp/edp_ctrl.c9
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.xml.h99
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_connector.c43
-rw-r--r--drivers/gpu/drm/msm/hdmi/qfprom.xml.h12
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h32
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c39
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c9
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h3
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c22
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h398
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c20
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c128
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c11
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h3
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c24
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c7
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h1
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_common.xml.h16
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_format.c6
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_kms.h2
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c46
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c27
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h4
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c4
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h1
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c1
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c52
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h6
-rw-r--r--drivers/gpu/drm/msm/msm_kms.h3
56 files changed, 3218 insertions, 353 deletions
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 0a6f6764a37c..08ba8d0d93f5 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -46,3 +46,10 @@ config DRM_MSM_DSI
 	  Choose this option if you have a need for MIPI DSI connector
 	  support.
 
+config DRM_MSM_DSI_PLL
+	bool "Enable DSI PLL driver in MSM DRM"
+	depends on DRM_MSM_DSI && COMMON_CLK
+	default y
+	help
+	  Choose this option to enable DSI PLL driver which provides DSI
+	  source clocks under common clock framework.
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index ab2086783fee..16a81b94d6f0 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -1,4 +1,5 @@
 ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm
+ccflags-$(CONFIG_DRM_MSM_DSI_PLL) += -Idrivers/gpu/drm/msm/dsi
 
 msm-y := \
 	adreno/adreno_device.o \
@@ -50,10 +51,14 @@ msm-y := \
 
 msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
 msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
+
 msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
 			dsi/dsi_host.o \
 			dsi/dsi_manager.o \
 			dsi/dsi_phy.o \
 			mdp/mdp5/mdp5_cmd_encoder.o
 
+msm-$(CONFIG_DRM_MSM_DSI_PLL) += dsi/pll/dsi_pll.o \
+				dsi/pll/dsi_pll_28nm.o
+
 obj-$(CONFIG_DRM_MSM)	+= msm.o
diff --git a/drivers/gpu/drm/msm/adreno/a2xx.xml.h b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
index edc845fffdf4..23176e402796 100644
--- a/drivers/gpu/drm/msm/adreno/a2xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
@@ -12,9 +12,9 @@ The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  10551 bytes, from 2014-11-13 22:44:30)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  15085 bytes, from 2014-12-20 21:49:41)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  64344 bytes, from 2014-12-12 20:22:26)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  51069 bytes, from 2014-12-21 15:51:54)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14895 bytes, from 2015-04-19 15:23:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  66709 bytes, from 2015-04-12 18:16:35)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  60633 bytes, from 2015-05-20 14:48:19)
 
 Copyright (C) 2013-2014 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/adreno/a3xx.xml.h b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
index e91a739452d7..1c599e5cf318 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
@@ -12,11 +12,11 @@ The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  10551 bytes, from 2014-11-13 22:44:30)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  15085 bytes, from 2014-12-20 21:49:41)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  64344 bytes, from 2014-12-12 20:22:26)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  51069 bytes, from 2014-12-21 15:51:54)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14895 bytes, from 2015-04-19 15:23:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  66709 bytes, from 2015-04-12 18:16:35)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  60633 bytes, from 2015-05-20 14:48:19)
 
-Copyright (C) 2013-2014 by the following authors:
+Copyright (C) 2013-2015 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -130,6 +130,10 @@ enum a3xx_tex_fmt {
 	TFMT_I420_Y = 24,
 	TFMT_I420_U = 26,
 	TFMT_I420_V = 27,
+	TFMT_ATC_RGB = 32,
+	TFMT_ATC_RGBA_EXPLICIT = 33,
+	TFMT_ETC1 = 34,
+	TFMT_ATC_RGBA_INTERPOLATED = 35,
 	TFMT_DXT1 = 36,
 	TFMT_DXT3 = 37,
 	TFMT_DXT5 = 38,
@@ -178,10 +182,13 @@ enum a3xx_tex_fmt {
 	TFMT_32_SINT = 92,
 	TFMT_32_32_SINT = 93,
 	TFMT_32_32_32_32_SINT = 95,
-	TFMT_RGTC2_SNORM = 112,
-	TFMT_RGTC2_UNORM = 113,
-	TFMT_RGTC1_SNORM = 114,
-	TFMT_RGTC1_UNORM = 115,
+	TFMT_ETC2_RG11_SNORM = 112,
+	TFMT_ETC2_RG11_UNORM = 113,
+	TFMT_ETC2_R11_SNORM = 114,
+	TFMT_ETC2_R11_UNORM = 115,
+	TFMT_ETC2_RGBA8 = 116,
+	TFMT_ETC2_RGB8A1 = 117,
+	TFMT_ETC2_RGB8 = 118,
 };
 
 enum a3xx_tex_fetchsize {
@@ -209,14 +216,24 @@ enum a3xx_color_fmt {
 	RB_R10G10B10A2_UNORM = 16,
 	RB_A8_UNORM = 20,
 	RB_R8_UNORM = 21,
+	RB_R16_FLOAT = 24,
+	RB_R16G16_FLOAT = 25,
 	RB_R16G16B16A16_FLOAT = 27,
 	RB_R11G11B10_FLOAT = 28,
+	RB_R16_SNORM = 32,
+	RB_R16G16_SNORM = 33,
+	RB_R16G16B16A16_SNORM = 35,
+	RB_R16_UNORM = 36,
+	RB_R16G16_UNORM = 37,
+	RB_R16G16B16A16_UNORM = 39,
 	RB_R16_SINT = 40,
 	RB_R16G16_SINT = 41,
 	RB_R16G16B16A16_SINT = 43,
 	RB_R16_UINT = 44,
 	RB_R16G16_UINT = 45,
 	RB_R16G16B16A16_UINT = 47,
+	RB_R32_FLOAT = 48,
+	RB_R32G32_FLOAT = 49,
 	RB_R32G32B32A32_FLOAT = 51,
 	RB_R32_SINT = 52,
 	RB_R32G32_SINT = 53,
@@ -265,6 +282,12 @@ enum a3xx_intp_mode {
 	FLAT = 1,
 };
 
+enum a3xx_repl_mode {
+	S = 1,
+	T = 2,
+	ONE_T = 3,
+};
+
 enum a3xx_tex_filter {
 	A3XX_TEX_NEAREST = 0,
 	A3XX_TEX_LINEAR = 1,
@@ -751,7 +774,7 @@ static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL(float val)
 #define A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT			0
 static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_OFFSET(float val)
 {
-	return ((((int32_t)(val * 16384.0))) << A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;
+	return ((((int32_t)(val * 64.0))) << A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;
 }
 
 #define REG_A3XX_GRAS_SU_MODE_CONTROL				0x00002070
@@ -854,6 +877,12 @@ static inline uint32_t A3XX_RB_MODE_CONTROL_RENDER_MODE(enum a3xx_render_mode va
 {
 	return ((val) << A3XX_RB_MODE_CONTROL_RENDER_MODE__SHIFT) & A3XX_RB_MODE_CONTROL_RENDER_MODE__MASK;
 }
+#define A3XX_RB_MODE_CONTROL_MRT__MASK				0x00003000
+#define A3XX_RB_MODE_CONTROL_MRT__SHIFT				12
+static inline uint32_t A3XX_RB_MODE_CONTROL_MRT(uint32_t val)
+{
+	return ((val) << A3XX_RB_MODE_CONTROL_MRT__SHIFT) & A3XX_RB_MODE_CONTROL_MRT__MASK;
+}
 #define A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE		0x00008000
 #define A3XX_RB_MODE_CONTROL_PACKER_TIMER_ENABLE		0x00010000
 
@@ -1246,9 +1275,21 @@ static inline uint32_t A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(enum adreno_stencil_op v
 
 #define REG_A3XX_RB_STENCIL_CLEAR				0x00002105
 
-#define REG_A3XX_RB_STENCIL_BUF_INFO				0x00002106
+#define REG_A3XX_RB_STENCIL_INFO				0x00002106
+#define A3XX_RB_STENCIL_INFO_STENCIL_BASE__MASK			0xfffff800
+#define A3XX_RB_STENCIL_INFO_STENCIL_BASE__SHIFT		11
+static inline uint32_t A3XX_RB_STENCIL_INFO_STENCIL_BASE(uint32_t val)
+{
+	return ((val >> 12) << A3XX_RB_STENCIL_INFO_STENCIL_BASE__SHIFT) & A3XX_RB_STENCIL_INFO_STENCIL_BASE__MASK;
+}
 
-#define REG_A3XX_RB_STENCIL_BUF_PITCH				0x00002107
+#define REG_A3XX_RB_STENCIL_PITCH				0x00002107
+#define A3XX_RB_STENCIL_PITCH__MASK				0xffffffff
+#define A3XX_RB_STENCIL_PITCH__SHIFT				0
+static inline uint32_t A3XX_RB_STENCIL_PITCH(uint32_t val)
+{
+	return ((val >> 3) << A3XX_RB_STENCIL_PITCH__SHIFT) & A3XX_RB_STENCIL_PITCH__MASK;
+}
 
 #define REG_A3XX_RB_STENCILREFMASK				0x00002108
 #define A3XX_RB_STENCILREFMASK_STENCILREF__MASK			0x000000ff
@@ -1356,6 +1397,7 @@ static inline uint32_t A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(enum adreno_pa_
 {
 	return ((val) << A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__SHIFT) & A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__MASK;
 }
+#define A3XX_PC_PRIM_VTX_CNTL_POLYMODE_ENABLE			0x00001000
 #define A3XX_PC_PRIM_VTX_CNTL_PRIMITIVE_RESTART			0x00100000
 #define A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST		0x02000000
 #define A3XX_PC_PRIM_VTX_CNTL_PSIZE				0x04000000
@@ -1805,6 +1847,102 @@ static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_CF(enum a3xx_intp_mode val)
 static inline uint32_t REG_A3XX_VPC_VARYING_PS_REPL(uint32_t i0) { return 0x00002286 + 0x1*i0; }
 
 static inline uint32_t REG_A3XX_VPC_VARYING_PS_REPL_MODE(uint32_t i0) { return 0x00002286 + 0x1*i0; }
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C0__MASK			0x00000003
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C0__SHIFT			0
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C0(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C0__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C0__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C1__MASK			0x0000000c
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C1__SHIFT			2
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C1(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C1__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C1__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C2__MASK			0x00000030
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C2__SHIFT			4
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C2(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C2__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C2__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C3__MASK			0x000000c0
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C3__SHIFT			6
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C3(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C3__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C3__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C4__MASK			0x00000300
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C4__SHIFT			8
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C4(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C4__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C4__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C5__MASK			0x00000c00
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C5__SHIFT			10
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C5(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C5__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C5__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C6__MASK			0x00003000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C6__SHIFT			12
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C6(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C6__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C6__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C7__MASK			0x0000c000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C7__SHIFT			14
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C7(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C7__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C7__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C8__MASK			0x00030000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C8__SHIFT			16
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C8(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C8__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C8__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C9__MASK			0x000c0000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C9__SHIFT			18
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C9(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C9__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C9__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CA__MASK			0x00300000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CA__SHIFT			20
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CA(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CA__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CA__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CB__MASK			0x00c00000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CB__SHIFT			22
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CB(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CB__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CB__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CC__MASK			0x03000000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CC__SHIFT			24
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CC(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CC__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CC__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CD__MASK			0x0c000000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CD__SHIFT			26
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CD(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CD__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CD__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CE__MASK			0x30000000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CE__SHIFT			28
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CE(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CE__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CE__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CF__MASK			0xc0000000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CF__SHIFT			30
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CF(enum a3xx_repl_mode val)
+{
+	return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CF__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CF__MASK;
+}
 
 #define REG_A3XX_VPC_VARY_CYLWRAP_ENABLE_0			0x0000228a
 
@@ -2107,6 +2245,12 @@ static inline uint32_t A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
 #define REG_A3XX_SP_FS_FLAT_SHAD_MODE_REG_1			0x000022e9
 
 #define REG_A3XX_SP_FS_OUTPUT_REG				0x000022ec
+#define A3XX_SP_FS_OUTPUT_REG_MRT__MASK				0x00000003
+#define A3XX_SP_FS_OUTPUT_REG_MRT__SHIFT			0
+static inline uint32_t A3XX_SP_FS_OUTPUT_REG_MRT(uint32_t val)
+{
+	return ((val) << A3XX_SP_FS_OUTPUT_REG_MRT__SHIFT) & A3XX_SP_FS_OUTPUT_REG_MRT__MASK;
+}
 #define A3XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE			0x00000080
 #define A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK			0x0000ff00
 #define A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT		8
@@ -2661,7 +2805,7 @@ static inline uint32_t A3XX_TEX_CONST_2_SWAP(enum a3xx_color_swap val)
 }
 
 #define REG_A3XX_TEX_CONST_3					0x00000003
-#define A3XX_TEX_CONST_3_LAYERSZ1__MASK				0x0000000f
+#define A3XX_TEX_CONST_3_LAYERSZ1__MASK				0x00007fff
 #define A3XX_TEX_CONST_3_LAYERSZ1__SHIFT			0
 static inline uint32_t A3XX_TEX_CONST_3_LAYERSZ1(uint32_t val)
 {
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index b66c53bdc039..fd266ed963b6 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -93,7 +93,10 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
 		/* Set up AOOO: */
 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
-
+	} else if (adreno_is_a306(adreno_gpu)) {
+		gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
+		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x0000000a);
+		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x0000000a);
 	} else if (adreno_is_a320(adreno_gpu)) {
 		/* Set up 16 deep read/write request queues: */
 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
@@ -186,7 +189,9 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
 	gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
 
 	/* Enable Clock gating: */
-	if (adreno_is_a320(adreno_gpu))
+	if (adreno_is_a306(adreno_gpu))
+		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
+	else if (adreno_is_a320(adreno_gpu))
 		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);
 	else if (adreno_is_a330v2(adreno_gpu))
 		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
@@ -271,7 +276,8 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
 		gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]);
 
 	/* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
-	if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu)) {
+	if (adreno_is_a305(adreno_gpu) || adreno_is_a306(adreno_gpu) ||
+			adreno_is_a320(adreno_gpu)) {
 		gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS,
 				AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) |
 				AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) |
@@ -295,9 +301,12 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
 
 static void a3xx_recover(struct msm_gpu *gpu)
 {
+	adreno_dump_info(gpu);
+
 	/* dump registers before resetting gpu, if enabled: */
 	if (hang_debug)
 		a3xx_dump(gpu);
+
 	gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
 	gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
 	gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
diff --git a/drivers/gpu/drm/msm/adreno/a4xx.xml.h b/drivers/gpu/drm/msm/adreno/a4xx.xml.h
index 755723fd8ba5..3f06ecf62583 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a4xx.xml.h
@@ -12,11 +12,11 @@ The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  10551 bytes, from 2014-11-13 22:44:30)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  15085 bytes, from 2014-12-20 21:49:41)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  64344 bytes, from 2014-12-12 20:22:26)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  51069 bytes, from 2014-12-21 15:51:54)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14895 bytes, from 2015-04-19 15:23:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  66709 bytes, from 2015-04-12 18:16:35)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  60633 bytes, from 2015-05-20 14:48:19)
 
-Copyright (C) 2013-2014 by the following authors:
+Copyright (C) 2013-2015 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -43,10 +43,40 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 enum a4xx_color_fmt {
 	RB4_A8_UNORM = 1,
+	RB4_R8_UNORM = 2,
+	RB4_R4G4B4A4_UNORM = 8,
+	RB4_R5G5B5A1_UNORM = 10,
 	RB4_R5G6R5_UNORM = 14,
-	RB4_Z16_UNORM = 15,
+	RB4_R8G8_UNORM = 15,
+	RB4_R8G8_SNORM = 16,
+	RB4_R8G8_UINT = 17,
+	RB4_R8G8_SINT = 18,
+	RB4_R16_FLOAT = 21,
+	RB4_R16_UINT = 22,
+	RB4_R16_SINT = 23,
 	RB4_R8G8B8_UNORM = 25,
 	RB4_R8G8B8A8_UNORM = 26,
+	RB4_R8G8B8A8_SNORM = 28,
+	RB4_R8G8B8A8_UINT = 29,
+	RB4_R8G8B8A8_SINT = 30,
+	RB4_R10G10B10A2_UNORM = 31,
+	RB4_R10G10B10A2_UINT = 34,
+	RB4_R11G11B10_FLOAT = 39,
+	RB4_R16G16_FLOAT = 42,
+	RB4_R16G16_UINT = 43,
+	RB4_R16G16_SINT = 44,
+	RB4_R32_FLOAT = 45,
+	RB4_R32_UINT = 46,
+	RB4_R32_SINT = 47,
+	RB4_R16G16B16A16_FLOAT = 54,
+	RB4_R16G16B16A16_UINT = 55,
+	RB4_R16G16B16A16_SINT = 56,
+	RB4_R32G32_FLOAT = 57,
+	RB4_R32G32_UINT = 58,
+	RB4_R32G32_SINT = 59,
+	RB4_R32G32B32A32_FLOAT = 60,
+	RB4_R32G32B32A32_UINT = 61,
+	RB4_R32G32B32A32_SINT = 62,
 };
 
 enum a4xx_tile_mode {
@@ -91,7 +121,14 @@ enum a4xx_vtx_fmt {
 	VFMT4_16_16_UNORM = 29,
 	VFMT4_16_16_16_UNORM = 30,
 	VFMT4_16_16_16_16_UNORM = 31,
+	VFMT4_32_UINT = 32,
+	VFMT4_32_32_UINT = 33,
+	VFMT4_32_32_32_UINT = 34,
+	VFMT4_32_32_32_32_UINT = 35,
+	VFMT4_32_SINT = 36,
 	VFMT4_32_32_SINT = 37,
+	VFMT4_32_32_32_SINT = 38,
+	VFMT4_32_32_32_32_SINT = 39,
 	VFMT4_8_UINT = 40,
 	VFMT4_8_8_UINT = 41,
 	VFMT4_8_8_8_UINT = 42,
@@ -125,12 +162,57 @@ enum a4xx_tex_fmt {
 	TFMT4_8_UNORM = 4,
 	TFMT4_8_8_UNORM = 14,
 	TFMT4_8_8_8_8_UNORM = 28,
+	TFMT4_8_8_SNORM = 15,
+	TFMT4_8_8_8_8_SNORM = 29,
+	TFMT4_8_8_UINT = 16,
+	TFMT4_8_8_8_8_UINT = 30,
+	TFMT4_8_8_SINT = 17,
+	TFMT4_8_8_8_8_SINT = 31,
+	TFMT4_16_UINT = 21,
+	TFMT4_16_16_UINT = 41,
+	TFMT4_16_16_16_16_UINT = 54,
+	TFMT4_16_SINT = 22,
+	TFMT4_16_16_SINT = 42,
+	TFMT4_16_16_16_16_SINT = 55,
+	TFMT4_32_UINT = 44,
+	TFMT4_32_32_UINT = 57,
+	TFMT4_32_32_32_32_UINT = 64,
+	TFMT4_32_SINT = 45,
+	TFMT4_32_32_SINT = 58,
+	TFMT4_32_32_32_32_SINT = 65,
 	TFMT4_16_FLOAT = 20,
 	TFMT4_16_16_FLOAT = 40,
 	TFMT4_16_16_16_16_FLOAT = 53,
 	TFMT4_32_FLOAT = 43,
 	TFMT4_32_32_FLOAT = 56,
 	TFMT4_32_32_32_32_FLOAT = 63,
+	TFMT4_9_9_9_E5_FLOAT = 32,
+	TFMT4_11_11_10_FLOAT = 37,
+	TFMT4_ATC_RGB = 100,
+	TFMT4_ATC_RGBA_EXPLICIT = 101,
+	TFMT4_ATC_RGBA_INTERPOLATED = 102,
+	TFMT4_ETC2_RG11_UNORM = 103,
+	TFMT4_ETC2_RG11_SNORM = 104,
+	TFMT4_ETC2_R11_UNORM = 105,
+	TFMT4_ETC2_R11_SNORM = 106,
+	TFMT4_ETC1 = 107,
+	TFMT4_ETC2_RGB8 = 108,
+	TFMT4_ETC2_RGBA8 = 109,
+	TFMT4_ETC2_RGB8A1 = 110,
+	TFMT4_ASTC_4x4 = 111,
+	TFMT4_ASTC_5x4 = 112,
+	TFMT4_ASTC_5x5 = 113,
+	TFMT4_ASTC_6x5 = 114,
+	TFMT4_ASTC_6x6 = 115,
+	TFMT4_ASTC_8x5 = 116,
+	TFMT4_ASTC_8x6 = 117,
+	TFMT4_ASTC_8x8 = 118,
+	TFMT4_ASTC_10x5 = 119,
+	TFMT4_ASTC_10x6 = 120,
+	TFMT4_ASTC_10x8 = 121,
+	TFMT4_ASTC_10x10 = 122,
+	TFMT4_ASTC_12x10 = 123,
+	TFMT4_ASTC_12x12 = 124,
 };
 
 enum a4xx_tex_fetchsize {
@@ -147,9 +229,16 @@ enum a4xx_depth_format {
 	DEPTH4_24_8 = 2,
 };
 
+enum a4xx_tess_spacing {
+	EQUAL_SPACING = 0,
+	ODD_SPACING = 2,
+	EVEN_SPACING = 3,
+};
+
 enum a4xx_tex_filter {
 	A4XX_TEX_NEAREST = 0,
 	A4XX_TEX_LINEAR = 1,
+	A4XX_TEX_ANISO = 2,
 };
 
 enum a4xx_tex_clamp {
@@ -159,6 +248,14 @@ enum a4xx_tex_clamp {
 	A4XX_TEX_CLAMP_NONE = 3,
 };
 
+enum a4xx_tex_aniso {
+	A4XX_TEX_ANISO_1 = 0,
+	A4XX_TEX_ANISO_2 = 1,
+	A4XX_TEX_ANISO_4 = 2,
+	A4XX_TEX_ANISO_8 = 3,
+	A4XX_TEX_ANISO_16 = 4,
+};
+
 enum a4xx_tex_swiz {
 	A4XX_TEX_X = 0,
 	A4XX_TEX_Y = 1,
@@ -279,13 +376,16 @@ static inline uint32_t A4XX_RB_MSAA_CONTROL_SAMPLES(uint32_t val)
 #define A4XX_RB_RENDER_CONTROL2_YCOORD				0x00000002
 #define A4XX_RB_RENDER_CONTROL2_ZCOORD				0x00000004
 #define A4XX_RB_RENDER_CONTROL2_WCOORD				0x00000008
+#define A4XX_RB_RENDER_CONTROL2_SAMPLEMASK			0x00000010
 #define A4XX_RB_RENDER_CONTROL2_FACENESS			0x00000020
+#define A4XX_RB_RENDER_CONTROL2_SAMPLEID			0x00000040
 #define A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__MASK		0x00000380
 #define A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__SHIFT		7
 static inline uint32_t A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES(uint32_t val)
 {
 	return ((val) << A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__SHIFT) & A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__MASK;
 }
+#define A4XX_RB_RENDER_CONTROL2_SAMPLEID_HR			0x00000800
 #define A4XX_RB_RENDER_CONTROL2_VARYING				0x00001000
 
 static inline uint32_t REG_A4XX_RB_MRT(uint32_t i0) { return 0x000020a4 + 0x5*i0; }
@@ -310,6 +410,12 @@ static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT(enum a4xx_color_fmt val
 {
 	return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT__MASK;
 }
+#define A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK		0x000000c0
+#define A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT		6
+static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(enum a4xx_tile_mode val)
+{
+	return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK;
+}
 #define A4XX_RB_MRT_BUF_INFO_DITHER_MODE__MASK			0x00000600
 #define A4XX_RB_MRT_BUF_INFO_DITHER_MODE__SHIFT			9
 static inline uint32_t A4XX_RB_MRT_BUF_INFO_DITHER_MODE(enum adreno_rb_dither_mode val)
@@ -322,6 +428,7 @@ static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_SWAP(enum a3xx_color_swap val)
 {
 	return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK;
 }
+#define A4XX_RB_MRT_BUF_INFO_COLOR_SRGB				0x00002000
 #define A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__MASK		0x007fc000
 #define A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__SHIFT		14
 static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(uint32_t val)
@@ -449,7 +556,12 @@ static inline uint32_t A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(enum adreno_compare
 }
 
 #define REG_A4XX_RB_FS_OUTPUT					0x000020f9
-#define A4XX_RB_FS_OUTPUT_ENABLE_BLEND				0x00000001
+#define A4XX_RB_FS_OUTPUT_ENABLE_BLEND__MASK			0x000000ff
+#define A4XX_RB_FS_OUTPUT_ENABLE_BLEND__SHIFT			0
+static inline uint32_t A4XX_RB_FS_OUTPUT_ENABLE_BLEND(uint32_t val)
+{
+	return ((val) << A4XX_RB_FS_OUTPUT_ENABLE_BLEND__SHIFT) & A4XX_RB_FS_OUTPUT_ENABLE_BLEND__MASK;
+}
 #define A4XX_RB_FS_OUTPUT_FAST_CLEAR				0x00000100
 #define A4XX_RB_FS_OUTPUT_SAMPLE_MASK__MASK			0xffff0000
 #define A4XX_RB_FS_OUTPUT_SAMPLE_MASK__SHIFT			16
@@ -458,12 +570,54 @@ static inline uint32_t A4XX_RB_FS_OUTPUT_SAMPLE_MASK(uint32_t val)
 	return ((val) << A4XX_RB_FS_OUTPUT_SAMPLE_MASK__SHIFT) & A4XX_RB_FS_OUTPUT_SAMPLE_MASK__MASK;
 }
 
-#define REG_A4XX_RB_RENDER_CONTROL3				0x000020fb
-#define A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE__MASK		0x0000001f
-#define A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE__SHIFT		0
-static inline uint32_t A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE(uint32_t val)
+#define REG_A4XX_RB_RENDER_COMPONENTS				0x000020fb
+#define A4XX_RB_RENDER_COMPONENTS_RT0__MASK			0x0000000f
+#define A4XX_RB_RENDER_COMPONENTS_RT0__SHIFT			0
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT0(uint32_t val)
 {
-	return ((val) << A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE__SHIFT) & A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE__MASK;
+	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT0__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT0__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT1__MASK			0x000000f0
+#define A4XX_RB_RENDER_COMPONENTS_RT1__SHIFT			4
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT1(uint32_t val)
+{
+	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT1__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT1__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT2__MASK			0x00000f00
+#define A4XX_RB_RENDER_COMPONENTS_RT2__SHIFT			8
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT2(uint32_t val)
+{
+	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT2__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT2__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT3__MASK			0x0000f000
+#define A4XX_RB_RENDER_COMPONENTS_RT3__SHIFT			12
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT3(uint32_t val)
+{
+	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT3__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT3__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT4__MASK			0x000f0000
+#define A4XX_RB_RENDER_COMPONENTS_RT4__SHIFT			16
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT4(uint32_t val)
+{
+	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT4__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT4__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT5__MASK			0x00f00000
+#define A4XX_RB_RENDER_COMPONENTS_RT5__SHIFT			20
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT5(uint32_t val)
+{
+	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT5__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT5__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT6__MASK			0x0f000000
+#define A4XX_RB_RENDER_COMPONENTS_RT6__SHIFT			24
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT6(uint32_t val)
+{
+	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT6__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT6__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT7__MASK			0xf0000000
+#define A4XX_RB_RENDER_COMPONENTS_RT7__SHIFT			28
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT7(uint32_t val)
+{
+	return ((val) << A4XX_RB_RENDER_COMPONENTS_RT7__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT7__MASK;
 }
 
 #define REG_A4XX_RB_COPY_CONTROL				0x000020fc
@@ -547,7 +701,12 @@ static inline uint32_t A4XX_RB_COPY_DEST_INFO_TILE(enum a4xx_tile_mode val)
 }
 
 #define REG_A4XX_RB_FS_OUTPUT_REG				0x00002100
-#define A4XX_RB_FS_OUTPUT_REG_COLOR_PIPE_ENABLE			0x00000001
+#define A4XX_RB_FS_OUTPUT_REG_MRT__MASK				0x0000000f
+#define A4XX_RB_FS_OUTPUT_REG_MRT__SHIFT			0
+static inline uint32_t A4XX_RB_FS_OUTPUT_REG_MRT(uint32_t val)
+{
+	return ((val) << A4XX_RB_FS_OUTPUT_REG_MRT__SHIFT) & A4XX_RB_FS_OUTPUT_REG_MRT__MASK;
+}
 #define A4XX_RB_FS_OUTPUT_REG_FRAG_WRITES_Z			0x00000020
 
 #define REG_A4XX_RB_DEPTH_CONTROL				0x00002101
@@ -930,6 +1089,10 @@ static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1_REG(uint32_t i0)
 
 #define REG_A4XX_CP_IB2_BUFSZ					0x00000209
 
+#define REG_A4XX_CP_ME_NRT_ADDR					0x0000020c
+
+#define REG_A4XX_CP_ME_NRT_DATA					0x0000020d
+
 #define REG_A4XX_CP_ME_RB_DONE_DATA				0x00000217
 
 #define REG_A4XX_CP_QUEUE_THRESH2				0x00000219
@@ -940,9 +1103,9 @@ static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1_REG(uint32_t i0)
 
 #define REG_A4XX_CP_ROQ_DATA					0x0000021d
 
-#define REG_A4XX_CP_MEQ_ADDR 					0x0000021e
+#define REG_A4XX_CP_MEQ_ADDR					0x0000021e
 
-#define REG_A4XX_CP_MEQ_DATA 					0x0000021f
+#define REG_A4XX_CP_MEQ_DATA					0x0000021f
 
 #define REG_A4XX_CP_MERCIU_ADDR					0x00000220
 
@@ -1004,12 +1167,17 @@ static inline uint32_t REG_A4XX_CP_SCRATCH_REG(uint32_t i0) { return 0x00000578
 
 #define REG_A4XX_SP_VS_STATUS					0x00000ec0
 
+#define REG_A4XX_SP_MODE_CONTROL				0x00000ec3
+
 #define REG_A4XX_SP_PERFCTR_SP_SEL_11				0x00000ecf
 
 #define REG_A4XX_SP_SP_CTRL_REG					0x000022c0
 #define A4XX_SP_SP_CTRL_REG_BINNING_PASS			0x00080000
 
 #define REG_A4XX_SP_INSTR_CACHE_CTRL				0x000022c1
+#define A4XX_SP_INSTR_CACHE_CTRL_VS_BUFFER			0x00000080
+#define A4XX_SP_INSTR_CACHE_CTRL_FS_BUFFER			0x00000100
+#define A4XX_SP_INSTR_CACHE_CTRL_INSTR_BUFFER			0x00000400
 
 #define REG_A4XX_SP_VS_CTRL_REG0				0x000022c4
 #define A4XX_SP_VS_CTRL_REG0_THREADMODE__MASK			0x00000001
@@ -1229,6 +1397,12 @@ static inline uint32_t A4XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
 #define REG_A4XX_SP_FS_LENGTH_REG				0x000022ef
 
 #define REG_A4XX_SP_FS_OUTPUT_REG				0x000022f0
+#define A4XX_SP_FS_OUTPUT_REG_MRT__MASK				0x0000000f
+#define A4XX_SP_FS_OUTPUT_REG_MRT__SHIFT			0
+static inline uint32_t A4XX_SP_FS_OUTPUT_REG_MRT(uint32_t val)
+{
+	return ((val) << A4XX_SP_FS_OUTPUT_REG_MRT__SHIFT) & A4XX_SP_FS_OUTPUT_REG_MRT__MASK;
+}
 #define A4XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE			0x00000080
 #define A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK			0x0000ff00
 #define A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT		8
@@ -1236,6 +1410,12 @@ static inline uint32_t A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID(uint32_t val)
 {
 	return ((val) << A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT) & A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK;
 }
+#define A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__MASK		0xff000000
+#define A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__SHIFT		24
+static inline uint32_t A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID(uint32_t val)
+{
+	return ((val) << A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__SHIFT) & A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__MASK;
+}
 
 static inline uint32_t REG_A4XX_SP_FS_MRT(uint32_t i0) { return 0x000022f1 + 0x1*i0; }
 
@@ -1254,6 +1434,20 @@ static inline uint32_t A4XX_SP_FS_MRT_REG_MRTFORMAT(enum a4xx_color_fmt val)
 	return ((val) << A4XX_SP_FS_MRT_REG_MRTFORMAT__SHIFT) & A4XX_SP_FS_MRT_REG_MRTFORMAT__MASK;
 }
 
+#define REG_A4XX_SP_CS_CTRL_REG0				0x00002300
+
+#define REG_A4XX_SP_CS_OBJ_OFFSET_REG				0x00002301
+
+#define REG_A4XX_SP_CS_OBJ_START				0x00002302
+
+#define REG_A4XX_SP_CS_PVT_MEM_PARAM				0x00002303
+
+#define REG_A4XX_SP_CS_PVT_MEM_ADDR				0x00002304
+
+#define REG_A4XX_SP_CS_PVT_MEM_SIZE				0x00002305
+
+#define REG_A4XX_SP_CS_LENGTH_REG				0x00002306
+
 #define REG_A4XX_SP_HS_OBJ_OFFSET_REG				0x0000230d
 #define A4XX_SP_HS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK	0x01ff0000
 #define A4XX_SP_HS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT	16
@@ -1268,6 +1462,14 @@ static inline uint32_t A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
 	return ((val) << A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
 }
 
+#define REG_A4XX_SP_HS_OBJ_START				0x0000230e
+
+#define REG_A4XX_SP_HS_PVT_MEM_PARAM				0x0000230f
+
+#define REG_A4XX_SP_HS_PVT_MEM_ADDR				0x00002310
+
+#define REG_A4XX_SP_HS_LENGTH_REG				0x00002312
+
 #define REG_A4XX_SP_DS_OBJ_OFFSET_REG				0x00002334
 #define A4XX_SP_DS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK	0x01ff0000
 #define A4XX_SP_DS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT	16
@@ -1282,6 +1484,14 @@ static inline uint32_t A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
 	return ((val) << A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
 }
 
+#define REG_A4XX_SP_DS_OBJ_START				0x00002335
+
+#define REG_A4XX_SP_DS_PVT_MEM_PARAM				0x00002336
+
+#define REG_A4XX_SP_DS_PVT_MEM_ADDR				0x00002337
+
+#define REG_A4XX_SP_DS_LENGTH_REG				0x00002339
+
 #define REG_A4XX_SP_GS_OBJ_OFFSET_REG				0x0000235b
 #define A4XX_SP_GS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK	0x01ff0000
 #define A4XX_SP_GS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT	16
@@ -1296,6 +1506,12 @@ static inline uint32_t A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
 	return ((val) << A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
 }
 
+#define REG_A4XX_SP_GS_OBJ_START				0x0000235c
+
+#define REG_A4XX_SP_GS_PVT_MEM_PARAM				0x0000235d
+
+#define REG_A4XX_SP_GS_PVT_MEM_ADDR				0x0000235e
+
 #define REG_A4XX_SP_GS_LENGTH_REG				0x00002360
 
 #define REG_A4XX_VPC_DEBUG_RAM_SEL				0x00000e60
@@ -1418,6 +1634,10 @@ static inline uint32_t REG_A4XX_VSC_PIPE_DATA_LENGTH_REG(uint32_t i0) { return 0
 
 #define REG_A4XX_VFD_PERFCTR_VFD_SEL_7				0x00000e4a
 
+#define REG_A4XX_VGT_CL_INITIATOR				0x000021d0
+
+#define REG_A4XX_VGT_EVENT_INITIATOR				0x000021d9
+
 #define REG_A4XX_VFD_CONTROL_0					0x00002200
 #define A4XX_VFD_CONTROL_0_TOTALATTRTOVS__MASK			0x000000ff
 #define A4XX_VFD_CONTROL_0_TOTALATTRTOVS__SHIFT			0
@@ -1554,10 +1774,54 @@ static inline uint32_t A4XX_VFD_DECODE_INSTR_SHIFTCNT(uint32_t val)
 
 #define REG_A4XX_TPL1_DEBUG_ECO_CONTROL				0x00000f00
 
+#define REG_A4XX_TPL1_TP_MODE_CONTROL				0x00000f03
+
 #define REG_A4XX_TPL1_PERFCTR_TP_SEL_7				0x00000f0b
 
 #define REG_A4XX_TPL1_TP_TEX_OFFSET				0x00002380
 
+#define REG_A4XX_TPL1_TP_TEX_COUNT				0x00002381
+#define A4XX_TPL1_TP_TEX_COUNT_VS__MASK				0x000000ff
+#define A4XX_TPL1_TP_TEX_COUNT_VS__SHIFT			0
+static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_VS(uint32_t val)
+{
+	return ((val) << A4XX_TPL1_TP_TEX_COUNT_VS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_VS__MASK;
+}
+#define A4XX_TPL1_TP_TEX_COUNT_HS__MASK				0x0000ff00
+#define A4XX_TPL1_TP_TEX_COUNT_HS__SHIFT			8
+static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_HS(uint32_t val)
+{
+	return ((val) << A4XX_TPL1_TP_TEX_COUNT_HS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_HS__MASK;
+}
+#define A4XX_TPL1_TP_TEX_COUNT_DS__MASK				0x00ff0000
+#define A4XX_TPL1_TP_TEX_COUNT_DS__SHIFT			16
+static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_DS(uint32_t val)
+{
+	return ((val) << A4XX_TPL1_TP_TEX_COUNT_DS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_DS__MASK;
+}
+#define A4XX_TPL1_TP_TEX_COUNT_GS__MASK				0xff000000
+#define A4XX_TPL1_TP_TEX_COUNT_GS__SHIFT			24
+static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_GS(uint32_t val)
+{
+	return ((val) << A4XX_TPL1_TP_TEX_COUNT_GS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_GS__MASK;
+}
+
+#define REG_A4XX_TPL1_TP_VS_BORDER_COLOR_BASE_ADDR		0x00002384
+
+#define REG_A4XX_TPL1_TP_HS_BORDER_COLOR_BASE_ADDR		0x00002387
+
+#define REG_A4XX_TPL1_TP_DS_BORDER_COLOR_BASE_ADDR		0x0000238a
+
+#define REG_A4XX_TPL1_TP_GS_BORDER_COLOR_BASE_ADDR		0x0000238d
+
+#define REG_A4XX_TPL1_TP_FS_TEX_COUNT				0x000023a0
+
+#define REG_A4XX_TPL1_TP_FS_BORDER_COLOR_BASE_ADDR		0x000023a1
+
+#define REG_A4XX_TPL1_TP_CS_BORDER_COLOR_BASE_ADDR		0x000023a4
+
+#define REG_A4XX_TPL1_TP_CS_SAMPLER_BASE_ADDR			0x000023a5
+
 #define REG_A4XX_TPL1_TP_CS_TEXMEMOBJ_BASE_ADDR			0x000023a6
 
 #define REG_A4XX_GRAS_TSE_STATUS				0x00000c80
@@ -1676,6 +1940,14 @@ static inline uint32_t A4XX_GRAS_SU_POLY_OFFSET_OFFSET(float val)
 	return ((fui(val)) << A4XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A4XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;
 }
 
+#define REG_A4XX_GRAS_SU_POLY_OFFSET_CLAMP			0x00002076
+#define A4XX_GRAS_SU_POLY_OFFSET_CLAMP__MASK			0xffffffff
+#define A4XX_GRAS_SU_POLY_OFFSET_CLAMP__SHIFT			0
+static inline uint32_t A4XX_GRAS_SU_POLY_OFFSET_CLAMP(float val)
+{
+	return ((fui(val)) << A4XX_GRAS_SU_POLY_OFFSET_CLAMP__SHIFT) & A4XX_GRAS_SU_POLY_OFFSET_CLAMP__MASK;
+}
+
 #define REG_A4XX_GRAS_DEPTH_CONTROL				0x00002077
 #define A4XX_GRAS_DEPTH_CONTROL_FORMAT__MASK			0x00000003
 #define A4XX_GRAS_DEPTH_CONTROL_FORMAT__SHIFT			0
@@ -1828,6 +2100,8 @@ static inline uint32_t A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y(uint32_t val)
 
 #define REG_A4XX_HLSQ_DEBUG_ECO_CONTROL				0x00000e04
 
+#define REG_A4XX_HLSQ_MODE_CONTROL				0x00000e05
+
 #define REG_A4XX_HLSQ_PERF_PIPE_MASK				0x00000e0e
 
 #define REG_A4XX_HLSQ_CONTROL_0_REG				0x000023c0
@@ -1867,7 +2141,12 @@ static inline uint32_t A4XX_HLSQ_CONTROL_1_REG_COORDREGID(uint32_t val)
 {
 	return ((val) << A4XX_HLSQ_CONTROL_1_REG_COORDREGID__SHIFT) & A4XX_HLSQ_CONTROL_1_REG_COORDREGID__MASK;
 }
-#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORD				0x02000000
+#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__MASK		0xff000000
+#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__SHIFT		24
+static inline uint32_t A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID(uint32_t val)
+{
+	return ((val) << A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__SHIFT) & A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__MASK;
+}
 
 #define REG_A4XX_HLSQ_CONTROL_2_REG				0x000023c2
 #define A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__MASK	0xfc000000
@@ -1882,6 +2161,18 @@ static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_FACEREGID(uint32_t val)
 {
 	return ((val) << A4XX_HLSQ_CONTROL_2_REG_FACEREGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_FACEREGID__MASK;
 }
+#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__MASK		0x0003fc00
+#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__SHIFT		10
+static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID(uint32_t val)
+{
+	return ((val) << A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__MASK;
+}
+#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__MASK		0x03fc0000
+#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__SHIFT		18
+static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID(uint32_t val)
+{
+	return ((val) << A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__MASK;
+}
 
 #define REG_A4XX_HLSQ_CONTROL_3_REG				0x000023c3
 #define A4XX_HLSQ_CONTROL_3_REG_REGID__MASK			0x000000ff
@@ -1891,6 +2182,8 @@ static inline uint32_t A4XX_HLSQ_CONTROL_3_REG_REGID(uint32_t val)
 	return ((val) << A4XX_HLSQ_CONTROL_3_REG_REGID__SHIFT) & A4XX_HLSQ_CONTROL_3_REG_REGID__MASK;
 }
 
+#define REG_A4XX_HLSQ_CONTROL_4_REG				0x000023c4
+
 #define REG_A4XX_HLSQ_VS_CONTROL_REG				0x000023c5
 #define A4XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__MASK		0x000000ff
 #define A4XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__SHIFT		0
@@ -1904,6 +2197,7 @@ static inline uint32_t A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
 {
 	return ((val) << A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
 }
+#define A4XX_HLSQ_VS_CONTROL_REG_ENABLED			0x00010000
 #define A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00fe0000
 #define A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		17
 static inline uint32_t A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
@@ -1930,6 +2224,7 @@ static inline uint32_t A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
 {
 	return ((val) << A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
 }
+#define A4XX_HLSQ_FS_CONTROL_REG_ENABLED			0x00010000
 #define A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00fe0000
 #define A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		17
 static inline uint32_t A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
@@ -1956,6 +2251,7 @@ static inline uint32_t A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
 {
 	return ((val) << A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
 }
+#define A4XX_HLSQ_HS_CONTROL_REG_ENABLED			0x00010000
 #define A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00fe0000
 #define A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		17
 static inline uint32_t A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
@@ -1982,6 +2278,7 @@ static inline uint32_t A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
 {
 	return ((val) << A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
 }
+#define A4XX_HLSQ_DS_CONTROL_REG_ENABLED			0x00010000
 #define A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00fe0000
 #define A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		17
 static inline uint32_t A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
@@ -2008,6 +2305,7 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
 {
 	return ((val) << A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
 }
+#define A4XX_HLSQ_GS_CONTROL_REG_ENABLED			0x00010000
 #define A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00fe0000
 #define A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		17
 static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
@@ -2021,6 +2319,36 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
 	return ((val) << A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH__SHIFT) & A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH__MASK;
 }
 
+#define REG_A4XX_HLSQ_CS_CONTROL				0x000023ca
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_0				0x000023cd
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_1				0x000023ce
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_2				0x000023cf
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_3				0x000023d0
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_4				0x000023d1
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_5				0x000023d2
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_6				0x000023d3
+
+#define REG_A4XX_HLSQ_CL_CONTROL_0				0x000023d4
+
+#define REG_A4XX_HLSQ_CL_CONTROL_1				0x000023d5
+
+#define REG_A4XX_HLSQ_CL_KERNEL_CONST				0x000023d6
+
+#define REG_A4XX_HLSQ_CL_KERNEL_GROUP_X				0x000023d7
+
+#define REG_A4XX_HLSQ_CL_KERNEL_GROUP_Y				0x000023d8
+
+#define REG_A4XX_HLSQ_CL_KERNEL_GROUP_Z				0x000023d9
+
+#define REG_A4XX_HLSQ_CL_WG_OFFSET				0x000023da
+
 #define REG_A4XX_HLSQ_UPDATE_CONTROL				0x000023db
 
 #define REG_A4XX_PC_BINNING_COMMAND				0x00000d00
@@ -2035,7 +2363,13 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
 #define REG_A4XX_PC_BIN_BASE					0x000021c0
 
 #define REG_A4XX_PC_PRIM_VTX_CNTL				0x000021c4
-#define A4XX_PC_PRIM_VTX_CNTL_VAROUT				0x00000001
+#define A4XX_PC_PRIM_VTX_CNTL_VAROUT__MASK			0x0000000f
+#define A4XX_PC_PRIM_VTX_CNTL_VAROUT__SHIFT			0
+static inline uint32_t A4XX_PC_PRIM_VTX_CNTL_VAROUT(uint32_t val)
+{
+	return ((val) << A4XX_PC_PRIM_VTX_CNTL_VAROUT__SHIFT) & A4XX_PC_PRIM_VTX_CNTL_VAROUT__MASK;
+}
+#define A4XX_PC_PRIM_VTX_CNTL_PRIMITIVE_RESTART			0x00100000
 #define A4XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST		0x02000000
 #define A4XX_PC_PRIM_VTX_CNTL_PSIZE				0x04000000
 
@@ -2044,8 +2378,45 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
 #define REG_A4XX_PC_RESTART_INDEX				0x000021c6
 
 #define REG_A4XX_PC_GS_PARAM					0x000021e5
+#define A4XX_PC_GS_PARAM_MAX_VERTICES__MASK			0x000003ff
+#define A4XX_PC_GS_PARAM_MAX_VERTICES__SHIFT			0
+static inline uint32_t A4XX_PC_GS_PARAM_MAX_VERTICES(uint32_t val)
+{
+	return ((val) << A4XX_PC_GS_PARAM_MAX_VERTICES__SHIFT) & A4XX_PC_GS_PARAM_MAX_VERTICES__MASK;
+}
+#define A4XX_PC_GS_PARAM_INVOCATIONS__MASK			0x0000f800
+#define A4XX_PC_GS_PARAM_INVOCATIONS__SHIFT			11
+static inline uint32_t A4XX_PC_GS_PARAM_INVOCATIONS(uint32_t val)
+{
+	return ((val) << A4XX_PC_GS_PARAM_INVOCATIONS__SHIFT) & A4XX_PC_GS_PARAM_INVOCATIONS__MASK;
+}
+#define A4XX_PC_GS_PARAM_PRIMTYPE__MASK				0x01800000
+#define A4XX_PC_GS_PARAM_PRIMTYPE__SHIFT			23
+static inline uint32_t A4XX_PC_GS_PARAM_PRIMTYPE(enum adreno_pa_su_sc_draw val)
+{
+	return ((val) << A4XX_PC_GS_PARAM_PRIMTYPE__SHIFT) & A4XX_PC_GS_PARAM_PRIMTYPE__MASK;
+}
+#define A4XX_PC_GS_PARAM_LAYER					0x80000000
 
 #define REG_A4XX_PC_HS_PARAM					0x000021e7
+#define A4XX_PC_HS_PARAM_VERTICES_OUT__MASK			0x0000003f
+#define A4XX_PC_HS_PARAM_VERTICES_OUT__SHIFT			0
+static inline uint32_t A4XX_PC_HS_PARAM_VERTICES_OUT(uint32_t val)
+{
+	return ((val) << A4XX_PC_HS_PARAM_VERTICES_OUT__SHIFT) & A4XX_PC_HS_PARAM_VERTICES_OUT__MASK;
+}
+#define A4XX_PC_HS_PARAM_SPACING__MASK				0x00600000
+#define A4XX_PC_HS_PARAM_SPACING__SHIFT				21
+static inline uint32_t A4XX_PC_HS_PARAM_SPACING(enum a4xx_tess_spacing val)
+{
+	return ((val) << A4XX_PC_HS_PARAM_SPACING__SHIFT) & A4XX_PC_HS_PARAM_SPACING__MASK;
+}
+#define A4XX_PC_HS_PARAM_PRIMTYPE__MASK				0x01800000
+#define A4XX_PC_HS_PARAM_PRIMTYPE__SHIFT			23
+static inline uint32_t A4XX_PC_HS_PARAM_PRIMTYPE(enum adreno_pa_su_sc_draw val)
+{
+	return ((val) << A4XX_PC_HS_PARAM_PRIMTYPE__SHIFT) & A4XX_PC_HS_PARAM_PRIMTYPE__MASK;
+}
 
 #define REG_A4XX_VBIF_VERSION					0x00003000
 
@@ -2074,16 +2445,10 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
 
 #define REG_A4XX_UNKNOWN_0D01					0x00000d01
 
-#define REG_A4XX_UNKNOWN_0E05					0x00000e05
-
 #define REG_A4XX_UNKNOWN_0E42					0x00000e42
 
 #define REG_A4XX_UNKNOWN_0EC2					0x00000ec2
 
-#define REG_A4XX_UNKNOWN_0EC3					0x00000ec3
-
-#define REG_A4XX_UNKNOWN_0F03					0x00000f03
-
 #define REG_A4XX_UNKNOWN_2001					0x00002001
 
 #define REG_A4XX_UNKNOWN_209B					0x0000209b
@@ -2124,10 +2489,6 @@ static inline uint32_t A4XX_UNKNOWN_20F7(float val)
 
 #define REG_A4XX_UNKNOWN_22D7					0x000022d7
 
-#define REG_A4XX_UNKNOWN_2381					0x00002381
-
-#define REG_A4XX_UNKNOWN_23A0					0x000023a0
-
 #define REG_A4XX_TEX_SAMP_0					0x00000000
 #define A4XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR			0x00000001
 #define A4XX_TEX_SAMP_0_XY_MAG__MASK				0x00000006
@@ -2160,6 +2521,12 @@ static inline uint32_t A4XX_TEX_SAMP_0_WRAP_R(enum a4xx_tex_clamp val)
 {
 	return ((val) << A4XX_TEX_SAMP_0_WRAP_R__SHIFT) & A4XX_TEX_SAMP_0_WRAP_R__MASK;
 }
+#define A4XX_TEX_SAMP_0_ANISO__MASK				0x0001c000
+#define A4XX_TEX_SAMP_0_ANISO__SHIFT				14
+static inline uint32_t A4XX_TEX_SAMP_0_ANISO(enum a4xx_tex_aniso val)
+{
+	return ((val) << A4XX_TEX_SAMP_0_ANISO__SHIFT) & A4XX_TEX_SAMP_0_ANISO__MASK;
+}
 
 #define REG_A4XX_TEX_SAMP_1					0x00000001
 #define A4XX_TEX_SAMP_1_COMPARE_FUNC__MASK			0x0000000e
@@ -2185,6 +2552,7 @@ static inline uint32_t A4XX_TEX_SAMP_1_MIN_LOD(float val)
 
 #define REG_A4XX_TEX_CONST_0					0x00000000
 #define A4XX_TEX_CONST_0_TILED					0x00000001
+#define A4XX_TEX_CONST_0_SRGB					0x00000004
 #define A4XX_TEX_CONST_0_SWIZ_X__MASK				0x00000070
 #define A4XX_TEX_CONST_0_SWIZ_X__SHIFT				4
 static inline uint32_t A4XX_TEX_CONST_0_SWIZ_X(enum a4xx_tex_swiz val)
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
index 91221836c5ad..a53f1be05f75 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
@@ -268,6 +268,8 @@ static int a4xx_hw_init(struct msm_gpu *gpu)
 
 static void a4xx_recover(struct msm_gpu *gpu)
 {
+	adreno_dump_info(gpu);
+
 	/* dump registers before resetting gpu, if enabled: */
 	if (hang_debug)
 		a4xx_dump(gpu);
@@ -505,7 +507,6 @@ static const unsigned int a4xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
 
 static void a4xx_dump(struct msm_gpu *gpu)
 {
-	adreno_dump(gpu);
 	printk("status:   %08x\n",
 			gpu_read(gpu, REG_A4XX_RBBM_STATUS));
 	adreno_dump(gpu);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
index 8531beb982e7..9562a1fa552b 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
@@ -12,9 +12,9 @@ The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  10551 bytes, from 2014-11-13 22:44:30)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  15085 bytes, from 2014-12-20 21:49:41)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  64344 bytes, from 2014-12-12 20:22:26)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  51069 bytes, from 2014-12-21 15:51:54)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14895 bytes, from 2015-04-19 15:23:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  66709 bytes, from 2015-04-12 18:16:35)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  60633 bytes, from 2015-05-20 14:48:19)
 
 Copyright (C) 2013-2014 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index be83dee83d08..1ea2df524fac 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -19,7 +19,7 @@
 
 #include "adreno_gpu.h"
 
-#if defined(CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF)
+#if defined(DOWNSTREAM_CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF)
 #  include <mach/kgsl.h>
 #endif
 
@@ -42,6 +42,14 @@ static const struct adreno_info gpulist[] = {
 		.gmem  = SZ_256K,
 		.init  = a3xx_gpu_init,
 	}, {
+		.rev   = ADRENO_REV(3, 0, 6, 0),
+		.revn  = 307,        /* because a305c is revn==306 */
+		.name  = "A306",
+		.pm4fw = "a300_pm4.fw",
+		.pfpfw = "a300_pfp.fw",
+		.gmem  = SZ_128K,
+		.init  = a3xx_gpu_init,
+	}, {
 		.rev   = ADRENO_REV(3, 2, ANY_ID, ANY_ID),
 		.revn  = 320,
 		.name  = "A320",
@@ -240,7 +248,7 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
 			config.rev = ADRENO_REV(3, 0, 5, 0);
 
 	}
-#  ifdef CONFIG_MSM_BUS_SCALING
+#  ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
 	config.bus_scale_table = pdata->bus_scale_table;
 #  endif
 #endif
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index bbdcab0a56c1..a3b54cc76495 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -176,6 +176,17 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 	OUT_PKT3(ring, CP_INTERRUPT, 1);
 	OUT_RING(ring, 0x80000000);
 
+	/* Workaround for missing irq issue on 8x16/a306.  Unsure if the
+	 * root cause is a platform issue or some a306 quirk, but this
+	 * keeps things humming along:
+	 */
+	if (adreno_is_a306(adreno_gpu)) {
+		OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
+		OUT_RING(ring, 0x00000000);
+		OUT_PKT3(ring, CP_INTERRUPT, 1);
+		OUT_RING(ring, 0x80000000);
+	}
+
 #if 0
 	if (adreno_is_a3xx(adreno_gpu)) {
 		/* Dummy set-constant to trigger context rollover */
@@ -249,8 +260,13 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
 }
 #endif
 
-/* would be nice to not have to duplicate the _show() stuff with printk(): */
-void adreno_dump(struct msm_gpu *gpu)
+/* Dump common gpu status and scratch registers on any hang, to make
+ * the hangcheck logs more useful.  The scratch registers seem always
+ * safe to read when GPU has hung (unlike some other regs, depending
+ * on how the GPU hung), and they are useful to match up to cmdstream
+ * dumps when debugging hangs:
+ */
+void adreno_dump_info(struct msm_gpu *gpu)
 {
 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
 	int i;
@@ -266,6 +282,18 @@ void adreno_dump(struct msm_gpu *gpu)
 	printk("wptr:     %d\n", adreno_gpu->memptrs->wptr);
 	printk("rb wptr:  %d\n", get_wptr(gpu->rb));
 
+	for (i = 0; i < 8; i++) {
+		printk("CP_SCRATCH_REG%d: %u\n", i,
+			gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
+	}
+}
+
+/* would be nice to not have to duplicate the _show() stuff with printk(): */
+void adreno_dump(struct msm_gpu *gpu)
+{
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	int i;
+
 	/* dump these out in a form that can be parsed by demsm: */
 	printk("IO:region %s 00000000 00020000\n", gpu->name);
 	for (i = 0; adreno_gpu->registers[i] != ~0; i += 2) {
@@ -317,7 +345,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
 	gpu->fast_rate = config->fast_rate;
 	gpu->slow_rate = config->slow_rate;
 	gpu->bus_freq  = config->bus_freq;
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
 	gpu->bus_scale_table = config->bus_scale_table;
 #endif
 
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index a0cc30977e67..0a312e9d3afd 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -167,7 +167,7 @@ struct adreno_gpu {
 struct adreno_platform_config {
 	struct adreno_rev rev;
 	uint32_t fast_rate, slow_rate, bus_freq;
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
 	struct msm_bus_scale_pdata *bus_scale_table;
 #endif
 };
@@ -197,6 +197,12 @@ static inline bool adreno_is_a305(struct adreno_gpu *gpu)
 	return gpu->revn == 305;
 }
 
+static inline bool adreno_is_a306(struct adreno_gpu *gpu)
+{
+	/* yes, 307, because a305c is 306 */
+	return gpu->revn == 307;
+}
+
 static inline bool adreno_is_a320(struct adreno_gpu *gpu)
 {
 	return gpu->revn == 320;
@@ -233,6 +239,7 @@ void adreno_idle(struct msm_gpu *gpu);
 #ifdef CONFIG_DEBUG_FS
 void adreno_show(struct msm_gpu *gpu, struct seq_file *m);
 #endif
+void adreno_dump_info(struct msm_gpu *gpu);
 void adreno_dump(struct msm_gpu *gpu);
 void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords);
 
diff --git a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
index 6ffc4f6c8af1..bd5b23bf9041 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
@@ -12,11 +12,11 @@ The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2014-06-02 15:21:30)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  10551 bytes, from 2014-11-13 22:44:30)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  15085 bytes, from 2014-12-20 21:49:41)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  64344 bytes, from 2014-12-12 20:22:26)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  51069 bytes, from 2014-12-21 15:51:54)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  14895 bytes, from 2015-04-19 15:23:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  66709 bytes, from 2015-04-12 18:16:35)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (  60633 bytes, from 2015-05-20 14:48:19)
 
-Copyright (C) 2013-2014 by the following authors:
+Copyright (C) 2013-2015 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -76,16 +76,11 @@ enum pc_di_primtype {
 	DI_PT_LINELOOP = 7,
 	DI_PT_RECTLIST = 8,
 	DI_PT_POINTLIST_A3XX = 9,
-	DI_PT_QUADLIST = 13,
-	DI_PT_QUADSTRIP = 14,
-	DI_PT_POLYGON = 15,
-	DI_PT_2D_COPY_RECT_LIST_V0 = 16,
-	DI_PT_2D_COPY_RECT_LIST_V1 = 17,
-	DI_PT_2D_COPY_RECT_LIST_V2 = 18,
-	DI_PT_2D_COPY_RECT_LIST_V3 = 19,
-	DI_PT_2D_FILL_RECT_LIST = 20,
-	DI_PT_2D_LINE_STRIP = 21,
-	DI_PT_2D_TRI_STRIP = 22,
+	DI_PT_LINE_ADJ = 10,
+	DI_PT_LINESTRIP_ADJ = 11,
+	DI_PT_TRI_ADJ = 12,
+	DI_PT_TRISTRIP_ADJ = 13,
+	DI_PT_PATCHES = 34,
 };
 
 enum pc_di_src_sel {
@@ -192,6 +187,7 @@ enum adreno_state_block {
 	SB_FRAG_TEX = 2,
 	SB_FRAG_MIPADDR = 3,
 	SB_VERT_SHADER = 4,
+	SB_GEOM_SHADER = 5,
 	SB_FRAG_SHADER = 6,
 };
 
@@ -382,12 +378,19 @@ static inline uint32_t CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT(enum pc_di_src_sel va
 {
 	return ((val) << CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK;
 }
+#define CP_DRAW_INDX_OFFSET_0_TESSELLATE			0x00000100
 #define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK			0x00000c00
 #define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT			10
 static inline uint32_t CP_DRAW_INDX_OFFSET_0_INDEX_SIZE(enum a4xx_index_size val)
 {
 	return ((val) << CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK;
 }
+#define CP_DRAW_INDX_OFFSET_0_TESS_MODE__MASK			0x01f00000
+#define CP_DRAW_INDX_OFFSET_0_TESS_MODE__SHIFT			20
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_TESS_MODE(uint32_t val)
+{
+	return ((val) << CP_DRAW_INDX_OFFSET_0_TESS_MODE__SHIFT) & CP_DRAW_INDX_OFFSET_0_TESS_MODE__MASK;
+}
 
 #define REG_CP_DRAW_INDX_OFFSET_1				0x00000001
 #define CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES__MASK		0xffffffff
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index ad50b80225f5..1f2561e2ff71 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -23,12 +23,47 @@ struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
 		msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID];
 }
 
+static int dsi_get_phy(struct msm_dsi *msm_dsi)
+{
+	struct platform_device *pdev = msm_dsi->pdev;
+	struct platform_device *phy_pdev;
+	struct device_node *phy_node;
+
+	phy_node = of_parse_phandle(pdev->dev.of_node, "qcom,dsi-phy", 0);
+	if (!phy_node) {
+		dev_err(&pdev->dev, "cannot find phy device\n");
+		return -ENXIO;
+	}
+
+	phy_pdev = of_find_device_by_node(phy_node);
+	if (phy_pdev)
+		msm_dsi->phy = platform_get_drvdata(phy_pdev);
+
+	of_node_put(phy_node);
+
+	if (!phy_pdev || !msm_dsi->phy) {
+		dev_err(&pdev->dev, "%s: phy driver is not ready\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	msm_dsi->phy_dev = get_device(&phy_pdev->dev);
+
+	return 0;
+}
+
 static void dsi_destroy(struct msm_dsi *msm_dsi)
 {
 	if (!msm_dsi)
 		return;
 
 	msm_dsi_manager_unregister(msm_dsi);
+
+	if (msm_dsi->phy_dev) {
+		put_device(msm_dsi->phy_dev);
+		msm_dsi->phy = NULL;
+		msm_dsi->phy_dev = NULL;
+	}
+
 	if (msm_dsi->host) {
 		msm_dsi_host_destroy(msm_dsi->host);
 		msm_dsi->host = NULL;
@@ -43,7 +78,6 @@ static struct msm_dsi *dsi_init(struct platform_device *pdev)
 	int ret;
 
 	if (!pdev) {
-		dev_err(&pdev->dev, "no dsi device\n");
 		ret = -ENXIO;
 		goto fail;
 	}
@@ -63,6 +97,11 @@ static struct msm_dsi *dsi_init(struct platform_device *pdev)
 	if (ret)
 		goto fail;
 
+	/* GET dsi PHY */
+	ret = dsi_get_phy(msm_dsi);
+	if (ret)
+		goto fail;
+
 	/* Register to dsi manager */
 	ret = msm_dsi_manager_register(msm_dsi);
 	if (ret)
@@ -142,12 +181,14 @@ static struct platform_driver dsi_driver = {
 void __init msm_dsi_register(void)
 {
 	DBG("");
+	msm_dsi_phy_driver_register();
 	platform_driver_register(&dsi_driver);
 }
 
 void __exit msm_dsi_unregister(void)
 {
 	DBG("");
+	msm_dsi_phy_driver_unregister();
 	platform_driver_unregister(&dsi_driver);
 }
 
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 10f54d4e379a..92d697de4858 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -14,6 +14,7 @@
 #ifndef __DSI_CONNECTOR_H__
 #define __DSI_CONNECTOR_H__
 
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 
 #include "drm_crtc.h"
@@ -38,6 +39,28 @@
 #define DSI_ENCODER_MASTER	DSI_1
 #define DSI_ENCODER_SLAVE	DSI_0
 
+enum msm_dsi_phy_type {
+	MSM_DSI_PHY_28NM_HPM,
+	MSM_DSI_PHY_28NM_LP,
+	MSM_DSI_PHY_MAX
+};
+
+#define DSI_DEV_REGULATOR_MAX	8
+
+/* Regulators for DSI devices */
+struct dsi_reg_entry {
+	char name[32];
+	int min_voltage;
+	int max_voltage;
+	int enable_load;
+	int disable_load;
+};
+
+struct dsi_reg_config {
+	int num;
+	struct dsi_reg_entry regs[DSI_DEV_REGULATOR_MAX];
+};
+
 struct msm_dsi {
 	struct drm_device *dev;
 	struct platform_device *pdev;
@@ -49,6 +72,8 @@ struct msm_dsi {
 	struct msm_dsi_phy *phy;
 	struct drm_panel *panel;
 	unsigned long panel_flags;
+
+	struct device *phy_dev;
 	bool phy_enabled;
 
 	/* the encoders we are hooked to (outside of dsi block) */
@@ -73,6 +98,29 @@ void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
 /* msm dsi */
 struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi);
 
+/* dsi pll */
+struct msm_dsi_pll;
+#ifdef CONFIG_DRM_MSM_DSI_PLL
+struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
+			enum msm_dsi_phy_type type, int dsi_id);
+void msm_dsi_pll_destroy(struct msm_dsi_pll *pll);
+int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll,
+	struct clk **byte_clk_provider, struct clk **pixel_clk_provider);
+#else
+static inline struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
+			 enum msm_dsi_phy_type type, int id) {
+	return ERR_PTR(-ENODEV);
+}
+static inline void msm_dsi_pll_destroy(struct msm_dsi_pll *pll)
+{
+}
+static inline int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll,
+	struct clk **byte_clk_provider, struct clk **pixel_clk_provider)
+{
+	return -ENODEV;
+}
+#endif
+
 /* dsi host */
 int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host,
 					const struct mipi_dsi_msg *msg);
@@ -94,6 +142,8 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
 					unsigned long *panel_flags);
 int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer);
 void msm_dsi_host_unregister(struct mipi_dsi_host *host);
+int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
+			struct msm_dsi_pll *src_pll);
 void msm_dsi_host_destroy(struct mipi_dsi_host *host);
 int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
 					struct drm_device *dev);
@@ -101,17 +151,14 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi);
 
 /* dsi phy */
 struct msm_dsi_phy;
-enum msm_dsi_phy_type {
-	MSM_DSI_PHY_UNKNOWN,
-	MSM_DSI_PHY_28NM,
-	MSM_DSI_PHY_MAX
-};
-struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev,
-			enum msm_dsi_phy_type type, int id);
+void msm_dsi_phy_driver_register(void);
+void msm_dsi_phy_driver_unregister(void);
 int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel,
 	const unsigned long bit_rate, const unsigned long esc_rate);
 int msm_dsi_phy_disable(struct msm_dsi_phy *phy);
 void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,
 					u32 *clk_pre, u32 *clk_post);
+struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy);
+
 #endif /* __DSI_CONNECTOR_H__ */
 
diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 1dcfae265e98..9791ea04bcbc 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -8,8 +8,17 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /usr2/hali/local/envytools/envytools/rnndb/dsi/dsi.xml             (  18681 bytes, from 2015-03-04 23:08:31)
-- /usr2/hali/local/envytools/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2015-01-28 21:43:22)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)
 
 Copyright (C) 2013-2015 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -394,6 +403,9 @@ static inline uint32_t DSI_CLKOUT_TIMING_CTRL_T_CLK_POST(uint32_t val)
 #define DSI_EOT_PACKET_CTRL_TX_EOT_APPEND			0x00000001
 #define DSI_EOT_PACKET_CTRL_RX_EOT_IGNORE			0x00000010
 
+#define REG_DSI_LANE_CTRL					0x000000a8
+#define DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST			0x10000000
+
 #define REG_DSI_LANE_SWAP_CTRL					0x000000ac
 #define DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL__MASK			0x00000007
 #define DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL__SHIFT			0
@@ -835,5 +847,152 @@ static inline uint32_t DSI_28nm_PHY_TIMING_CTRL_11_TRIG3_CMD(uint32_t val)
 
 #define REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG			0x00000018
 
+#define REG_DSI_28nm_PHY_PLL_REFCLK_CFG				0x00000000
+#define DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR			0x00000001
+
+#define REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG			0x00000004
+
+#define REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG			0x00000008
+
+#define REG_DSI_28nm_PHY_PLL_VCOLPF_CFG				0x0000000c
+
+#define REG_DSI_28nm_PHY_PLL_VREG_CFG				0x00000010
+#define DSI_28nm_PHY_PLL_VREG_CFG_POSTDIV1_BYPASS_B		0x00000002
+
+#define REG_DSI_28nm_PHY_PLL_PWRGEN_CFG				0x00000014
+
+#define REG_DSI_28nm_PHY_PLL_DMUX_CFG				0x00000018
+
+#define REG_DSI_28nm_PHY_PLL_AMUX_CFG				0x0000001c
+
+#define REG_DSI_28nm_PHY_PLL_GLB_CFG				0x00000020
+#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B			0x00000001
+#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B		0x00000002
+#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B		0x00000004
+#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE			0x00000008
+
+#define REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG			0x00000024
+
+#define REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG			0x00000028
+
+#define REG_DSI_28nm_PHY_PLL_LPFR_CFG				0x0000002c
+
+#define REG_DSI_28nm_PHY_PLL_LPFC1_CFG				0x00000030
+
+#define REG_DSI_28nm_PHY_PLL_LPFC2_CFG				0x00000034
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG0				0x00000038
+#define DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__MASK			0x0000003f
+#define DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__SHIFT		0
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(uint32_t val)
+{
+	return ((val) << DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__MASK;
+}
+#define DSI_28nm_PHY_PLL_SDM_CFG0_BYP				0x00000040
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG1				0x0000003c
+#define DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK		0x0000003f
+#define DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__SHIFT		0
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(uint32_t val)
+{
+	return ((val) << DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK;
+}
+#define DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__MASK		0x00000040
+#define DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__SHIFT		6
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN(uint32_t val)
+{
+	return ((val) << DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__MASK;
+}
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG2				0x00000040
+#define DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__MASK		0x000000ff
+#define DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__SHIFT		0
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(uint32_t val)
+{
+	return ((val) << DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__MASK;
+}
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG3				0x00000044
+#define DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8__MASK		0x000000ff
+#define DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8__SHIFT		0
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(uint32_t val)
+{
+	return ((val) << DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8__MASK;
+}
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG4				0x00000048
+
+#define REG_DSI_28nm_PHY_PLL_SSC_CFG0				0x0000004c
+
+#define REG_DSI_28nm_PHY_PLL_SSC_CFG1				0x00000050
+
+#define REG_DSI_28nm_PHY_PLL_SSC_CFG2				0x00000054
+
+#define REG_DSI_28nm_PHY_PLL_SSC_CFG3				0x00000058
+
+#define REG_DSI_28nm_PHY_PLL_LKDET_CFG0				0x0000005c
+
+#define REG_DSI_28nm_PHY_PLL_LKDET_CFG1				0x00000060
+
+#define REG_DSI_28nm_PHY_PLL_LKDET_CFG2				0x00000064
+
+#define REG_DSI_28nm_PHY_PLL_TEST_CFG				0x00000068
+#define DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET			0x00000001
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG0				0x0000006c
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG1				0x00000070
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG2				0x00000074
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG3				0x00000078
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG4				0x0000007c
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG5				0x00000080
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG6				0x00000084
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG7				0x00000088
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG8				0x0000008c
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG9				0x00000090
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG10				0x00000094
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG11				0x00000098
+
+#define REG_DSI_28nm_PHY_PLL_EFUSE_CFG				0x0000009c
+
+#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS_SEL			0x000000a0
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_42				0x000000a4
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_43				0x000000a8
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_44				0x000000ac
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_45				0x000000b0
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_46				0x000000b4
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_47				0x000000b8
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_48				0x000000bc
+
+#define REG_DSI_28nm_PHY_PLL_STATUS				0x000000c0
+#define DSI_28nm_PHY_PLL_STATUS_PLL_RDY				0x00000001
+
+#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS0				0x000000c4
+
+#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS1				0x000000c8
+
+#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS2				0x000000cc
+
+#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS3				0x000000d0
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_54				0x000000d4
+
 
 #endif /* DSI_XML */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 649d20d29f92..de0400923303 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
@@ -36,35 +37,19 @@
 
 #define DSI_6G_REG_SHIFT	4
 
-#define DSI_REGULATOR_MAX	8
-struct dsi_reg_entry {
-	char name[32];
-	int min_voltage;
-	int max_voltage;
-	int enable_load;
-	int disable_load;
-};
-
-struct dsi_reg_config {
-	int num;
-	struct dsi_reg_entry regs[DSI_REGULATOR_MAX];
-};
-
 struct dsi_config {
 	u32 major;
 	u32 minor;
 	u32 io_offset;
-	enum msm_dsi_phy_type phy_type;
 	struct dsi_reg_config reg_cfg;
 };
 
 static const struct dsi_config dsi_cfgs[] = {
-	{MSM_DSI_VER_MAJOR_V2, 0, 0, MSM_DSI_PHY_UNKNOWN},
+	{MSM_DSI_VER_MAJOR_V2, 0, 0, {0,} },
 	{ /* 8974 v1 */
 		.major = MSM_DSI_VER_MAJOR_6G,
 		.minor = MSM_DSI_6G_VER_MINOR_V1_0,
 		.io_offset = DSI_6G_REG_SHIFT,
-		.phy_type = MSM_DSI_PHY_28NM,
 		.reg_cfg = {
 			.num = 4,
 			.regs = {
@@ -79,7 +64,6 @@ static const struct dsi_config dsi_cfgs[] = {
 		.major = MSM_DSI_VER_MAJOR_6G,
 		.minor = MSM_DSI_6G_VER_MINOR_V1_1,
 		.io_offset = DSI_6G_REG_SHIFT,
-		.phy_type = MSM_DSI_PHY_28NM,
 		.reg_cfg = {
 			.num = 4,
 			.regs = {
@@ -94,7 +78,6 @@ static const struct dsi_config dsi_cfgs[] = {
 		.major = MSM_DSI_VER_MAJOR_6G,
 		.minor = MSM_DSI_6G_VER_MINOR_V1_1_1,
 		.io_offset = DSI_6G_REG_SHIFT,
-		.phy_type = MSM_DSI_PHY_28NM,
 		.reg_cfg = {
 			.num = 4,
 			.regs = {
@@ -109,7 +92,6 @@ static const struct dsi_config dsi_cfgs[] = {
 		.major = MSM_DSI_VER_MAJOR_6G,
 		.minor = MSM_DSI_6G_VER_MINOR_V1_2,
 		.io_offset = DSI_6G_REG_SHIFT,
-		.phy_type = MSM_DSI_PHY_28NM,
 		.reg_cfg = {
 			.num = 4,
 			.regs = {
@@ -124,7 +106,6 @@ static const struct dsi_config dsi_cfgs[] = {
 		.major = MSM_DSI_VER_MAJOR_6G,
 		.minor = MSM_DSI_6G_VER_MINOR_V1_3_1,
 		.io_offset = DSI_6G_REG_SHIFT,
-		.phy_type = MSM_DSI_PHY_28NM,
 		.reg_cfg = {
 			.num = 4,
 			.regs = {
@@ -197,7 +178,7 @@ struct msm_dsi_host {
 	int id;
 
 	void __iomem *ctrl_base;
-	struct regulator_bulk_data supplies[DSI_REGULATOR_MAX];
+	struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX];
 	struct clk *mdp_core_clk;
 	struct clk *ahb_clk;
 	struct clk *axi_clk;
@@ -205,6 +186,9 @@ struct msm_dsi_host {
 	struct clk *byte_clk;
 	struct clk *esc_clk;
 	struct clk *pixel_clk;
+	struct clk *byte_clk_src;
+	struct clk *pixel_clk_src;
+
 	u32 byte_clk_rate;
 
 	struct gpio_desc *disp_en_gpio;
@@ -273,7 +257,7 @@ static const struct dsi_config *dsi_get_config(struct msm_dsi_host *msm_host)
 	u32 major = 0, minor = 0;
 
 	gdsc_reg = regulator_get(&msm_host->pdev->dev, "gdsc");
-	if (IS_ERR_OR_NULL(gdsc_reg)) {
+	if (IS_ERR(gdsc_reg)) {
 		pr_err("%s: cannot get gdsc\n", __func__);
 		goto fail;
 	}
@@ -463,6 +447,22 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host)
 		goto exit;
 	}
 
+	msm_host->byte_clk_src = devm_clk_get(dev, "byte_clk_src");
+	if (IS_ERR(msm_host->byte_clk_src)) {
+		ret = PTR_ERR(msm_host->byte_clk_src);
+		pr_err("%s: can't find byte_clk_src. ret=%d\n", __func__, ret);
+		msm_host->byte_clk_src = NULL;
+		goto exit;
+	}
+
+	msm_host->pixel_clk_src = devm_clk_get(dev, "pixel_clk_src");
+	if (IS_ERR(msm_host->pixel_clk_src)) {
+		ret = PTR_ERR(msm_host->pixel_clk_src);
+		pr_err("%s: can't find pixel_clk_src. ret=%d\n", __func__, ret);
+		msm_host->pixel_clk_src = NULL;
+		goto exit;
+	}
+
 exit:
 	return ret;
 }
@@ -787,6 +787,11 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
 		dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
 			DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_0123));
 	}
+
+	if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
+		dsi_write(msm_host, REG_DSI_LANE_CTRL,
+			DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST);
+
 	data |= DSI_CTRL_ENABLE;
 
 	dsi_write(msm_host, REG_DSI_CTRL, data);
@@ -1345,36 +1350,19 @@ static irqreturn_t dsi_host_irq(int irq, void *ptr)
 static int dsi_host_init_panel_gpios(struct msm_dsi_host *msm_host,
 			struct device *panel_device)
 {
-	int ret;
-
-	msm_host->disp_en_gpio = devm_gpiod_get(panel_device,
-						"disp-enable");
+	msm_host->disp_en_gpio = devm_gpiod_get_optional(panel_device,
+							 "disp-enable",
+							 GPIOD_OUT_LOW);
 	if (IS_ERR(msm_host->disp_en_gpio)) {
 		DBG("cannot get disp-enable-gpios %ld",
 				PTR_ERR(msm_host->disp_en_gpio));
-		msm_host->disp_en_gpio = NULL;
-	}
-	if (msm_host->disp_en_gpio) {
-		ret = gpiod_direction_output(msm_host->disp_en_gpio, 0);
-		if (ret) {
-			pr_err("cannot set dir to disp-en-gpios %d\n", ret);
-			return ret;
-		}
+		return PTR_ERR(msm_host->disp_en_gpio);
 	}
 
-	msm_host->te_gpio = devm_gpiod_get(panel_device, "disp-te");
+	msm_host->te_gpio = devm_gpiod_get(panel_device, "disp-te", GPIOD_IN);
 	if (IS_ERR(msm_host->te_gpio)) {
 		DBG("cannot get disp-te-gpios %ld", PTR_ERR(msm_host->te_gpio));
-		msm_host->te_gpio = NULL;
-	}
-
-	if (msm_host->te_gpio) {
-		ret = gpiod_direction_input(msm_host->te_gpio);
-		if (ret) {
-			pr_err("%s: cannot set dir to disp-te-gpios, %d\n",
-				__func__, ret);
-			return ret;
-		}
+		return PTR_ERR(msm_host->te_gpio);
 	}
 
 	return 0;
@@ -1508,13 +1496,6 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
 	msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0);
 	INIT_WORK(&msm_host->err_work, dsi_err_worker);
 
-	msm_dsi->phy = msm_dsi_phy_init(pdev, msm_host->cfg->phy_type,
-					msm_host->id);
-	if (!msm_dsi->phy) {
-		ret = -EINVAL;
-		pr_err("%s: phy init failed\n", __func__);
-		goto fail;
-	}
 	msm_dsi->host = &msm_host->base;
 	msm_dsi->id = msm_host->id;
 
@@ -1824,6 +1805,39 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, u32 iova, u32 len)
 	wmb();
 }
 
+int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
+	struct msm_dsi_pll *src_pll)
+{
+	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+	struct clk *byte_clk_provider, *pixel_clk_provider;
+	int ret;
+
+	ret = msm_dsi_pll_get_clk_provider(src_pll,
+				&byte_clk_provider, &pixel_clk_provider);
+	if (ret) {
+		pr_info("%s: can't get provider from pll, don't set parent\n",
+			__func__);
+		return 0;
+	}
+
+	ret = clk_set_parent(msm_host->byte_clk_src, byte_clk_provider);
+	if (ret) {
+		pr_err("%s: can't set parent to byte_clk_src. ret=%d\n",
+			__func__, ret);
+		goto exit;
+	}
+
+	ret = clk_set_parent(msm_host->pixel_clk_src, pixel_clk_provider);
+	if (ret) {
+		pr_err("%s: can't set parent to pixel_clk_src. ret=%d\n",
+			__func__, ret);
+		goto exit;
+	}
+
+exit:
+	return ret;
+}
+
 int msm_dsi_host_enable(struct mipi_dsi_host *host)
 {
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 0a40f3c64e8b..87ac6612b6f8 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -60,6 +60,53 @@ static int dsi_mgr_parse_dual_panel(struct device_node *np, int id)
 	return 0;
 }
 
+static int dsi_mgr_host_register(int id)
+{
+	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+	struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
+	struct msm_dsi *clk_master_dsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
+	struct msm_dsi_pll *src_pll;
+	int ret;
+
+	if (!IS_DUAL_PANEL()) {
+		ret = msm_dsi_host_register(msm_dsi->host, true);
+		if (ret)
+			return ret;
+
+		src_pll = msm_dsi_phy_get_pll(msm_dsi->phy);
+		ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll);
+	} else if (!other_dsi) {
+		ret = 0;
+	} else {
+		struct msm_dsi *mdsi = IS_MASTER_PANEL(id) ?
+					msm_dsi : other_dsi;
+		struct msm_dsi *sdsi = IS_MASTER_PANEL(id) ?
+					other_dsi : msm_dsi;
+		/* Register slave host first, so that slave DSI device
+		 * has a chance to probe, and do not block the master
+		 * DSI device's probe.
+		 * Also, do not check defer for the slave host,
+		 * because only master DSI device adds the panel to global
+		 * panel list. The panel's device is the master DSI device.
+		 */
+		ret = msm_dsi_host_register(sdsi->host, false);
+		if (ret)
+			return ret;
+		ret = msm_dsi_host_register(mdsi->host, true);
+		if (ret)
+			return ret;
+
+		/* PLL0 is to drive both 2 DSI link clocks in Dual DSI mode. */
+		src_pll = msm_dsi_phy_get_pll(clk_master_dsi->phy);
+		ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll);
+		if (ret)
+			return ret;
+		ret = msm_dsi_host_set_src_pll(other_dsi->host, src_pll);
+	}
+
+	return ret;
+}
+
 struct dsi_connector {
 	struct drm_connector base;
 	int id;
@@ -652,7 +699,6 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
 {
 	struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
 	int id = msm_dsi->id;
-	struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
 	int ret;
 
 	if (id > DSI_MAX) {
@@ -670,31 +716,20 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
 	ret = dsi_mgr_parse_dual_panel(msm_dsi->pdev->dev.of_node, id);
 	if (ret) {
 		pr_err("%s: failed to parse dual panel info\n", __func__);
-		return ret;
+		goto fail;
 	}
 
-	if (!IS_DUAL_PANEL()) {
-		ret = msm_dsi_host_register(msm_dsi->host, true);
-	} else if (!other_dsi) {
-		return 0;
-	} else {
-		struct msm_dsi *mdsi = IS_MASTER_PANEL(id) ?
-					msm_dsi : other_dsi;
-		struct msm_dsi *sdsi = IS_MASTER_PANEL(id) ?
-					other_dsi : msm_dsi;
-		/* Register slave host first, so that slave DSI device
-		 * has a chance to probe, and do not block the master
-		 * DSI device's probe.
-		 * Also, do not check defer for the slave host,
-		 * because only master DSI device adds the panel to global
-		 * panel list. The panel's device is the master DSI device.
-		 */
-		ret = msm_dsi_host_register(sdsi->host, false);
-		if (ret)
-			return ret;
-		ret = msm_dsi_host_register(mdsi->host, true);
+	ret = dsi_mgr_host_register(id);
+	if (ret) {
+		pr_err("%s: failed to register mipi dsi host for DSI %d\n",
+			__func__, id);
+		goto fail;
 	}
 
+	return 0;
+
+fail:
+	msm_dsim->dsi[id] = NULL;
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/msm/dsi/dsi_phy.c b/drivers/gpu/drm/msm/dsi/dsi_phy.c
index f0cea8927388..2d3b33ce1cc5 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_phy.c
@@ -11,12 +11,27 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
 #include "dsi.h"
 #include "dsi.xml.h"
 
 #define dsi_phy_read(offset) msm_readl((offset))
 #define dsi_phy_write(offset, data) msm_writel((data), (offset))
 
+struct dsi_phy_ops {
+	int (*enable)(struct msm_dsi_phy *phy, bool is_dual_panel,
+		const unsigned long bit_rate, const unsigned long esc_rate);
+	int (*disable)(struct msm_dsi_phy *phy);
+};
+
+struct dsi_phy_cfg {
+	enum msm_dsi_phy_type type;
+	struct dsi_reg_config reg_cfg;
+	struct dsi_phy_ops ops;
+};
+
 struct dsi_dphy_timing {
 	u32 clk_pre;
 	u32 clk_post;
@@ -34,15 +49,106 @@ struct dsi_dphy_timing {
 };
 
 struct msm_dsi_phy {
+	struct platform_device *pdev;
 	void __iomem *base;
 	void __iomem *reg_base;
 	int id;
+
+	struct clk *ahb_clk;
+	struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX];
+
 	struct dsi_dphy_timing timing;
-	int (*enable)(struct msm_dsi_phy *phy, bool is_dual_panel,
-		const unsigned long bit_rate, const unsigned long esc_rate);
-	int (*disable)(struct msm_dsi_phy *phy);
+	const struct dsi_phy_cfg *cfg;
+
+	struct msm_dsi_pll *pll;
 };
 
+static int dsi_phy_regulator_init(struct msm_dsi_phy *phy)
+{
+	struct regulator_bulk_data *s = phy->supplies;
+	const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
+	struct device *dev = &phy->pdev->dev;
+	int num = phy->cfg->reg_cfg.num;
+	int i, ret;
+
+	for (i = 0; i < num; i++)
+		s[i].supply = regs[i].name;
+
+	ret = devm_regulator_bulk_get(&phy->pdev->dev, num, s);
+	if (ret < 0) {
+		dev_err(dev, "%s: failed to init regulator, ret=%d\n",
+						__func__, ret);
+		return ret;
+	}
+
+	for (i = 0; i < num; i++) {
+		if ((regs[i].min_voltage >= 0) && (regs[i].max_voltage >= 0)) {
+			ret = regulator_set_voltage(s[i].consumer,
+				regs[i].min_voltage, regs[i].max_voltage);
+			if (ret < 0) {
+				dev_err(dev,
+					"regulator %d set voltage failed, %d\n",
+					i, ret);
+				return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void dsi_phy_regulator_disable(struct msm_dsi_phy *phy)
+{
+	struct regulator_bulk_data *s = phy->supplies;
+	const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
+	int num = phy->cfg->reg_cfg.num;
+	int i;
+
+	DBG("");
+	for (i = num - 1; i >= 0; i--)
+		if (regs[i].disable_load >= 0)
+			regulator_set_load(s[i].consumer,
+						regs[i].disable_load);
+
+	regulator_bulk_disable(num, s);
+}
+
+static int dsi_phy_regulator_enable(struct msm_dsi_phy *phy)
+{
+	struct regulator_bulk_data *s = phy->supplies;
+	const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
+	struct device *dev = &phy->pdev->dev;
+	int num = phy->cfg->reg_cfg.num;
+	int ret, i;
+
+	DBG("");
+	for (i = 0; i < num; i++) {
+		if (regs[i].enable_load >= 0) {
+			ret = regulator_set_load(s[i].consumer,
+							regs[i].enable_load);
+			if (ret < 0) {
+				dev_err(dev,
+					"regulator %d set op mode failed, %d\n",
+					i, ret);
+				goto fail;
+			}
+		}
+	}
+
+	ret = regulator_bulk_enable(num, s);
+	if (ret < 0) {
+		dev_err(dev, "regulator enable failed, %d\n", ret);
+		goto fail;
+	}
+
+	return 0;
+
+fail:
+	for (i--; i >= 0; i--)
+		regulator_set_load(s[i].consumer, regs[i].disable_load);
+	return ret;
+}
+
 #define S_DIV_ROUND_UP(n, d)	\
 	(((n) >= 0) ? (((n) + (d) - 1) / (d)) : (((n) - (d) + 1) / (d)))
 
@@ -284,59 +390,200 @@ static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
 	return 0;
 }
 
-#define dsi_phy_func_init(name)	\
-	do {	\
-		phy->enable = dsi_##name##_phy_enable;	\
-		phy->disable = dsi_##name##_phy_disable;	\
-	} while (0)
+static int dsi_phy_enable_resource(struct msm_dsi_phy *phy)
+{
+	int ret;
+
+	pm_runtime_get_sync(&phy->pdev->dev);
 
-struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev,
-			enum msm_dsi_phy_type type, int id)
+	ret = clk_prepare_enable(phy->ahb_clk);
+	if (ret) {
+		pr_err("%s: can't enable ahb clk, %d\n", __func__, ret);
+		pm_runtime_put_sync(&phy->pdev->dev);
+	}
+
+	return ret;
+}
+
+static void dsi_phy_disable_resource(struct msm_dsi_phy *phy)
+{
+	clk_disable_unprepare(phy->ahb_clk);
+	pm_runtime_put_sync(&phy->pdev->dev);
+}
+
+static const struct dsi_phy_cfg dsi_phy_cfgs[MSM_DSI_PHY_MAX] = {
+	[MSM_DSI_PHY_28NM_HPM] = {
+		.type = MSM_DSI_PHY_28NM_HPM,
+		.reg_cfg = {
+			.num = 1,
+			.regs = {
+				{"vddio", 1800000, 1800000, 100000, 100},
+			},
+		},
+		.ops = {
+			.enable = dsi_28nm_phy_enable,
+			.disable = dsi_28nm_phy_disable,
+		}
+	},
+	[MSM_DSI_PHY_28NM_LP] = {
+		.type = MSM_DSI_PHY_28NM_LP,
+		.reg_cfg = {
+			.num = 1,
+			.regs = {
+				{"vddio", 1800000, 1800000, 100000, 100},
+			},
+		},
+		.ops = {
+			.enable = dsi_28nm_phy_enable,
+			.disable = dsi_28nm_phy_disable,
+		}
+	},
+};
+
+static const struct of_device_id dsi_phy_dt_match[] = {
+	{ .compatible = "qcom,dsi-phy-28nm-hpm",
+	  .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_HPM],},
+	{ .compatible = "qcom,dsi-phy-28nm-lp",
+	  .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_LP],},
+	{}
+};
+
+static int dsi_phy_driver_probe(struct platform_device *pdev)
 {
 	struct msm_dsi_phy *phy;
+	const struct of_device_id *match;
+	int ret;
 
 	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
 	if (!phy)
-		return NULL;
+		return -ENOMEM;
+
+	match = of_match_node(dsi_phy_dt_match, pdev->dev.of_node);
+	if (!match)
+		return -ENODEV;
+
+	phy->cfg = match->data;
+	phy->pdev = pdev;
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+				"qcom,dsi-phy-index", &phy->id);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"%s: PHY index not specified, ret=%d\n",
+			__func__, ret);
+		goto fail;
+	}
 
 	phy->base = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");
-	if (IS_ERR_OR_NULL(phy->base)) {
-		pr_err("%s: failed to map phy base\n", __func__);
-		return NULL;
+	if (IS_ERR(phy->base)) {
+		dev_err(&pdev->dev, "%s: failed to map phy base\n", __func__);
+		ret = -ENOMEM;
+		goto fail;
 	}
 	phy->reg_base = msm_ioremap(pdev, "dsi_phy_regulator", "DSI_PHY_REG");
-	if (IS_ERR_OR_NULL(phy->reg_base)) {
-		pr_err("%s: failed to map phy regulator base\n", __func__);
-		return NULL;
+	if (IS_ERR(phy->reg_base)) {
+		dev_err(&pdev->dev,
+			"%s: failed to map phy regulator base\n", __func__);
+		ret = -ENOMEM;
+		goto fail;
 	}
 
-	switch (type) {
-	case MSM_DSI_PHY_28NM:
-		dsi_phy_func_init(28nm);
-		break;
-	default:
-		pr_err("%s: unsupported type, %d\n", __func__, type);
-		return NULL;
+	ret = dsi_phy_regulator_init(phy);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: failed to init regulator\n", __func__);
+		goto fail;
+	}
+
+	phy->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
+	if (IS_ERR(phy->ahb_clk)) {
+		pr_err("%s: Unable to get ahb clk\n", __func__);
+		ret = PTR_ERR(phy->ahb_clk);
+		goto fail;
 	}
 
-	phy->id = id;
+	/* PLL init will call into clk_register which requires
+	 * register access, so we need to enable power and ahb clock.
+	 */
+	ret = dsi_phy_enable_resource(phy);
+	if (ret)
+		goto fail;
+
+	phy->pll = msm_dsi_pll_init(pdev, phy->cfg->type, phy->id);
+	if (!phy->pll)
+		dev_info(&pdev->dev,
+			"%s: pll init failed, need separate pll clk driver\n",
+			__func__);
+
+	dsi_phy_disable_resource(phy);
+
+	platform_set_drvdata(pdev, phy);
+
+	return 0;
 
-	return phy;
+fail:
+	return ret;
+}
+
+static int dsi_phy_driver_remove(struct platform_device *pdev)
+{
+	struct msm_dsi_phy *phy = platform_get_drvdata(pdev);
+
+	if (phy && phy->pll) {
+		msm_dsi_pll_destroy(phy->pll);
+		phy->pll = NULL;
+	}
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver dsi_phy_platform_driver = {
+	.probe      = dsi_phy_driver_probe,
+	.remove     = dsi_phy_driver_remove,
+	.driver     = {
+		.name   = "msm_dsi_phy",
+		.of_match_table = dsi_phy_dt_match,
+	},
+};
+
+void __init msm_dsi_phy_driver_register(void)
+{
+	platform_driver_register(&dsi_phy_platform_driver);
+}
+
+void __exit msm_dsi_phy_driver_unregister(void)
+{
+	platform_driver_unregister(&dsi_phy_platform_driver);
 }
 
 int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel,
 	const unsigned long bit_rate, const unsigned long esc_rate)
 {
-	if (!phy || !phy->enable)
+	int ret;
+
+	if (!phy || !phy->cfg->ops.enable)
 		return -EINVAL;
-	return phy->enable(phy, is_dual_panel, bit_rate, esc_rate);
+
+	ret = dsi_phy_regulator_enable(phy);
+	if (ret) {
+		dev_err(&phy->pdev->dev, "%s: regulator enable failed, %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	return phy->cfg->ops.enable(phy, is_dual_panel, bit_rate, esc_rate);
 }
 
 int msm_dsi_phy_disable(struct msm_dsi_phy *phy)
 {
-	if (!phy || !phy->disable)
+	if (!phy || !phy->cfg->ops.disable)
 		return -EINVAL;
-	return phy->disable(phy);
+
+	phy->cfg->ops.disable(phy);
+	dsi_phy_regulator_disable(phy);
+
+	return 0;
 }
 
 void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,
@@ -350,3 +597,11 @@ void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,
 		*clk_post = phy->timing.clk_post;
 }
 
+struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy)
+{
+	if (!phy)
+		return NULL;
+
+	return phy->pll;
+}
+
diff --git a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
index 695f99d4bec2..728152f3ef48 100644
--- a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
+++ b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
@@ -10,15 +10,15 @@ git clone https://github.com/freedreno/envytools.git
 The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)
 
 Copyright (C) 2013-2014 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
new file mode 100644
index 000000000000..509376fdd112
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "dsi_pll.h"
+
+static int dsi_pll_enable(struct msm_dsi_pll *pll)
+{
+	int i, ret = 0;
+
+	/*
+	 * Certain PLLs do not allow VCO rate update when it is on.
+	 * Keep track of their status to turn on/off after set rate success.
+	 */
+	if (unlikely(pll->pll_on))
+		return 0;
+
+	/* Try all enable sequences until one succeeds */
+	for (i = 0; i < pll->en_seq_cnt; i++) {
+		ret = pll->enable_seqs[i](pll);
+		DBG("DSI PLL %s after sequence #%d",
+			ret ? "unlocked" : "locked", i + 1);
+		if (!ret)
+			break;
+	}
+
+	if (ret) {
+		DRM_ERROR("DSI PLL failed to lock\n");
+		return ret;
+	}
+
+	pll->pll_on = true;
+
+	return 0;
+}
+
+static void dsi_pll_disable(struct msm_dsi_pll *pll)
+{
+	if (unlikely(!pll->pll_on))
+		return;
+
+	pll->disable_seq(pll);
+
+	pll->pll_on = false;
+}
+
+/*
+ * DSI PLL Helper functions
+ */
+long msm_dsi_pll_helper_clk_round_rate(struct clk_hw *hw,
+		unsigned long rate, unsigned long *parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+
+	if      (rate < pll->min_rate)
+		return  pll->min_rate;
+	else if (rate > pll->max_rate)
+		return  pll->max_rate;
+	else
+		return rate;
+}
+
+int msm_dsi_pll_helper_clk_prepare(struct clk_hw *hw)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	int ret;
+
+	/*
+	 * Certain PLLs need to update the same VCO rate and registers
+	 * after resume in suspend/resume scenario.
+	 */
+	if (pll->restore_state) {
+		ret = pll->restore_state(pll);
+		if (ret)
+			goto error;
+	}
+
+	ret = dsi_pll_enable(pll);
+
+error:
+	return ret;
+}
+
+void msm_dsi_pll_helper_clk_unprepare(struct clk_hw *hw)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+
+	if (pll->save_state)
+		pll->save_state(pll);
+
+	dsi_pll_disable(pll);
+}
+
+void msm_dsi_pll_helper_unregister_clks(struct platform_device *pdev,
+					struct clk **clks, u32 num_clks)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+
+	if (!num_clks || !clks)
+		return;
+
+	do {
+		clk_unregister(clks[--num_clks]);
+		clks[num_clks] = NULL;
+	} while (num_clks);
+}
+
+/*
+ * DSI PLL API
+ */
+int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll,
+	struct clk **byte_clk_provider, struct clk **pixel_clk_provider)
+{
+	if (pll->get_provider)
+		return pll->get_provider(pll,
+					byte_clk_provider,
+					pixel_clk_provider);
+
+	return -EINVAL;
+}
+
+void msm_dsi_pll_destroy(struct msm_dsi_pll *pll)
+{
+	if (pll->destroy)
+		pll->destroy(pll);
+}
+
+struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
+			enum msm_dsi_phy_type type, int id)
+{
+	struct device *dev = &pdev->dev;
+	struct msm_dsi_pll *pll;
+
+	switch (type) {
+	case MSM_DSI_PHY_28NM_HPM:
+	case MSM_DSI_PHY_28NM_LP:
+		pll = msm_dsi_pll_28nm_init(pdev, type, id);
+		break;
+	default:
+		pll = ERR_PTR(-ENXIO);
+		break;
+	}
+
+	if (IS_ERR(pll)) {
+		dev_err(dev, "%s: failed to init DSI PLL\n", __func__);
+		return NULL;
+	}
+
+	pll->type = type;
+
+	DBG("DSI:%d PLL registered", id);
+
+	return pll;
+}
+
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
new file mode 100644
index 000000000000..5a3bb241c039
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DSI_PLL_H__
+#define __DSI_PLL_H__
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#include "dsi.h"
+
+#define NUM_DSI_CLOCKS_MAX	6
+#define MAX_DSI_PLL_EN_SEQS	10
+
+struct msm_dsi_pll {
+	enum msm_dsi_phy_type type;
+
+	struct clk_hw	clk_hw;
+	bool		pll_on;
+
+	unsigned long	min_rate;
+	unsigned long	max_rate;
+	u32		en_seq_cnt;
+
+	int (*enable_seqs[MAX_DSI_PLL_EN_SEQS])(struct msm_dsi_pll *pll);
+	void (*disable_seq)(struct msm_dsi_pll *pll);
+	int (*get_provider)(struct msm_dsi_pll *pll,
+			struct clk **byte_clk_provider,
+			struct clk **pixel_clk_provider);
+	void (*destroy)(struct msm_dsi_pll *pll);
+	void (*save_state)(struct msm_dsi_pll *pll);
+	int (*restore_state)(struct msm_dsi_pll *pll);
+};
+
+#define hw_clk_to_pll(x) container_of(x, struct msm_dsi_pll, clk_hw)
+
+static inline void pll_write(void __iomem *reg, u32 data)
+{
+	msm_writel(data, reg);
+}
+
+static inline u32 pll_read(const void __iomem *reg)
+{
+	return msm_readl(reg);
+}
+
+static inline void pll_write_udelay(void __iomem *reg, u32 data, u32 delay_us)
+{
+	pll_write(reg, data);
+	udelay(delay_us);
+}
+
+static inline void pll_write_ndelay(void __iomem *reg, u32 data, u32 delay_ns)
+{
+	pll_write((reg), data);
+	ndelay(delay_ns);
+}
+
+/*
+ * DSI PLL Helper functions
+ */
+
+/* clock callbacks */
+long msm_dsi_pll_helper_clk_round_rate(struct clk_hw *hw,
+		unsigned long rate, unsigned long *parent_rate);
+int msm_dsi_pll_helper_clk_prepare(struct clk_hw *hw);
+void msm_dsi_pll_helper_clk_unprepare(struct clk_hw *hw);
+/* misc */
+void msm_dsi_pll_helper_unregister_clks(struct platform_device *pdev,
+					struct clk **clks, u32 num_clks);
+
+/*
+ * Initialization for Each PLL Type
+ */
+struct msm_dsi_pll *msm_dsi_pll_28nm_init(struct platform_device *pdev,
+					enum msm_dsi_phy_type type, int id);
+
+#endif /* __DSI_PLL_H__ */
+
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
new file mode 100644
index 000000000000..eb8ac3097ff5
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
@@ -0,0 +1,652 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#include "dsi_pll.h"
+#include "dsi.xml.h"
+
+/*
+ * DSI PLL 28nm - clock diagram (eg: DSI0):
+ *
+ *         dsi0analog_postdiv_clk
+ *                             |         dsi0indirect_path_div2_clk
+ *                             |          |
+ *                   +------+  |  +----+  |  |\   dsi0byte_mux
+ *  dsi0vco_clk --o--| DIV1 |--o--| /2 |--o--| \   |
+ *                |  +------+     +----+     | m|  |  +----+
+ *                |                          | u|--o--| /4 |-- dsi0pllbyte
+ *                |                          | x|     +----+
+ *                o--------------------------| /
+ *                |                          |/
+ *                |          +------+
+ *                o----------| DIV3 |------------------------- dsi0pll
+ *                           +------+
+ */
+
+#define POLL_MAX_READS			10
+#define POLL_TIMEOUT_US		50
+
+#define NUM_PROVIDED_CLKS		2
+
+#define VCO_REF_CLK_RATE		19200000
+#define VCO_MIN_RATE			350000000
+#define VCO_MAX_RATE			750000000
+
+#define DSI_BYTE_PLL_CLK		0
+#define DSI_PIXEL_PLL_CLK		1
+
+#define LPFR_LUT_SIZE			10
+struct lpfr_cfg {
+	unsigned long vco_rate;
+	u32 resistance;
+};
+
+/* Loop filter resistance: */
+static const struct lpfr_cfg lpfr_lut[LPFR_LUT_SIZE] = {
+	{ 479500000,  8 },
+	{ 480000000, 11 },
+	{ 575500000,  8 },
+	{ 576000000, 12 },
+	{ 610500000,  8 },
+	{ 659500000,  9 },
+	{ 671500000, 10 },
+	{ 672000000, 14 },
+	{ 708500000, 10 },
+	{ 750000000, 11 },
+};
+
+struct pll_28nm_cached_state {
+	unsigned long vco_rate;
+	u8 postdiv3;
+	u8 postdiv1;
+	u8 byte_mux;
+};
+
+struct dsi_pll_28nm {
+	struct msm_dsi_pll base;
+
+	int id;
+	struct platform_device *pdev;
+	void __iomem *mmio;
+
+	int vco_delay;
+
+	/* private clocks: */
+	struct clk *clks[NUM_DSI_CLOCKS_MAX];
+	u32 num_clks;
+
+	/* clock-provider: */
+	struct clk *provided_clks[NUM_PROVIDED_CLKS];
+	struct clk_onecell_data clk_data;
+
+	struct pll_28nm_cached_state cached_state;
+};
+
+#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, base)
+
+static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,
+				u32 nb_tries, u32 timeout_us)
+{
+	bool pll_locked = false;
+	u32 val;
+
+	while (nb_tries--) {
+		val = pll_read(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_STATUS);
+		pll_locked = !!(val & DSI_28nm_PHY_PLL_STATUS_PLL_RDY);
+
+		if (pll_locked)
+			break;
+
+		udelay(timeout_us);
+	}
+	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");
+
+	return pll_locked;
+}
+
+static void pll_28nm_software_reset(struct dsi_pll_28nm *pll_28nm)
+{
+	void __iomem *base = pll_28nm->mmio;
+
+	/*
+	 * Add HW recommended delays after toggling the software
+	 * reset bit off and back on.
+	 */
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG,
+			DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET, 1);
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG, 0x00, 1);
+}
+
+/*
+ * Clock Callbacks
+ */
+static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct device *dev = &pll_28nm->pdev->dev;
+	void __iomem *base = pll_28nm->mmio;
+	unsigned long div_fbx1000, gen_vco_clk;
+	u32 refclk_cfg, frac_n_mode, frac_n_value;
+	u32 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3;
+	u32 cal_cfg10, cal_cfg11;
+	u32 rem;
+	int i;
+
+	VERB("rate=%lu, parent's=%lu", rate, parent_rate);
+
+	/* Force postdiv2 to be div-4 */
+	pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG, 3);
+
+	/* Configure the Loop filter resistance */
+	for (i = 0; i < LPFR_LUT_SIZE; i++)
+		if (rate <= lpfr_lut[i].vco_rate)
+			break;
+	if (i == LPFR_LUT_SIZE) {
+		dev_err(dev, "unable to get loop filter resistance. vco=%lu\n",
+				rate);
+		return -EINVAL;
+	}
+	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFR_CFG, lpfr_lut[i].resistance);
+
+	/* Loop filter capacitance values : c1 and c2 */
+	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC1_CFG, 0x70);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC2_CFG, 0x15);
+
+	rem = rate % VCO_REF_CLK_RATE;
+	if (rem) {
+		refclk_cfg = DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;
+		frac_n_mode = 1;
+		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 500);
+		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 500);
+	} else {
+		refclk_cfg = 0x0;
+		frac_n_mode = 0;
+		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 1000);
+		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 1000);
+	}
+
+	DBG("refclk_cfg = %d", refclk_cfg);
+
+	rem = div_fbx1000 % 1000;
+	frac_n_value = (rem << 16) / 1000;
+
+	DBG("div_fb = %lu", div_fbx1000);
+	DBG("frac_n_value = %d", frac_n_value);
+
+	DBG("Generated VCO Clock: %lu", gen_vco_clk);
+	rem = 0;
+	sdm_cfg1 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1);
+	sdm_cfg1 &= ~DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK;
+	if (frac_n_mode) {
+		sdm_cfg0 = 0x0;
+		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(0);
+		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(
+				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1));
+		sdm_cfg3 = frac_n_value >> 8;
+		sdm_cfg2 = frac_n_value & 0xff;
+	} else {
+		sdm_cfg0 = DSI_28nm_PHY_PLL_SDM_CFG0_BYP;
+		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(
+				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1));
+		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(0);
+		sdm_cfg2 = 0;
+		sdm_cfg3 = 0;
+	}
+
+	DBG("sdm_cfg0=%d", sdm_cfg0);
+	DBG("sdm_cfg1=%d", sdm_cfg1);
+	DBG("sdm_cfg2=%d", sdm_cfg2);
+	DBG("sdm_cfg3=%d", sdm_cfg3);
+
+	cal_cfg11 = (u32)(gen_vco_clk / (256 * 1000000));
+	cal_cfg10 = (u32)((gen_vco_clk % (256 * 1000000)) / 1000000);
+	DBG("cal_cfg10=%d, cal_cfg11=%d", cal_cfg10, cal_cfg11);
+
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG, 0x02);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG3,    0x2b);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG4,    0x06);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,  0x0d);
+
+	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1, sdm_cfg1);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2,
+		DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(sdm_cfg2));
+	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3,
+		DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(sdm_cfg3));
+	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG4, 0x00);
+
+	/* Add hardware recommended delay for correct PLL configuration */
+	if (pll_28nm->vco_delay)
+		udelay(pll_28nm->vco_delay);
+
+	pll_write(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG, refclk_cfg);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG, 0x00);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_VCOLPF_CFG, 0x31);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0,   sdm_cfg0);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG0,   0x12);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG6,   0x30);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG7,   0x00);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG8,   0x60);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG9,   0x00);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG10,  cal_cfg10 & 0xff);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG11,  cal_cfg11 & 0xff);
+	pll_write(base + REG_DSI_28nm_PHY_PLL_EFUSE_CFG,  0x20);
+
+	return 0;
+}
+
+static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+	return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,
+					POLL_TIMEOUT_US);
+}
+
+static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	void __iomem *base = pll_28nm->mmio;
+	u32 sdm0, doubler, sdm_byp_div;
+	u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3;
+	u32 ref_clk = VCO_REF_CLK_RATE;
+	unsigned long vco_rate;
+
+	VERB("parent_rate=%lu", parent_rate);
+
+	/* Check to see if the ref clk doubler is enabled */
+	doubler = pll_read(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG) &
+			DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;
+	ref_clk += (doubler * VCO_REF_CLK_RATE);
+
+	/* see if it is integer mode or sdm mode */
+	sdm0 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0);
+	if (sdm0 & DSI_28nm_PHY_PLL_SDM_CFG0_BYP) {
+		/* integer mode */
+		sdm_byp_div = FIELD(
+				pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0),
+				DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV) + 1;
+		vco_rate = ref_clk * sdm_byp_div;
+	} else {
+		/* sdm mode */
+		sdm_dc_off = FIELD(
+				pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1),
+				DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET);
+		DBG("sdm_dc_off = %d", sdm_dc_off);
+		sdm2 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2),
+				DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0);
+		sdm3 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3),
+				DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8);
+		sdm_freq_seed = (sdm3 << 8) | sdm2;
+		DBG("sdm_freq_seed = %d", sdm_freq_seed);
+
+		vco_rate = (ref_clk * (sdm_dc_off + 1)) +
+			mult_frac(ref_clk, sdm_freq_seed, BIT(16));
+		DBG("vco rate = %lu", vco_rate);
+	}
+
+	DBG("returning vco rate = %lu", vco_rate);
+
+	return vco_rate;
+}
+
+static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {
+	.round_rate = msm_dsi_pll_helper_clk_round_rate,
+	.set_rate = dsi_pll_28nm_clk_set_rate,
+	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,
+	.prepare = msm_dsi_pll_helper_clk_prepare,
+	.unprepare = msm_dsi_pll_helper_clk_unprepare,
+	.is_enabled = dsi_pll_28nm_clk_is_enabled,
+};
+
+/*
+ * PLL Callbacks
+ */
+static int dsi_pll_28nm_enable_seq_hpm(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct device *dev = &pll_28nm->pdev->dev;
+	void __iomem *base = pll_28nm->mmio;
+	u32 max_reads = 5, timeout_us = 100;
+	bool locked;
+	u32 val;
+	int i;
+
+	DBG("id=%d", pll_28nm->id);
+
+	pll_28nm_software_reset(pll_28nm);
+
+	/*
+	 * PLL power up sequence.
+	 * Add necessary delays recommended by hardware.
+	 */
+	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);
+
+	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+
+	for (i = 0; i < 2; i++) {
+		/* DSI Uniphy lock detect setting */
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,
+				0x0c, 100);
+		pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
+
+		/* poll for PLL ready status */
+		locked = pll_28nm_poll_for_ready(pll_28nm,
+						max_reads, timeout_us);
+		if (locked)
+			break;
+
+		pll_28nm_software_reset(pll_28nm);
+
+		/*
+		 * PLL power up sequence.
+		 * Add necessary delays recommended by hardware.
+		 */
+		val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);
+
+		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 250);
+
+		val &= ~DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
+		pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+	}
+
+	if (unlikely(!locked))
+		dev_err(dev, "DSI PLL lock failed\n");
+	else
+		DBG("DSI PLL Lock success");
+
+	return locked ? 0 : -EINVAL;
+}
+
+static int dsi_pll_28nm_enable_seq_lp(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct device *dev = &pll_28nm->pdev->dev;
+	void __iomem *base = pll_28nm->mmio;
+	bool locked;
+	u32 max_reads = 10, timeout_us = 50;
+	u32 val;
+
+	DBG("id=%d", pll_28nm->id);
+
+	pll_28nm_software_reset(pll_28nm);
+
+	/*
+	 * PLL power up sequence.
+	 * Add necessary delays recommended by hardware.
+	 */
+	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_CAL_CFG1, 0x34, 500);
+
+	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
+	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
+	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B |
+		DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
+	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+	/* DSI PLL toggle lock detect setting */
+	pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x04, 500);
+	pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x05, 512);
+
+	locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);
+
+	if (unlikely(!locked))
+		dev_err(dev, "DSI PLL lock failed\n");
+	else
+		DBG("DSI PLL lock success");
+
+	return locked ? 0 : -EINVAL;
+}
+
+static void dsi_pll_28nm_disable_seq(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+	DBG("id=%d", pll_28nm->id);
+	pll_write(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_GLB_CFG, 0x00);
+}
+
+static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
+	void __iomem *base = pll_28nm->mmio;
+
+	cached_state->postdiv3 =
+			pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG);
+	cached_state->postdiv1 =
+			pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);
+	cached_state->byte_mux = pll_read(base + REG_DSI_28nm_PHY_PLL_VREG_CFG);
+	cached_state->vco_rate = __clk_get_rate(pll->clk_hw.clk);
+}
+
+static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
+	void __iomem *base = pll_28nm->mmio;
+	int ret;
+
+	if ((cached_state->vco_rate != 0) &&
+		(cached_state->vco_rate == __clk_get_rate(pll->clk_hw.clk))) {
+		ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,
+						cached_state->vco_rate, 0);
+		if (ret) {
+			dev_err(&pll_28nm->pdev->dev,
+				"restore vco rate failed. ret=%d\n", ret);
+			return ret;
+		}
+
+		pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,
+				cached_state->postdiv3);
+		pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,
+				cached_state->postdiv1);
+		pll_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG,
+				cached_state->byte_mux);
+
+		cached_state->vco_rate = 0;
+	}
+
+	return 0;
+}
+
+static int dsi_pll_28nm_get_provider(struct msm_dsi_pll *pll,
+				struct clk **byte_clk_provider,
+				struct clk **pixel_clk_provider)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+	if (byte_clk_provider)
+		*byte_clk_provider = pll_28nm->provided_clks[DSI_BYTE_PLL_CLK];
+	if (pixel_clk_provider)
+		*pixel_clk_provider =
+				pll_28nm->provided_clks[DSI_PIXEL_PLL_CLK];
+
+	return 0;
+}
+
+static void dsi_pll_28nm_destroy(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	int i;
+
+	msm_dsi_pll_helper_unregister_clks(pll_28nm->pdev,
+					pll_28nm->clks, pll_28nm->num_clks);
+
+	for (i = 0; i < NUM_PROVIDED_CLKS; i++)
+		pll_28nm->provided_clks[i] = NULL;
+
+	pll_28nm->num_clks = 0;
+	pll_28nm->clk_data.clks = NULL;
+	pll_28nm->clk_data.clk_num = 0;
+}
+
+static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)
+{
+	char clk_name[32], parent1[32], parent2[32], vco_name[32];
+	struct clk_init_data vco_init = {
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.name = vco_name,
+		.ops = &clk_ops_dsi_pll_28nm_vco,
+	};
+	struct device *dev = &pll_28nm->pdev->dev;
+	struct clk **clks = pll_28nm->clks;
+	struct clk **provided_clks = pll_28nm->provided_clks;
+	int num = 0;
+	int ret;
+
+	DBG("%d", pll_28nm->id);
+
+	snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->id);
+	pll_28nm->base.clk_hw.init = &vco_init;
+	clks[num++] = clk_register(dev, &pll_28nm->base.clk_hw);
+
+	snprintf(clk_name, 32, "dsi%danalog_postdiv_clk", pll_28nm->id);
+	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
+	clks[num++] = clk_register_divider(dev, clk_name,
+			parent1, CLK_SET_RATE_PARENT,
+			pll_28nm->mmio +
+			REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,
+			0, 4, 0, NULL);
+
+	snprintf(clk_name, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);
+	snprintf(parent1, 32, "dsi%danalog_postdiv_clk", pll_28nm->id);
+	clks[num++] = clk_register_fixed_factor(dev, clk_name,
+			parent1, CLK_SET_RATE_PARENT,
+			1, 2);
+
+	snprintf(clk_name, 32, "dsi%dpll", pll_28nm->id);
+	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
+	clks[num++] = provided_clks[DSI_PIXEL_PLL_CLK] =
+			clk_register_divider(dev, clk_name,
+				parent1, 0, pll_28nm->mmio +
+				REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,
+				0, 8, 0, NULL);
+
+	snprintf(clk_name, 32, "dsi%dbyte_mux", pll_28nm->id);
+	snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
+	snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);
+	clks[num++] = clk_register_mux(dev, clk_name,
+			(const char *[]){
+				parent1, parent2
+			}, 2, CLK_SET_RATE_PARENT, pll_28nm->mmio +
+			REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL);
+
+	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
+	snprintf(parent1, 32, "dsi%dbyte_mux", pll_28nm->id);
+	clks[num++] = provided_clks[DSI_BYTE_PLL_CLK] =
+			clk_register_fixed_factor(dev, clk_name,
+				parent1, CLK_SET_RATE_PARENT, 1, 4);
+
+	pll_28nm->num_clks = num;
+
+	pll_28nm->clk_data.clk_num = NUM_PROVIDED_CLKS;
+	pll_28nm->clk_data.clks = provided_clks;
+
+	ret = of_clk_add_provider(dev->of_node,
+			of_clk_src_onecell_get, &pll_28nm->clk_data);
+	if (ret) {
+		dev_err(dev, "failed to register clk provider: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+struct msm_dsi_pll *msm_dsi_pll_28nm_init(struct platform_device *pdev,
+					enum msm_dsi_phy_type type, int id)
+{
+	struct dsi_pll_28nm *pll_28nm;
+	struct msm_dsi_pll *pll;
+	int ret;
+
+	if (!pdev)
+		return ERR_PTR(-ENODEV);
+
+	pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);
+	if (!pll_28nm)
+		return ERR_PTR(-ENOMEM);
+
+	pll_28nm->pdev = pdev;
+	pll_28nm->id = id;
+
+	pll_28nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
+	if (IS_ERR_OR_NULL(pll_28nm->mmio)) {
+		dev_err(&pdev->dev, "%s: failed to map pll base\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pll = &pll_28nm->base;
+	pll->min_rate = VCO_MIN_RATE;
+	pll->max_rate = VCO_MAX_RATE;
+	pll->get_provider = dsi_pll_28nm_get_provider;
+	pll->destroy = dsi_pll_28nm_destroy;
+	pll->disable_seq = dsi_pll_28nm_disable_seq;
+	pll->save_state = dsi_pll_28nm_save_state;
+	pll->restore_state = dsi_pll_28nm_restore_state;
+
+	if (type == MSM_DSI_PHY_28NM_HPM) {
+		pll_28nm->vco_delay = 1;
+
+		pll->en_seq_cnt = 3;
+		pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_hpm;
+		pll->enable_seqs[1] = dsi_pll_28nm_enable_seq_hpm;
+		pll->enable_seqs[2] = dsi_pll_28nm_enable_seq_hpm;
+	} else if (type == MSM_DSI_PHY_28NM_LP) {
+		pll_28nm->vco_delay = 1000;
+
+		pll->en_seq_cnt = 1;
+		pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_lp;
+	} else {
+		dev_err(&pdev->dev, "phy type (%d) is not 28nm\n", type);
+		return ERR_PTR(-EINVAL);
+	}
+
+	ret = pll_28nm_register(pll_28nm);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register PLL: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	return pll;
+}
+
diff --git a/drivers/gpu/drm/msm/dsi/sfpb.xml.h b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
index 50ff9851d73d..26f268e2dd3d 100644
--- a/drivers/gpu/drm/msm/dsi/sfpb.xml.h
+++ b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
@@ -10,15 +10,15 @@ git clone https://github.com/freedreno/envytools.git
 The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/edp/edp.xml.h b/drivers/gpu/drm/msm/edp/edp.xml.h
index a29f1df15143..f9c71dceb5e2 100644
--- a/drivers/gpu/drm/msm/edp/edp.xml.h
+++ b/drivers/gpu/drm/msm/edp/edp.xml.h
@@ -10,17 +10,17 @@ git clone https://github.com/freedreno/envytools.git
 The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)
 
-Copyright (C) 2013-2014 by the following authors:
+Copyright (C) 2013-2015 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -288,5 +288,92 @@ static inline uint32_t REG_EDP_PHY_LN_PD_CTL(uint32_t i0) { return 0x00000404 +
 
 #define REG_EDP_PHY_GLB_PHY_STATUS				0x00000598
 
+#define REG_EDP_28nm_PHY_PLL_REFCLK_CFG				0x00000000
+
+#define REG_EDP_28nm_PHY_PLL_POSTDIV1_CFG			0x00000004
+
+#define REG_EDP_28nm_PHY_PLL_CHGPUMP_CFG			0x00000008
+
+#define REG_EDP_28nm_PHY_PLL_VCOLPF_CFG				0x0000000c
+
+#define REG_EDP_28nm_PHY_PLL_VREG_CFG				0x00000010
+
+#define REG_EDP_28nm_PHY_PLL_PWRGEN_CFG				0x00000014
+
+#define REG_EDP_28nm_PHY_PLL_DMUX_CFG				0x00000018
+
+#define REG_EDP_28nm_PHY_PLL_AMUX_CFG				0x0000001c
+
+#define REG_EDP_28nm_PHY_PLL_GLB_CFG				0x00000020
+#define EDP_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B			0x00000001
+#define EDP_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B		0x00000002
+#define EDP_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B		0x00000004
+#define EDP_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE			0x00000008
+
+#define REG_EDP_28nm_PHY_PLL_POSTDIV2_CFG			0x00000024
+
+#define REG_EDP_28nm_PHY_PLL_POSTDIV3_CFG			0x00000028
+
+#define REG_EDP_28nm_PHY_PLL_LPFR_CFG				0x0000002c
+
+#define REG_EDP_28nm_PHY_PLL_LPFC1_CFG				0x00000030
+
+#define REG_EDP_28nm_PHY_PLL_LPFC2_CFG				0x00000034
+
+#define REG_EDP_28nm_PHY_PLL_SDM_CFG0				0x00000038
+
+#define REG_EDP_28nm_PHY_PLL_SDM_CFG1				0x0000003c
+
+#define REG_EDP_28nm_PHY_PLL_SDM_CFG2				0x00000040
+
+#define REG_EDP_28nm_PHY_PLL_SDM_CFG3				0x00000044
+
+#define REG_EDP_28nm_PHY_PLL_SDM_CFG4				0x00000048
+
+#define REG_EDP_28nm_PHY_PLL_SSC_CFG0				0x0000004c
+
+#define REG_EDP_28nm_PHY_PLL_SSC_CFG1				0x00000050
+
+#define REG_EDP_28nm_PHY_PLL_SSC_CFG2				0x00000054
+
+#define REG_EDP_28nm_PHY_PLL_SSC_CFG3				0x00000058
+
+#define REG_EDP_28nm_PHY_PLL_LKDET_CFG0				0x0000005c
+
+#define REG_EDP_28nm_PHY_PLL_LKDET_CFG1				0x00000060
+
+#define REG_EDP_28nm_PHY_PLL_LKDET_CFG2				0x00000064
+
+#define REG_EDP_28nm_PHY_PLL_TEST_CFG				0x00000068
+#define EDP_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET			0x00000001
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG0				0x0000006c
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG1				0x00000070
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG2				0x00000074
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG3				0x00000078
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG4				0x0000007c
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG5				0x00000080
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG6				0x00000084
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG7				0x00000088
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG8				0x0000008c
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG9				0x00000090
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG10				0x00000094
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG11				0x00000098
+
+#define REG_EDP_28nm_PHY_PLL_EFUSE_CFG				0x0000009c
+
+#define REG_EDP_28nm_PHY_PLL_DEBUG_BUS_SEL			0x000000a0
+
 
 #endif /* EDP_XML */
diff --git a/drivers/gpu/drm/msm/edp/edp_aux.c b/drivers/gpu/drm/msm/edp/edp_aux.c
index 208f9d47f82e..82789dd249ee 100644
--- a/drivers/gpu/drm/msm/edp/edp_aux.c
+++ b/drivers/gpu/drm/msm/edp/edp_aux.c
@@ -115,10 +115,12 @@ static int edp_msg_fifo_rx(struct edp_aux *aux, struct drm_dp_aux_msg *msg)
  * msm_edp_aux_ctrl() running concurrently in other threads, i.e.
  * start transaction only when AUX channel is fully enabled.
  */
-ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, struct drm_dp_aux_msg *msg)
+static ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux,
+		struct drm_dp_aux_msg *msg)
 {
 	struct edp_aux *aux = to_edp_aux(drm_aux);
 	ssize_t ret;
+	unsigned long time_left;
 	bool native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
 	bool read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
 
@@ -147,15 +149,17 @@ ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, struct drm_dp_aux_msg *msg)
 		goto unlock_exit;
 
 	DBG("wait_for_completion");
-	ret = wait_for_completion_timeout(&aux->msg_comp, 300);
-	if (ret <= 0) {
+	time_left = wait_for_completion_timeout(&aux->msg_comp,
+						msecs_to_jiffies(300));
+	if (!time_left) {
 		/*
 		 * Clear GO and reset AUX channel
 		 * to cancel the current transaction.
 		 */
 		edp_write(aux->base + REG_EDP_AUX_TRANS_CTRL, 0);
 		msm_edp_aux_ctrl(aux, 1);
-		pr_err("%s: aux timeout, %zd\n", __func__, ret);
+		pr_err("%s: aux timeout,\n", __func__);
+		ret = -ETIMEDOUT;
 		goto unlock_exit;
 	}
 	DBG("completion");
diff --git a/drivers/gpu/drm/msm/edp/edp_ctrl.c b/drivers/gpu/drm/msm/edp/edp_ctrl.c
index 29e52d7c61c0..7991069dd492 100644
--- a/drivers/gpu/drm/msm/edp/edp_ctrl.c
+++ b/drivers/gpu/drm/msm/edp/edp_ctrl.c
@@ -1018,7 +1018,7 @@ static void edp_ctrl_off_worker(struct work_struct *work)
 {
 	struct edp_ctrl *ctrl = container_of(
 				work, struct edp_ctrl, off_work);
-	int ret;
+	unsigned long time_left;
 
 	mutex_lock(&ctrl->dev_mutex);
 
@@ -1030,11 +1030,10 @@ static void edp_ctrl_off_worker(struct work_struct *work)
 	reinit_completion(&ctrl->idle_comp);
 	edp_state_ctrl(ctrl, EDP_STATE_CTRL_PUSH_IDLE);
 
-	ret = wait_for_completion_timeout(&ctrl->idle_comp,
+	time_left = wait_for_completion_timeout(&ctrl->idle_comp,
 						msecs_to_jiffies(500));
-	if (ret <= 0)
-		DBG("%s: idle pattern timedout, %d\n",
-				__func__, ret);
+	if (!time_left)
+		DBG("%s: idle pattern timedout\n", __func__);
 
 	edp_state_ctrl(ctrl, 0);
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
index 350988740e9f..e6f034808371 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
@@ -10,15 +10,15 @@ git clone https://github.com/freedreno/envytools.git
 The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)
 
 Copyright (C) 2013-2015 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -750,5 +750,92 @@ static inline uint32_t HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(uint32_t val)
 
 #define REG_HDMI_8x74_BIST_PATN3				0x00000048
 
+#define REG_HDMI_28nm_PHY_PLL_REFCLK_CFG			0x00000000
+
+#define REG_HDMI_28nm_PHY_PLL_POSTDIV1_CFG			0x00000004
+
+#define REG_HDMI_28nm_PHY_PLL_CHGPUMP_CFG			0x00000008
+
+#define REG_HDMI_28nm_PHY_PLL_VCOLPF_CFG			0x0000000c
+
+#define REG_HDMI_28nm_PHY_PLL_VREG_CFG				0x00000010
+
+#define REG_HDMI_28nm_PHY_PLL_PWRGEN_CFG			0x00000014
+
+#define REG_HDMI_28nm_PHY_PLL_DMUX_CFG				0x00000018
+
+#define REG_HDMI_28nm_PHY_PLL_AMUX_CFG				0x0000001c
+
+#define REG_HDMI_28nm_PHY_PLL_GLB_CFG				0x00000020
+#define HDMI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B			0x00000001
+#define HDMI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B		0x00000002
+#define HDMI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B		0x00000004
+#define HDMI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE			0x00000008
+
+#define REG_HDMI_28nm_PHY_PLL_POSTDIV2_CFG			0x00000024
+
+#define REG_HDMI_28nm_PHY_PLL_POSTDIV3_CFG			0x00000028
+
+#define REG_HDMI_28nm_PHY_PLL_LPFR_CFG				0x0000002c
+
+#define REG_HDMI_28nm_PHY_PLL_LPFC1_CFG				0x00000030
+
+#define REG_HDMI_28nm_PHY_PLL_LPFC2_CFG				0x00000034
+
+#define REG_HDMI_28nm_PHY_PLL_SDM_CFG0				0x00000038
+
+#define REG_HDMI_28nm_PHY_PLL_SDM_CFG1				0x0000003c
+
+#define REG_HDMI_28nm_PHY_PLL_SDM_CFG2				0x00000040
+
+#define REG_HDMI_28nm_PHY_PLL_SDM_CFG3				0x00000044
+
+#define REG_HDMI_28nm_PHY_PLL_SDM_CFG4				0x00000048
+
+#define REG_HDMI_28nm_PHY_PLL_SSC_CFG0				0x0000004c
+
+#define REG_HDMI_28nm_PHY_PLL_SSC_CFG1				0x00000050
+
+#define REG_HDMI_28nm_PHY_PLL_SSC_CFG2				0x00000054
+
+#define REG_HDMI_28nm_PHY_PLL_SSC_CFG3				0x00000058
+
+#define REG_HDMI_28nm_PHY_PLL_LKDET_CFG0			0x0000005c
+
+#define REG_HDMI_28nm_PHY_PLL_LKDET_CFG1			0x00000060
+
+#define REG_HDMI_28nm_PHY_PLL_LKDET_CFG2			0x00000064
+
+#define REG_HDMI_28nm_PHY_PLL_TEST_CFG				0x00000068
+#define HDMI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET			0x00000001
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG0				0x0000006c
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG1				0x00000070
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG2				0x00000074
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG3				0x00000078
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG4				0x0000007c
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG5				0x00000080
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG6				0x00000084
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG7				0x00000088
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG8				0x0000008c
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG9				0x00000090
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG10				0x00000094
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG11				0x00000098
+
+#define REG_HDMI_28nm_PHY_PLL_EFUSE_CFG				0x0000009c
+
+#define REG_HDMI_28nm_PHY_PLL_DEBUG_BUS_SEL			0x000000a0
+
 
 #endif /* HDMI_XML */
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
index b62cdb968614..54aa93ff5473 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
@@ -16,6 +16,7 @@
  */
 
 #include <linux/gpio.h>
+#include <linux/pinctrl/consumer.h>
 
 #include "msm_kms.h"
 #include "hdmi.h"
@@ -29,14 +30,14 @@ struct hdmi_connector {
 
 static int gpio_config(struct hdmi *hdmi, bool on)
 {
-	struct drm_device *dev = hdmi->dev;
+	struct device *dev = &hdmi->pdev->dev;
 	const struct hdmi_platform_config *config = hdmi->config;
 	int ret;
 
 	if (on) {
 		ret = gpio_request(config->ddc_clk_gpio, "HDMI_DDC_CLK");
 		if (ret) {
-			dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
+			dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
 				"HDMI_DDC_CLK", config->ddc_clk_gpio, ret);
 			goto error1;
 		}
@@ -44,7 +45,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)
 
 		ret = gpio_request(config->ddc_data_gpio, "HDMI_DDC_DATA");
 		if (ret) {
-			dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
+			dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
 				"HDMI_DDC_DATA", config->ddc_data_gpio, ret);
 			goto error2;
 		}
@@ -52,7 +53,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)
 
 		ret = gpio_request(config->hpd_gpio, "HDMI_HPD");
 		if (ret) {
-			dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
+			dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
 				"HDMI_HPD", config->hpd_gpio, ret);
 			goto error3;
 		}
@@ -62,7 +63,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)
 		if (config->mux_en_gpio != -1) {
 			ret = gpio_request(config->mux_en_gpio, "HDMI_MUX_EN");
 			if (ret) {
-				dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
+				dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
 					"HDMI_MUX_EN", config->mux_en_gpio, ret);
 				goto error4;
 			}
@@ -72,7 +73,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)
 		if (config->mux_sel_gpio != -1) {
 			ret = gpio_request(config->mux_sel_gpio, "HDMI_MUX_SEL");
 			if (ret) {
-				dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
+				dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
 					"HDMI_MUX_SEL", config->mux_sel_gpio, ret);
 				goto error5;
 			}
@@ -83,7 +84,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)
 			ret = gpio_request(config->mux_lpm_gpio,
 					"HDMI_MUX_LPM");
 			if (ret) {
-				dev_err(dev->dev,
+				dev_err(dev,
 					"'%s'(%d) gpio_request failed: %d\n",
 					"HDMI_MUX_LPM",
 					config->mux_lpm_gpio, ret);
@@ -136,7 +137,7 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)
 {
 	struct hdmi *hdmi = hdmi_connector->hdmi;
 	const struct hdmi_platform_config *config = hdmi->config;
-	struct drm_device *dev = hdmi_connector->base.dev;
+	struct device *dev = &hdmi->pdev->dev;
 	struct hdmi_phy *phy = hdmi->phy;
 	uint32_t hpd_ctrl;
 	int i, ret;
@@ -144,15 +145,21 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)
 	for (i = 0; i < config->hpd_reg_cnt; i++) {
 		ret = regulator_enable(hdmi->hpd_regs[i]);
 		if (ret) {
-			dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n",
+			dev_err(dev, "failed to enable hpd regulator: %s (%d)\n",
 					config->hpd_reg_names[i], ret);
 			goto fail;
 		}
 	}
 
+	ret = pinctrl_pm_select_default_state(dev);
+	if (ret) {
+		dev_err(dev, "pinctrl state chg failed: %d\n", ret);
+		goto fail;
+	}
+
 	ret = gpio_config(hdmi, true);
 	if (ret) {
-		dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret);
+		dev_err(dev, "failed to configure GPIOs: %d\n", ret);
 		goto fail;
 	}
 
@@ -161,13 +168,13 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)
 			ret = clk_set_rate(hdmi->hpd_clks[i],
 					config->hpd_freq[i]);
 			if (ret)
-				dev_warn(dev->dev, "failed to set clk %s (%d)\n",
+				dev_warn(dev, "failed to set clk %s (%d)\n",
 						config->hpd_clk_names[i], ret);
 		}
 
 		ret = clk_prepare_enable(hdmi->hpd_clks[i]);
 		if (ret) {
-			dev_err(dev->dev, "failed to enable hpd clk: %s (%d)\n",
+			dev_err(dev, "failed to enable hpd clk: %s (%d)\n",
 					config->hpd_clk_names[i], ret);
 			goto fail;
 		}
@@ -204,7 +211,7 @@ static void hdp_disable(struct hdmi_connector *hdmi_connector)
 {
 	struct hdmi *hdmi = hdmi_connector->hdmi;
 	const struct hdmi_platform_config *config = hdmi->config;
-	struct drm_device *dev = hdmi_connector->base.dev;
+	struct device *dev = &hdmi->pdev->dev;
 	int i, ret = 0;
 
 	/* Disable HPD interrupt */
@@ -217,12 +224,16 @@ static void hdp_disable(struct hdmi_connector *hdmi_connector)
 
 	ret = gpio_config(hdmi, false);
 	if (ret)
-		dev_warn(dev->dev, "failed to unconfigure GPIOs: %d\n", ret);
+		dev_warn(dev, "failed to unconfigure GPIOs: %d\n", ret);
+
+	ret = pinctrl_pm_select_sleep_state(dev);
+	if (ret)
+		dev_warn(dev, "pinctrl state chg failed: %d\n", ret);
 
 	for (i = 0; i < config->hpd_reg_cnt; i++) {
 		ret = regulator_disable(hdmi->hpd_regs[i]);
 		if (ret)
-			dev_warn(dev->dev, "failed to disable hpd regulator: %s (%d)\n",
+			dev_warn(dev, "failed to disable hpd regulator: %s (%d)\n",
 					config->hpd_reg_names[i], ret);
 	}
 }
@@ -433,7 +444,7 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi)
 
 	ret = hpd_enable(hdmi_connector);
 	if (ret) {
-		dev_err(hdmi->dev->dev, "failed to enable HPD: %d\n", ret);
+		dev_err(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
 		goto fail;
 	}
 
diff --git a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
index 43bb54a9afbf..978c3f70872a 100644
--- a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
@@ -10,15 +10,15 @@ git clone https://github.com/freedreno/envytools.git
 The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
index 1d39174d91fb..153fc487d683 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
@@ -10,17 +10,17 @@ git clone https://github.com/freedreno/envytools.git
 The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)
 
-Copyright (C) 2013-2014 by the following authors:
+Copyright (C) 2013-2015 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -680,18 +680,18 @@ static inline uint32_t MDP4_PIPE_SRC_STRIDE_B_P3(uint32_t val)
 	return ((val) << MDP4_PIPE_SRC_STRIDE_B_P3__SHIFT) & MDP4_PIPE_SRC_STRIDE_B_P3__MASK;
 }
 
-static inline uint32_t REG_MDP4_PIPE_FRAME_SIZE(enum mdp4_pipe i0) { return 0x00020048 + 0x10000*i0; }
-#define MDP4_PIPE_FRAME_SIZE_HEIGHT__MASK			0xffff0000
-#define MDP4_PIPE_FRAME_SIZE_HEIGHT__SHIFT			16
-static inline uint32_t MDP4_PIPE_FRAME_SIZE_HEIGHT(uint32_t val)
+static inline uint32_t REG_MDP4_PIPE_SSTILE_FRAME_SIZE(enum mdp4_pipe i0) { return 0x00020048 + 0x10000*i0; }
+#define MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT__MASK		0xffff0000
+#define MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT__SHIFT		16
+static inline uint32_t MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT(uint32_t val)
 {
-	return ((val) << MDP4_PIPE_FRAME_SIZE_HEIGHT__SHIFT) & MDP4_PIPE_FRAME_SIZE_HEIGHT__MASK;
+	return ((val) << MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT__SHIFT) & MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT__MASK;
 }
-#define MDP4_PIPE_FRAME_SIZE_WIDTH__MASK			0x0000ffff
-#define MDP4_PIPE_FRAME_SIZE_WIDTH__SHIFT			0
-static inline uint32_t MDP4_PIPE_FRAME_SIZE_WIDTH(uint32_t val)
+#define MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH__MASK			0x0000ffff
+#define MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH__SHIFT		0
+static inline uint32_t MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH(uint32_t val)
 {
-	return ((val) << MDP4_PIPE_FRAME_SIZE_WIDTH__SHIFT) & MDP4_PIPE_FRAME_SIZE_WIDTH__MASK;
+	return ((val) << MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH__SHIFT) & MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH__MASK;
 }
 
 static inline uint32_t REG_MDP4_PIPE_SRC_FORMAT(enum mdp4_pipe i0) { return 0x00020050 + 0x10000*i0; }
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index 73afa21822b4..c4bb9d9c7667 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -51,6 +51,11 @@ struct mdp4_crtc {
 	/* if there is a pending flip, these will be non-null: */
 	struct drm_pending_vblank_event *event;
 
+	/* Bits have been flushed at the last commit,
+	 * used to decide if a vsync has happened since last commit.
+	 */
+	u32 flushed_mask;
+
 #define PENDING_CURSOR 0x1
 #define PENDING_FLIP   0x2
 	atomic_t pending;
@@ -93,6 +98,8 @@ static void crtc_flush(struct drm_crtc *crtc)
 
 	DBG("%s: flush=%08x", mdp4_crtc->name, flush);
 
+	mdp4_crtc->flushed_mask = flush;
+
 	mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush);
 }
 
@@ -537,6 +544,29 @@ static void mdp4_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
 	crtc_flush(crtc);
 }
 
+static void mdp4_crtc_wait_for_flush_done(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+	struct mdp4_kms *mdp4_kms = get_kms(crtc);
+	int ret;
+
+	ret = drm_crtc_vblank_get(crtc);
+	if (ret)
+		return;
+
+	ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue,
+		!(mdp4_read(mdp4_kms, REG_MDP4_OVERLAY_FLUSH) &
+			mdp4_crtc->flushed_mask),
+		msecs_to_jiffies(50));
+	if (ret <= 0)
+		dev_warn(dev->dev, "vblank time out, crtc=%d\n", mdp4_crtc->id);
+
+	mdp4_crtc->flushed_mask = 0;
+
+	drm_crtc_vblank_put(crtc);
+}
+
 uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc)
 {
 	struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
@@ -600,6 +630,15 @@ void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer)
 	mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel);
 }
 
+void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc)
+{
+	/* wait_for_flush_done is the only case for now.
+	 * Later we will have command mode CRTC to wait for
+	 * other event.
+	 */
+	mdp4_crtc_wait_for_flush_done(crtc);
+}
+
 static const char *dma_names[] = {
 		"DMA_P", "DMA_S", "DMA_E",
 };
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
index 7896323b2631..89614c6a6c1b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
@@ -38,7 +38,7 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
 	return to_mdp4_kms(to_mdp_kms(priv->kms));
 }
 
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
 #include <mach/board.h>
 /* not ironically named at all.. no, really.. */
 static void bs_init(struct mdp4_dtv_encoder *mdp4_dtv_encoder)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index d847b9436194..531e4acc2a87 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -119,6 +119,8 @@ static int mdp4_hw_init(struct msm_kms *kms)
 	if (mdp4_kms->rev > 1)
 		mdp4_write(mdp4_kms, REG_MDP4_RESET_STATUS, 1);
 
+	dev->mode_config.allow_fb_modifiers = true;
+
 out:
 	pm_runtime_put_sync(dev->dev);
 
@@ -157,6 +159,12 @@ static void mdp4_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s
 	mdp4_disable(mdp4_kms);
 }
 
+static void mdp4_wait_for_crtc_commit_done(struct msm_kms *kms,
+						struct drm_crtc *crtc)
+{
+	mdp4_crtc_wait_for_commit_done(crtc);
+}
+
 static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,
 		struct drm_encoder *encoder)
 {
@@ -195,6 +203,7 @@ static const struct mdp_kms_funcs kms_funcs = {
 		.disable_vblank  = mdp4_disable_vblank,
 		.prepare_commit  = mdp4_prepare_commit,
 		.complete_commit = mdp4_complete_commit,
+		.wait_for_crtc_commit_done = mdp4_wait_for_crtc_commit_done,
 		.get_format      = mdp_get_format,
 		.round_pixclk    = mdp4_round_pixclk,
 		.preclose        = mdp4_preclose,
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index 0a5c58bde7a9..c1ecb9d6bdef 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
@@ -206,6 +206,7 @@ uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc);
 void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
 void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config);
 void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer);
+void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc);
 struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
 		struct drm_plane *plane, int id, int ovlp_id,
 		enum mdp4_dma dma_id);
@@ -229,7 +230,7 @@ static inline struct clk *mpd4_lvds_pll_init(struct drm_device *dev)
 }
 #endif
 
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
 static inline int match_dev_name(struct device *dev, void *data)
 {
 	return !strcmp(dev_name(dev), data);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
index 60ec8222c9f6..c04843376c54 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
@@ -38,7 +38,7 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
 	return to_mdp4_kms(to_mdp_kms(priv->kms));
 }
 
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
 #include <mach/board.h>
 static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder)
 {
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index dbc068988377..0d1dbb737933 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -33,6 +33,21 @@ struct mdp4_plane {
 };
 #define to_mdp4_plane(x) container_of(x, struct mdp4_plane, base)
 
+/* MDP format helper functions */
+static inline
+enum mdp4_frame_format mdp4_get_frame_format(struct drm_framebuffer *fb)
+{
+	bool is_tile = false;
+
+	if (fb->modifier[1] == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
+		is_tile = true;
+
+	if (fb->pixel_format == DRM_FORMAT_NV12 && is_tile)
+		return FRAME_TILE_YCBCR_420;
+
+	return FRAME_LINEAR;
+}
+
 static void mdp4_plane_set_scanout(struct drm_plane *plane,
 		struct drm_framebuffer *fb);
 static int mdp4_plane_mode_set(struct drm_plane *plane,
@@ -205,6 +220,7 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
 	uint32_t op_mode = 0;
 	uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
 	uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
+	enum mdp4_frame_format frame_type = mdp4_get_frame_format(fb);
 
 	if (!(crtc && fb)) {
 		DBG("%s: disabled!", mdp4_plane->name);
@@ -304,6 +320,7 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
 			MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
 			MDP4_PIPE_SRC_FORMAT_FETCH_PLANES(format->fetch_type) |
 			MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample) |
+			MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT(frame_type) |
 			COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT));
 
 	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe),
@@ -324,6 +341,11 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
 	mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step);
 	mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step);
 
+	if (frame_type != FRAME_LINEAR)
+		mdp4_write(mdp4_kms, REG_MDP4_PIPE_SSTILE_FRAME_SIZE(pipe),
+				MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH(src_w) |
+				MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT(src_h));
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
index b9a4ded6e400..50e17527e2e5 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
@@ -8,9 +8,17 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp5.xml            (  29312 bytes, from 2015-03-23 21:18:48)
-- /local/mnt2/workspace2/sviau/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2014-06-02 18:31:15)
-- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2015-03-23 20:38:49)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)
 
 Copyright (C) 2013-2015 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -120,6 +128,21 @@ enum mdp5_data_format {
 	DATA_FORMAT_YUV = 1,
 };
 
+enum mdp5_block_size {
+	BLOCK_SIZE_64 = 0,
+	BLOCK_SIZE_128 = 1,
+};
+
+enum mdp5_rotate_mode {
+	ROTATE_0 = 0,
+	ROTATE_90 = 1,
+};
+
+enum mdp5_chroma_downsample_method {
+	DS_MTHD_NO_PIXEL_DROP = 0,
+	DS_MTHD_PIXEL_DROP = 1,
+};
+
 #define MDP5_IRQ_WB_0_DONE					0x00000001
 #define MDP5_IRQ_WB_1_DONE					0x00000002
 #define MDP5_IRQ_WB_2_DONE					0x00000010
@@ -314,19 +337,19 @@ static inline uint32_t MDP5_MDP_IGC_LUT_REG_VAL(uint32_t val)
 #define MDP5_MDP_IGC_LUT_REG_DISABLE_PIPE_1			0x20000000
 #define MDP5_MDP_IGC_LUT_REG_DISABLE_PIPE_2			0x40000000
 
-#define REG_MDP5_SPLIT_DPL_EN					0x000003f4
+static inline uint32_t REG_MDP5_MDP_SPLIT_DPL_EN(uint32_t i0) { return 0x000002f4 + __offset_MDP(i0); }
 
-#define REG_MDP5_SPLIT_DPL_UPPER				0x000003f8
-#define MDP5_SPLIT_DPL_UPPER_SMART_PANEL			0x00000002
-#define MDP5_SPLIT_DPL_UPPER_SMART_PANEL_FREE_RUN		0x00000004
-#define MDP5_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX			0x00000010
-#define MDP5_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX			0x00000100
+static inline uint32_t REG_MDP5_MDP_SPLIT_DPL_UPPER(uint32_t i0) { return 0x000002f8 + __offset_MDP(i0); }
+#define MDP5_MDP_SPLIT_DPL_UPPER_SMART_PANEL			0x00000002
+#define MDP5_MDP_SPLIT_DPL_UPPER_SMART_PANEL_FREE_RUN		0x00000004
+#define MDP5_MDP_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX		0x00000010
+#define MDP5_MDP_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX		0x00000100
 
-#define REG_MDP5_SPLIT_DPL_LOWER				0x000004f0
-#define MDP5_SPLIT_DPL_LOWER_SMART_PANEL			0x00000002
-#define MDP5_SPLIT_DPL_LOWER_SMART_PANEL_FREE_RUN		0x00000004
-#define MDP5_SPLIT_DPL_LOWER_INTF1_TG_SYNC			0x00000010
-#define MDP5_SPLIT_DPL_LOWER_INTF2_TG_SYNC			0x00000100
+static inline uint32_t REG_MDP5_MDP_SPLIT_DPL_LOWER(uint32_t i0) { return 0x000003f0 + __offset_MDP(i0); }
+#define MDP5_MDP_SPLIT_DPL_LOWER_SMART_PANEL			0x00000002
+#define MDP5_MDP_SPLIT_DPL_LOWER_SMART_PANEL_FREE_RUN		0x00000004
+#define MDP5_MDP_SPLIT_DPL_LOWER_INTF1_TG_SYNC			0x00000010
+#define MDP5_MDP_SPLIT_DPL_LOWER_INTF2_TG_SYNC			0x00000100
 
 static inline uint32_t __offset_CTL(uint32_t idx)
 {
@@ -782,7 +805,7 @@ static inline uint32_t MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(uint32_t val)
 #define MDP5_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB			0x00040000
 #define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK			0x00180000
 #define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT			19
-static inline uint32_t MDP5_PIPE_SRC_FORMAT_NUM_PLANES(enum mdp_sspp_fetch_type val)
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_NUM_PLANES(enum mdp_fetch_type val)
 {
 	return ((val) << MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT) & MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK;
 }
@@ -1234,6 +1257,351 @@ static inline uint32_t REG_MDP5_PP_FBC_BUDGET_CTL(uint32_t i0) { return 0x000000
 
 static inline uint32_t REG_MDP5_PP_FBC_LOSSY_MODE(uint32_t i0) { return 0x0000003c + __offset_PP(i0); }
 
+static inline uint32_t __offset_WB(uint32_t idx)
+{
+	switch (idx) {
+		default: return INVALID_IDX(idx);
+	}
+}
+static inline uint32_t REG_MDP5_WB(uint32_t i0) { return 0x00000000 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DST_FORMAT(uint32_t i0) { return 0x00000000 + __offset_WB(i0); }
+#define MDP5_WB_DST_FORMAT_DSTC0_OUT__MASK			0x00000003
+#define MDP5_WB_DST_FORMAT_DSTC0_OUT__SHIFT			0
+static inline uint32_t MDP5_WB_DST_FORMAT_DSTC0_OUT(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_FORMAT_DSTC0_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC0_OUT__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DSTC1_OUT__MASK			0x0000000c
+#define MDP5_WB_DST_FORMAT_DSTC1_OUT__SHIFT			2
+static inline uint32_t MDP5_WB_DST_FORMAT_DSTC1_OUT(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_FORMAT_DSTC1_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC1_OUT__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DSTC2_OUT__MASK			0x00000030
+#define MDP5_WB_DST_FORMAT_DSTC2_OUT__SHIFT			4
+static inline uint32_t MDP5_WB_DST_FORMAT_DSTC2_OUT(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_FORMAT_DSTC2_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC2_OUT__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DSTC3_OUT__MASK			0x000000c0
+#define MDP5_WB_DST_FORMAT_DSTC3_OUT__SHIFT			6
+static inline uint32_t MDP5_WB_DST_FORMAT_DSTC3_OUT(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_FORMAT_DSTC3_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC3_OUT__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DSTC3_EN				0x00000100
+#define MDP5_WB_DST_FORMAT_DST_BPP__MASK			0x00000600
+#define MDP5_WB_DST_FORMAT_DST_BPP__SHIFT			9
+static inline uint32_t MDP5_WB_DST_FORMAT_DST_BPP(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_FORMAT_DST_BPP__SHIFT) & MDP5_WB_DST_FORMAT_DST_BPP__MASK;
+}
+#define MDP5_WB_DST_FORMAT_PACK_COUNT__MASK			0x00003000
+#define MDP5_WB_DST_FORMAT_PACK_COUNT__SHIFT			12
+static inline uint32_t MDP5_WB_DST_FORMAT_PACK_COUNT(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_FORMAT_PACK_COUNT__SHIFT) & MDP5_WB_DST_FORMAT_PACK_COUNT__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DST_ALPHA_X				0x00004000
+#define MDP5_WB_DST_FORMAT_PACK_TIGHT				0x00020000
+#define MDP5_WB_DST_FORMAT_PACK_ALIGN_MSB			0x00040000
+#define MDP5_WB_DST_FORMAT_WRITE_PLANES__MASK			0x00180000
+#define MDP5_WB_DST_FORMAT_WRITE_PLANES__SHIFT			19
+static inline uint32_t MDP5_WB_DST_FORMAT_WRITE_PLANES(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_FORMAT_WRITE_PLANES__SHIFT) & MDP5_WB_DST_FORMAT_WRITE_PLANES__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DST_DITHER_EN			0x00400000
+#define MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP__MASK		0x03800000
+#define MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP__SHIFT		23
+static inline uint32_t MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP__SHIFT) & MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DST_CHROMA_SITE__MASK		0x3c000000
+#define MDP5_WB_DST_FORMAT_DST_CHROMA_SITE__SHIFT		26
+static inline uint32_t MDP5_WB_DST_FORMAT_DST_CHROMA_SITE(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_FORMAT_DST_CHROMA_SITE__SHIFT) & MDP5_WB_DST_FORMAT_DST_CHROMA_SITE__MASK;
+}
+#define MDP5_WB_DST_FORMAT_FRAME_FORMAT__MASK			0xc0000000
+#define MDP5_WB_DST_FORMAT_FRAME_FORMAT__SHIFT			30
+static inline uint32_t MDP5_WB_DST_FORMAT_FRAME_FORMAT(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_FORMAT_FRAME_FORMAT__SHIFT) & MDP5_WB_DST_FORMAT_FRAME_FORMAT__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_DST_OP_MODE(uint32_t i0) { return 0x00000004 + __offset_WB(i0); }
+#define MDP5_WB_DST_OP_MODE_BWC_ENC_EN				0x00000001
+#define MDP5_WB_DST_OP_MODE_BWC_ENC_OP__MASK			0x00000006
+#define MDP5_WB_DST_OP_MODE_BWC_ENC_OP__SHIFT			1
+static inline uint32_t MDP5_WB_DST_OP_MODE_BWC_ENC_OP(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_OP_MODE_BWC_ENC_OP__SHIFT) & MDP5_WB_DST_OP_MODE_BWC_ENC_OP__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_BLOCK_SIZE__MASK			0x00000010
+#define MDP5_WB_DST_OP_MODE_BLOCK_SIZE__SHIFT			4
+static inline uint32_t MDP5_WB_DST_OP_MODE_BLOCK_SIZE(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_OP_MODE_BLOCK_SIZE__SHIFT) & MDP5_WB_DST_OP_MODE_BLOCK_SIZE__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_ROT_MODE__MASK			0x00000020
+#define MDP5_WB_DST_OP_MODE_ROT_MODE__SHIFT			5
+static inline uint32_t MDP5_WB_DST_OP_MODE_ROT_MODE(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_OP_MODE_ROT_MODE__SHIFT) & MDP5_WB_DST_OP_MODE_ROT_MODE__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_ROT_EN				0x00000040
+#define MDP5_WB_DST_OP_MODE_CSC_EN				0x00000100
+#define MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT__MASK		0x00000200
+#define MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT__SHIFT		9
+static inline uint32_t MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT__SHIFT) & MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT__MASK		0x00000400
+#define MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT__SHIFT		10
+static inline uint32_t MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT__SHIFT) & MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_EN		0x00000800
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT__MASK	0x00001000
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT__SHIFT	12
+static inline uint32_t MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT__SHIFT) & MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD__MASK	0x00002000
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD__SHIFT	13
+static inline uint32_t MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD__SHIFT) & MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD__MASK	0x00004000
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD__SHIFT	14
+static inline uint32_t MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD__SHIFT) & MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_DST_PACK_PATTERN(uint32_t i0) { return 0x00000008 + __offset_WB(i0); }
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT0__MASK			0x00000003
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT0__SHIFT		0
+static inline uint32_t MDP5_WB_DST_PACK_PATTERN_ELEMENT0(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_PACK_PATTERN_ELEMENT0__SHIFT) & MDP5_WB_DST_PACK_PATTERN_ELEMENT0__MASK;
+}
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT1__MASK			0x00000300
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT1__SHIFT		8
+static inline uint32_t MDP5_WB_DST_PACK_PATTERN_ELEMENT1(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_PACK_PATTERN_ELEMENT1__SHIFT) & MDP5_WB_DST_PACK_PATTERN_ELEMENT1__MASK;
+}
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT2__MASK			0x00030000
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT2__SHIFT		16
+static inline uint32_t MDP5_WB_DST_PACK_PATTERN_ELEMENT2(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_PACK_PATTERN_ELEMENT2__SHIFT) & MDP5_WB_DST_PACK_PATTERN_ELEMENT2__MASK;
+}
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT3__MASK			0x03000000
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT3__SHIFT		24
+static inline uint32_t MDP5_WB_DST_PACK_PATTERN_ELEMENT3(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_PACK_PATTERN_ELEMENT3__SHIFT) & MDP5_WB_DST_PACK_PATTERN_ELEMENT3__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_DST0_ADDR(uint32_t i0) { return 0x0000000c + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DST1_ADDR(uint32_t i0) { return 0x00000010 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DST2_ADDR(uint32_t i0) { return 0x00000014 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DST3_ADDR(uint32_t i0) { return 0x00000018 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DST_YSTRIDE0(uint32_t i0) { return 0x0000001c + __offset_WB(i0); }
+#define MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE__MASK			0x0000ffff
+#define MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE__SHIFT		0
+static inline uint32_t MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE__SHIFT) & MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE__MASK;
+}
+#define MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE__MASK			0xffff0000
+#define MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE__SHIFT		16
+static inline uint32_t MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE__SHIFT) & MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_DST_YSTRIDE1(uint32_t i0) { return 0x00000020 + __offset_WB(i0); }
+#define MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE__MASK			0x0000ffff
+#define MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE__SHIFT		0
+static inline uint32_t MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE__SHIFT) & MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE__MASK;
+}
+#define MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE__MASK			0xffff0000
+#define MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE__SHIFT		16
+static inline uint32_t MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE(uint32_t val)
+{
+	return ((val) << MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE__SHIFT) & MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_DST_DITHER_BITDEPTH(uint32_t i0) { return 0x00000024 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DITHER_MATRIX_ROW0(uint32_t i0) { return 0x00000030 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DITHER_MATRIX_ROW1(uint32_t i0) { return 0x00000034 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DITHER_MATRIX_ROW2(uint32_t i0) { return 0x00000038 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DITHER_MATRIX_ROW3(uint32_t i0) { return 0x0000003c + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DST_WRITE_CONFIG(uint32_t i0) { return 0x00000048 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_ROTATION_DNSCALER(uint32_t i0) { return 0x00000050 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_N16_INIT_PHASE_X_0_3(uint32_t i0) { return 0x00000060 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_N16_INIT_PHASE_X_1_2(uint32_t i0) { return 0x00000064 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_N16_INIT_PHASE_Y_0_3(uint32_t i0) { return 0x00000068 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_N16_INIT_PHASE_Y_1_2(uint32_t i0) { return 0x0000006c + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_OUT_SIZE(uint32_t i0) { return 0x00000074 + __offset_WB(i0); }
+#define MDP5_WB_OUT_SIZE_DST_W__MASK				0x0000ffff
+#define MDP5_WB_OUT_SIZE_DST_W__SHIFT				0
+static inline uint32_t MDP5_WB_OUT_SIZE_DST_W(uint32_t val)
+{
+	return ((val) << MDP5_WB_OUT_SIZE_DST_W__SHIFT) & MDP5_WB_OUT_SIZE_DST_W__MASK;
+}
+#define MDP5_WB_OUT_SIZE_DST_H__MASK				0xffff0000
+#define MDP5_WB_OUT_SIZE_DST_H__SHIFT				16
+static inline uint32_t MDP5_WB_OUT_SIZE_DST_H(uint32_t val)
+{
+	return ((val) << MDP5_WB_OUT_SIZE_DST_H__SHIFT) & MDP5_WB_OUT_SIZE_DST_H__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_ALPHA_X_VALUE(uint32_t i0) { return 0x00000078 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_0(uint32_t i0) { return 0x00000260 + __offset_WB(i0); }
+#define MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11__MASK		0x00001fff
+#define MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11__SHIFT		0
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11__MASK;
+}
+#define MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12__MASK		0x1fff0000
+#define MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12__SHIFT		16
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_1(uint32_t i0) { return 0x00000264 + __offset_WB(i0); }
+#define MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13__MASK		0x00001fff
+#define MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13__SHIFT		0
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13__MASK;
+}
+#define MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21__MASK		0x1fff0000
+#define MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21__SHIFT		16
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_2(uint32_t i0) { return 0x00000268 + __offset_WB(i0); }
+#define MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22__MASK		0x00001fff
+#define MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22__SHIFT		0
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22__MASK;
+}
+#define MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23__MASK		0x1fff0000
+#define MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23__SHIFT		16
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_3(uint32_t i0) { return 0x0000026c + __offset_WB(i0); }
+#define MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31__MASK		0x00001fff
+#define MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31__SHIFT		0
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31__MASK;
+}
+#define MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32__MASK		0x1fff0000
+#define MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32__SHIFT		16
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_4(uint32_t i0) { return 0x00000270 + __offset_WB(i0); }
+#define MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33__MASK		0x00001fff
+#define MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33__SHIFT		0
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_PRECLAMP(uint32_t i0, uint32_t i1) { return 0x00000274 + __offset_WB(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_PRECLAMP_REG(uint32_t i0, uint32_t i1) { return 0x00000274 + __offset_WB(i0) + 0x4*i1; }
+#define MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH__MASK		0x000000ff
+#define MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH__SHIFT		0
+static inline uint32_t MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH__SHIFT) & MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH__MASK;
+}
+#define MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW__MASK			0x0000ff00
+#define MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW__SHIFT		8
+static inline uint32_t MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW__SHIFT) & MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_POSTCLAMP(uint32_t i0, uint32_t i1) { return 0x00000280 + __offset_WB(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_POSTCLAMP_REG(uint32_t i0, uint32_t i1) { return 0x00000280 + __offset_WB(i0) + 0x4*i1; }
+#define MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH__MASK		0x000000ff
+#define MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH__SHIFT		0
+static inline uint32_t MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH__SHIFT) & MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH__MASK;
+}
+#define MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW__MASK		0x0000ff00
+#define MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW__SHIFT		8
+static inline uint32_t MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW__SHIFT) & MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_PREBIAS(uint32_t i0, uint32_t i1) { return 0x0000028c + __offset_WB(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_PREBIAS_REG(uint32_t i0, uint32_t i1) { return 0x0000028c + __offset_WB(i0) + 0x4*i1; }
+#define MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE__MASK		0x000001ff
+#define MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE__SHIFT		0
+static inline uint32_t MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE__SHIFT) & MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_POSTBIAS(uint32_t i0, uint32_t i1) { return 0x00000298 + __offset_WB(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_POSTBIAS_REG(uint32_t i0, uint32_t i1) { return 0x00000298 + __offset_WB(i0) + 0x4*i1; }
+#define MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE__MASK		0x000001ff
+#define MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE__SHIFT		0
+static inline uint32_t MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE(uint32_t val)
+{
+	return ((val) << MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE__SHIFT) & MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE__MASK;
+}
+
 static inline uint32_t __offset_INTF(uint32_t idx)
 {
 	switch (idx) {
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
index e4e89567f51d..ee31b16fe7ea 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
@@ -30,7 +30,7 @@ static struct mdp5_kms *get_kms(struct drm_encoder *encoder)
 	return to_mdp5_kms(to_mdp_kms(priv->kms));
 }
 
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
 #include <mach/board.h>
 #include <linux/msm-bus.h>
 #include <linux/msm-bus-board.h>
@@ -216,16 +216,12 @@ static void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder,
 static void mdp5_cmd_encoder_disable(struct drm_encoder *encoder)
 {
 	struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
-	struct mdp5_kms *mdp5_kms = get_kms(encoder);
 	struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc);
 	struct mdp5_interface *intf = &mdp5_cmd_enc->intf;
-	int lm = mdp5_crtc_get_lm(encoder->crtc);
 
 	if (WARN_ON(!mdp5_cmd_enc->enabled))
 		return;
 
-	/* Wait for the last frame done */
-	mdp_irq_wait(&mdp5_kms->base, lm2ppdone(lm));
 	pingpong_tearcheck_disable(encoder);
 
 	mdp5_ctl_set_encoder_state(ctl, false);
@@ -281,22 +277,22 @@ int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder,
 	 * start signal for the slave encoder
 	 */
 	if (intf_num == 1)
-		data |= MDP5_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX;
+		data |= MDP5_MDP_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX;
 	else if (intf_num == 2)
-		data |= MDP5_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX;
+		data |= MDP5_MDP_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX;
 	else
 		return -EINVAL;
 
 	/* Smart Panel, Sync mode */
-	data |= MDP5_SPLIT_DPL_UPPER_SMART_PANEL;
+	data |= MDP5_MDP_SPLIT_DPL_UPPER_SMART_PANEL;
 
 	/* Make sure clocks are on when connectors calling this function. */
 	mdp5_enable(mdp5_kms);
-	mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, data);
+	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_UPPER(0), data);
 
-	mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER,
-			MDP5_SPLIT_DPL_LOWER_SMART_PANEL);
-	mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1);
+	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_LOWER(0),
+			MDP5_MDP_SPLIT_DPL_LOWER_SMART_PANEL);
+	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_EN(0), 1);
 	mdp5_disable(mdp5_kms);
 
 	return 0;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index c1530772187d..dea3d2e559b1 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -46,6 +46,11 @@ struct mdp5_crtc {
 	/* if there is a pending flip, these will be non-null: */
 	struct drm_pending_vblank_event *event;
 
+	/* Bits have been flushed at the last commit,
+	 * used to decide if a vsync has happened since last commit.
+	 */
+	u32 flushed_mask;
+
 #define PENDING_CURSOR 0x1
 #define PENDING_FLIP   0x2
 	atomic_t pending;
@@ -55,6 +60,11 @@ struct mdp5_crtc {
 
 	struct mdp_irq vblank;
 	struct mdp_irq err;
+	struct mdp_irq pp_done;
+
+	struct completion pp_completion;
+
+	bool cmd_mode;
 
 	struct {
 		/* protect REG_MDP5_LM_CURSOR* registers and cursor scanout_bo*/
@@ -82,12 +92,18 @@ static void request_pending(struct drm_crtc *crtc, uint32_t pending)
 	mdp_irq_register(&get_kms(crtc)->base, &mdp5_crtc->vblank);
 }
 
-static void crtc_flush(struct drm_crtc *crtc, u32 flush_mask)
+static void request_pp_done_pending(struct drm_crtc *crtc)
+{
+	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+	reinit_completion(&mdp5_crtc->pp_completion);
+}
+
+static u32 crtc_flush(struct drm_crtc *crtc, u32 flush_mask)
 {
 	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 
 	DBG("%s: flush=%08x", mdp5_crtc->name, flush_mask);
-	mdp5_ctl_commit(mdp5_crtc->ctl, flush_mask);
+	return mdp5_ctl_commit(mdp5_crtc->ctl, flush_mask);
 }
 
 /*
@@ -95,7 +111,7 @@ static void crtc_flush(struct drm_crtc *crtc, u32 flush_mask)
  * so that we can safely queue unref to current fb (ie. next
  * vblank we know hw is done w/ previous scanout_fb).
  */
-static void crtc_flush_all(struct drm_crtc *crtc)
+static u32 crtc_flush_all(struct drm_crtc *crtc)
 {
 	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 	struct drm_plane *plane;
@@ -103,7 +119,7 @@ static void crtc_flush_all(struct drm_crtc *crtc)
 
 	/* this should not happen: */
 	if (WARN_ON(!mdp5_crtc->ctl))
-		return;
+		return 0;
 
 	drm_atomic_crtc_for_each_plane(plane, crtc) {
 		flush_mask |= mdp5_plane_get_flush(plane);
@@ -111,7 +127,7 @@ static void crtc_flush_all(struct drm_crtc *crtc)
 
 	flush_mask |= mdp_ctl_flush_mask_lm(mdp5_crtc->lm);
 
-	crtc_flush(crtc, flush_mask);
+	return crtc_flush(crtc, flush_mask);
 }
 
 /* if file!=NULL, this is preclose potential cancel-flip path */
@@ -143,6 +159,8 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
 	}
 
 	if (mdp5_crtc->ctl && !crtc->state->enable) {
+		/* set STAGE_UNUSED for all layers */
+		mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x00000000);
 		mdp5_ctl_release(mdp5_crtc->ctl);
 		mdp5_crtc->ctl = NULL;
 	}
@@ -274,8 +292,8 @@ static void mdp5_crtc_disable(struct drm_crtc *crtc)
 	if (WARN_ON(!mdp5_crtc->enabled))
 		return;
 
-	/* set STAGE_UNUSED for all layers */
-	mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x00000000);
+	if (mdp5_crtc->cmd_mode)
+		mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->pp_done);
 
 	mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err);
 	mdp5_disable(mdp5_kms);
@@ -296,6 +314,9 @@ static void mdp5_crtc_enable(struct drm_crtc *crtc)
 	mdp5_enable(mdp5_kms);
 	mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err);
 
+	if (mdp5_crtc->cmd_mode)
+		mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->pp_done);
+
 	mdp5_crtc->enabled = true;
 }
 
@@ -396,7 +417,18 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc)
 		return;
 
 	blend_setup(crtc);
-	crtc_flush_all(crtc);
+
+	/* PP_DONE irq is only used by command mode for now.
+	 * It is better to request pending before FLUSH and START trigger
+	 * to make sure no pp_done irq missed.
+	 * This is safe because no pp_done will happen before SW trigger
+	 * in command mode.
+	 */
+	if (mdp5_crtc->cmd_mode)
+		request_pp_done_pending(crtc);
+
+	mdp5_crtc->flushed_mask = crtc_flush_all(crtc);
+
 	request_pending(crtc, PENDING_FLIP);
 }
 
@@ -601,6 +633,52 @@ static void mdp5_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
 	DBG("%s: error: %08x", mdp5_crtc->name, irqstatus);
 }
 
+static void mdp5_crtc_pp_done_irq(struct mdp_irq *irq, uint32_t irqstatus)
+{
+	struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc,
+								pp_done);
+
+	complete(&mdp5_crtc->pp_completion);
+}
+
+static void mdp5_crtc_wait_for_pp_done(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+	int ret;
+
+	ret = wait_for_completion_timeout(&mdp5_crtc->pp_completion,
+						msecs_to_jiffies(50));
+	if (ret == 0)
+		dev_warn(dev->dev, "pp done time out, lm=%d\n", mdp5_crtc->lm);
+}
+
+static void mdp5_crtc_wait_for_flush_done(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+	int ret;
+
+	/* Should not call this function if crtc is disabled. */
+	if (!mdp5_crtc->ctl)
+		return;
+
+	ret = drm_crtc_vblank_get(crtc);
+	if (ret)
+		return;
+
+	ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue,
+		((mdp5_ctl_get_commit_status(mdp5_crtc->ctl) &
+		mdp5_crtc->flushed_mask) == 0),
+		msecs_to_jiffies(50));
+	if (ret <= 0)
+		dev_warn(dev->dev, "vblank time out, crtc=%d\n", mdp5_crtc->id);
+
+	mdp5_crtc->flushed_mask = 0;
+
+	drm_crtc_vblank_put(crtc);
+}
+
 uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc)
 {
 	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
@@ -622,16 +700,19 @@ void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf)
 
 	/* now that we know what irq's we want: */
 	mdp5_crtc->err.irqmask = intf2err(intf->num);
+	mdp5_crtc->vblank.irqmask = intf2vblank(lm, intf);
+
+	if ((intf->type == INTF_DSI) &&
+		(intf->mode == MDP5_INTF_DSI_MODE_COMMAND)) {
+		mdp5_crtc->pp_done.irqmask = lm2ppdone(lm);
+		mdp5_crtc->pp_done.irq = mdp5_crtc_pp_done_irq;
+		mdp5_crtc->cmd_mode = true;
+	} else {
+		mdp5_crtc->pp_done.irqmask = 0;
+		mdp5_crtc->pp_done.irq = NULL;
+		mdp5_crtc->cmd_mode = false;
+	}
 
-	/* Register command mode Pingpong done as vblank for now,
-	 * so that atomic commit should wait for it to finish.
-	 * Ideally, in the future, we should take rd_ptr done as vblank,
-	 * and let atomic commit wait for pingpong done for commond mode.
-	 */
-	if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
-		mdp5_crtc->vblank.irqmask = lm2ppdone(lm);
-	else
-		mdp5_crtc->vblank.irqmask = intf2vblank(lm, intf);
 	mdp_irq_update(&mdp5_kms->base);
 
 	mdp5_ctl_set_intf(mdp5_crtc->ctl, intf);
@@ -649,6 +730,16 @@ struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc)
 	return WARN_ON(!crtc) ? NULL : mdp5_crtc->ctl;
 }
 
+void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc)
+{
+	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+
+	if (mdp5_crtc->cmd_mode)
+		mdp5_crtc_wait_for_pp_done(crtc);
+	else
+		mdp5_crtc_wait_for_flush_done(crtc);
+}
+
 /* initialize crtc */
 struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
 		struct drm_plane *plane, int id)
@@ -667,6 +758,7 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
 
 	spin_lock_init(&mdp5_crtc->lm_lock);
 	spin_lock_init(&mdp5_crtc->cursor.lock);
+	init_completion(&mdp5_crtc->pp_completion);
 
 	mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
 	mdp5_crtc->err.irq = mdp5_crtc_err_irq;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
index 5488b687c8d1..f2530f224a76 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
@@ -392,8 +392,10 @@ static u32 fix_sw_flush(struct mdp5_ctl *ctl, u32 flush_mask)
  * CTL registers need to be flushed in some circumstances; if that is the
  * case, some trigger bits will be present in both flush mask and
  * ctl->pending_ctl_trigger.
+ *
+ * Return H/W flushed bit mask.
  */
-int mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask)
+u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask)
 {
 	struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
 	struct op_mode *pipeline = &ctl->pipeline;
@@ -424,7 +426,12 @@ int mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask)
 		refill_start_mask(ctl);
 	}
 
-	return 0;
+	return flush_mask;
+}
+
+u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl)
+{
+	return ctl_read(ctl, REG_MDP5_CTL_FLUSH(ctl->id));
 }
 
 void mdp5_ctl_release(struct mdp5_ctl *ctl)
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
index 7a62000994a1..4678228c4f14 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
@@ -88,7 +88,8 @@ u32 mdp_ctl_flush_mask_cursor(int cursor_id);
 u32 mdp_ctl_flush_mask_encoder(struct mdp5_interface *intf);
 
 /* @flush_mask: see CTL flush masks definitions below */
-int mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask);
+u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask);
+u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl);
 
 void mdp5_ctl_release(struct mdp5_ctl *ctl);
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index 1188f4bf1e60..de97c08f3f1f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -36,7 +36,7 @@ static struct mdp5_kms *get_kms(struct drm_encoder *encoder)
 	return to_mdp5_kms(to_mdp_kms(priv->kms));
 }
 
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
 #include <mach/board.h>
 #include <mach/msm_bus.h>
 #include <mach/msm_bus_board.h>
@@ -144,10 +144,14 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
 			mode->type, mode->flags);
 
 	ctrl_pol = 0;
-	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
-		ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW;
-	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
-		ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW;
+
+	/* DSI controller cannot handle active-low sync signals. */
+	if (mdp5_encoder->intf.type != INTF_DSI) {
+		if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+			ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW;
+		if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+			ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW;
+	}
 	/* probably need to get DATA_EN polarity from panel.. */
 
 	dtv_hsync_skew = 0;  /* get this from panel? */
@@ -304,9 +308,9 @@ int mdp5_encoder_set_split_display(struct drm_encoder *encoder,
 	 * to use the master's enable signal for the slave encoder.
 	 */
 	if (intf_num == 1)
-		data |= MDP5_SPLIT_DPL_LOWER_INTF2_TG_SYNC;
+		data |= MDP5_MDP_SPLIT_DPL_LOWER_INTF2_TG_SYNC;
 	else if (intf_num == 2)
-		data |= MDP5_SPLIT_DPL_LOWER_INTF1_TG_SYNC;
+		data |= MDP5_MDP_SPLIT_DPL_LOWER_INTF1_TG_SYNC;
 	else
 		return -EINVAL;
 
@@ -315,9 +319,9 @@ int mdp5_encoder_set_split_display(struct drm_encoder *encoder,
 	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPARE_0(0),
 		MDP5_MDP_SPARE_0_SPLIT_DPL_SINGLE_FLUSH_EN);
 	/* Dumb Panel, Sync mode */
-	mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, 0);
-	mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER, data);
-	mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1);
+	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_UPPER(0), 0);
+	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_LOWER(0), data);
+	mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_EN(0), 1);
 	mdp5_disable(mdp5_kms);
 
 	return 0;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index bbacf9d2b738..206f758f7d64 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -80,6 +80,12 @@ static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s
 	mdp5_disable(mdp5_kms);
 }
 
+static void mdp5_wait_for_crtc_commit_done(struct msm_kms *kms,
+						struct drm_crtc *crtc)
+{
+	mdp5_crtc_wait_for_commit_done(crtc);
+}
+
 static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate,
 		struct drm_encoder *encoder)
 {
@@ -141,6 +147,7 @@ static const struct mdp_kms_funcs kms_funcs = {
 		.disable_vblank  = mdp5_disable_vblank,
 		.prepare_commit  = mdp5_prepare_commit,
 		.complete_commit = mdp5_complete_commit,
+		.wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done,
 		.get_format      = mdp_get_format,
 		.round_pixclk    = mdp5_round_pixclk,
 		.set_split_display = mdp5_set_split_display,
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 2c0de174cc09..e0eb24587c84 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -237,6 +237,7 @@ int mdp5_crtc_get_lm(struct drm_crtc *crtc);
 struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc);
 void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
 void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf);
+void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc);
 struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
 		struct drm_plane *plane, int id);
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
index a1d35f162c7f..641d036c5bcb 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
@@ -10,17 +10,17 @@ git clone https://github.com/freedreno/envytools.git
 The rules-ng-ng source files this header was generated from are:
 - /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  22094 bytes, from 2015-05-12 12:45:23)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-12 12:45:23)
 
-Copyright (C) 2013-2014 by the following authors:
+Copyright (C) 2013-2015 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -52,7 +52,7 @@ enum mdp_chroma_samp_type {
 	CHROMA_420 = 3,
 };
 
-enum mdp_sspp_fetch_type {
+enum mdp_fetch_type {
 	MDP_PLANE_INTERLEAVED = 0,
 	MDP_PLANE_PLANAR = 1,
 	MDP_PLANE_PSEUDO_PLANAR = 2,
diff --git a/drivers/gpu/drm/msm/mdp/mdp_format.c b/drivers/gpu/drm/msm/mdp/mdp_format.c
index f683433b6727..7b0524dc1872 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_format.c
+++ b/drivers/gpu/drm/msm/mdp/mdp_format.c
@@ -96,6 +96,12 @@ static const struct mdp_format formats[] = {
 	/*  name      a  r  g  b   e0 e1 e2 e3  alpha   tight  cpp cnt ... */
 	FMT(ARGB8888, 8, 8, 8, 8,  1, 0, 2, 3,  true,   true,  4,  4,
 			MDP_PLANE_INTERLEAVED, CHROMA_RGB),
+	FMT(ABGR8888, 8, 8, 8, 8,  2, 0, 1, 3,  true,   true,  4,  4,
+			MDP_PLANE_INTERLEAVED, CHROMA_RGB),
+	FMT(RGBA8888, 8, 8, 8, 8,  3, 1, 0, 2,  true,   true,  4,  4,
+			MDP_PLANE_INTERLEAVED, CHROMA_RGB),
+	FMT(BGRA8888, 8, 8, 8, 8,  3, 2, 0, 1,  true,   true,  4,  4,
+			MDP_PLANE_INTERLEAVED, CHROMA_RGB),
 	FMT(XRGB8888, 8, 8, 8, 8,  1, 0, 2, 3,  false,  true,  4,  4,
 			MDP_PLANE_INTERLEAVED, CHROMA_RGB),
 	FMT(RGB888,   0, 8, 8, 8,  1, 0, 2, 0,  false,  true,  3,  3,
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h
index 5ae4039d68e4..2d3428cb74d0 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h
@@ -88,7 +88,7 @@ struct mdp_format {
 	uint8_t unpack[4];
 	bool alpha_enable, unpack_tight;
 	uint8_t cpp, unpack_count;
-	enum mdp_sspp_fetch_type fetch_type;
+	enum mdp_fetch_type fetch_type;
 	enum mdp_chroma_samp_type chroma_sample;
 };
 #define to_mdp_format(x) container_of(x, struct mdp_format, base)
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 5b192128cda2..1b22d8bfe142 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -84,6 +84,33 @@ static void commit_destroy(struct msm_commit *c)
 	kfree(c);
 }
 
+static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
+		struct drm_atomic_state *old_state)
+{
+	struct drm_crtc *crtc;
+	struct msm_drm_private *priv = old_state->dev->dev_private;
+	struct msm_kms *kms = priv->kms;
+	int ncrtcs = old_state->dev->mode_config.num_crtc;
+	int i;
+
+	for (i = 0; i < ncrtcs; i++) {
+		crtc = old_state->crtcs[i];
+
+		if (!crtc)
+			continue;
+
+		if (!crtc->state->enable)
+			continue;
+
+		/* Legacy cursor ioctls are completely unsynced, and userspace
+		 * relies on that (by doing tons of cursor updates). */
+		if (old_state->legacy_cursor_update)
+			continue;
+
+		kms->funcs->wait_for_crtc_commit_done(kms, crtc);
+	}
+}
+
 /* The (potentially) asynchronous part of the commit.  At this point
  * nothing can fail short of armageddon.
  */
@@ -115,7 +142,7 @@ static void complete_commit(struct msm_commit *c)
 	 * not be critical path)
 	 */
 
-	drm_atomic_helper_wait_for_vblanks(dev, state);
+	msm_atomic_wait_for_commit_done(dev, state);
 
 	drm_atomic_helper_cleanup_planes(dev, state);
 
@@ -139,7 +166,6 @@ static void add_fb(struct msm_commit *c, struct drm_framebuffer *fb)
 	c->fence = max(c->fence, msm_gem_fence(to_msm_bo(obj), MSM_PREP_READ));
 }
 
-
 int msm_atomic_check(struct drm_device *dev,
 		     struct drm_atomic_state *state)
 {
@@ -178,7 +204,7 @@ int msm_atomic_commit(struct drm_device *dev,
 {
 	int nplanes = dev->mode_config.num_total_plane;
 	int ncrtcs = dev->mode_config.num_crtc;
-	struct timespec timeout;
+	ktime_t timeout;
 	struct msm_commit *c;
 	int i, ret;
 
@@ -187,8 +213,10 @@ int msm_atomic_commit(struct drm_device *dev,
 		return ret;
 
 	c = commit_init(state);
-	if (!c)
-		return -ENOMEM;
+	if (!c) {
+		ret = -ENOMEM;
+		goto error;
+	}
 
 	/*
 	 * Figure out what crtcs we have:
@@ -221,7 +249,7 @@ int msm_atomic_commit(struct drm_device *dev,
 	ret = start_atomic(dev->dev_private, c->crtc_mask);
 	if (ret) {
 		kfree(c);
-		return ret;
+		goto error;
 	}
 
 	/*
@@ -253,7 +281,7 @@ int msm_atomic_commit(struct drm_device *dev,
 		return 0;
 	}
 
-	jiffies_to_timespec(jiffies + msecs_to_jiffies(1000), &timeout);
+	timeout = ktime_add_ms(ktime_get(), 1000);
 
 	ret = msm_wait_fence_interruptable(dev, c->fence, &timeout);
 	if (ret) {
@@ -265,4 +293,8 @@ int msm_atomic_commit(struct drm_device *dev,
 	complete_commit(c);
 
 	return 0;
+
+error:
+	drm_atomic_helper_cleanup_planes(dev, state);
+	return ret;
 }
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index c80a6bee2b18..b7ef56ed8d1c 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -638,7 +638,7 @@ static void msm_debugfs_cleanup(struct drm_minor *minor)
  */
 
 int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
-		struct timespec *timeout)
+		ktime_t *timeout)
 {
 	struct msm_drm_private *priv = dev->dev_private;
 	int ret;
@@ -656,14 +656,16 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
 		/* no-wait: */
 		ret = fence_completed(dev, fence) ? 0 : -EBUSY;
 	} else {
-		unsigned long timeout_jiffies = timespec_to_jiffies(timeout);
-		unsigned long start_jiffies = jiffies;
+		ktime_t now = ktime_get();
 		unsigned long remaining_jiffies;
 
-		if (time_after(start_jiffies, timeout_jiffies))
+		if (ktime_compare(*timeout, now) < 0) {
 			remaining_jiffies = 0;
-		else
-			remaining_jiffies = timeout_jiffies - start_jiffies;
+		} else {
+			ktime_t rem = ktime_sub(*timeout, now);
+			struct timespec ts = ktime_to_timespec(rem);
+			remaining_jiffies = timespec_to_jiffies(&ts);
+		}
 
 		ret = wait_event_interruptible_timeout(priv->fence_event,
 				fence_completed(dev, fence),
@@ -772,13 +774,17 @@ static int msm_ioctl_gem_new(struct drm_device *dev, void *data,
 			args->flags, &args->handle);
 }
 
-#define TS(t) ((struct timespec){ .tv_sec = (t).tv_sec, .tv_nsec = (t).tv_nsec })
+static inline ktime_t to_ktime(struct drm_msm_timespec timeout)
+{
+	return ktime_set(timeout.tv_sec, timeout.tv_nsec);
+}
 
 static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
 		struct drm_file *file)
 {
 	struct drm_msm_gem_cpu_prep *args = data;
 	struct drm_gem_object *obj;
+	ktime_t timeout = to_ktime(args->timeout);
 	int ret;
 
 	if (args->op & ~MSM_PREP_FLAGS) {
@@ -790,7 +796,7 @@ static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
 	if (!obj)
 		return -ENOENT;
 
-	ret = msm_gem_cpu_prep(obj, args->op, &TS(args->timeout));
+	ret = msm_gem_cpu_prep(obj, args->op, &timeout);
 
 	drm_gem_object_unreference_unlocked(obj);
 
@@ -840,14 +846,14 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
 		struct drm_file *file)
 {
 	struct drm_msm_wait_fence *args = data;
+	ktime_t timeout = to_ktime(args->timeout);
 
 	if (args->pad) {
 		DRM_ERROR("invalid pad: %08x\n", args->pad);
 		return -EINVAL;
 	}
 
-	return msm_wait_fence_interruptable(dev, args->fence,
-			&TS(args->timeout));
+	return msm_wait_fence_interruptable(dev, args->fence, &timeout);
 }
 
 static const struct drm_ioctl_desc msm_ioctls[] = {
@@ -885,6 +891,7 @@ static struct drm_driver msm_driver = {
 				DRIVER_GEM |
 				DRIVER_PRIME |
 				DRIVER_RENDER |
+				DRIVER_ATOMIC |
 				DRIVER_MODESET,
 	.load               = msm_load,
 	.unload             = msm_unload,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 04db4bd1b5b6..e7c5ea125d45 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -165,7 +165,7 @@ int msm_atomic_commit(struct drm_device *dev,
 int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
 
 int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
-		struct timespec *timeout);
+		ktime_t *timeout);
 int msm_queue_fence_cb(struct drm_device *dev,
 		struct msm_fence_cb *cb, uint32_t fence);
 void msm_update_fence(struct drm_device *dev, uint32_t fence);
@@ -205,7 +205,7 @@ void msm_gem_move_to_active(struct drm_gem_object *obj,
 		struct msm_gpu *gpu, bool write, uint32_t fence);
 void msm_gem_move_to_inactive(struct drm_gem_object *obj);
 int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
-		struct timespec *timeout);
+		ktime_t *timeout);
 int msm_gem_cpu_fini(struct drm_gem_object *obj);
 void msm_gem_free_object(struct drm_gem_object *obj);
 int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 52839769eb6c..f211b80e3a1e 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -448,8 +448,7 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj)
 	list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
 }
 
-int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
-		struct timespec *timeout)
+int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
 {
 	struct drm_device *dev = obj->dev;
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
@@ -540,6 +539,7 @@ void msm_gem_free_object(struct drm_gem_object *obj)
 		if (msm_obj->pages)
 			drm_free_large(msm_obj->pages);
 
+		drm_prime_gem_destroy(obj, msm_obj->sgt);
 	} else {
 		vunmap(msm_obj->vaddr);
 		put_pages(obj);
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 85d481e29276..6fc59bfeedeb 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -96,6 +96,7 @@ static inline uint32_t msm_gem_fence(struct msm_gem_object *msm_obj,
 struct msm_gem_submit {
 	struct drm_device *dev;
 	struct msm_gpu *gpu;
+	struct list_head node;   /* node in gpu submit_list */
 	struct list_head bo_list;
 	struct ww_acquire_ctx ticket;
 	uint32_t fence;
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index cd0554f68316..6d7cd3fe21e7 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -314,7 +314,6 @@ static void submit_cleanup(struct msm_gem_submit *submit, bool fail)
 	}
 
 	ww_acquire_fini(&submit->ticket);
-	kfree(submit);
 }
 
 int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 4a0dce587745..8f70d9248ac5 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -24,7 +24,7 @@
  * Power Management:
  */
 
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
 #include <mach/board.h>
 static void bs_init(struct msm_gpu *gpu)
 {
@@ -265,6 +265,8 @@ static void inactive_start(struct msm_gpu *gpu)
  * Hangcheck detection for locked gpu:
  */
 
+static void retire_submits(struct msm_gpu *gpu, uint32_t fence);
+
 static void recover_worker(struct work_struct *work)
 {
 	struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work);
@@ -274,8 +276,19 @@ static void recover_worker(struct work_struct *work)
 
 	mutex_lock(&dev->struct_mutex);
 	if (msm_gpu_active(gpu)) {
+		struct msm_gem_submit *submit;
+		uint32_t fence = gpu->funcs->last_fence(gpu);
+
+		/* retire completed submits, plus the one that hung: */
+		retire_submits(gpu, fence + 1);
+
 		inactive_cancel(gpu);
 		gpu->funcs->recover(gpu);
+
+		/* replay the remaining submits after the one that hung: */
+		list_for_each_entry(submit, &gpu->submit_list, node) {
+			gpu->funcs->submit(gpu, submit, NULL);
+		}
 	}
 	mutex_unlock(&dev->struct_mutex);
 
@@ -418,6 +431,27 @@ out:
  * Cmdstream submission/retirement:
  */
 
+static void retire_submits(struct msm_gpu *gpu, uint32_t fence)
+{
+	struct drm_device *dev = gpu->dev;
+
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	while (!list_empty(&gpu->submit_list)) {
+		struct msm_gem_submit *submit;
+
+		submit = list_first_entry(&gpu->submit_list,
+				struct msm_gem_submit, node);
+
+		if (submit->fence <= fence) {
+			list_del(&submit->node);
+			kfree(submit);
+		} else {
+			break;
+		}
+	}
+}
+
 static void retire_worker(struct work_struct *work)
 {
 	struct msm_gpu *gpu = container_of(work, struct msm_gpu, retire_work);
@@ -428,6 +462,8 @@ static void retire_worker(struct work_struct *work)
 
 	mutex_lock(&dev->struct_mutex);
 
+	retire_submits(gpu, fence);
+
 	while (!list_empty(&gpu->active_list)) {
 		struct msm_gem_object *obj;
 
@@ -467,21 +503,22 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 	struct msm_drm_private *priv = dev->dev_private;
 	int i, ret;
 
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
 	submit->fence = ++priv->next_fence;
 
 	gpu->submitted_fence = submit->fence;
 
 	inactive_cancel(gpu);
 
+	list_add_tail(&submit->node, &gpu->submit_list);
+
 	msm_rd_dump_submit(submit);
 
 	gpu->submitted_fence = submit->fence;
 
 	update_sw_cntrs(gpu);
 
-	ret = gpu->funcs->submit(gpu, submit, ctx);
-	priv->lastctx = ctx;
-
 	for (i = 0; i < submit->nr_bos; i++) {
 		struct msm_gem_object *msm_obj = submit->bos[i].obj;
 
@@ -505,6 +542,10 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 		if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
 			msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
 	}
+
+	ret = gpu->funcs->submit(gpu, submit, ctx);
+	priv->lastctx = ctx;
+
 	hangcheck_timer_reset(gpu);
 
 	return ret;
@@ -522,6 +563,7 @@ static irqreturn_t irq_handler(int irq, void *data)
 
 static const char *clk_names[] = {
 		"src_clk", "core_clk", "iface_clk", "mem_clk", "mem_iface_clk",
+		"alt_mem_iface_clk",
 };
 
 int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
@@ -544,6 +586,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
 	INIT_WORK(&gpu->inactive_work, inactive_worker);
 	INIT_WORK(&gpu->recover_work, recover_worker);
 
+	INIT_LIST_HEAD(&gpu->submit_list);
+
 	setup_timer(&gpu->inactive_timer, inactive_handler,
 			(unsigned long)gpu);
 	setup_timer(&gpu->hangcheck_timer, hangcheck_handler,
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index fd1e4b4a6d40..2bbe85a3d6f6 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -100,10 +100,10 @@ struct msm_gpu {
 
 	/* Power Control: */
 	struct regulator *gpu_reg, *gpu_cx;
-	struct clk *ebi1_clk, *grp_clks[5];
+	struct clk *ebi1_clk, *grp_clks[6];
 	uint32_t fast_rate, slow_rate, bus_freq;
 
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
 	struct msm_bus_scale_pdata *bus_scale_table;
 	uint32_t bsc;
 #endif
@@ -119,6 +119,8 @@ struct msm_gpu {
 	struct timer_list hangcheck_timer;
 	uint32_t hangcheck_fence;
 	struct work_struct recover_work;
+
+	struct list_head submit_list;
 };
 
 static inline bool msm_gpu_active(struct msm_gpu *gpu)
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index a9f17bdb4530..9bcabaada179 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -43,6 +43,9 @@ struct msm_kms_funcs {
 	/* modeset, bracketing atomic_commit(): */
 	void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
 	void (*complete_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
+	/* functions to wait for atomic commit completed on each CRTC */
+	void (*wait_for_crtc_commit_done)(struct msm_kms *kms,
+					struct drm_crtc *crtc);
 	/* misc: */
 	const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t format);
 	long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,