diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 56f6576..afb8c79 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -175,7 +175,8 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
 	struct dpu_rect plane_crtc_roi;
 
 	u32 flush_mask;
-	uint32_t stage_idx, lm_idx;
+	uint32_t stage_idx = 0, lm_idx;
+	int i;
 	int zpos_cnt[DPU_STAGE_MAX + 1] = { 0 };
 	bool bg_alpha_enable = false;
 
@@ -204,11 +205,11 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
 
 		dpu_plane_get_ctl_flush(plane, ctl, &flush_mask);
 
-		DPU_DEBUG("crtc %d stage:%d - plane %d sspp %d fb %d\n",
-				crtc->base.id,
-				pstate->stage,
-				plane->base.id,
-				dpu_plane_pipe(plane) - SSPP_VIG0,
+		DPU_DEBUG("crtc %d stage%d: plane%d ssppmode%d[%d %d] fb%d\n",
+				crtc->base.id, pstate->stage,
+				plane->base.id, pstate->num_pipes,
+				dpu_plane_pipe(pstate->pipe_hw[0]) - SSPP_VIG0,
+				dpu_plane_pipe(pstate->pipe_hw[1]) - SSPP_VIG0,
 				state->fb ? state->fb->base.id : -1);
 
 		format = to_dpu_format(msm_framebuffer_format(pstate->base.fb));
@@ -221,19 +222,25 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
 			bg_alpha_enable = true;
 
 		DPU_EVT32(DRMID(crtc), DRMID(plane),
-				state->fb ? state->fb->base.id : -1,
-				state->src_x >> 16, state->src_y >> 16,
-				state->src_w >> 16, state->src_h >> 16,
-				state->crtc_x, state->crtc_y,
-				state->crtc_w, state->crtc_h);
-
-		stage_idx = zpos_cnt[pstate->stage]++;
-		stage_cfg->stage[pstate->stage][stage_idx] =
-					dpu_plane_pipe(plane);
-
-		DPU_EVT32(DRMID(crtc), DRMID(plane), stage_idx,
-			dpu_plane_pipe(plane) - SSPP_VIG0, pstate->stage,
-			format->base.pixel_format, fb ? fb->modifier : 0);
+			state->fb ? state->fb->base.id : -1,
+			state->src_x >> 16, state->src_y >> 16,
+			state->src_w >> 16, state->src_h >> 16,
+			state->crtc_x, state->crtc_y,
+			state->crtc_w, state->crtc_h);
+
+		for (i = 0; i < pstate->num_pipes; i++) {
+			stage_idx = zpos_cnt[pstate->stage]++;
+			if (stage_idx >= PIPES_PER_STAGE)
+				break;
+
+			stage_cfg->stage[pstate->stage][stage_idx] =
+				dpu_plane_pipe(pstate->pipe_hw[i]);
+
+			DPU_EVT32(DRMID(crtc), DRMID(plane), stage_idx,
+				dpu_plane_pipe(pstate->pipe_hw[i]) - SSPP_VIG0,
+				pstate->stage, format->base.pixel_format,
+				fb ? fb->modifier : 0);
+		}
 
 		/* blend config update */
 		for (lm_idx = 0; lm_idx < cstate->num_mixers; lm_idx++) {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index be40a2c..2c6960e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -81,40 +81,26 @@ enum dpu_plane_qos {
 
 /*
  * struct dpu_plane - local dpu plane structure
- * @aspace: address space pointer
  * @csc_ptr: Points to dpu_csc_cfg structure to use for current
- * @catalog: Points to dpu catalog structure
- * @revalidate: force revalidation of all the plane properties
  */
 struct dpu_plane {
 	struct drm_plane base;
 
 	struct mutex lock;
 
-	enum dpu_sspp pipe;
-	uint32_t features;      /* capabilities from catalog */
 	uint32_t nformats;
 	uint32_t formats[64];
 
-	struct dpu_hw_pipe *pipe_hw;
-	struct dpu_hw_pipe_cfg pipe_cfg;
-	struct dpu_hw_pipe_qos_cfg pipe_qos_cfg;
 	uint32_t color_fill;
 	bool is_error;
-	bool is_rt_pipe;
-	struct dpu_mdss_cfg *catalog;
+	bool is_rt_client;
 
 	struct dpu_csc_cfg *csc_ptr;
-
-	const struct dpu_sspp_sub_blks *pipe_sblk;
-	char pipe_name[DPU_NAME_SIZE];
+	char name[DPU_NAME_SIZE];
 
 	/* debugfs related stuff */
 	struct dentry *debugfs_root;
-	struct dpu_debugfs_regset32 debugfs_src;
-	struct dpu_debugfs_regset32 debugfs_scaler;
-	struct dpu_debugfs_regset32 debugfs_csc;
-	bool debugfs_default_scale;
+
 };
 
 #define to_dpu_plane(x) container_of(x, struct dpu_plane, base)
@@ -141,14 +127,46 @@ static bool dpu_plane_sspp_enabled(struct drm_plane_state *state)
 	return state && state->crtc;
 }
 
+void _dpu_plane_get_roi_config(struct drm_plane_state *state,
+		struct dpu_rect *src, struct dpu_rect *dst)
+{
+	struct dpu_plane_state *pstate = to_dpu_plane_state(state);
+	bool q16_data = true;
+	int div = (pstate->num_pipes == PLANE_DUAL_PIPES) ? 2 : 1;
+
+	DPU_DEBUG("plane %d:", state->plane->base.id);
+
+	if (src) {
+		POPULATE_RECT(src, state->src_x, state->src_y,
+		state->src_w, state->src_h, q16_data);
+
+		DPU_DEBUG("src_rect: %u,%u,(%u/%d)x%u\n",
+			src->x, src->y, src->w, div, src->h);
+
+		src->w /= div;
+	}
+
+	if (dst) {
+		POPULATE_RECT(dst, state->crtc_x, state->crtc_y,
+		state->crtc_w, state->crtc_h, !q16_data);
+
+		DPU_DEBUG("dst_rect: %d,%d,(%u/%d)x%u\n",
+			dst->x, dst->y, dst->w, div, dst->h);
+
+		dst->w /= div;
+	}
+}
+
 /**
  * _dpu_plane_calc_fill_level - calculate fill level of the given source format
  * @plane:		Pointer to drm plane
+ * @pipe_hw:	Pointer to hardware pipe
  * @fmt:		Pointer to source buffer format
  * @src_wdith:		width of source buffer
  * Return: fill level corresponding to the source buffer/format or 0 if error
  */
 static inline int _dpu_plane_calc_fill_level(struct drm_plane *plane,
+		struct dpu_hw_pipe *pipe_hw,
 		const struct dpu_format *fmt, u32 src_width)
 {
 	struct dpu_kms *kms;
@@ -179,12 +197,12 @@ static inline int _dpu_plane_calc_fill_level(struct drm_plane *plane,
 				((src_width + 32) * fmt->bpp);
 		}
 	} else {
-			total_fl = (fixed_buff_size) * 2 /
+		total_fl = (fixed_buff_size) * 2 /
 				((src_width + 32) * fmt->bpp);
 	}
 
-	DPU_DEBUG("plane%u: pnum:%d fmt: %4.4s w:%u fl:%u\n",
-			plane->base.id, pdpu->pipe - SSPP_VIG0,
+	DPU_DEBUG("plane%d: pnum:%d fmt:%4.4s w:%u fl:%u\n",
+			plane->base.id, pipe_hw->idx - SSPP_VIG0,
 			(char *)&fmt->base.pixel_format,
 			src_width, total_fl);
 
@@ -219,39 +237,38 @@ static u64 _dpu_plane_get_qos_lut(const struct dpu_qos_lut_tbl *tbl,
 /**
  * _dpu_plane_set_qos_lut - set QoS LUT of the given plane
  * @plane:		Pointer to drm plane
+ * @pipe_hw:		Pointer to hardware pipe
+ * @pipe_cfg:		Pointer to hardware pipe config
  * @fb:			Pointer to framebuffer associated with the given plane
  */
 static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
-		struct drm_framebuffer *fb)
+	struct dpu_hw_pipe *pipe_hw, struct dpu_hw_pipe_cfg *pipe_cfg,
+	struct drm_framebuffer *fb)
 {
+	struct dpu_kms *kms;
 	struct dpu_plane *pdpu;
 	const struct dpu_format *fmt = NULL;
 	u64 qos_lut;
 	u32 total_fl = 0, lut_usage;
+	struct dpu_hw_pipe_qos_cfg pipe_qos_cfg;
 
-	if (!plane || !fb) {
-		DPU_ERROR("invalid arguments plane %d fb %d\n",
-				plane != 0, fb != 0);
+	if (!plane || !pipe_hw || !pipe_cfg || !fb ||
+		!pipe_hw->ops.setup_creq_lut) {
+		DPU_ERROR("invalid arguments plane %d hw %d cfg %d fb %d\n",
+			plane != 0, pipe_hw != 0, pipe_cfg != 0, fb != 0);
 		return;
 	}
 
 	pdpu = to_dpu_plane(plane);
+	kms = _dpu_plane_get_kms(&pdpu->base);
 
-	if (!pdpu->pipe_hw || !pdpu->pipe_sblk || !pdpu->catalog) {
-		DPU_ERROR("invalid arguments\n");
-		return;
-	} else if (!pdpu->pipe_hw->ops.setup_creq_lut) {
-		return;
-	}
-
-	if (!pdpu->is_rt_pipe) {
+	if (!pdpu->is_rt_client) {
 		lut_usage = DPU_QOS_LUT_USAGE_NRT;
 	} else {
-		fmt = dpu_get_dpu_format_ext(
-				fb->format->format,
-				fb->modifier);
-		total_fl = _dpu_plane_calc_fill_level(plane, fmt,
-				pdpu->pipe_cfg.src_rect.w);
+		fmt = dpu_get_dpu_format_ext(fb->format->format,
+					fb->modifier);
+		total_fl = _dpu_plane_calc_fill_level(plane, pipe_hw,
+					fmt, pipe_cfg->src_rect.w);
 
 		if (fmt && DPU_FORMAT_IS_LINEAR(fmt))
 			lut_usage = DPU_QOS_LUT_USAGE_LINEAR;
@@ -260,53 +277,52 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
 	}
 
 	qos_lut = _dpu_plane_get_qos_lut(
-			&pdpu->catalog->perf.qos_lut_tbl[lut_usage], total_fl);
+		&kms->catalog->perf.qos_lut_tbl[lut_usage], total_fl);
 
-	pdpu->pipe_qos_cfg.creq_lut = qos_lut;
+	memset(&pipe_qos_cfg, 0, sizeof(struct dpu_hw_pipe_qos_cfg));
+	pipe_qos_cfg.creq_lut = qos_lut;
 
-	trace_dpu_perf_set_qos_luts(pdpu->pipe - SSPP_VIG0,
-			(fmt) ? fmt->base.pixel_format : 0,
-			pdpu->is_rt_pipe, total_fl, qos_lut, lut_usage);
+	trace_dpu_perf_set_qos_luts(pipe_hw->idx - SSPP_VIG0,
+		(fmt) ? fmt->base.pixel_format : 0,
+		pdpu->is_rt_client, total_fl, qos_lut, lut_usage);
 
 	DPU_DEBUG("plane%u: pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n",
-			plane->base.id,
-			pdpu->pipe - SSPP_VIG0,
-			fmt ? (char *)&fmt->base.pixel_format : NULL,
-			pdpu->is_rt_pipe, total_fl, qos_lut);
+		plane->base.id, pipe_hw->idx - SSPP_VIG0,
+		fmt ? (char *)&fmt->base.pixel_format : NULL,
+		pdpu->is_rt_client, total_fl, qos_lut);
 
-	pdpu->pipe_hw->ops.setup_creq_lut(pdpu->pipe_hw, &pdpu->pipe_qos_cfg);
+	pipe_hw->ops.setup_creq_lut(pipe_hw, &pipe_qos_cfg);
 }
 
 /**
- * _dpu_plane_set_panic_lut - set danger/safe LUT of the given plane
+ * _dpu_plane_set_danger_lut - set danger/safe LUT of the given plane
  * @plane:		Pointer to drm plane
- * @fb:			Pointer to framebuffer associated with the given plane
+ * @pipe_hw:		Pointer to hardware pipe
+ * @fb:		Pointer to framebuffer associated with the given plane
  */
 static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
-		struct drm_framebuffer *fb)
+		struct dpu_hw_pipe *pipe_hw, struct drm_framebuffer *fb)
 {
+	struct dpu_kms *kms;
 	struct dpu_plane *pdpu;
 	const struct dpu_format *fmt = NULL;
 	u32 danger_lut, safe_lut;
+	struct dpu_hw_pipe_qos_cfg pipe_qos_cfg;
 
-	if (!plane || !fb) {
-		DPU_ERROR("invalid arguments\n");
+	if (!plane || !pipe_hw || !fb ||
+		!pipe_hw->ops.setup_danger_safe_lut) {
+		DPU_ERROR("invalid arguments plane %d hw %d fb %d\n",
+			plane != 0, pipe_hw != 0, fb != 0);
 		return;
 	}
 
 	pdpu = to_dpu_plane(plane);
+	kms = _dpu_plane_get_kms(&pdpu->base);
 
-	if (!pdpu->pipe_hw || !pdpu->pipe_sblk || !pdpu->catalog) {
-		DPU_ERROR("invalid arguments\n");
-		return;
-	} else if (!pdpu->pipe_hw->ops.setup_danger_safe_lut) {
-		return;
-	}
-
-	if (!pdpu->is_rt_pipe) {
-		danger_lut = pdpu->catalog->perf.danger_lut_tbl
+	if (!pdpu->is_rt_client) {
+		danger_lut = kms->catalog->perf.danger_lut_tbl
 				[DPU_QOS_LUT_USAGE_NRT];
-		safe_lut = pdpu->catalog->perf.safe_lut_tbl
+		safe_lut = kms->catalog->perf.safe_lut_tbl
 				[DPU_QOS_LUT_USAGE_NRT];
 	} else {
 		fmt = dpu_get_dpu_format_ext(
@@ -314,105 +330,101 @@ static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
 				fb->modifier);
 
 		if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) {
-			danger_lut = pdpu->catalog->perf.danger_lut_tbl
+			danger_lut = kms->catalog->perf.danger_lut_tbl
 					[DPU_QOS_LUT_USAGE_LINEAR];
-			safe_lut = pdpu->catalog->perf.safe_lut_tbl
+			safe_lut = kms->catalog->perf.safe_lut_tbl
 					[DPU_QOS_LUT_USAGE_LINEAR];
 		} else {
-			danger_lut = pdpu->catalog->perf.danger_lut_tbl
+			danger_lut = kms->catalog->perf.danger_lut_tbl
 					[DPU_QOS_LUT_USAGE_MACROTILE];
-			safe_lut = pdpu->catalog->perf.safe_lut_tbl
+			safe_lut = kms->catalog->perf.safe_lut_tbl
 					[DPU_QOS_LUT_USAGE_MACROTILE];
 		}
 	}
 
-	pdpu->pipe_qos_cfg.danger_lut = danger_lut;
-	pdpu->pipe_qos_cfg.safe_lut = safe_lut;
+	memset(&pipe_qos_cfg, 0, sizeof(struct dpu_hw_pipe_qos_cfg));
+	pipe_qos_cfg.danger_lut = danger_lut;
+	pipe_qos_cfg.safe_lut = safe_lut;
 
-	trace_dpu_perf_set_danger_luts(pdpu->pipe - SSPP_VIG0,
-			(fmt) ? fmt->base.pixel_format : 0,
-			(fmt) ? fmt->fetch_mode : 0,
-			pdpu->pipe_qos_cfg.danger_lut,
-			pdpu->pipe_qos_cfg.safe_lut);
+	trace_dpu_perf_set_danger_luts(pipe_hw->idx - SSPP_VIG0,
+		(fmt) ? fmt->base.pixel_format : 0,
+		(fmt) ? fmt->fetch_mode : 0,
+		pipe_qos_cfg.danger_lut, pipe_qos_cfg.safe_lut);
 
-	DPU_DEBUG("plane%u: pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n",
-		plane->base.id,
-		pdpu->pipe - SSPP_VIG0,
+	DPU_DEBUG("plane%u:pnum:%d fmt:%4.4s mode:%d luts[0x%x,0x%x]\n",
+		plane->base.id, pipe_hw->idx - SSPP_VIG0,
 		fmt ? (char *)&fmt->base.pixel_format : NULL,
-		fmt ? fmt->fetch_mode : -1,
-		pdpu->pipe_qos_cfg.danger_lut,
-		pdpu->pipe_qos_cfg.safe_lut);
+		fmt ? fmt->fetch_mode : -1, pipe_qos_cfg.danger_lut,
+		pipe_qos_cfg.safe_lut);
+
+	pipe_hw->ops.setup_danger_safe_lut(pipe_hw, &pipe_qos_cfg);
 
-	pdpu->pipe_hw->ops.setup_danger_safe_lut(pdpu->pipe_hw,
-			&pdpu->pipe_qos_cfg);
 }
 
 /**
  * _dpu_plane_set_qos_ctrl - set QoS control of the given plane
  * @plane:		Pointer to drm plane
+ * @pipe_hw:		Pointer to hardware pipe
  * @enable:		true to enable QoS control
  * @flags:		QoS control mode (enum dpu_plane_qos)
  */
 static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
-	bool enable, u32 flags)
+		struct dpu_hw_pipe *pipe_hw, bool enable, u32 flags)
 {
 	struct dpu_plane *pdpu;
+	struct dpu_hw_pipe_qos_cfg pipe_qos_cfg;
 
-	if (!plane) {
+	if (!plane || !pipe_hw || !pipe_hw->cap->sblk ||
+		!pipe_hw->ops.setup_qos_ctrl) {
 		DPU_ERROR("invalid arguments\n");
 		return;
 	}
 
 	pdpu = to_dpu_plane(plane);
-
-	if (!pdpu->pipe_hw || !pdpu->pipe_sblk) {
-		DPU_ERROR("invalid arguments\n");
-		return;
-	} else if (!pdpu->pipe_hw->ops.setup_qos_ctrl) {
-		return;
-	}
+	memset(&pipe_qos_cfg, 0, sizeof(struct dpu_hw_pipe_qos_cfg));
 
 	if (flags & DPU_PLANE_QOS_VBLANK_CTRL) {
-		pdpu->pipe_qos_cfg.creq_vblank = pdpu->pipe_sblk->creq_vblank;
-		pdpu->pipe_qos_cfg.danger_vblank =
-				pdpu->pipe_sblk->danger_vblank;
-		pdpu->pipe_qos_cfg.vblank_en = enable;
+		pipe_qos_cfg.creq_vblank =
+			pipe_hw->cap->sblk->creq_vblank;
+		pipe_qos_cfg.danger_vblank =
+			pipe_hw->cap->sblk->danger_vblank;
+		pipe_qos_cfg.vblank_en = enable;
 	}
 
 	if (flags & DPU_PLANE_QOS_VBLANK_AMORTIZE) {
 		/* this feature overrules previous VBLANK_CTRL */
-		pdpu->pipe_qos_cfg.vblank_en = false;
-		pdpu->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
+		pipe_qos_cfg.vblank_en = false;
+		/* clear vblank bits */
+		pipe_qos_cfg.creq_vblank = 0;
 	}
 
 	if (flags & DPU_PLANE_QOS_PANIC_CTRL)
-		pdpu->pipe_qos_cfg.danger_safe_en = enable;
+		pipe_qos_cfg.danger_safe_en = enable;
 
-	if (!pdpu->is_rt_pipe) {
-		pdpu->pipe_qos_cfg.vblank_en = false;
-		pdpu->pipe_qos_cfg.danger_safe_en = false;
+	if (!pdpu->is_rt_client) {
+		pipe_qos_cfg.vblank_en = false;
+		pipe_qos_cfg.danger_safe_en = false;
 	}
 
-	DPU_DEBUG("plane%u: pnum:%d ds:%d vb:%d pri[0x%x, 0x%x] is_rt:%d\n",
-		plane->base.id,
-		pdpu->pipe - SSPP_VIG0,
-		pdpu->pipe_qos_cfg.danger_safe_en,
-		pdpu->pipe_qos_cfg.vblank_en,
-		pdpu->pipe_qos_cfg.creq_vblank,
-		pdpu->pipe_qos_cfg.danger_vblank,
-		pdpu->is_rt_pipe);
+	DPU_DEBUG("plane%u:pnum:%d ds:%d vb:%d pr[0x%x,0x%x]is_rt:%d\n",
+		plane->base.id, pipe_hw->idx - SSPP_VIG0,
+		pipe_qos_cfg.danger_safe_en, pipe_qos_cfg.vblank_en,
+		pipe_qos_cfg.creq_vblank, pipe_qos_cfg.danger_vblank,
+		pdpu->is_rt_client);
+
+	pipe_hw->ops.setup_qos_ctrl(pipe_hw, &pipe_qos_cfg);
 
-	pdpu->pipe_hw->ops.setup_qos_ctrl(pdpu->pipe_hw,
-			&pdpu->pipe_qos_cfg);
 }
 
 int dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
 {
 	struct dpu_plane *pdpu;
+	struct dpu_plane_state *pstate;
 	struct msm_drm_private *priv;
 	struct dpu_kms *dpu_kms;
+	int i;
 
-	if (!plane || !plane->dev) {
+	if (!plane || !plane->dev || !plane->state) {
 		DPU_ERROR("invalid arguments\n");
 		return -EINVAL;
 	}
@@ -425,12 +437,15 @@ int dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
 
 	dpu_kms = to_dpu_kms(priv->kms);
 	pdpu = to_dpu_plane(plane);
+	pstate = to_dpu_plane_state(plane->state);
 
-	if (!pdpu->is_rt_pipe)
+	if (!pdpu->is_rt_client)
 		goto end;
 
 	pm_runtime_get_sync(&dpu_kms->pdev->dev);
-	_dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL);
+	for (i = 0; i < pstate->num_pipes; i++)
+		_dpu_plane_set_qos_ctrl(plane,  pstate->pipe_hw[i],
+			enable, DPU_PLANE_QOS_PANIC_CTRL);
 	pm_runtime_put_sync(&dpu_kms->pdev->dev);
 
 end:
@@ -440,19 +455,22 @@ int dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
 /**
  * _dpu_plane_set_ot_limit - set OT limit for the given plane
  * @plane:		Pointer to drm plane
+ * @pipe_hw:		Pointer to hardware pipe
+ * @pipe_cfg:		Pointer to hardware pipe config
  * @crtc:		Pointer to drm crtc
  */
 static void _dpu_plane_set_ot_limit(struct drm_plane *plane,
-		struct drm_crtc *crtc)
+	struct dpu_hw_pipe *pipe_hw, struct dpu_hw_pipe_cfg *pipe_cfg,
+	struct drm_crtc *crtc)
 {
 	struct dpu_plane *pdpu;
 	struct dpu_vbif_set_ot_params ot_params;
 	struct msm_drm_private *priv;
 	struct dpu_kms *dpu_kms;
 
-	if (!plane || !plane->dev || !crtc) {
-		DPU_ERROR("invalid arguments plane %d crtc %d\n",
-				plane != 0, crtc != 0);
+	if (!plane || !plane->dev || !pipe_hw || !pipe_cfg || !crtc) {
+		DPU_ERROR("invalid arguments plane %d hw %d cfg %d crtc %d\n",
+			plane != 0, pipe_hw != 0, pipe_cfg != 0, crtc != 0);
 		return;
 	}
 
@@ -463,38 +481,38 @@ static void _dpu_plane_set_ot_limit(struct drm_plane *plane,
 	}
 
 	dpu_kms = to_dpu_kms(priv->kms);
+
 	pdpu = to_dpu_plane(plane);
-	if (!pdpu->pipe_hw) {
-		DPU_ERROR("invalid pipe reference\n");
-		return;
-	}
 
 	memset(&ot_params, 0, sizeof(ot_params));
-	ot_params.xin_id = pdpu->pipe_hw->cap->xin_id;
-	ot_params.num = pdpu->pipe_hw->idx - SSPP_NONE;
-	ot_params.width = pdpu->pipe_cfg.src_rect.w;
-	ot_params.height = pdpu->pipe_cfg.src_rect.h;
-	ot_params.is_wfd = !pdpu->is_rt_pipe;
+	ot_params.xin_id = pipe_hw->cap->xin_id;
+	ot_params.num = pipe_hw->idx - SSPP_NONE;
+	ot_params.width = pipe_cfg->src_rect.w;
+	ot_params.height = pipe_cfg->src_rect.h;
+	ot_params.is_wfd = !pdpu->is_rt_client;
 	ot_params.frame_rate = crtc->mode.vrefresh;
 	ot_params.vbif_idx = VBIF_RT;
-	ot_params.clk_ctrl = pdpu->pipe_hw->cap->clk_ctrl;
+	ot_params.clk_ctrl = pipe_hw->cap->clk_ctrl;
 	ot_params.rd = true;
 
 	dpu_vbif_set_ot_limit(dpu_kms, &ot_params);
+
 }
 
 /**
  * _dpu_plane_set_vbif_qos - set vbif QoS for the given plane
  * @plane:		Pointer to drm plane
+ * @pipe_hw:		Pointer to hardware pipe
  */
-static void _dpu_plane_set_qos_remap(struct drm_plane *plane)
+static void _dpu_plane_set_qos_remap(struct drm_plane *plane,
+	struct dpu_hw_pipe *pipe_hw)
 {
 	struct dpu_plane *pdpu;
 	struct dpu_vbif_set_qos_params qos_params;
 	struct msm_drm_private *priv;
 	struct dpu_kms *dpu_kms;
 
-	if (!plane || !plane->dev) {
+	if (!plane || !plane->dev || !pipe_hw) {
 		DPU_ERROR("invalid arguments\n");
 		return;
 	}
@@ -507,23 +525,17 @@ static void _dpu_plane_set_qos_remap(struct drm_plane *plane)
 
 	dpu_kms = to_dpu_kms(priv->kms);
 	pdpu = to_dpu_plane(plane);
-	if (!pdpu->pipe_hw) {
-		DPU_ERROR("invalid pipe reference\n");
-		return;
-	}
 
 	memset(&qos_params, 0, sizeof(qos_params));
 	qos_params.vbif_idx = VBIF_RT;
-	qos_params.clk_ctrl = pdpu->pipe_hw->cap->clk_ctrl;
-	qos_params.xin_id = pdpu->pipe_hw->cap->xin_id;
-	qos_params.num = pdpu->pipe_hw->idx - SSPP_VIG0;
-	qos_params.is_rt = pdpu->is_rt_pipe;
+	qos_params.clk_ctrl = pipe_hw->cap->clk_ctrl;
+	qos_params.xin_id = pipe_hw->cap->xin_id;
+	qos_params.num = pipe_hw->idx - SSPP_VIG0;
+	qos_params.is_rt = pdpu->is_rt_client;
 
 	DPU_DEBUG("plane%d pipe:%d vbif:%d xin:%d rt:%d, clk_ctrl:%d\n",
-			plane->base.id, qos_params.num,
-			qos_params.vbif_idx,
-			qos_params.xin_id, qos_params.is_rt,
-			qos_params.clk_ctrl);
+		plane->base.id, qos_params.num, qos_params.vbif_idx,
+		qos_params.xin_id, qos_params.is_rt, qos_params.clk_ctrl);
 
 	dpu_vbif_set_qos_remap(dpu_kms, &qos_params);
 }
@@ -554,25 +566,16 @@ static int _dpu_plane_get_aspace(
 	return 0;
 }
 
-static inline void _dpu_plane_set_scanout(struct drm_plane *plane,
-		struct dpu_plane_state *pstate,
-		struct dpu_hw_pipe_cfg *pipe_cfg,
-		struct drm_framebuffer *fb)
+static inline void _dpu_plane_set_scanout(struct dpu_plane *pdpu,
+	struct dpu_plane_state *pstate, struct dpu_hw_pipe *pipe_hw,
+	struct dpu_hw_pipe_cfg *pipe_cfg, struct drm_framebuffer *fb)
 {
-	struct dpu_plane *pdpu;
 	struct msm_gem_address_space *aspace = NULL;
 	int ret;
 
-	if (!plane || !pstate || !pipe_cfg || !fb) {
-		DPU_ERROR(
-			"invalid arg(s), plane %d state %d cfg %d fb %d\n",
-			plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
-		return;
-	}
-
-	pdpu = to_dpu_plane(plane);
-	if (!pdpu->pipe_hw) {
-		DPU_ERROR_PLANE(pdpu, "invalid pipe_hw\n");
+	if (!pdpu || !pstate || !pipe_hw || !pipe_cfg || !fb) {
+		DPU_ERROR("invalid: plane %d state %d hw %d cfg %d fb %d\n",
+		pdpu != 0, pstate != 0, pipe_hw != 0, pipe_cfg != 0, fb != 0);
 		return;
 	}
 
@@ -587,8 +590,8 @@ static inline void _dpu_plane_set_scanout(struct drm_plane *plane,
 		DPU_DEBUG_PLANE(pdpu, "not updating same src addrs\n");
 	else if (ret)
 		DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret);
-	else if (pdpu->pipe_hw->ops.setup_sourceaddress) {
-		DPU_EVT32_VERBOSE(pdpu->pipe_hw->idx,
+	else if (pipe_hw->ops.setup_sourceaddress) {
+		DPU_EVT32_VERBOSE(pipe_hw->idx,
 				pipe_cfg->layout.width,
 				pipe_cfg->layout.height,
 				pipe_cfg->layout.plane_addr[0],
@@ -599,11 +602,11 @@ static inline void _dpu_plane_set_scanout(struct drm_plane *plane,
 				pipe_cfg->layout.plane_size[2],
 				pipe_cfg->layout.plane_addr[3],
 				pipe_cfg->layout.plane_size[3]);
-		pdpu->pipe_hw->ops.setup_sourceaddress(pdpu->pipe_hw, pipe_cfg);
+		pipe_hw->ops.setup_sourceaddress(pipe_hw, pipe_cfg);
 	}
 }
 
-static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu,
+static void _dpu_plane_setup_scaler3(
 		struct dpu_plane_state *pstate,
 		uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
 		struct dpu_hw_scaler3_cfg *scale_cfg,
@@ -612,12 +615,12 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu,
 {
 	uint32_t i;
 
-	if (!pdpu || !pstate || !scale_cfg || !fmt || !chroma_subsmpl_h ||
-			!chroma_subsmpl_v) {
+	if (!pstate || !scale_cfg || !fmt ||
+		!chroma_subsmpl_h || !chroma_subsmpl_v) {
 		DPU_ERROR(
-			"pdpu %d pstate %d scale_cfg %d fmt %d smp_h %d smp_v %d\n",
-			!!pdpu, !!pstate, !!scale_cfg, !!fmt, chroma_subsmpl_h,
-			chroma_subsmpl_v);
+		"pstate%d scale_cfg%d fmt%d smp_h%d smp_v%d\n",
+		!!pstate, !!scale_cfg, !!fmt, chroma_subsmpl_h,
+		chroma_subsmpl_v);
 		return;
 	}
 
@@ -673,7 +676,7 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu,
 	scale_cfg->enable = 1;
 }
 
-static inline void _dpu_plane_setup_csc(struct dpu_plane *pdpu)
+static inline void _dpu_plane_setup_csc(struct dpu_plane *pdpu, u32 features)
 {
 	static const struct dpu_csc_cfg dpu_csc_YUV2RGB_601L = {
 		{
@@ -709,7 +712,7 @@ static inline void _dpu_plane_setup_csc(struct dpu_plane *pdpu)
 		return;
 	}
 
-	if (BIT(DPU_SSPP_CSC_10BIT) & pdpu->features)
+	if (BIT(DPU_SSPP_CSC_10BIT) & features)
 		pdpu->csc_ptr = (struct dpu_csc_cfg *)&dpu_csc10_YUV2RGB_601L;
 	else
 		pdpu->csc_ptr = (struct dpu_csc_cfg *)&dpu_csc_YUV2RGB_601L;
@@ -720,16 +723,18 @@ static inline void _dpu_plane_setup_csc(struct dpu_plane *pdpu)
 			pdpu->csc_ptr->csc_mv[2]);
 }
 
-static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
+
+static void _dpu_plane_setup_scaler(
 		struct dpu_plane_state *pstate,
+		struct dpu_hw_pipe_cfg *pipe_cfg,
 		const struct dpu_format *fmt, bool color_fill)
 {
 	struct dpu_hw_pixel_ext *pe;
 	uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
 
-	if (!pdpu || !fmt || !pstate) {
-		DPU_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
-				pdpu != 0, fmt != 0, pstate != 0);
+	if (!fmt || !pstate) {
+		DPU_ERROR("invalid arg(s), fmt %d state %d\n",
+				fmt != 0, pstate != 0);
 		return;
 	}
 
@@ -742,11 +747,11 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
 		drm_format_vert_chroma_subsampling(fmt->base.pixel_format);
 
 	/* update scaler. calculate default config for QSEED3 */
-	_dpu_plane_setup_scaler3(pdpu, pstate,
-			pdpu->pipe_cfg.src_rect.w,
-			pdpu->pipe_cfg.src_rect.h,
-			pdpu->pipe_cfg.dst_rect.w,
-			pdpu->pipe_cfg.dst_rect.h,
+	_dpu_plane_setup_scaler3(pstate,
+			pipe_cfg->src_rect.w,
+			pipe_cfg->src_rect.h,
+			pipe_cfg->dst_rect.w,
+			pipe_cfg->dst_rect.h,
 			&pstate->scaler3_cfg, fmt,
 			chroma_subsmpl_h, chroma_subsmpl_v);
 }
@@ -764,17 +769,14 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu,
 	const struct dpu_format *fmt;
 	const struct drm_plane *plane;
 	struct dpu_plane_state *pstate;
+	struct dpu_hw_pipe_cfg pipe_cfg;
+	int i;
 
 	if (!pdpu || !pdpu->base.state) {
 		DPU_ERROR("invalid plane\n");
 		return -EINVAL;
 	}
 
-	if (!pdpu->pipe_hw) {
-		DPU_ERROR_PLANE(pdpu, "invalid plane h/w pointer\n");
-		return -EINVAL;
-	}
-
 	plane = &pdpu->base;
 	pstate = to_dpu_plane_state(plane->state);
 
@@ -786,34 +788,49 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu,
 	 */
 	fmt = dpu_get_dpu_format(DRM_FORMAT_ABGR8888);
 
-	/* update sspp */
-	if (fmt && pdpu->pipe_hw->ops.setup_solidfill) {
-		pdpu->pipe_hw->ops.setup_solidfill(pdpu->pipe_hw,
-				(color & 0xFFFFFF) | ((alpha & 0xFF) << 24));
-
-		/* override scaler/decimation if solid fill */
-		pdpu->pipe_cfg.src_rect.x = 0;
-		pdpu->pipe_cfg.src_rect.y = 0;
-		pdpu->pipe_cfg.src_rect.w = pdpu->pipe_cfg.dst_rect.w;
-		pdpu->pipe_cfg.src_rect.h = pdpu->pipe_cfg.dst_rect.h;
-		_dpu_plane_setup_scaler(pdpu, pstate, fmt, true);
+	memset(&pipe_cfg, 0, sizeof(struct dpu_hw_pipe_cfg));
 
-		if (pdpu->pipe_hw->ops.setup_format)
-			pdpu->pipe_hw->ops.setup_format(pdpu->pipe_hw,
-					fmt, DPU_SSPP_SOLID_FILL);
+	_dpu_plane_get_roi_config(plane->state, NULL, &pipe_cfg.dst_rect);
 
-		if (pdpu->pipe_hw->ops.setup_rects)
-			pdpu->pipe_hw->ops.setup_rects(pdpu->pipe_hw,
-					&pdpu->pipe_cfg);
-
-		if (pdpu->pipe_hw->ops.setup_pe)
-			pdpu->pipe_hw->ops.setup_pe(pdpu->pipe_hw,
-					&pstate->pixel_ext);
+	/* update sspp */
+	for (i = 0; i < pstate->num_pipes; i++) {
+		if (fmt && pstate->pipe_hw[i] &&
+			pstate->pipe_hw[i]->ops.setup_solidfill) {
+			pstate->pipe_hw[i]->ops.setup_solidfill(
+				pstate->pipe_hw[i],
+				(color & 0xFFFFFF) | ((alpha & 0xFF) << 24));
 
-		if (pdpu->pipe_hw->ops.setup_scaler)
-			pdpu->pipe_hw->ops.setup_scaler(pdpu->pipe_hw,
-					&pdpu->pipe_cfg, &pstate->pixel_ext,
+			/*
+			 * override scaler/decimation if solid fill
+			 * also, adjust the dst.x in case of dual pipe
+			 */
+			pipe_cfg.dst_rect.x += pipe_cfg.dst_rect.w * i;
+			pipe_cfg.src_rect.x = 0;
+			pipe_cfg.src_rect.y = 0;
+			pipe_cfg.src_rect.w = pipe_cfg.dst_rect.w;
+			pipe_cfg.src_rect.h = pipe_cfg.dst_rect.h;
+
+			_dpu_plane_setup_scaler(pstate, &pipe_cfg, fmt, true);
+
+			if (pstate->pipe_hw[i]->ops.setup_format)
+				pstate->pipe_hw[i]->ops.setup_format(
+					pstate->pipe_hw[i], fmt,
+					DPU_SSPP_SOLID_FILL);
+
+			if (pstate->pipe_hw[i]->ops.setup_rects)
+				pstate->pipe_hw[i]->ops.setup_rects(
+					pstate->pipe_hw[i], &pipe_cfg);
+
+			if (pstate->pipe_hw[i]->ops.setup_pe)
+				pstate->pipe_hw[i]->ops.setup_pe(
+					pstate->pipe_hw[i], &pstate->pixel_ext);
+
+			if (pstate->pipe_hw[i]->ops.setup_scaler)
+				pstate->pipe_hw[i]->ops.setup_scaler(
+					pstate->pipe_hw[i], &pipe_cfg,
+					&pstate->pixel_ext,
 					&pstate->scaler3_cfg);
+		}
 	}
 
 	return 0;
@@ -829,6 +846,7 @@ void dpu_plane_get_ctl_flush(struct drm_plane *plane, struct dpu_hw_ctl *ctl,
 		u32 *flush_sspp)
 {
 	struct dpu_plane_state *pstate;
+	int i;
 
 	if (!plane || !flush_sspp) {
 		DPU_ERROR("invalid parameters\n");
@@ -837,7 +855,10 @@ void dpu_plane_get_ctl_flush(struct drm_plane *plane, struct dpu_hw_ctl *ctl,
 
 	pstate = to_dpu_plane_state(plane->state);
 
-	*flush_sspp = ctl->ops.get_bitmask_sspp(ctl, dpu_plane_pipe(plane));
+	for (i = 0; i < pstate->num_pipes; i++)
+		*flush_sspp |= ctl->ops.get_bitmask_sspp(ctl,
+				dpu_plane_pipe(pstate->pipe_hw[i]));
+
 }
 
 static int dpu_plane_prepare_fb(struct drm_plane *plane,
@@ -921,11 +942,12 @@ static int dpu_plane_sspp_atomic_check(struct drm_plane *plane,
 	struct dpu_kms *kms;
 	struct dpu_plane *pdpu;
 	struct dpu_plane_state *pstate;
+	struct dpu_private_state *dpu_priv_state;
 	const struct dpu_format *fmt;
 	struct dpu_rect src, dst;
 	uint32_t max_upscale, max_downscale, min_src_size, max_linewidth;
 	bool q16_data = true;
-	uint32_t caps = 0;
+	uint32_t caps = 0, req_num_pipes = 0;
 
 	if (!plane || !state) {
 		DPU_ERROR("invalid arg(s), plane %d state %d\n",
@@ -950,7 +972,20 @@ static int dpu_plane_sspp_atomic_check(struct drm_plane *plane,
 		dpu_plane_enabled(plane->state), dpu_plane_enabled(state));
 
 	if (!dpu_plane_enabled(state))
+		goto modeset_update;
+
+	/* With plane virtualization, a drm plane can be attached
+	 * to maximum of two hw pipes, i.e. we can go up to 2x
+	 * the pipe's max width.
+	 */
+	if (src.w > 2 * max_linewidth) {
+		DPU_ERROR_PLANE(pdpu, "invalid src w:%u, line w * 2:%u\n",
+					src.w, max_linewidth * 2);
+		ret = -E2BIG;
 		goto exit;
+	}
+
+	req_num_pipes = (src.w > max_linewidth) ? 2 : 1;
 
 	fmt = to_dpu_format(msm_framebuffer_format(state->fb));
 
@@ -988,13 +1023,6 @@ static int dpu_plane_sspp_atomic_check(struct drm_plane *plane,
 				dst.x, dst.y, dst.w, dst.h);
 		ret = -EINVAL;
 
-	/* check decimated source width */
-	} else if (src.w > max_linewidth) {
-		DPU_ERROR_PLANE(pdpu,
-				"invalid src w:%u, line w:%u\n",
-				src.w, max_linewidth);
-		ret = -E2BIG;
-
 	/* check max scaler capability */
 	} else if (((src.w * max_upscale) < dst.w) ||
 		((src.h * max_upscale) < dst.h) ||
@@ -1006,6 +1034,44 @@ static int dpu_plane_sspp_atomic_check(struct drm_plane *plane,
 		ret = -E2BIG;
 	}
 
+modeset_update:
+	if (!ret) {
+		dpu_priv_state = dpu_get_private_state(state->state);
+		if (IS_ERR(dpu_priv_state))
+			goto exit;
+
+		/**
+		 * (re)allocate hw pipes if mismatch in number of pipes
+		 * or caps of allocated vs requested.
+		 */
+		DPU_DEBUG_PLANE(pdpu, " num pipes %d -> %d caps %d\n",
+			 pstate->num_pipes, req_num_pipes, caps);
+
+		if ((pstate->num_pipes != req_num_pipes) || (pstate->pipe_hw[0]
+			&& (caps & ~pstate->pipe_hw[0]->cap->features))) {
+			/**
+			 * Release called only for planes with pipes attached.
+			 * New plane will have no resources to be released.
+			 */
+			if (pstate->num_pipes)
+				dpu_rm_release_plane_res(&dpu_priv_state->rm,
+							pstate);
+
+			/**
+			 * Reserve called only for planes that are enabled.
+			 * Plane that is disabling will require no resources.
+			 */
+			if (req_num_pipes) {
+				ret = dpu_rm_reserve_plane_res(
+					&dpu_priv_state->rm, pstate,
+					req_num_pipes, caps);
+				if (ret)
+					DPU_ERROR_PLANE(pdpu,
+					"failed to reserve resources\n");
+			}
+		}
+	}
+
 exit:
 	return ret;
 }
@@ -1039,6 +1105,7 @@ void dpu_plane_flush(struct drm_plane *plane)
 {
 	struct dpu_plane *pdpu;
 	struct dpu_plane_state *pstate;
+	int i;
 
 	if (!plane || !plane->state) {
 		DPU_ERROR("invalid plane\n");
@@ -1058,8 +1125,14 @@ void dpu_plane_flush(struct drm_plane *plane)
 	else if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG)
 		/* force 100% alpha */
 		_dpu_plane_color_fill(pdpu, pdpu->color_fill, 0xFF);
-	else if (pdpu->pipe_hw && pdpu->csc_ptr && pdpu->pipe_hw->ops.setup_csc)
-		pdpu->pipe_hw->ops.setup_csc(pdpu->pipe_hw, pdpu->csc_ptr);
+	else {
+		for (i = 0; i < pstate->num_pipes; i++) {
+			if (pstate->pipe_hw[i] && pdpu->csc_ptr &&
+				pstate->pipe_hw[i]->ops.setup_csc)
+				pstate->pipe_hw[i]->ops.setup_csc(
+					pstate->pipe_hw[i], pdpu->csc_ptr);
+		}
+	}
 
 	/* force black color fill during suspend */
 	if (dpu_kms_is_suspend_state(plane->dev) && suspend_blank)
@@ -1089,6 +1162,7 @@ static int dpu_plane_sspp_atomic_update(struct drm_plane *plane,
 				struct drm_plane_state *old_state)
 {
 	uint32_t nplanes, src_flags;
+	struct dpu_kms *kms;
 	struct dpu_plane *pdpu;
 	struct drm_plane_state *state;
 	struct dpu_plane_state *pstate;
@@ -1097,7 +1171,8 @@ static int dpu_plane_sspp_atomic_update(struct drm_plane *plane,
 	struct drm_crtc *crtc;
 	struct drm_framebuffer *fb;
 	struct dpu_rect src, dst;
-	bool q16_data = true;
+	struct dpu_hw_pipe_cfg pipe_cfg;
+	int i;
 
 	if (!plane) {
 		DPU_ERROR("invalid plane\n");
@@ -1124,96 +1199,115 @@ static int dpu_plane_sspp_atomic_update(struct drm_plane *plane,
 				crtc != 0, fb != 0);
 		return -EINVAL;
 	}
+
+	kms = _dpu_plane_get_kms(&pdpu->base);
+	if (!kms || !kms->catalog) {
+		DPU_ERROR("invalid kms catalog\n");
+		return -EINVAL;
+	}
+
 	fmt = to_dpu_format(msm_framebuffer_format(fb));
 	nplanes = fmt->num_planes;
 
-	memset(&(pdpu->pipe_cfg), 0, sizeof(struct dpu_hw_pipe_cfg));
-
-	_dpu_plane_set_scanout(plane, pstate, &pdpu->pipe_cfg, fb);
+	DPU_DEBUG_PLANE(pdpu, "%4.4s ubwc %d\n",
+		(char *)&fmt->base.pixel_format, DPU_FORMAT_IS_UBWC(fmt));
 
 	pstate->pending = true;
+	pdpu->is_rt_client = (dpu_crtc_get_client_type(crtc) != NRT_CLIENT);
 
-	pdpu->is_rt_pipe = (dpu_crtc_get_client_type(crtc) != NRT_CLIENT);
-	_dpu_plane_set_qos_ctrl(plane, false, DPU_PLANE_QOS_PANIC_CTRL);
+	_dpu_plane_get_roi_config(state, &src, &dst);
 
-	/* update roi config */
-	POPULATE_RECT(&src, state->src_x, state->src_y,
-		state->src_w, state->src_h, q16_data);
-	POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
-		state->crtc_w, state->crtc_h, !q16_data);
+	for (i = 0; i < pstate->num_pipes; i++) {
+		memset(&pipe_cfg, 0, sizeof(struct dpu_hw_pipe_cfg));
 
-	DPU_DEBUG_PLANE(pdpu,
-		"FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
-			fb->base.id, src.x, src.y, src.w, src.h,
-			crtc->base.id, dst.x, dst.y, dst.w, dst.h,
-			(char *)&fmt->base.pixel_format,
-			DPU_FORMAT_IS_UBWC(fmt));
+		_dpu_plane_set_scanout(pdpu, pstate, pstate->pipe_hw[i],
+					&pipe_cfg, fb);
+		_dpu_plane_set_qos_ctrl(plane,  pstate->pipe_hw[i],
+					false, DPU_PLANE_QOS_PANIC_CTRL);
 
+		/*
+		 * if the plane comprises of 2 hw pipes, assume that the width
+		 * is split equally across them. The only parameters that varies
+		 * between the 2 pipes are src_x and dst_x
+		 */
+		src.x += src.w * i;
+		dst.x += dst.w * i;
 
-	pdpu->pipe_cfg.src_rect = src;
-	pdpu->pipe_cfg.dst_rect = dst;
+		pipe_cfg.src_rect = src;
+		pipe_cfg.dst_rect = dst;
 
-	_dpu_plane_setup_scaler(pdpu, pstate, fmt, false);
+		_dpu_plane_setup_scaler(pstate, &pipe_cfg, fmt, false);
 
-	/* override for color fill */
-	if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) {
-		/* skip remaining processing on color fill */
-		return 0;
-	}
+		/* override for color fill */
+		if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) {
+			/* skip remaining processing on color fill */
+			return 0;
+		}
 
-	if (pdpu->pipe_hw->ops.setup_rects) {
-		pdpu->pipe_hw->ops.setup_rects(pdpu->pipe_hw,
-				&pdpu->pipe_cfg);
-	}
+		if (pstate->pipe_hw[i]->ops.setup_rects) {
+			pstate->pipe_hw[i]->ops.setup_rects(pstate->pipe_hw[i],
+					&pipe_cfg);
+		}
 
-	if (pdpu->pipe_hw->ops.setup_pe)
-		pdpu->pipe_hw->ops.setup_pe(pdpu->pipe_hw,
-				&pstate->pixel_ext);
+		if (pstate->pipe_hw[i]->ops.setup_pe)
+			pstate->pipe_hw[i]->ops.setup_pe(pstate->pipe_hw[i],
+					&pstate->pixel_ext);
 
-	if (pdpu->pipe_hw->ops.setup_scaler)
-		pdpu->pipe_hw->ops.setup_scaler(pdpu->pipe_hw,
-				&pdpu->pipe_cfg, &pstate->pixel_ext,
-				&pstate->scaler3_cfg);
+		if (pstate->pipe_hw[i]->ops.setup_scaler)
+			pstate->pipe_hw[i]->ops.setup_scaler(pstate->pipe_hw[i],
+					&pipe_cfg, &pstate->pixel_ext,
+					&pstate->scaler3_cfg);
 
-	if (pdpu->pipe_hw->ops.setup_format) {
-		src_flags = 0x0;
+		if (pstate->pipe_hw[i]->ops.setup_format) {
+			src_flags = 0x0;
 
-		/* update format */
-		pdpu->pipe_hw->ops.setup_format(pdpu->pipe_hw, fmt, src_flags);
+			/* update format */
+			pstate->pipe_hw[i]->ops.setup_format(
+					pstate->pipe_hw[i], fmt, src_flags);
 
-		if (pdpu->pipe_hw->ops.setup_cdp) {
-			struct dpu_hw_pipe_cdp_cfg *cdp_cfg = &pstate->cdp_cfg;
+			if (pstate->pipe_hw[i]->ops.setup_cdp) {
+				struct dpu_hw_pipe_cdp_cfg *cdp_cfg =
+						&pstate->cdp_cfg;
 
-			memset(cdp_cfg, 0, sizeof(struct dpu_hw_pipe_cdp_cfg));
+				memset(cdp_cfg, 0,
+					sizeof(struct dpu_hw_pipe_cdp_cfg));
 
-			cdp_cfg->enable = pdpu->catalog->perf.cdp_cfg
+				cdp_cfg->enable = kms->catalog->perf.cdp_cfg
 					[DPU_PERF_CDP_USAGE_RT].rd_enable;
-			cdp_cfg->ubwc_meta_enable =
+				cdp_cfg->ubwc_meta_enable =
 					DPU_FORMAT_IS_UBWC(fmt);
-			cdp_cfg->tile_amortize_enable =
+				cdp_cfg->tile_amortize_enable =
 					DPU_FORMAT_IS_UBWC(fmt) ||
 					DPU_FORMAT_IS_TILE(fmt);
-			cdp_cfg->preload_ahead = DPU_SSPP_CDP_PRELOAD_AHEAD_64;
-
-			pdpu->pipe_hw->ops.setup_cdp(pdpu->pipe_hw, cdp_cfg);
+				cdp_cfg->preload_ahead =
+					DPU_SSPP_CDP_PRELOAD_AHEAD_64;
+
+				pstate->pipe_hw[i]->ops.setup_cdp(
+					pstate->pipe_hw[i], cdp_cfg);
+			}
+
+			/* update csc */
+			if (DPU_FORMAT_IS_YUV(fmt))
+				_dpu_plane_setup_csc(pdpu,
+					pstate->pipe_hw[i]->cap->features);
+			else
+				pdpu->csc_ptr = 0;
 		}
 
-		/* update csc */
-		if (DPU_FORMAT_IS_YUV(fmt))
-			_dpu_plane_setup_csc(pdpu);
-		else
-			pdpu->csc_ptr = 0;
-	}
+		_dpu_plane_set_qos_lut(plane, pstate->pipe_hw[i],
+					&pipe_cfg, fb);
+		_dpu_plane_set_danger_lut(plane, pstate->pipe_hw[i], fb);
 
-	_dpu_plane_set_qos_lut(plane, fb);
-	_dpu_plane_set_danger_lut(plane, fb);
+		if (plane->type != DRM_PLANE_TYPE_CURSOR) {
+			_dpu_plane_set_qos_ctrl(plane,  pstate->pipe_hw[i],
+					true, DPU_PLANE_QOS_PANIC_CTRL);
+			_dpu_plane_set_ot_limit(plane,  pstate->pipe_hw[i],
+					&pipe_cfg, crtc);
+		}
 
-	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
-		_dpu_plane_set_qos_ctrl(plane, true, DPU_PLANE_QOS_PANIC_CTRL);
-		_dpu_plane_set_ot_limit(plane, crtc);
+		_dpu_plane_set_qos_remap(plane, pstate->pipe_hw[i]);
 	}
 
-	_dpu_plane_set_qos_remap(plane);
 	return 0;
 }
 
@@ -1270,11 +1364,19 @@ void dpu_plane_restore(struct drm_plane *plane)
 static void dpu_plane_destroy(struct drm_plane *plane)
 {
 	struct dpu_plane *pdpu = plane ? to_dpu_plane(plane) : NULL;
+	struct dpu_plane_state *pstate;
+	int i;
 
 	DPU_DEBUG_PLANE(pdpu, "\n");
 
 	if (pdpu) {
-		_dpu_plane_set_qos_ctrl(plane, false, DPU_PLANE_QOS_PANIC_CTRL);
+		pstate = plane->state ? to_dpu_plane_state(plane->state) : NULL;
+		if (pstate) {
+			for (i = 0; i < pstate->num_pipes; i++)
+				_dpu_plane_set_qos_ctrl(plane,
+					pstate->pipe_hw[i], false,
+					DPU_PLANE_QOS_PANIC_CTRL);
+		}
 
 		mutex_destroy(&pdpu->lock);
 
@@ -1484,7 +1586,7 @@ static int _dpu_plane_init_debugfs(struct drm_plane *plane)
 
 	/* create overall sub-directory for the pipe */
 	pdpu->debugfs_root =
-		debugfs_create_dir(pdpu->pipe_name,
+		debugfs_create_dir(pdpu->name,
 				plane->dev->primary->debugfs_root);
 
 	if (!pdpu->debugfs_root)
@@ -1546,9 +1648,9 @@ static void dpu_plane_early_unregister(struct drm_plane *plane)
 		.atomic_update = dpu_plane_atomic_update,
 };
 
-enum dpu_sspp dpu_plane_pipe(struct drm_plane *plane)
+enum dpu_sspp dpu_plane_pipe(struct dpu_hw_pipe *pipe_hw)
 {
-	return plane ? to_dpu_plane(plane)->pipe : SSPP_NONE;
+	return pipe_hw ? pipe_hw->idx : SSPP_NONE;
 }
 
 /* initialize plane */
@@ -1578,8 +1680,8 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
 		DPU_ERROR("[%u]invalid KMS reference\n", pipe);
 		goto exit;
 	}
-	kms = to_dpu_kms(priv->kms);
 
+	kms = to_dpu_kms(priv->kms);
 	if (!kms->catalog) {
 		DPU_ERROR("[%u]invalid catalog reference\n", pipe);
 		goto exit;
@@ -1625,11 +1727,11 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
 	drm_plane_helper_add(plane, &dpu_plane_helper_funcs);
 
 	/* save user friendly pipe name for later */
-	snprintf(pdpu->pipe_name, DPU_NAME_SIZE, "plane%u", plane->base.id);
+	snprintf(pdpu->name, DPU_NAME_SIZE, "plane%u", plane->base.id);
 
 	mutex_init(&pdpu->lock);
 
-	DPU_DEBUG("%s created for pipe:%u id:%u\n", pdpu->pipe_name,
+	DPU_DEBUG("%s created for pipe:%u id:%u\n", pdpu->name,
 					pipe, plane->base.id);
 	return plane;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
index 4eb929b..3ebc4c1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
@@ -71,10 +71,10 @@ struct dpu_plane_state {
 
 /**
  * dpu_plane_pipe - return sspp identifier for the given plane
- * @plane:   Pointer to DRM plane object
+ * @pipe_hw:   Pointer to DPU pipe hw
  * Returns: sspp identifier of the given plane
  */
-enum dpu_sspp dpu_plane_pipe(struct drm_plane *plane);
+enum dpu_sspp dpu_plane_pipe(struct dpu_hw_pipe *pipe_hw);
 
 /**
  * dpu_plane_get_ctl_flush - get control flush mask
