diff --git a/Documentation/devicetree/bindings/drm/msm/mdp.txt b/Documentation/devicetree/bindings/drm/msm/mdp.txt
index 99ba764..0114a87 100644
--- a/Documentation/devicetree/bindings/drm/msm/mdp.txt
+++ b/Documentation/devicetree/bindings/drm/msm/mdp.txt
@@ -22,6 +22,7 @@ Optional properties:
   * "iommu_clk"
   * "mmagic_clk"
 - mmagic-supply: phandle for mmagic GDSC regulator used during IOMMU translation
+- iommus: phandle for IOMMU v2 device
 
 Example:
 
@@ -48,5 +49,6 @@ Example:
 		    <&mmcc TV_SRC>,
 		    <&mmcc HDMI_TV_CLK>,
 		    <&mmcc MDP_TV_CLK>;
+		iommus = <&mdp_smmu 0>;
 	};
 };
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index a1e26f2..bb1225a 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -27,6 +27,8 @@ const struct mdp5_cfg_hw msm8x74v1_config = {
 	.mdp = {
 		.count = 1,
 		.base = { 0x00100 },
+		.caps = MDP_CAP_SMP |
+			0,
 	},
 	.smp = {
 		.mmb_count = 22,
@@ -96,6 +98,8 @@ const struct mdp5_cfg_hw msm8x74v2_config = {
 	.mdp = {
 		.count = 1,
 		.base = { 0x00100 },
+		.caps = MDP_CAP_SMP |
+			0,
 	},
 	.smp = {
 		.mmb_count = 22,
@@ -165,6 +169,8 @@ const struct mdp5_cfg_hw apq8084_config = {
 	.mdp = {
 		.count = 1,
 		.base = { 0x00100 },
+		.caps = MDP_CAP_SMP |
+			0,
 	},
 	.smp = {
 		.mmb_count = 44,
@@ -242,6 +248,8 @@ const struct mdp5_cfg_hw msm8x16_config = {
 	.mdp = {
 		.count = 1,
 		.base = { 0x01000 },
+		.caps = MDP_CAP_SMP |
+			0,
 	},
 	.smp = {
 		.mmb_count = 8,
@@ -301,6 +309,8 @@ const struct mdp5_cfg_hw msm8x94_config = {
 	.mdp = {
 		.count = 1,
 		.base = { 0x01000 },
+		.caps = MDP_CAP_SMP |
+			0,
 	},
 	.smp = {
 		.mmb_count = 44,
@@ -370,7 +380,89 @@ const struct mdp5_cfg_hw msm8x94_config = {
 			[3] = INTF_HDMI,
 		},
 	},
-	.max_clk = 320000000,
+	.max_clk = 400000000,
+};
+
+const struct mdp5_cfg_hw msm8x96_config = {
+	.name = "msm8x96",
+	.mdp = {
+		.count = 1,
+		.base = { 0x01000 },
+		.caps = MDP_CAP_DSC |
+			MDP_CAP_CDM |
+			0,
+	},
+	.ctl = {
+		.count = 5,
+		.base = { 0x02000, 0x02200, 0x02400, 0x02600, 0x02800 },
+		.flush_hw_mask = 0xf4ffffff,
+	},
+	.pipe_vig = {
+		.count = 4,
+		.base = { 0x05000, 0x07000, 0x09000, 0x0b000 },
+		.caps = MDP_PIPE_CAP_HFLIP	|
+			MDP_PIPE_CAP_VFLIP	|
+			MDP_PIPE_CAP_SCALE	|
+			MDP_PIPE_CAP_CSC	|
+			MDP_PIPE_CAP_DECIMATION	|
+			MDP_PIPE_CAP_SW_PIX_EXT	|
+			0,
+	},
+	.pipe_rgb = {
+		.count = 4,
+		.base = { 0x15000, 0x17000, 0x19000, 0x1b000 },
+		.caps = MDP_PIPE_CAP_HFLIP	|
+			MDP_PIPE_CAP_VFLIP	|
+			MDP_PIPE_CAP_SCALE	|
+			MDP_PIPE_CAP_DECIMATION	|
+			MDP_PIPE_CAP_SW_PIX_EXT	|
+			0,
+	},
+	.pipe_dma = {
+		.count = 2,
+		.base = { 0x25000, 0x27000 },
+		.caps = MDP_PIPE_CAP_HFLIP	|
+			MDP_PIPE_CAP_VFLIP	|
+			MDP_PIPE_CAP_SW_PIX_EXT	|
+			0,
+	},
+	.lm = {
+		.count = 6,
+		.base = { 0x45000, 0x46000, 0x47000, 0x48000, 0x49000, 0x4a000 },
+		.nb_stages = 8,
+		.max_width = 2560,
+		.max_height = 0xFFFF,
+	},
+	.dspp = {
+		.count = 2,
+		.base = { 0x55000, 0x57000 },
+	},
+	.ad = {
+		.count = 3,
+		.base = { 0x79000, 0x79800, 0x7a000 },
+	},
+	.pp = {
+		.count = 4,
+		.base = { 0x71000, 0x71800, 0x72000, 0x72800 },
+	},
+	.cdm = {
+		.count = 1,
+		.base = { 0x7a200 },
+	},
+	.dsc = {
+		.count = 2,
+		.base = { 0x81000, 0x81400 },
+	},
+	.intf = {
+		.base = { 0x6b000, 0x6b800, 0x6c000, 0x6c800, 0x6d000 },
+		.connect = {
+			[0] = INTF_DISABLED,
+			[1] = INTF_DSI,
+			[2] = INTF_DSI,
+			[3] = INTF_HDMI,
+		},
+	},
+	.max_clk = 412500000,
 };
 
 static const struct mdp5_cfg_handler cfg_handlers[] = {
@@ -379,6 +471,7 @@ static const struct mdp5_cfg_handler cfg_handlers[] = {
 	{ .revision = 3, .config = { .hw = &apq8084_config } },
 	{ .revision = 6, .config = { .hw = &msm8x16_config } },
 	{ .revision = 9, .config = { .hw = &msm8x94_config } },
+	{ .revision = 7, .config = { .hw = &msm8x96_config } },
 };
 
 static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
index a6facaf..050e161 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
@@ -64,6 +64,11 @@ struct mdp5_smp_block {
 	uint8_t reserved[MAX_CLIENTS];	/* # of MMBs allocated per client */
 };
 
+struct mdp5_mdp_block {
+	MDP5_SUB_BLOCK_DEFINITION;
+	uint32_t caps;			/* MDP capabilities: MDP_CAP_xxx bits */
+};
+
 #define MDP5_INTF_NUM_MAX	5
 
 struct mdp5_intf_block {
@@ -74,7 +79,7 @@ struct mdp5_intf_block {
 struct mdp5_cfg_hw {
 	char  *name;
 
-	struct mdp5_sub_block mdp;
+	struct mdp5_mdp_block mdp;
 	struct mdp5_smp_block smp;
 	struct mdp5_ctl_block ctl;
 	struct mdp5_pipe_block pipe_vig;
@@ -84,6 +89,8 @@ struct mdp5_cfg_hw {
 	struct mdp5_sub_block dspp;
 	struct mdp5_sub_block ad;
 	struct mdp5_sub_block pp;
+	struct mdp5_sub_block dsc;
+	struct mdp5_sub_block cdm;
 	struct mdp5_intf_block intf;
 
 	uint32_t max_clk;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 983bd53..0041d64 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -614,15 +614,23 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
 	}
 
 	config = mdp5_cfg_get_config(mdp5_kms->cfg);
+	mdp5_kms->caps = config->hw->mdp.caps;
 
 	/* TODO: compute core clock rate at runtime */
 	clk_set_rate(mdp5_kms->src_clk, config->hw->max_clk);
 
-	mdp5_kms->smp = mdp5_smp_init(mdp5_kms->dev, &config->hw->smp);
-	if (IS_ERR(mdp5_kms->smp)) {
-		ret = PTR_ERR(mdp5_kms->smp);
-		mdp5_kms->smp = NULL;
-		goto fail;
+	/*
+	 * Some chipsets have a Shared Memory Pool (SMP), while others
+	 * have dedicated latency buffering per source pipe instead;
+	 * this section initializes the SMP:
+	 */
+	if (mdp5_kms->caps & MDP_CAP_SMP) {
+		mdp5_kms->smp = mdp5_smp_init(mdp5_kms->dev, &config->hw->smp);
+		if (IS_ERR(mdp5_kms->smp)) {
+			ret = PTR_ERR(mdp5_kms->smp);
+			mdp5_kms->smp = NULL;
+			goto fail;
+		}
 	}
 
 	mdp5_kms->ctlm = mdp5_ctlm_init(dev, mdp5_kms->mmio, mdp5_kms->cfg);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index ab19d52a..977ef62 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -32,6 +32,8 @@ struct mdp5_kms {
 	struct drm_device *dev;
 
 	struct mdp5_cfg_handler *cfg;
+	uint32_t caps;	/* MDP capabilities (MDP_CAP_XXX bits) */
+
 
 	/* mapper-id used to request GEM buffer mapped for scanout: */
 	int id;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index c86f49f..8ee62dc 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -699,10 +699,12 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 			crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
 
 	/* Request some memory from the SMP: */
-	ret = mdp5_smp_request(mdp5_kms->smp,
-			mdp5_plane->pipe, format, src_w, false);
-	if (ret)
-		return ret;
+	if (mdp5_kms->smp) {
+		ret = mdp5_smp_request(mdp5_kms->smp,
+				mdp5_plane->pipe, format, src_w, false);
+		if (ret)
+			return ret;
+	}
 
 	/*
 	 * Currently we update the hw for allocations/requests immediately,
@@ -710,7 +712,8 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 	 * would move into atomic->check_plane_state(), while updating the
 	 * hw would remain here:
 	 */
-	mdp5_smp_configure(mdp5_kms->smp, pipe);
+	if (mdp5_kms->smp)
+		mdp5_smp_configure(mdp5_kms->smp, pipe);
 
 	ret = calc_scalex_steps(plane, pix_format, src_w, crtc_w, phasex_step);
 	if (ret)
@@ -829,7 +832,8 @@ void mdp5_plane_complete_flip(struct drm_plane *plane)
 
 	DBG("%s: complete flip", mdp5_plane->name);
 
-	mdp5_smp_commit(mdp5_kms->smp, pipe);
+	if (mdp5_kms->smp)
+		mdp5_smp_commit(mdp5_kms->smp, pipe);
 
 	to_mdp5_plane_state(plane->state)->pending = false;
 }
@@ -855,7 +859,7 @@ void mdp5_plane_complete_commit(struct drm_plane *plane,
 	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
 	enum mdp5_pipe pipe = mdp5_plane->pipe;
 
-	if (!plane_enabled(plane->state)) {
+	if (!plane_enabled(plane->state) && mdp5_kms->smp) {
 		DBG("%s: free SMP", mdp5_plane->name);
 		mdp5_smp_release(mdp5_kms->smp, pipe);
 	}
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h
index 0af2a541..3031303 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h
@@ -100,6 +100,11 @@ struct mdp_format {
 uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool rgb_only);
 const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
 
+/* MDP capabilities */
+#define MDP_CAP_SMP		BIT(0)	/* Shared Memory Pool                 */
+#define MDP_CAP_DSC		BIT(1)	/* VESA Display Stream Compression    */
+#define MDP_CAP_CDM		BIT(2)	/* Chroma Down Module (HDMI 2.0 YUV)  */
+
 /* MDP pipe capabilities */
 #define MDP_PIPE_CAP_HFLIP			BIT(0)
 #define MDP_PIPE_CAP_VFLIP			BIT(1)
