diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 49bdd5953b9f..49bd9df387b8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -892,7 +892,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 	struct dpu_global_state *global_state = dpu_kms_get_global_state(state);
 
 	struct dpu_plane_state **pstates;
-	struct dpu_plane_state *pstate;
+	struct dpu_plane_state *pstate, *prev_plane_state;
 
 	struct drm_plane_state *plane_state;
 	struct drm_plane *plane;
@@ -962,6 +962,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 	}
 
 	stage = DPU_STAGE_0;
+	prev_plane_state = NULL;
 	for (i = 0; i <= max_zpos; i++) {
 		pstate = pstates[i];
 		if (!pstate)
@@ -977,8 +978,6 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 
 		plane_state = &pstate->base;
 
-		dpu_plane_clear_multirect(plane_state);
-
 		dst = drm_plane_state_dest(plane_state);
 		if (!drm_rect_intersect(&dst, &crtc_rect)) {
 			DPU_ERROR("invalid vertical/horizontal destination\n");
@@ -990,7 +989,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 		}
 
 		plane = pstate->base.plane;
-		rc = dpu_plane_set_pipe(plane, pstate);
+		rc = dpu_plane_set_pipe(plane, pstate, prev_plane_state);
 		if (rc) {
 			DPU_ERROR("%s: error setting pipe for %s\n", dpu_crtc->name, plane->name);
 			goto end;
@@ -1002,6 +1001,17 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 			goto end;
 		}
 
+		/*
+		 * If this plane was not selected for multirect, so we can try
+		 * using it together with the next pipe.  If it selected for
+		 * the REC1, next pipe will have to start from REC_SOLO (and
+		 * maybe be promoted to REC0 later.
+		 */
+		if (pstate->multirect_index == DPU_SSPP_RECT_SOLO)
+			prev_plane_state = pstate;
+		else
+			prev_plane_state = NULL;
+
 		pstates[i]->stage = stage++;
 		DRM_DEBUG_ATOMIC("%s: stage %d\n", dpu_crtc->name, stage);
 	}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 08a7e56cc98f..c3c3972627ca 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -646,7 +646,7 @@ static int _dpu_kms_create_planes_virtual(struct dpu_kms *dpu_kms, int max_crtc_
 	catalog = dpu_kms->catalog;
 
 	/* Create the planes, keeping track of one primary/cursor per crtc */
-	for (i = 0; i < catalog->sspp_count; i++) {
+	for (i = 0; i < 2 * catalog->sspp_count; i++) {
 		enum drm_plane_type type;
 
 		if (primary_planes_idx < max_crtc_count)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 420cdd90e89b..77cb4f172379 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -292,10 +292,10 @@ 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
  * @fb:			Pointer to framebuffer associated with the given plane
- * @pipe_cfg:		Pointer to pipe configuration
+ * @src_width:		Plane source width (max for both multirect planes).
  */
 static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
-		struct drm_framebuffer *fb, struct dpu_hw_pipe_cfg *pipe_cfg)
+		struct drm_framebuffer *fb, u32 src_width)
 {
 	struct dpu_plane *pdpu = to_dpu_plane(plane);
 	struct dpu_plane_state *pstate = to_dpu_plane_state(plane->state);
@@ -309,8 +309,7 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
 		fmt = dpu_get_dpu_format_ext(
 				fb->format->format,
 				fb->modifier);
-		total_fl = _dpu_plane_calc_fill_level(plane, fmt,
-				drm_rect_width(&pipe_cfg->src_rect));
+		total_fl = _dpu_plane_calc_fill_level(plane, fmt, src_width);
 
 		if (fmt && DPU_FORMAT_IS_LINEAR(fmt))
 			lut_usage = DPU_QOS_LUT_USAGE_LINEAR;
@@ -570,6 +569,9 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu,
 		&& (src_w == dst_w))
 		return;
 
+	if (pstate->multirect_index != DPU_SSPP_RECT_SOLO)
+		return;
+
 	scale_cfg->dst_width = dst_w;
 	scale_cfg->dst_height = dst_h;
 	scale_cfg->y_rgb_filter_cfg = DPU_SCALE_BIL;
@@ -638,13 +640,16 @@ static const struct dpu_csc_cfg *_dpu_plane_get_csc(struct dpu_plane *pdpu, cons
 
 static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
 		struct dpu_plane_state *pstate,
-		const struct dpu_format *fmt, bool color_fill,
+		const struct dpu_format *fmt,
 		struct dpu_hw_pipe_cfg *pipe_cfg)
 {
 	const struct drm_format_info *info = drm_format_info(fmt->base.pixel_format);
 	struct dpu_hw_scaler3_cfg scaler3_cfg;
 	struct dpu_hw_pixel_ext pixel_ext;
 
+	if (pstate->multirect_index == DPU_SSPP_RECT_1)
+		return;
+
 	memset(&scaler3_cfg, 0, sizeof(scaler3_cfg));
 	memset(&pixel_ext, 0, sizeof(pixel_ext));
 
@@ -667,8 +672,7 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
 	 * bypassed. Still we need to update alpha and bitwidth
 	 * ONLY for RECT0
 	 */
-	if (pstate->pipe_hw->ops.setup_scaler &&
-			pstate->multirect_index != DPU_SSPP_RECT_1)
+	if (pstate->pipe_hw->ops.setup_scaler)
 		pstate->pipe_hw->ops.setup_scaler(pstate->pipe_hw,
 				pipe_cfg, &pixel_ext,
 				&scaler3_cfg);
@@ -723,23 +727,15 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu,
 					&pipe_cfg,
 					pstate->multirect_index);
 
-		_dpu_plane_setup_scaler(pdpu, pstate, fmt, true, &pipe_cfg);
+		_dpu_plane_setup_scaler(pdpu, pstate, fmt, &pipe_cfg);
 	}
 
 	return 0;
 }
 
-void dpu_plane_clear_multirect(const struct drm_plane_state *drm_state)
-{
-	struct dpu_plane_state *pstate = to_dpu_plane_state(drm_state);
-
-	pstate->multirect_index = DPU_SSPP_RECT_SOLO;
-	pstate->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
-}
-
-int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane)
+static int dpu_plane_validate_multirect_v2(struct dpu_plane_state *pstate0,
+					   struct dpu_plane_state *pstate1)
 {
-	struct dpu_plane_state *pstate[R_MAX];
 	const struct drm_plane_state *drm_state[R_MAX];
 	struct drm_rect src[R_MAX], dst[R_MAX];
 	struct dpu_plane *dpu_plane[R_MAX];
@@ -750,9 +746,17 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane)
 	bool has_tiled_rect = false;
 
 	for (i = 0; i < R_MAX; i++) {
+		struct dpu_plane_state *pstate;
 		const struct msm_format *msm_fmt;
 
-		drm_state[i] = i ? plane->r1 : plane->r0;
+		pstate = i ? pstate1 : pstate0;
+		if (pstate == NULL) {
+			DPU_DEBUG("DPU plane state of plane id %d is NULL\n",
+				drm_state[i]->plane->base.id);
+			return -EINVAL;
+		}
+
+		drm_state[i] = &pstate->base;
 		msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
 		fmt[i] = to_dpu_format(msm_fmt);
 
@@ -766,15 +770,8 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane)
 	for (i = 0; i < R_MAX; i++) {
 		int width_threshold;
 
-		pstate[i] = to_dpu_plane_state(drm_state[i]);
 		dpu_plane[i] = to_dpu_plane(drm_state[i]->plane);
 
-		if (pstate[i] == NULL) {
-			DPU_ERROR("DPU plane state of plane id %d is NULL\n",
-				drm_state[i]->plane->base.id);
-			return -EINVAL;
-		}
-
 		src[i].x1 = drm_state[i]->src_x >> 16;
 		src[i].y1 = drm_state[i]->src_y >> 16;
 		src[i].x2 = src[i].x1 + (drm_state[i]->src_w >> 16);
@@ -784,13 +781,13 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane)
 
 		if (drm_rect_calc_hscale(&src[i], &dst[i], 1, 1) != 1 ||
 		    drm_rect_calc_vscale(&src[i], &dst[i], 1, 1) != 1) {
-			DPU_ERROR_PLANE(dpu_plane[i],
+			DPU_DEBUG_PLANE(dpu_plane[i],
 				"scaling is not supported in multirect mode\n");
 			return -EINVAL;
 		}
 
 		if (DPU_FORMAT_IS_YUV(fmt[i])) {
-			DPU_ERROR_PLANE(dpu_plane[i],
+			DPU_DEBUG_PLANE(dpu_plane[i],
 				"Unsupported format for multirect mode\n");
 			return -EINVAL;
 		}
@@ -816,8 +813,8 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane)
 
 	/* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
 	if (parallel_fetch_qualified) {
-		pstate[R0]->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
-		pstate[R1]->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
+		pstate0->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
+		pstate1->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
 
 		goto done;
 	}
@@ -827,10 +824,10 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane)
 
 	if (dst[R1].y1 >= dst[R0].y2 + buffer_lines ||
 	    dst[R0].y1 >= dst[R1].y2 + buffer_lines) {
-		pstate[R0]->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX;
-		pstate[R1]->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX;
+		pstate0->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX;
+		pstate1->multirect_mode = DPU_SSPP_MULTIRECT_TIME_MX;
 	} else {
-		DPU_ERROR(
+		DPU_DEBUG(
 			"No multirect mode possible for the planes (%d - %d)\n",
 			drm_state[R0]->plane->base.id,
 			drm_state[R1]->plane->base.id);
@@ -838,13 +835,15 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane)
 	}
 
 done:
-	pstate[R0]->multirect_index = DPU_SSPP_RECT_0;
-	pstate[R1]->multirect_index = DPU_SSPP_RECT_1;
+	pstate0->multirect_index = DPU_SSPP_RECT_0;
+	pstate1->multirect_index = DPU_SSPP_RECT_1;
+
+	pstate0->qos_src_w = max(pstate0->qos_src_w, pstate1->base.src_w >> 16);
 
 	DPU_DEBUG_PLANE(dpu_plane[R0], "R0: %d - %d\n",
-		pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
+		pstate0->multirect_mode, pstate0->multirect_index);
 	DPU_DEBUG_PLANE(dpu_plane[R1], "R1: %d - %d\n",
-		pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
+		pstate1->multirect_mode, pstate1->multirect_index);
 	return 0;
 }
 
@@ -928,7 +927,8 @@ static bool dpu_plane_validate_src(struct drm_rect *src,
 		drm_rect_equals(fb_rect, src);
 }
 
-int dpu_plane_set_pipe(struct drm_plane *plane, struct dpu_plane_state *pstate)
+int dpu_plane_set_pipe(struct drm_plane *plane, struct dpu_plane_state *pstate,
+		struct dpu_plane_state *prev_plane_state)
 {
 	struct dpu_kms *kms = _dpu_plane_get_kms(plane);
 	struct dpu_plane *pdpu = to_dpu_plane(plane);
@@ -936,11 +936,24 @@ int dpu_plane_set_pipe(struct drm_plane *plane, struct dpu_plane_state *pstate)
 	enum dpu_sspp pipe;
 	bool yuv, scale;
 
+	pstate->multirect_index = DPU_SSPP_RECT_SOLO;
+	pstate->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
+
 	if (pdpu->pipe != SSPP_NONE) {
 		pipe = pdpu->pipe;
 		goto out;
 	}
 
+	if (prev_plane_state &&
+	    kms->catalog->caps->smart_dma_rev != DPU_SMART_DMA_UNSUPPORTED &&
+	    !dpu_plane_validate_multirect_v2(prev_plane_state, pstate)) {
+		/* multirect capable, use the same pipe */
+		DPU_DEBUG_PLANE(pdpu, "multirect, SSPP %d\n", prev_plane_state->pipe_hw->idx);
+		pstate->pipe_hw = prev_plane_state->pipe_hw;
+
+		return 0;
+	}
+
 	yuv = pstate->base.fb ? DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(pstate->base.fb))) : false;
 	scale = (pstate->base.src_w >> 16 != pstate->base.crtc_w) ||
 		(pstate->base.src_h >> 16 != pstate->base.crtc_h);
@@ -953,6 +966,8 @@ int dpu_plane_set_pipe(struct drm_plane *plane, struct dpu_plane_state *pstate)
 	if (pipe == SSPP_NONE || pipe >= SSPP_MAX || !kms->rm.sspp_blks[pipe - SSPP_NONE])
 		return -EINVAL;
 
+	pstate->qos_src_w = pstate->base.src_w >> 16;
+
 	pstate->pipe_hw = to_dpu_hw_pipe(kms->rm.sspp_blks[pipe - SSPP_NONE]);
 
 	return 0;
@@ -988,7 +1003,7 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
 
 		DRM_DEBUG_ATOMIC("PLANE %d released SSPP %d\n", plane->base.id, pstate->pipe_hw->idx);
 		dpu_rm_release_sspp(&dpu_kms->rm, global_state, plane->base.id);
-		pstate->pipe_hw = NULL;
+		/* do not clear pipe_hw here, use it in atomic_disable to cleanup mutlirect */
 	}
 
 	return 0;
@@ -1199,7 +1214,7 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
 				pstate->multirect_index);
 	}
 
-	_dpu_plane_setup_scaler(pdpu, pstate, fmt, false, &pipe_cfg);
+	_dpu_plane_setup_scaler(pdpu, pstate, fmt, &pipe_cfg);
 
 	if (pstate->pipe_hw->ops.setup_multirect)
 		pstate->pipe_hw->ops.setup_multirect(
@@ -1245,8 +1260,10 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
 		}
 	}
 
-	_dpu_plane_set_qos_lut(plane, fb, &pipe_cfg);
-	_dpu_plane_set_danger_lut(plane, fb);
+	if (pstate->multirect_index != DPU_SSPP_RECT_1) {
+		_dpu_plane_set_qos_lut(plane, fb, pstate->qos_src_w);
+		_dpu_plane_set_danger_lut(plane, fb);
+	}
 
 	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
 		_dpu_plane_set_qos_ctrl(plane, true, DPU_PLANE_QOS_PANIC_CTRL);
@@ -1279,7 +1296,13 @@ static void _dpu_plane_atomic_disable(struct drm_plane *plane)
 
 	pstate->pending = true;
 
-	pstate->pipe_hw = NULL;
+	if (pstate->multirect_index != DPU_SSPP_RECT_SOLO &&
+	    pstate->pipe_hw &&
+	    pstate->pipe_hw->ops.setup_multirect)
+		pstate->pipe_hw->ops.setup_multirect(
+				pstate->pipe_hw,
+				DPU_SSPP_RECT_SOLO,
+				DPU_SSPP_MULTIRECT_NONE);
 }
 
 static void dpu_plane_atomic_update(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
index 0940ffbb8b28..6ec7f5edc06a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
@@ -23,6 +23,7 @@
  * @multirect_index: index of the rectangle of SSPP
  * @multirect_mode: parallel or time multiplex multirect mode
  * @pending:	whether the current update is still pending
+ * @qos_src_w: src_width used for qos_lut setup
  * @plane_fetch_bw: calculated BW per plane
  * @plane_clk: calculated clk per plane
  */
@@ -35,22 +36,14 @@ struct dpu_plane_state {
 	uint32_t multirect_mode;
 	bool pending;
 
+	uint32_t qos_src_w;
+
 	struct dpu_hw_pipe *pipe_hw;
 
 	u64 plane_fetch_bw;
 	u64 plane_clk;
 };
 
-/**
- * struct dpu_multirect_plane_states: Defines multirect pair of drm plane states
- * @r0: drm plane configured on rect 0
- * @r1: drm plane configured on rect 1
- */
-struct dpu_multirect_plane_states {
-	const struct drm_plane_state *r0;
-	const struct drm_plane_state *r1;
-};
-
 #define to_dpu_plane_state(x) \
 	container_of(x, struct dpu_plane_state, base)
 
@@ -78,19 +71,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
 		uint32_t pipe, enum drm_plane_type type,
 		unsigned long possible_crtcs);
 
-/**
- * dpu_plane_validate_multirecti_v2 - validate the multirect planes
- *				      against hw limitations
- * @plane: drm plate states of the multirect pair
- */
-int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane);
-
-/**
- * dpu_plane_clear_multirect - clear multirect bits for the given pipe
- * @drm_state: Pointer to DRM plane state
- */
-void dpu_plane_clear_multirect(const struct drm_plane_state *drm_state);
-
 /**
  * dpu_plane_color_fill - enables color fill on plane
  * @plane:  Pointer to DRM plane object
@@ -107,7 +87,8 @@ void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable);
 static inline void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) {}
 #endif
 
-int dpu_plane_set_pipe(struct drm_plane *plane, struct dpu_plane_state *pstate);
+int dpu_plane_set_pipe(struct drm_plane *plane, struct dpu_plane_state *pstate,
+		struct dpu_plane_state *prev_plane_state);
 
 int dpu_plane_real_atomic_check(struct drm_plane *plane,
 				struct drm_atomic_state *state);
