diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
index e0688895..4eb929b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
@@ -25,6 +25,8 @@
 #include "dpu_hw_mdss.h"
 #include "dpu_hw_sspp.h"
 
+#define PLANE_DUAL_PIPES 2
+
 /**
  * struct dpu_plane_state: Define dpu extension of drm plane state object
  * @base:	base drm plane state object
@@ -36,6 +38,8 @@
  * @multirect_index: index of the rectangle of SSPP
  * @multirect_mode: parallel or time multiplex multirect mode
  * @pending:	whether the current update is still pending
+ * @num_pipes: number of pipes attached to plane
+ * @pipe_hw: array of pointers to hardware pipes reserved for plane
  * @scaler3_cfg: configuration data for scaler3
  * @pixel_ext: configuration data for pixel extensions
  * @scaler_check_state: indicates status of user provided pixel extension data
@@ -48,6 +52,10 @@ struct dpu_plane_state {
 	enum dpu_stage stage;
 	bool pending;
 
+	/* HW pipe config */
+	u32 num_pipes;
+	struct dpu_hw_pipe *pipe_hw[PLANE_DUAL_PIPES];
+
 	/* scaler configuration */
 	struct dpu_hw_scaler3_cfg scaler3_cfg;
 	struct dpu_hw_pixel_ext pixel_ext;
@@ -58,6 +66,9 @@ struct dpu_plane_state {
 #define to_dpu_plane_state(x) \
 	container_of(x, struct dpu_plane_state, base)
 
+/* get plane id from dpu plane state */
+#define get_plane_id(x) ((x->base.plane)->base.id)
+
 /**
  * dpu_plane_pipe - return sspp identifier for the given plane
  * @plane:   Pointer to DRM plane object
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 018d01a..5387600 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -14,6 +14,7 @@
 
 #define pr_fmt(fmt)	"[drm:%s] " fmt, __func__
 #include "dpu_kms.h"
+#include "dpu_hw_sspp.h"
 #include "dpu_hw_lm.h"
 #include "dpu_hw_ctl.h"
 #include "dpu_hw_cdm.h"
@@ -22,10 +23,13 @@
 #include "dpu_encoder.h"
 #include "dpu_rm.h"
 
+#define RESERVED_BY_OTHER(drm_map_id, drm_id) \
+		(drm_map_id && (drm_map_id != drm_id))
+
 /**
  * struct dpu_rm_hw_blk - hardware block tracking list member
  * @type:	Type of hardware block this structure tracks
- * @drm_id:	DRM component ID associated with the HW block
+ * @rm_id:	DRM component ID associated with the HW block
  * @id:		Hardware ID number, within it's own space, ie. LM_X
  * @hw:		Pointer to the hardware register access object for this block
  */
@@ -157,7 +161,8 @@ static void _dpu_rm_hw_destroy(enum dpu_hw_blk_type type, void *hw)
 		dpu_hw_intf_destroy(hw);
 		break;
 	case DPU_HW_BLK_SSPP:
-		/* SSPPs are not managed by the resource manager */
+		dpu_hw_sspp_destroy(hw);
+		break;
 	case DPU_HW_BLK_TOP:
 		/* Top is a singleton, not managed in hw_blks list */
 	case DPU_HW_BLK_MAX:
@@ -229,7 +234,8 @@ static int _dpu_rm_hw_blk_create(
 		hw = dpu_hw_intf_init(id, mmio, cat);
 		break;
 	case DPU_HW_BLK_SSPP:
-		/* SSPPs are not managed by the resource manager */
+		hw = dpu_hw_sspp_init(id, mmio, cat);
+		break;
 	case DPU_HW_BLK_TOP:
 		/* Top is a singleton, not managed in hw_blks list */
 	case DPU_HW_BLK_MAX:
@@ -281,6 +287,15 @@ int dpu_rm_init(struct dpu_rm *rm,
 	}
 
 	/* Interrogate HW catalog and create tracking items for hw blocks */
+	for (i = 0; i < cat->sspp_count; i++) {
+		rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_SSPP,
+				cat->sspp[i].id, &cat->sspp[i]);
+		if (rc) {
+			DPU_ERROR("failed: sspp hw not available\n");
+			goto fail;
+		}
+	}
+
 	for (i = 0; i < cat->mixer_count; i++) {
 		struct dpu_lm_cfg *lm = &cat->mixer[i];
 
@@ -570,12 +585,10 @@ static int _dpu_rm_reserve_intf_related_hw(
 }
 
 static int _dpu_rm_release_hw_blk(
-		struct dpu_rm *rm,
-		struct dpu_crtc_state *state,
+		struct dpu_rm *rm, int drm_id,
 		enum dpu_hw_blk_type type)
 {
 	struct dpu_rm_hw_iter iter;
-	int drm_id = get_crtc_id(state);
 	int num_released = 0;
 	int *drm_map = rm->hw_drm_map[type];
 
@@ -590,15 +603,15 @@ static int _dpu_rm_release_hw_blk(
 	return num_released;
 }
 
-static int _dpu_rm_release_lms(struct dpu_rm *rm, struct dpu_crtc_state *state)
+static int _dpu_rm_release_lms(struct dpu_rm *rm, int drm_id)
 {
 	int num_lm, num_pp;
 
 	/* Release LM blocks */
-	num_lm = _dpu_rm_release_hw_blk(rm, state, DPU_HW_BLK_LM);
+	num_lm = _dpu_rm_release_hw_blk(rm, drm_id, DPU_HW_BLK_LM);
 
 	/* Rlease ping pong blocks */
-	num_pp = _dpu_rm_release_hw_blk(rm, state, DPU_HW_BLK_PINGPONG);
+	num_pp = _dpu_rm_release_hw_blk(rm, drm_id, DPU_HW_BLK_PINGPONG);
 	if (num_pp != num_lm) {
 		DPU_ERROR("lm chain count mismatch lm: %d pp:%d\n",
 				num_lm, num_pp);
@@ -639,26 +652,28 @@ int dpu_rm_reserve_crtc_res(struct dpu_rm *rm, struct dpu_crtc_state *state,
 int dpu_rm_release_crtc_res(struct dpu_rm *rm, struct dpu_crtc_state *state)
 {
 	int rc = 0, num_released;
+	int drm_id = get_crtc_id(state);
 
 	mutex_lock(&rm->rm_lock);
 
-	num_released = _dpu_rm_release_lms(rm, state);
+	num_released = _dpu_rm_release_lms(rm, drm_id);
 	if (num_released != state->num_mixers) {
 		DPU_ERROR(
 		"lm release count doesn't match for crtc: %d (%d != %d)\n",
-			get_crtc_id(state), num_released, state->num_mixers);
+			drm_id, num_released, state->num_mixers);
 		rc = -EINVAL;
 		goto release_done;
 	}
 
-	num_released = _dpu_rm_release_hw_blk(rm, state, DPU_HW_BLK_CTL);
+	num_released = _dpu_rm_release_hw_blk(rm, drm_id, DPU_HW_BLK_CTL);
 	if (num_released != state->num_ctls) {
 		DPU_ERROR(
 		"lm release count doesn't match for crtc: %d (%d != %d)\n",
-			get_crtc_id(state), num_released, state->num_ctls);
+			drm_id, num_released, state->num_ctls);
 		rc = -EINVAL;
 		goto release_done;
 	}
+
  release_done:
 	mutex_unlock(&rm->rm_lock);
 
@@ -692,14 +707,15 @@ int dpu_rm_release_encoder_res(struct dpu_rm *rm, struct dpu_crtc_state *state)
 {
 	int num_released;
 	int rc = 0;
+	int drm_id = get_crtc_id(state);
 
 	mutex_lock(&rm->rm_lock);
 
-	num_released = _dpu_rm_release_hw_blk(rm, state, DPU_HW_BLK_INTF);
+	num_released = _dpu_rm_release_hw_blk(rm, drm_id, DPU_HW_BLK_INTF);
 	if (num_released != state->num_intfs) {
 		DPU_ERROR(
 		"intf release count doesn't match for crtc: %d (%d != %d)\n",
-			get_crtc_id(state), num_released, state->num_intfs);
+			drm_id, num_released, state->num_intfs);
 		rc = -EINVAL;
 	}
 
@@ -711,3 +727,113 @@ int dpu_rm_release_encoder_res(struct dpu_rm *rm, struct dpu_crtc_state *state)
 	return rc;
 }
 
+static int _dpu_rm_reserve_sspp(struct dpu_rm *rm,
+		struct dpu_plane_state *state, u32 num_pipes, u32 caps)
+{
+	struct dpu_rm_hw_blk *sspp[MAX_BLOCKS];
+	struct dpu_rm_hw_iter iter_i, iter_j;
+	const struct dpu_sspp_cfg *lpipe_cfg, *rpipe_cfg;
+	int sspp_count = 0, i;
+	int drm_id = get_plane_id(state);
+	int *sspp_drm_map = rm->hw_drm_map[DPU_HW_BLK_SSPP];
+
+	dpu_rm_init_hw_iter(&iter_i, 0, DPU_HW_BLK_SSPP);
+
+	while ((sspp_count != num_pipes) &&
+			_dpu_rm_get_hw_locked(rm, &iter_i)) {
+		sspp_count = 0;
+
+		/* skip if pipe has been reserved by different plane */
+		if (RESERVED_BY_OTHER(sspp_drm_map[iter_i.blk->rm_id], drm_id))
+			continue;
+
+		/* skip if pipe doesn't support the required caps */
+		lpipe_cfg = to_dpu_hw_pipe(iter_i.blk->hw)->cap;
+		if (caps & ~lpipe_cfg->features)
+			continue;
+
+		/* skip cursor pipe assignment to non cursor plane type */
+		if ((caps & DPU_SSPP_CURSOR) &&
+			(state->base.plane)->type != DRM_PLANE_TYPE_CURSOR)
+			continue;
+
+		sspp[sspp_count++] = iter_i.blk;
+
+		/**
+		 * Find another sspp of same type and honoring
+		 * priority - VIG0 > VIG1
+		 */
+		dpu_rm_init_hw_iter(&iter_j, 0, DPU_HW_BLK_SSPP);
+
+		while (sspp_count != num_pipes &&
+				_dpu_rm_get_hw_locked(rm, &iter_j)) {
+			if ((iter_i.blk == iter_j.blk) || RESERVED_BY_OTHER(
+				sspp_drm_map[iter_j.blk->rm_id], drm_id))
+				continue;
+
+			rpipe_cfg = to_dpu_hw_pipe(iter_j.blk->hw)->cap;
+			if ((rpipe_cfg->features != lpipe_cfg->features)
+				|| (lpipe_cfg->id > rpipe_cfg->id))
+				continue;
+
+			sspp[sspp_count++] = iter_j.blk;
+			break;
+		}
+	}
+
+	if (sspp_count != num_pipes) {
+		DPU_DEBUG("unable to find appropriate hw pipes\n");
+		return -ENAVAIL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sspp) && i < num_pipes; i++) {
+		sspp_drm_map[sspp[i]->rm_id] = drm_id;
+
+		state->pipe_hw[i] = to_dpu_hw_pipe(sspp[i]->hw);
+		DPU_DEBUG("%d : sspp %d reserved for plane id %d\n",
+				i, sspp[i]->id, drm_id);
+	}
+
+	state->num_pipes = num_pipes;
+	return 0;
+}
+
+int dpu_rm_reserve_plane_res(struct dpu_rm *rm,
+	struct dpu_plane_state *state, u32 num_pipes, u32 caps)
+{
+	int rc = 0;
+
+	mutex_lock(&rm->rm_lock);
+
+	rc = _dpu_rm_reserve_sspp(rm, state, num_pipes, caps);
+	if (rc)
+		DPU_ERROR("unable to allocate %d sspp for plane: %d\n",
+				num_pipes, get_plane_id(state));
+
+	mutex_unlock(&rm->rm_lock);
+	return rc;
+}
+
+int dpu_rm_release_plane_res(struct dpu_rm *rm, struct dpu_plane_state *state)
+{
+	int num_released;
+	int rc = 0;
+	int drm_id = get_plane_id(state);
+
+	mutex_lock(&rm->rm_lock);
+
+	num_released = _dpu_rm_release_hw_blk(rm, drm_id, DPU_HW_BLK_SSPP);
+	if (num_released != state->num_pipes) {
+		DPU_ERROR(
+			"sspp release count doesn't match for plane: %d (%d != %d)\n",
+				drm_id, num_released, state->num_pipes);
+		rc = -EINVAL;
+	}
+
+	mutex_unlock(&rm->rm_lock);
+
+	state->num_pipes = 0;
+	memset(&state->pipe_hw, 0, sizeof(state->pipe_hw));
+
+	return rc;
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index fa2cd70..b43e19a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -20,6 +20,7 @@
 #include "dpu_hw_top.h"
 #include "dpu_crtc.h"
 #include "dpu_encoder.h"
+#include "dpu_plane.h"
 
 /**
  * struct dpu_rm - DPU dynamic hardware resource manager
@@ -86,6 +87,25 @@ int dpu_rm_init(struct dpu_rm *rm,
 int dpu_rm_destroy(struct dpu_rm *rm);
 
 /**
+ * dpu_rm_reserve_plane_res - Reserve HW blocks for PLANE
+ * @rm: DPU Resource Manager handle
+ * @state: DPU PLANE state to cache HW block handles
+ * @num_pipes: Number of pipes to be reserved for the plane
+ * @caps: Reserve hw blocks with matching capabilities
+ * @Return: 0 on Success otherwise -ERROR
+ */
+int dpu_rm_reserve_plane_res(struct dpu_rm *rm, struct dpu_plane_state *state,
+				u32 num_pipes, u32 caps);
+
+/**
+ * dpu_rm_release_plane_res - Release HW blocks of PLANE
+ * @rm: DPU Resource Manager handle
+ * @state: DPU PLANE state to cache HW block handles
+ * @plane_id: Release reservation for given plane id
+ */
+int dpu_rm_release_plane_res(struct dpu_rm *rm, struct dpu_plane_state *state);
+
+/**
  * dpu_rm_reserve_crtc_res - Reserve HW blocks for CRTC
  * @rm: DPU Resource Manager handle
  * @state: DPU CRTC state to cache HW block handles
