diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 317dd2e..6c78c11c3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -47,6 +47,8 @@
 #define RIGHT_MIXER 1
 
 #define MISR_BUFF_SIZE			256
+#define MAX_VDISPLAY_SPLIT		1080
+
 
 static inline struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
 {
@@ -276,16 +278,7 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
 
 	DPU_DEBUG("%s\n", dpu_crtc->name);
 
-	if (cstate->num_mixers > CRTC_DUAL_MIXERS) {
-		DPU_ERROR("invalid number mixers: %d\n", cstate->num_mixers);
-		return;
-	}
-
 	for (i = 0; i < cstate->num_mixers; i++) {
-		if (!mixer[i].hw_lm || !mixer[i].lm_ctl) {
-			DPU_ERROR("invalid lm or ctl assigned to mixer\n");
-			return;
-		}
 		mixer[i].mixer_op_mode = 0;
 		mixer[i].flush_mask = 0;
 		if (mixer[i].lm_ctl->ops.clear_all_blendstages)
@@ -579,75 +572,27 @@ void dpu_crtc_complete_commit(struct drm_crtc *crtc,
 	DPU_EVT32_VERBOSE(DRMID(crtc));
 }
 
-static void _dpu_crtc_setup_mixer_for_encoder(
-		struct drm_crtc *crtc,
-		struct drm_encoder *enc)
+static void _dpu_crtc_setup_mixers(struct drm_crtc_state *crtc_state)
 {
-	struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state);
-	struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
-	struct dpu_rm *rm = &dpu_kms->rm;
+	struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
 	struct dpu_crtc_mixer *mixer;
-	struct dpu_hw_ctl *last_valid_ctl = NULL;
 	int i;
-	struct dpu_rm_hw_iter lm_iter, ctl_iter;
-
-	dpu_rm_init_hw_iter(&lm_iter, enc->base.id, DPU_HW_BLK_LM);
-	dpu_rm_init_hw_iter(&ctl_iter, enc->base.id, DPU_HW_BLK_CTL);
-
-	/* Set up all the mixers and ctls reserved by this encoder */
-	for (i = cstate->num_mixers; i < ARRAY_SIZE(cstate->mixers); i++) {
-		mixer = &cstate->mixers[i];
-
-		if (!dpu_rm_get_hw(rm, &lm_iter))
-			break;
-		mixer->hw_lm = (struct dpu_hw_mixer *)lm_iter.hw;
-
-		/* CTL may be <= LMs, if <, multiple LMs controlled by 1 CTL */
-		if (!dpu_rm_get_hw(rm, &ctl_iter)) {
-			DPU_DEBUG("no ctl assigned to lm %d, using previous\n",
-					mixer->hw_lm->idx - LM_0);
-			mixer->lm_ctl = last_valid_ctl;
-		} else {
-			mixer->lm_ctl = (struct dpu_hw_ctl *)ctl_iter.hw;
-			last_valid_ctl = mixer->lm_ctl;
-		}
-
-		/* Shouldn't happen, mixers are always >= ctls */
-		if (!mixer->lm_ctl) {
-			DPU_ERROR("no valid ctls found for lm %d\n",
-					mixer->hw_lm->idx - LM_0);
-			return;
-		}
 
-		mixer->encoder = enc;
-
-		cstate->num_mixers++;
-		DPU_DEBUG("setup mixer %d: lm %d\n",
-				i, mixer->hw_lm->idx - LM_0);
-		DPU_DEBUG("setup mixer %d: ctl %d\n",
-				i, mixer->lm_ctl->idx - CTL_0);
+	if (cstate->num_mixers > cstate->num_ctls) {
+		DPU_ERROR(
+			"lm count(%d) > ctl count(%d). No support for such topologies\n",
+			cstate->num_mixers, cstate->num_ctls);
+		return;
 	}
-}
-
-static void _dpu_crtc_setup_mixers(struct drm_crtc *crtc)
-{
-	struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
-	struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state);
-	struct drm_encoder *enc;
 
-	cstate->num_mixers = 0;
-	memset(cstate->mixers, 0, sizeof(cstate->mixers));
-
-	mutex_lock(&dpu_crtc->crtc_lock);
-	/* Check for mixers on all encoders attached to this crtc */
-	list_for_each_entry(enc, &crtc->dev->mode_config.encoder_list, head) {
-		if (enc->crtc != crtc)
-			continue;
+	/* Set up all the mixers and ctls reserved by this encoder */
+	for (i = 0; i < cstate->num_mixers; i++) {
+		cstate->mixers[i].lm_ctl = cstate->hw_ctls[i];
 
-		_dpu_crtc_setup_mixer_for_encoder(crtc, enc);
+		DPU_DEBUG("setup mixer %d: lm(%d) - ctl(%d)\n",
+				i, mixer->hw_lm->idx - LM_0,
+				mixer->lm_ctl->idx - CTL_0);
 	}
-
-	mutex_unlock(&dpu_crtc->crtc_lock);
 }
 
 static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
@@ -688,7 +633,7 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
 		struct drm_crtc_state *old_state)
 {
 	struct dpu_crtc *dpu_crtc;
-	struct dpu_crtc_state *cstate;
+	struct dpu_crtc_state *new_cstate;
 	struct drm_encoder *encoder;
 	struct drm_device *dev;
 	unsigned long flags;
@@ -708,14 +653,11 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
 	DPU_DEBUG("crtc%d\n", crtc->base.id);
 
 	dpu_crtc = to_dpu_crtc(crtc);
-	cstate = to_dpu_crtc_state(crtc->state);
+	new_cstate = to_dpu_crtc_state(crtc->state);
 	dev = crtc->dev;
 	smmu_state = &dpu_crtc->smmu_state;
 
-	if (!cstate->num_mixers) {
-		_dpu_crtc_setup_mixers(crtc);
-		_dpu_crtc_setup_lm_bounds(crtc, crtc->state);
-	}
+	_dpu_crtc_setup_lm_bounds(crtc, crtc->state);
 
 	if (dpu_crtc->event) {
 		WARN_ON(dpu_crtc->event);
@@ -739,7 +681,7 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
 	 * it means we are trying to flush a CRTC whose state is disabled:
 	 * nothing else needs to be done.
 	 */
-	if (unlikely(!cstate->num_mixers))
+	if (unlikely(!new_cstate->num_mixers))
 		return;
 
 	_dpu_crtc_blend_setup(crtc);
@@ -1157,9 +1099,9 @@ static void dpu_crtc_handle_power_event(u32 event_type, void *arg)
 {
 	struct drm_crtc *crtc = arg;
 	struct dpu_crtc *dpu_crtc;
+	struct dpu_crtc_state *cstate;
 	struct drm_encoder *encoder;
 	struct dpu_crtc_mixer *m;
-	struct dpu_crtc_state *cstate;
 	u32 i, misr_status;
 
 	if (!crtc) {
@@ -1167,6 +1109,7 @@ static void dpu_crtc_handle_power_event(u32 event_type, void *arg)
 		return;
 	}
 	dpu_crtc = to_dpu_crtc(crtc);
+	cstate = to_dpu_crtc_state(crtc->state);
 
 	mutex_lock(&dpu_crtc->crtc_lock);
 
@@ -1226,6 +1169,8 @@ static void dpu_crtc_disable(struct drm_crtc *crtc)
 	struct drm_encoder *encoder;
 	struct msm_drm_private *priv;
 	struct drm_event event;
+	struct dpu_private_state *dpu_priv_state;
+	struct dpu_kms *dpu_kms;
 	u32 power_on;
 	int ret;
 
@@ -1237,6 +1182,10 @@ static void dpu_crtc_disable(struct drm_crtc *crtc)
 	cstate = to_dpu_crtc_state(crtc->state);
 	mode = &cstate->base.adjusted_mode;
 	priv = crtc->dev->dev_private;
+	dpu_kms = to_dpu_kms(priv->kms);
+
+	/* accessing after swap state. piv_obj.state is the current state */
+	dpu_priv_state = to_dpu_private_state(dpu_kms->priv_obj.state);
 
 	DPU_DEBUG("crtc%d\n", crtc->base.id);
 
@@ -1289,14 +1238,14 @@ static void dpu_crtc_disable(struct drm_crtc *crtc)
 		dpu_power_handle_unregister_event(dpu_crtc->phandle,
 				dpu_crtc->power_event);
 
-
-	memset(cstate->mixers, 0, sizeof(cstate->mixers));
-	cstate->num_mixers = 0;
-
 	/* disable clk & bw control until clk & bw properties are set */
 	cstate->bw_control = false;
 	cstate->bw_split_vote = false;
 
+	ret = dpu_rm_release_crtc_res(&dpu_priv_state->rm, cstate);
+	if (ret)
+		DPU_ERROR("error in releasing crtc resources\n");
+
 	mutex_unlock(&dpu_crtc->crtc_lock);
 }
 
@@ -1356,6 +1305,31 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
 
 }
 
+static struct dpu_crtc_topology
+dpu_crtc_get_topology(struct dpu_crtc_state *cstate,
+		struct drm_display_mode *mode)
+{
+	struct dpu_crtc_topology topology;
+
+	memset(&topology, 0, sizeof(topology));
+
+	/* Use split topology for width > 1080 */
+	topology.num_lms = (mode->vdisplay > MAX_VDISPLAY_SPLIT) ? 2 : 1;
+	topology.num_ctls = topology.num_lms;
+
+	topology.needs_realloc = (topology.num_lms != cstate->num_mixers) ||
+		(topology.num_ctls != cstate->num_ctls);
+
+	if (topology.needs_realloc)
+		DPU_DEBUG(
+		"crtc %d needs hw reallocation. lm (%d - %d) ctl(%d - %d)\n",
+			get_crtc_id(cstate),
+			cstate->num_mixers, topology.num_lms,
+			cstate->num_ctls, topology.num_ctls);
+
+	return topology;
+}
+
 struct plane_state {
 	struct dpu_plane_state *dpu_pstate;
 	const struct drm_plane_state *drm_pstate;
@@ -1373,6 +1347,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 	const struct drm_plane_state *pstate;
 	struct drm_plane *plane;
 	struct drm_display_mode *mode;
+	struct dpu_crtc_topology topology;
+	struct dpu_private_state *dpu_priv_state;
 
 	int cnt = 0, rc = 0, mixer_width, i, z_pos;
 
@@ -1586,6 +1562,25 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 		}
 	}
 
+	/* Resource allocation */
+	dpu_priv_state = dpu_get_private_state(state->state);
+	if (IS_ERR(dpu_priv_state))
+		goto end;
+
+	topology = dpu_crtc_get_topology(cstate, &state->adjusted_mode);
+	if (!topology.needs_realloc)
+		goto end;
+
+	dpu_rm_release_crtc_res(&dpu_priv_state->rm, cstate);
+	rc = dpu_rm_reserve_crtc_res(&dpu_priv_state->rm, cstate, &topology);
+	if (rc) {
+		DPU_ERROR("failed to allocate resources for crtc: %d\n",
+				crtc->base.id);
+		goto end;
+	}
+
+	_dpu_crtc_setup_mixers(state);
+
 end:
 	return rc;
 }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index f3edff3..50c3d4b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -30,6 +30,8 @@
 /* define the maximum number of in-flight frame events */
 #define DPU_CRTC_FRAME_EVENT_SIZE	4
 
+struct dpu_kms;
+
 /**
  * enum dpu_crtc_client_type: crtc client type
  * @RT_CLIENT:	RealTime client like video/cmd mode display
@@ -83,15 +85,15 @@ struct dpu_crtc_smmu_state_data {
 /**
  * struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC
  * @hw_lm:	LM HW Driver context
- * @lm_ctl:	CTL Path HW driver context
- * @encoder:	Encoder attached to this lm & ctl
+ * @lm_ctl:	CTL path for associated LM HW
+ * @hw_pp:	Pingpong HW driver context
  * @mixer_op_mode:	mixer blending operation mode
  * @flush_mask:	mixer flush mask for ctl, mixer and pipe
  */
 struct dpu_crtc_mixer {
 	struct dpu_hw_mixer *hw_lm;
 	struct dpu_hw_ctl *lm_ctl;
-	struct drm_encoder *encoder;
+	struct dpu_hw_pingpong *hw_pp;
 	u32 mixer_op_mode;
 	u32 flush_mask;
 };
@@ -134,6 +136,13 @@ struct dpu_crtc_event {
  */
 #define DPU_CRTC_MAX_EVENT_COUNT	16
 
+struct dpu_crtc_topology {
+	bool needs_realloc;
+	int num_ctls;
+	int num_lms;
+	int num_intfs;
+};
+
 /**
  * struct dpu_crtc - virtualized CRTC data structure
  * @base          : Base drm crtc structure
@@ -243,6 +252,8 @@ struct dpu_crtc {
  * @mixers        : List of active mixers
  * @num_ctls      : Number of ctl paths in use
  * @hw_ctls       : List of activel ctl paths
+ * @num_intf      : Numeer of interfaces in uses
+ * @hw_intfs      : List of interfaces in use
  */
 struct dpu_crtc_state {
 	struct drm_crtc_state base;
@@ -262,11 +273,26 @@ struct dpu_crtc_state {
 
 	u32 num_ctls;
 	struct dpu_hw_ctl *hw_ctls[CRTC_DUAL_MIXERS];
+
+	/**
+	 * as drm encoders doesn't have dedicates state objects
+	 * and drm connectors are not owned by DPU, maintain
+	 * HW interface and other interface related blocks
+	 * in crtc state
+	 *
+	 * TODO: No support for clone mode yet where a crtc
+	 * can be attached with more than one encoder/connector.
+	 */
+	u32 num_intfs;
+	struct dpu_hw_intf *hw_intfs[CRTC_DUAL_MIXERS];
 };
 
 #define to_dpu_crtc_state(x) \
 	container_of(x, struct dpu_crtc_state, base)
 
+/* get crtc id from dpu crtc state*/
+#define get_crtc_id(x) ((x->base.crtc)->base.id)
+
 /**
  * dpu_crtc_get_mixer_width - get the mixer width
  * Mixer width will be same as panel width(/2 for split)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 5e820bc..128b0ea 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -69,8 +69,6 @@
 
 #define IDLE_SHORT_TIMEOUT	1
 
-#define MAX_VDISPLAY_SPLIT 1080
-
 /**
  * enum dpu_enc_rc_events - events for resource control state machine
  * @DPU_ENC_RC_EVENT_KICKOFF:
@@ -580,25 +578,32 @@ static void _dpu_encoder_adjust_mode(struct drm_connector *connector,
 	}
 }
 
-static struct msm_display_topology dpu_encoder_get_topology(
+static struct dpu_crtc_topology dpu_encoder_get_topology(
 			struct dpu_encoder_virt *dpu_enc,
-			struct dpu_kms *dpu_kms,
-			struct drm_display_mode *mode)
+			struct dpu_crtc_state *cstate)
 {
-	struct msm_display_topology topology;
+	struct dpu_crtc_topology topology;
 	int i, intf_count = 0;
 
+	memset(&topology, 0, sizeof(topology));
+
 	for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
 		if (dpu_enc->phys_encs[i])
 			intf_count++;
 
-	/* User split topology for width > 1080 */
-	topology.num_lm = (mode->vdisplay > MAX_VDISPLAY_SPLIT) ? 2 : 1;
-	topology.num_enc = 0;
-	topology.num_intf = intf_count;
+	topology.num_intfs = intf_count;
+
+	topology.needs_realloc = (cstate->num_intfs != topology.num_intfs);
+
+	if (topology.needs_realloc)
+		DPU_DEBUG_ENC(dpu_enc,
+			"crtc %d needs hw reallocation. intf (%d - %d)\n",
+			get_crtc_id(cstate),
+			cstate->num_intfs, topology.num_intfs);
 
 	return topology;
 }
+
 static int dpu_encoder_virt_atomic_check(
 		struct drm_encoder *drm_enc,
 		struct drm_crtc_state *crtc_state,
@@ -609,7 +614,10 @@ static int dpu_encoder_virt_atomic_check(
 	struct dpu_kms *dpu_kms;
 	const struct drm_display_mode *mode;
 	struct drm_display_mode *adj_mode;
-	struct msm_display_topology topology;
+	struct dpu_crtc_topology topology;
+	struct dpu_crtc_state *dpu_cstate;
+	struct dpu_private_state *dpu_priv_state;
+	struct dpu_encoder_hw_resources enc_hw_res;
 	int i = 0;
 	int ret = 0;
 
@@ -626,6 +634,7 @@ static int dpu_encoder_virt_atomic_check(
 	dpu_kms = to_dpu_kms(priv->kms);
 	mode = &crtc_state->mode;
 	adj_mode = &crtc_state->adjusted_mode;
+	dpu_cstate = to_dpu_crtc_state(crtc_state);
 	DPU_EVT32(DRMID(drm_enc));
 
 	/*
@@ -655,27 +664,33 @@ static int dpu_encoder_virt_atomic_check(
 		}
 	}
 
-	topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode);
+	if (ret)
+		goto end;
 
-	/* Reserve dynamic resources now. Indicating AtomicTest phase */
-	if (!ret) {
-		/*
-		 * Avoid reserving resources when mode set is pending. Topology
-		 * info may not be available to complete reservation.
-		 */
-		if (drm_atomic_crtc_needs_modeset(crtc_state)
-				&& dpu_enc->mode_set_complete) {
-			ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, crtc_state,
-				conn_state, topology, true);
-			dpu_enc->mode_set_complete = false;
-		}
+	/* hw resource allocation */
+	dpu_encoder_get_hw_resources(drm_enc, &enc_hw_res, conn_state);
+
+	dpu_priv_state = dpu_get_private_state(crtc_state->state);
+	if (IS_ERR(dpu_priv_state))
+		goto end;
+
+	topology = dpu_encoder_get_topology(dpu_enc, dpu_cstate);
+	if (!topology.needs_realloc)
+		goto end;
+
+	dpu_rm_release_encoder_res(&dpu_priv_state->rm, dpu_cstate);
+	ret = dpu_rm_reserve_encoder_res(&dpu_priv_state->rm,
+						     dpu_cstate, &enc_hw_res);
+	if (ret) {
+		DPU_ERROR_ENC(dpu_enc,
+				"failed to allocate hw resources\n");
+		goto end;
 	}
 
-	if (!ret)
-		drm_mode_set_crtcinfo(adj_mode, 0);
+	drm_mode_set_crtcinfo(adj_mode, 0);
 
 	DPU_EVT32(DRMID(drm_enc), adj_mode->flags, adj_mode->private_flags);
-
+end:
 	return ret;
 }
 
@@ -1031,11 +1046,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 	struct dpu_kms *dpu_kms;
 	struct list_head *connector_list;
 	struct drm_connector *conn = NULL, *conn_iter;
-	struct dpu_rm_hw_iter pp_iter, ctl_iter;
-	struct msm_display_topology topology;
-	struct dpu_hw_ctl *hw_ctl[MAX_CHANNELS_PER_ENC];
-
-	int i = 0, ret;
+	struct dpu_crtc_state *dpu_cstate;
+	int i = 0;
 
 	if (!drm_enc) {
 		DPU_ERROR("invalid encoder\n");
@@ -1063,52 +1075,16 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 		return;
 	}
 
-	topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode);
-
-	/* Reserve dynamic resources now. Indicating non-AtomicTest phase */
-	ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, drm_enc->crtc->state,
-			conn->state, topology, false);
-	if (ret) {
-		DPU_ERROR_ENC(dpu_enc,
-				"failed to reserve hw resources, %d\n", ret);
-		return;
-	}
-
-	dpu_rm_init_hw_iter(&pp_iter, drm_enc->base.id, DPU_HW_BLK_PINGPONG);
-	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
-		dpu_enc->hw_pp[i] = NULL;
-		if (!dpu_rm_get_hw(&dpu_kms->rm, &pp_iter))
-			break;
-		dpu_enc->hw_pp[i] = (struct dpu_hw_pingpong *) pp_iter.hw;
-	}
-
-	dpu_rm_init_hw_iter(&ctl_iter, drm_enc->base.id, DPU_HW_BLK_CTL);
-	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
-		hw_ctl[i] = NULL;
-		if (!dpu_rm_get_hw(&dpu_kms->rm, &ctl_iter))
-			break;
-		hw_ctl[i] = (struct dpu_hw_ctl *)ctl_iter.hw;
-	}
+	dpu_cstate = to_dpu_crtc_state(drm_enc->crtc->state);
 
 	for (i = 0; i < dpu_enc->num_phys_encs; i++) {
 		struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
 
 		if (phys) {
-			if (!dpu_enc->hw_pp[i]) {
-				DPU_ERROR_ENC(dpu_enc,
-				    "no pp block assigned at idx: %d\n", i);
-				return;
-			}
-			phys->hw_pp = dpu_enc->hw_pp[i];
-
-			if (!hw_ctl[i]) {
-				DPU_ERROR_ENC(dpu_enc,
-				    "no ctl block assigned at idx: %d\n", i);
-				return;
-			}
-			phys->hw_ctl = hw_ctl[i];
-
+			dpu_enc->hw_pp[i] = dpu_cstate->mixers[i].hw_pp;
+			phys->hw_pp = dpu_cstate->mixers[i].hw_pp;
 			phys->connector = conn->state->connector;
+			phys->hw_ctl = dpu_cstate->mixers[i].lm_ctl;
 			if (phys->ops.mode_set)
 				phys->ops.mode_set(phys, mode, adj_mode);
 		}
@@ -1252,7 +1228,9 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
 	struct msm_drm_private *priv;
 	struct dpu_kms *dpu_kms;
 	struct drm_display_mode *mode;
-	int i = 0;
+	struct dpu_private_state *dpu_priv_state;
+	struct dpu_crtc_state *cstate;
+	int rc, i = 0;
 
 	if (!drm_enc) {
 		DPU_ERROR("invalid encoder\n");
@@ -1266,6 +1244,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
 	}
 
 	mode = &drm_enc->crtc->state->adjusted_mode;
+	cstate = to_dpu_crtc_state(drm_enc->crtc->state);
 
 	dpu_enc = to_dpu_encoder_virt(drm_enc);
 	DPU_DEBUG_ENC(dpu_enc, "\n");
@@ -1273,6 +1252,9 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
 	priv = drm_enc->dev->dev_private;
 	dpu_kms = to_dpu_kms(priv->kms);
 
+	/* accessing after swap state. piv_obj.state is the current state */
+	dpu_priv_state = to_dpu_private_state(dpu_kms->priv_obj.state);
+
 	DPU_EVT32(DRMID(drm_enc));
 
 	/* wait for idle */
@@ -1302,9 +1284,11 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
 
 	dpu_enc->cur_master = NULL;
 
-	DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n");
+	rc = dpu_rm_release_encoder_res(&dpu_priv_state->rm, cstate);
+	if (rc)
+		DPU_ERROR("error in releasing encoder resources\n");
 
-	dpu_rm_release(&dpu_kms->rm, drm_enc);
+	DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n");
 }
 
 static enum dpu_intf dpu_encoder_get_intf(struct dpu_mdss_cfg *catalog,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 35ce88a..e21054f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -388,7 +388,7 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
 	dpu_cstate = to_dpu_crtc_state(phys_enc->parent->crtc->state);
 
 	if (phys_enc->split_role == ENC_ROLE_SOLO &&
-	    (dpu_cstate->num_mixers == 2))
+		(dpu_cstate->num_mixers == 2))
 		return BLEND_3D_H_ROW_INT;
 
 	return BLEND_3D_NONE;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index c74f4c4..cbc7f0d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -467,35 +467,25 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
 
 static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
 {
-	struct msm_drm_private *priv;
 	struct dpu_encoder_phys_vid *vid_enc;
-	struct dpu_rm_hw_iter iter;
 	struct dpu_hw_ctl *ctl;
-	u32 flush_mask = 0;
+	struct dpu_crtc_state *cstate;
+	u32 i, flush_mask = 0;
 
 	if (!phys_enc || !phys_enc->parent || !phys_enc->parent->dev ||
 			!phys_enc->parent->dev->dev_private) {
 		DPU_ERROR("invalid encoder/device\n");
 		return;
 	}
-	priv = phys_enc->parent->dev->dev_private;
-
 	vid_enc = to_dpu_encoder_phys_vid(phys_enc);
 	ctl = phys_enc->hw_ctl;
 
-	dpu_rm_init_hw_iter(&iter, phys_enc->parent->base.id, DPU_HW_BLK_INTF);
-	while (dpu_rm_get_hw(&phys_enc->dpu_kms->rm, &iter)) {
-		struct dpu_hw_intf *hw_intf = (struct dpu_hw_intf *)iter.hw;
+	cstate = to_dpu_crtc_state(phys_enc->parent->crtc->state);
+	for (i = 0; i < cstate->num_intfs; i++)	{
+		struct dpu_hw_intf *hw_intf = cstate->hw_intfs[i];
 
-		if (hw_intf->idx == phys_enc->intf_idx) {
+		if (hw_intf && (hw_intf->idx == phys_enc->intf_idx))
 			vid_enc->hw_intf = hw_intf;
-			break;
-		}
-	}
-
-	if (!vid_enc->hw_intf) {
-		DPU_ERROR("hw_intf not assigned\n");
-		return;
 	}
 
 	DPU_DEBUG_VIDENC(vid_enc, "\n");
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index b3eaf3f..8bd1224 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1005,6 +1005,7 @@ static long dpu_kms_round_pixclk(struct msm_kms *kms, unsigned long rate,
 static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
 {
 	struct drm_device *dev;
+	struct dpu_private_state *dpu_priv_state;
 	int i;
 
 	dev = dpu_kms->dev;
@@ -1039,9 +1040,12 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
 		}
 	}
 
-	if (dpu_kms->rm_init)
-		dpu_rm_destroy(&dpu_kms->rm);
-	dpu_kms->rm_init = false;
+	dpu_priv_state = to_dpu_private_state(dpu_kms->priv_obj.state);
+	if (dpu_priv_state) {
+		if (dpu_priv_state->rm_init)
+			dpu_rm_destroy(&dpu_priv_state->rm);
+		dpu_priv_state->rm_init = false;
+	}
 
 	if (dpu_kms->catalog)
 		dpu_hw_catalog_deinit(dpu_kms->catalog);
@@ -1391,6 +1395,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
 	struct dpu_kms *dpu_kms;
 	struct drm_device *dev;
 	struct msm_drm_private *priv;
+	struct dpu_private_state *dpu_priv_state;
 	int i, rc = -EINVAL;
 
 	if (!kms) {
@@ -1512,16 +1517,16 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
 		goto power_error;
 	}
 
-	rc = dpu_rm_init(&dpu_kms->rm, dpu_kms->catalog, dpu_kms->mmio,
-			dpu_kms->dev);
+	dpu_priv_state = to_dpu_private_state(dpu_kms->priv_obj.state);
+	rc = dpu_rm_init(&dpu_priv_state->rm, dpu_kms->catalog, dpu_kms->mmio);
 	if (rc) {
 		DPU_ERROR("rm init failed: %d\n", rc);
 		goto power_error;
 	}
 
-	dpu_kms->rm_init = true;
+	dpu_priv_state->rm_init = true;
 
-	dpu_kms->hw_mdp = dpu_rm_get_mdp(&dpu_kms->rm);
+	dpu_kms->hw_mdp = dpu_rm_get_mdp(&dpu_priv_state->rm);
 	if (IS_ERR_OR_NULL(dpu_kms->hw_mdp)) {
 		rc = PTR_ERR(dpu_kms->hw_mdp);
 		if (!dpu_kms->hw_mdp)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 924d8967..1e4b5b7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -32,10 +32,10 @@
 #include "dpu_hw_lm.h"
 #include "dpu_hw_interrupts.h"
 #include "dpu_hw_top.h"
-#include "dpu_rm.h"
 #include "dpu_power_handle.h"
 #include "dpu_irq.h"
 #include "dpu_core_perf.h"
+#include "dpu_rm.h"
 
 #define DRMID(x) ((x) ? (x)->base.id : -1)
 
@@ -184,9 +184,6 @@ struct dpu_kms {
 	struct drm_atomic_state *suspend_state;
 	bool suspend_block;
 
-	struct dpu_rm rm;
-	bool rm_init;
-
 	struct dpu_hw_vbif *hw_vbif[VBIF_MAX];
 	struct dpu_hw_mdp *hw_mdp;
 
@@ -202,6 +199,9 @@ struct dpu_kms {
 
 struct dpu_private_state {
 	struct drm_private_state base;
+
+	struct dpu_rm rm;
+	bool rm_init;
 };
 
 struct vsync_info {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index ef945d6..018d01a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -20,132 +20,59 @@
 #include "dpu_hw_pingpong.h"
 #include "dpu_hw_intf.h"
 #include "dpu_encoder.h"
-
-#define RESERVED_BY_OTHER(h, r) \
-	((h)->rsvp && ((h)->rsvp->enc_id != (r)->enc_id))
-
-#define RM_RQ_LOCK(r) ((r)->top_ctrl & BIT(DPU_RM_TOPCTL_RESERVE_LOCK))
-#define RM_RQ_CLEAR(r) ((r)->top_ctrl & BIT(DPU_RM_TOPCTL_RESERVE_CLEAR))
-#define RM_RQ_DS(r) ((r)->top_ctrl & BIT(DPU_RM_TOPCTL_DS))
-#define RM_IS_TOPOLOGY_MATCH(t, r) ((t).num_lm == (r).num_lm && \
-				(t).num_comp_enc == (r).num_enc && \
-				(t).num_intf == (r).num_intf)
-
-struct dpu_rm_topology_def {
-	enum dpu_rm_topology_name top_name;
-	int num_lm;
-	int num_comp_enc;
-	int num_intf;
-	int num_ctl;
-	int needs_split_display;
-};
-
-static const struct dpu_rm_topology_def g_top_table[] = {
-	{   DPU_RM_TOPOLOGY_NONE,                 0, 0, 0, 0, false },
-	{   DPU_RM_TOPOLOGY_SINGLEPIPE,           1, 0, 1, 1, false },
-	{   DPU_RM_TOPOLOGY_DUALPIPE,             2, 0, 2, 2, true  },
-	{   DPU_RM_TOPOLOGY_DUALPIPE_3DMERGE,     2, 0, 1, 1, false },
-};
-
-/**
- * struct dpu_rm_requirements - Reservation requirements parameter bundle
- * @top_ctrl:  topology control preference from kernel client
- * @top:       selected topology for the display
- * @hw_res:	   Hardware resources required as reported by the encoders
- */
-struct dpu_rm_requirements {
-	uint64_t top_ctrl;
-	const struct dpu_rm_topology_def *topology;
-	struct dpu_encoder_hw_resources hw_res;
-};
-
-/**
- * struct dpu_rm_rsvp - Use Case Reservation tagging structure
- *	Used to tag HW blocks as reserved by a CRTC->Encoder->Connector chain
- *	By using as a tag, rather than lists of pointers to HW blocks used
- *	we can avoid some list management since we don't know how many blocks
- *	of each type a given use case may require.
- * @list:	List head for list of all reservations
- * @seq:	Global RSVP sequence number for debugging, especially for
- *		differentiating differenct allocations for same encoder.
- * @enc_id:	Reservations are tracked by Encoder DRM object ID.
- *		CRTCs may be connected to multiple Encoders.
- *		An encoder or connector id identifies the display path.
- * @topology	DRM<->HW topology use case
- */
-struct dpu_rm_rsvp {
-	struct list_head list;
-	uint32_t seq;
-	uint32_t enc_id;
-	enum dpu_rm_topology_name topology;
-};
+#include "dpu_rm.h"
 
 /**
  * struct dpu_rm_hw_blk - hardware block tracking list member
- * @list:	List head for list of all hardware blocks tracking items
- * @rsvp:	Pointer to use case reservation if reserved by a client
- * @rsvp_nxt:	Temporary pointer used during reservation to the incoming
- *		request. Will be swapped into rsvp if proposal is accepted
  * @type:	Type of hardware block this structure tracks
+ * @drm_id:	DRM component ID associated with the HW block
  * @id:		Hardware ID number, within it's own space, ie. LM_X
- * @catalog:	Pointer to the hardware catalog entry for this block
  * @hw:		Pointer to the hardware register access object for this block
  */
 struct dpu_rm_hw_blk {
-	struct list_head list;
-	struct dpu_rm_rsvp *rsvp;
-	struct dpu_rm_rsvp *rsvp_nxt;
 	enum dpu_hw_blk_type type;
 	uint32_t id;
+	uint32_t rm_id;
 	struct dpu_hw_blk *hw;
 };
 
-/**
- * dpu_rm_dbg_rsvp_stage - enum of steps in making reservation for event logging
- */
-enum dpu_rm_dbg_rsvp_stage {
-	DPU_RM_STAGE_BEGIN,
-	DPU_RM_STAGE_AFTER_CLEAR,
-	DPU_RM_STAGE_AFTER_RSVPNEXT,
-	DPU_RM_STAGE_FINAL
+static char *blk_name[DPU_HW_BLK_MAX] = {
+	"HW_TOP",
+	"HW_SSPP",
+	"HW_LM",
+	"HW_CTL",
+	"HW_CDM",
+	"HW_PINGPONG",
+	"HW_INTF",
+	"HW_WB"
 };
 
-static void _dpu_rm_print_rsvps(
-		struct dpu_rm *rm,
-		enum dpu_rm_dbg_rsvp_stage stage)
+void dpu_rm_print_state(struct dpu_rm *rm)
 {
-	struct dpu_rm_rsvp *rsvp;
-	struct dpu_rm_hw_blk *blk;
-	enum dpu_hw_blk_type type;
+	int i;
+
+	mutex_lock(&rm->rm_lock);
 
-	DPU_DEBUG("%d\n", stage);
+	DPU_ERROR("DPU RM state:\n");
+	for (i = 0; i < DPU_HW_BLK_MAX; i++) {
+		int blk_len = rm->hw_blks_len[i];
+		int *drm_map = rm->hw_drm_map[i];
+		int j;
 
-	list_for_each_entry(rsvp, &rm->rsvps, list) {
-		DPU_DEBUG("%d rsvp[s%ue%u] topology %d\n", stage, rsvp->seq,
-				rsvp->enc_id, rsvp->topology);
-		DPU_EVT32(stage, rsvp->seq, rsvp->enc_id, rsvp->topology);
-	}
+		if (!blk_len)
+			continue;
 
-	for (type = 0; type < DPU_HW_BLK_MAX; type++) {
-		list_for_each_entry(blk, &rm->hw_blks[type], list) {
-			if (!blk->rsvp && !blk->rsvp_nxt)
+		DPU_ERROR("%s\ttotal: %d\n", blk_name[i], blk_len);
+
+		for (j = 0; j < blk_len; j++) {
+			if (!drm_map[j])
 				continue;
 
-			DPU_DEBUG("%d rsvp[s%ue%u->s%ue%u] %d %d\n", stage,
-				(blk->rsvp) ? blk->rsvp->seq : 0,
-				(blk->rsvp) ? blk->rsvp->enc_id : 0,
-				(blk->rsvp_nxt) ? blk->rsvp_nxt->seq : 0,
-				(blk->rsvp_nxt) ? blk->rsvp_nxt->enc_id : 0,
-				blk->type, blk->id);
-
-			DPU_EVT32(stage,
-				(blk->rsvp) ? blk->rsvp->seq : 0,
-				(blk->rsvp) ? blk->rsvp->enc_id : 0,
-				(blk->rsvp_nxt) ? blk->rsvp_nxt->seq : 0,
-				(blk->rsvp_nxt) ? blk->rsvp_nxt->enc_id : 0,
-				blk->type, blk->id);
+			DPU_ERROR("\tidx:%d drm_id: %d\n", j, drm_map[j]);
 		}
 	}
+
+	mutex_unlock(&rm->rm_lock);
 }
 
 struct dpu_hw_mdp *dpu_rm_get_mdp(struct dpu_rm *rm)
@@ -155,17 +82,19 @@ struct dpu_hw_mdp *dpu_rm_get_mdp(struct dpu_rm *rm)
 
 void dpu_rm_init_hw_iter(
 		struct dpu_rm_hw_iter *iter,
-		uint32_t enc_id,
+		uint32_t drm_id,
 		enum dpu_hw_blk_type type)
 {
 	memset(iter, 0, sizeof(*iter));
-	iter->enc_id = enc_id;
+	iter->drm_id = drm_id;
 	iter->type = type;
 }
 
 static bool _dpu_rm_get_hw_locked(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
 {
-	struct list_head *blk_list;
+	struct dpu_rm_hw_blk **blk_list;
+	uint32_t blk_len, index;
+	uint32_t *drm_map;
 
 	if (!rm || !i || i->type >= DPU_HW_BLK_MAX) {
 		DPU_ERROR("invalid rm\n");
@@ -173,33 +102,30 @@ static bool _dpu_rm_get_hw_locked(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
 	}
 
 	i->hw = NULL;
-	blk_list = &rm->hw_blks[i->type];
-
-	if (i->blk && (&i->blk->list == blk_list)) {
-		DPU_DEBUG("attempt resume iteration past last\n");
-		return false;
-	}
-
-	i->blk = list_prepare_entry(i->blk, blk_list, list);
+	blk_list = rm->hw_blks[i->type];
+	blk_len = rm->hw_blks_len[i->type];
+	drm_map = rm->hw_drm_map[i->type];
 
-	list_for_each_entry_continue(i->blk, blk_list, list) {
-		struct dpu_rm_rsvp *rsvp = i->blk->rsvp;
+	for (index = i->index; index < blk_len; index++) {
+		struct dpu_rm_hw_blk *blk = blk_list[index];
 
-		if (i->blk->type != i->type) {
-			DPU_ERROR("found incorrect block type %d on %d list\n",
-					i->blk->type, i->type);
+		if (!blk) {
+			DPU_ERROR("invalid block. index: %d type: %d\n",
+					index, i->type);
 			return false;
 		}
 
-		if ((i->enc_id == 0) || (rsvp && rsvp->enc_id == i->enc_id)) {
-			i->hw = i->blk->hw;
+		if (drm_map[index] == i->drm_id) {
+			i->hw = blk->hw;
+			i->index = index + 1;
+			i->blk = blk;
 			DPU_DEBUG("found type %d id %d for enc %d\n",
-					i->type, i->blk->id, i->enc_id);
+					i->type, blk->id, i->drm_id);
 			return true;
 		}
 	}
 
-	DPU_DEBUG("no match, type %d for enc %d\n", i->type, i->enc_id);
+	DPU_DEBUG("no match, type %d for enc %d\n", i->type, i->drm_id);
 
 	return false;
 }
@@ -224,9 +150,6 @@ static void _dpu_rm_hw_destroy(enum dpu_hw_blk_type type, void *hw)
 	case DPU_HW_BLK_CTL:
 		dpu_hw_ctl_destroy(hw);
 		break;
-	case DPU_HW_BLK_CDM:
-		dpu_hw_cdm_destroy(hw);
-		break;
 	case DPU_HW_BLK_PINGPONG:
 		dpu_hw_pingpong_destroy(hw);
 		break;
@@ -246,26 +169,25 @@ static void _dpu_rm_hw_destroy(enum dpu_hw_blk_type type, void *hw)
 
 int dpu_rm_destroy(struct dpu_rm *rm)
 {
-
-	struct dpu_rm_rsvp *rsvp_cur, *rsvp_nxt;
-	struct dpu_rm_hw_blk *hw_cur, *hw_nxt;
 	enum dpu_hw_blk_type type;
+	uint32_t i;
 
 	if (!rm) {
 		DPU_ERROR("invalid rm\n");
 		return -EINVAL;
 	}
 
-	list_for_each_entry_safe(rsvp_cur, rsvp_nxt, &rm->rsvps, list) {
-		list_del(&rsvp_cur->list);
-		kfree(rsvp_cur);
-	}
+	for (type = 0; type < DPU_HW_BLK_MAX; type++) {
+		uint32_t hw_blk_len = rm->hw_blks_len[type];
 
+		for (i = 0; i < hw_blk_len; i++) {
+			struct dpu_rm_hw_blk *hw_cur = rm->hw_blks[type][i];
 
-	for (type = 0; type < DPU_HW_BLK_MAX; type++) {
-		list_for_each_entry_safe(hw_cur, hw_nxt, &rm->hw_blks[type],
-				list) {
-			list_del(&hw_cur->list);
+			if (!hw_cur) {
+				DPU_ERROR("Invalid hw block. type:%d i: %d\n",
+					type, i);
+				return -EINVAL;
+			}
 			_dpu_rm_hw_destroy(hw_cur->type, hw_cur->hw);
 			kfree(hw_cur);
 		}
@@ -300,9 +222,6 @@ static int _dpu_rm_hw_blk_create(
 	case DPU_HW_BLK_CTL:
 		hw = dpu_hw_ctl_init(id, mmio, cat);
 		break;
-	case DPU_HW_BLK_CDM:
-		hw = dpu_hw_cdm_init(id, mmio, cat, hw_mdp);
-		break;
 	case DPU_HW_BLK_PINGPONG:
 		hw = dpu_hw_pingpong_init(id, mmio, cat);
 		break;
@@ -334,35 +253,24 @@ static int _dpu_rm_hw_blk_create(
 	blk->type = type;
 	blk->id = id;
 	blk->hw = hw;
-	list_add_tail(&blk->list, &rm->hw_blks[type]);
+	blk->rm_id = rm->hw_blks_len[type];
+
+	rm->hw_blks[type][rm->hw_blks_len[type]++] = blk;
 
 	return 0;
 }
 
 int dpu_rm_init(struct dpu_rm *rm,
 		struct dpu_mdss_cfg *cat,
-		void __iomem *mmio,
-		struct drm_device *dev)
+		void __iomem *mmio)
 {
 	int rc, i;
-	enum dpu_hw_blk_type type;
-
-	if (!rm || !cat || !mmio || !dev) {
-		DPU_ERROR("invalid kms\n");
-		return -EINVAL;
-	}
 
 	/* Clear, setup lists */
 	memset(rm, 0, sizeof(*rm));
 
 	mutex_init(&rm->rm_lock);
 
-	INIT_LIST_HEAD(&rm->rsvps);
-	for (type = 0; type < DPU_HW_BLK_MAX; type++)
-		INIT_LIST_HEAD(&rm->hw_blks[type]);
-
-	rm->dev = dev;
-
 	/* Some of the sub-blocks require an mdptop to be created */
 	rm->hw_mdp = dpu_hw_mdptop_init(MDP_TOP, mmio, cat);
 	if (IS_ERR_OR_NULL(rm->hw_mdp)) {
@@ -387,18 +295,6 @@ int dpu_rm_init(struct dpu_rm *rm,
 			DPU_ERROR("failed: lm hw not available\n");
 			goto fail;
 		}
-
-		if (!rm->lm_max_width) {
-			rm->lm_max_width = lm->sblk->maxwidth;
-		} else if (rm->lm_max_width != lm->sblk->maxwidth) {
-			/*
-			 * Don't expect to have hw where lm max widths differ.
-			 * If found, take the min.
-			 */
-			DPU_ERROR("unsupported: lm maxwidth differs\n");
-			if (rm->lm_max_width > lm->sblk->maxwidth)
-				rm->lm_max_width = lm->sblk->maxwidth;
-		}
 	}
 
 	for (i = 0; i < cat->pingpong_count; i++) {
@@ -433,15 +329,6 @@ int dpu_rm_init(struct dpu_rm *rm,
 		}
 	}
 
-	for (i = 0; i < cat->cdm_count; i++) {
-		rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_CDM,
-				cat->cdm[i].id, &cat->cdm[i]);
-		if (rc) {
-			DPU_ERROR("failed: cdm hw not available\n");
-			goto fail;
-		}
-	}
-
 	return 0;
 
 fail:
@@ -455,8 +342,7 @@ int dpu_rm_init(struct dpu_rm *rm,
  *	proposed use case requirements, incl. hardwired dependent blocks like
  *	pingpong
  * @rm: dpu resource manager handle
- * @rsvp: reservation currently being created
- * @reqs: proposed use case requirements
+ * @state: dpu crtc state handle
  * @lm: proposed layer mixer, function checks if lm, and all other hardwired
  *      blocks connected to the lm (pp) is available and appropriate
  * @pp: output parameter, pingpong block attached to the layer mixer.
@@ -467,8 +353,7 @@ int dpu_rm_init(struct dpu_rm *rm,
  */
 static bool _dpu_rm_check_lm_and_get_connected_blks(
 		struct dpu_rm *rm,
-		struct dpu_rm_rsvp *rsvp,
-		struct dpu_rm_requirements *reqs,
+		struct dpu_crtc_state *state,
 		struct dpu_rm_hw_blk *lm,
 		struct dpu_rm_hw_blk **pp,
 		struct dpu_rm_hw_blk *primary_lm)
@@ -493,12 +378,6 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(
 		}
 	}
 
-	/* Already reserved? */
-	if (RESERVED_BY_OTHER(lm, rsvp)) {
-		DPU_DEBUG("lm %d already reserved\n", lm_cfg->id);
-		return false;
-	}
-
 	dpu_rm_init_hw_iter(&iter, 0, DPU_HW_BLK_PINGPONG);
 	while (_dpu_rm_get_hw_locked(rm, &iter)) {
 		if (iter.blk->id == lm_cfg->pingpong) {
@@ -512,35 +391,24 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(
 		return false;
 	}
 
-	if (RESERVED_BY_OTHER(*pp, rsvp)) {
-		DPU_DEBUG("lm %d pp %d already reserved\n", lm->id,
-				(*pp)->id);
-		return false;
-	}
-
 	return true;
 }
 
 static int _dpu_rm_reserve_lms(
-		struct dpu_rm *rm,
-		struct dpu_rm_rsvp *rsvp,
-		struct dpu_rm_requirements *reqs)
-
+	struct dpu_rm *rm, struct dpu_crtc_state *state,
+	struct dpu_crtc_topology *topology)
 {
 	struct dpu_rm_hw_blk *lm[MAX_BLOCKS];
 	struct dpu_rm_hw_blk *pp[MAX_BLOCKS];
 	struct dpu_rm_hw_iter iter_i, iter_j;
 	int lm_count = 0;
-	int i, rc = 0;
-
-	if (!reqs->topology->num_lm) {
-		DPU_ERROR("invalid number of lm: %d\n", reqs->topology->num_lm);
-		return -EINVAL;
-	}
+	int i, drm_id = get_crtc_id(state);
+	int *lm_drm_map = rm->hw_drm_map[DPU_HW_BLK_LM];
+	int *pp_drm_map = rm->hw_drm_map[DPU_HW_BLK_PINGPONG];
 
 	/* Find a primary mixer */
 	dpu_rm_init_hw_iter(&iter_i, 0, DPU_HW_BLK_LM);
-	while (lm_count != reqs->topology->num_lm &&
+	while (lm_count != topology->num_lms &&
 			_dpu_rm_get_hw_locked(rm, &iter_i)) {
 		memset(&lm, 0, sizeof(lm));
 		memset(&pp, 0, sizeof(pp));
@@ -549,8 +417,7 @@ static int _dpu_rm_reserve_lms(
 		lm[lm_count] = iter_i.blk;
 
 		if (!_dpu_rm_check_lm_and_get_connected_blks(
-				rm, rsvp, reqs, lm[lm_count],
-				&pp[lm_count], NULL))
+				rm, state, lm[lm_count], &pp[lm_count], NULL))
 			continue;
 
 		++lm_count;
@@ -558,14 +425,14 @@ static int _dpu_rm_reserve_lms(
 		/* Valid primary mixer found, find matching peers */
 		dpu_rm_init_hw_iter(&iter_j, 0, DPU_HW_BLK_LM);
 
-		while (lm_count != reqs->topology->num_lm &&
+		while (lm_count != topology->num_lms &&
 				_dpu_rm_get_hw_locked(rm, &iter_j)) {
 			if (iter_i.blk == iter_j.blk)
 				continue;
 
 			if (!_dpu_rm_check_lm_and_get_connected_blks(
-					rm, rsvp, reqs, iter_j.blk,
-					&pp[lm_count], iter_i.blk))
+				rm, state, iter_j.blk,
+				&pp[lm_count], iter_i.blk))
 				continue;
 
 			lm[lm_count] = iter_j.blk;
@@ -573,7 +440,7 @@ static int _dpu_rm_reserve_lms(
 		}
 	}
 
-	if (lm_count != reqs->topology->num_lm) {
+	if (lm_count != topology->num_lms) {
 		DPU_DEBUG("unable to find appropriate mixers\n");
 		return -ENAVAIL;
 	}
@@ -582,492 +449,265 @@ static int _dpu_rm_reserve_lms(
 		if (!lm[i])
 			break;
 
-		lm[i]->rsvp_nxt = rsvp;
-		pp[i]->rsvp_nxt = rsvp;
+		lm_drm_map[lm[i]->rm_id] = drm_id;
+		pp_drm_map[pp[i]->rm_id] = drm_id;
 
-		DPU_EVT32(lm[i]->type, rsvp->enc_id, lm[i]->id, pp[i]->id);
+		state->mixers[i].hw_lm = (struct dpu_hw_mixer *)lm[i]->hw;
+		state->mixers[i].hw_pp = (struct dpu_hw_pingpong *)pp[i]->hw;
 	}
 
-	return rc;
+	state->num_mixers = topology->num_lms;
+
+	return 0;
 }
 
 static int _dpu_rm_reserve_ctls(
-		struct dpu_rm *rm,
-		struct dpu_rm_rsvp *rsvp,
-		const struct dpu_rm_topology_def *top)
+		struct dpu_rm *rm, struct dpu_crtc_state *state,
+		struct dpu_crtc_topology *topology)
 {
 	struct dpu_rm_hw_blk *ctls[MAX_BLOCKS];
 	struct dpu_rm_hw_iter iter;
-	int i = 0;
+	bool needs_split_display;
+	int i = 0, drm_id = get_crtc_id(state);
+	int *ctl_drm_map = rm->hw_drm_map[DPU_HW_BLK_CTL];
 
 	memset(&ctls, 0, sizeof(ctls));
 
+	needs_split_display = (topology->num_ctls == 2);
+
 	dpu_rm_init_hw_iter(&iter, 0, DPU_HW_BLK_CTL);
 	while (_dpu_rm_get_hw_locked(rm, &iter)) {
 		const struct dpu_hw_ctl *ctl = to_dpu_hw_ctl(iter.blk->hw);
 		unsigned long features = ctl->caps->features;
 		bool has_split_display;
 
-		if (RESERVED_BY_OTHER(iter.blk, rsvp))
-			continue;
-
 		has_split_display = BIT(DPU_CTL_SPLIT_DISPLAY) & features;
 
 		DPU_DEBUG("ctl %d caps 0x%lX\n", iter.blk->id, features);
 
-		if (top->needs_split_display != has_split_display)
+		if (needs_split_display != has_split_display)
 			continue;
 
 		ctls[i] = iter.blk;
 		DPU_DEBUG("ctl %d match\n", iter.blk->id);
 
-		if (++i == top->num_ctl)
+		if (++i == topology->num_ctls)
 			break;
 	}
 
-	if (i != top->num_ctl)
-		return -ENAVAIL;
-
-	for (i = 0; i < ARRAY_SIZE(ctls) && i < top->num_ctl; i++) {
-		ctls[i]->rsvp_nxt = rsvp;
-		DPU_EVT32(ctls[i]->type, rsvp->enc_id, ctls[i]->id);
-	}
-
-	return 0;
-}
-
-static int _dpu_rm_reserve_cdm(
-		struct dpu_rm *rm,
-		struct dpu_rm_rsvp *rsvp,
-		uint32_t id,
-		enum dpu_hw_blk_type type)
-{
-	struct dpu_rm_hw_iter iter;
-
-	dpu_rm_init_hw_iter(&iter, 0, DPU_HW_BLK_CDM);
-	while (_dpu_rm_get_hw_locked(rm, &iter)) {
-		const struct dpu_hw_cdm *cdm = to_dpu_hw_cdm(iter.blk->hw);
-		const struct dpu_cdm_cfg *caps = cdm->caps;
-		bool match = false;
-
-		if (RESERVED_BY_OTHER(iter.blk, rsvp))
-			continue;
-
-		if (type == DPU_HW_BLK_INTF && id != INTF_MAX)
-			match = test_bit(id, &caps->intf_connect);
-
-		DPU_DEBUG("type %d id %d, cdm intfs %lu match %d\n",
-				type, id, caps->intf_connect, match);
+	if (i != topology->num_ctls)
+		return -EINVAL;
 
-		if (!match)
-			continue;
+	for (i = 0; i < ARRAY_SIZE(ctls) && i < topology->num_ctls; i++) {
+		ctl_drm_map[ctls[i]->rm_id] = drm_id;
+		state->hw_ctls[i] = (struct dpu_hw_ctl *)ctls[i]->hw;
 
-		iter.blk->rsvp_nxt = rsvp;
-		DPU_EVT32(iter.blk->type, rsvp->enc_id, iter.blk->id);
-		break;
+		DPU_EVT32(ctls[i]->type, get_crtc_id(state), ctls[i]->id);
 	}
 
-	if (!iter.hw) {
-		DPU_ERROR("couldn't reserve cdm for type %d id %d\n", type, id);
-		return -ENAVAIL;
-	}
+	state->num_ctls = topology->num_ctls;
 
 	return 0;
 }
 
-static int _dpu_rm_reserve_intf(
+static struct dpu_rm_hw_blk *_dpu_rm_get_hw_id(
 		struct dpu_rm *rm,
-		struct dpu_rm_rsvp *rsvp,
 		uint32_t id,
-		enum dpu_hw_blk_type type,
-		bool needs_cdm)
+		enum dpu_hw_blk_type type)
 {
 	struct dpu_rm_hw_iter iter;
-	int ret = 0;
 
 	/* Find the block entry in the rm, and note the reservation */
 	dpu_rm_init_hw_iter(&iter, 0, type);
 	while (_dpu_rm_get_hw_locked(rm, &iter)) {
 		if (iter.blk->id != id)
 			continue;
-
-		if (RESERVED_BY_OTHER(iter.blk, rsvp)) {
-			DPU_ERROR("type %d id %d already reserved\n", type, id);
-			return -ENAVAIL;
-		}
-
-		iter.blk->rsvp_nxt = rsvp;
-		DPU_EVT32(iter.blk->type, rsvp->enc_id, iter.blk->id);
 		break;
 	}
 
-	/* Shouldn't happen since intfs are fixed at probe */
 	if (!iter.hw) {
 		DPU_ERROR("couldn't find type %d id %d\n", type, id);
-		return -EINVAL;
+		return NULL;
 	}
 
-	if (needs_cdm)
-		ret = _dpu_rm_reserve_cdm(rm, rsvp, id, type);
-
-	return ret;
+	return iter.blk;
 }
 
 static int _dpu_rm_reserve_intf_related_hw(
 		struct dpu_rm *rm,
-		struct dpu_rm_rsvp *rsvp,
+		struct dpu_crtc_state *state,
 		struct dpu_encoder_hw_resources *hw_res)
 {
-	int i, ret = 0;
-	u32 id;
+	struct dpu_rm_hw_blk *intf[INTF_MAX] = {};
+	u32 i, id, intf_count = 0;
+	u32 drm_id = get_crtc_id(state);
+	int *intf_drm_map = rm->hw_drm_map[DPU_HW_BLK_INTF];
 
 	for (i = 0; i < ARRAY_SIZE(hw_res->intfs); i++) {
 		if (hw_res->intfs[i] == INTF_MODE_NONE)
 			continue;
-		id = i + INTF_0;
-		ret = _dpu_rm_reserve_intf(rm, rsvp, id,
-				DPU_HW_BLK_INTF, hw_res->needs_cdm);
-		if (ret)
-			return ret;
-	}
 
-	return ret;
-}
-
-static int _dpu_rm_make_next_rsvp(
-		struct dpu_rm *rm,
-		struct drm_encoder *enc,
-		struct drm_crtc_state *crtc_state,
-		struct drm_connector_state *conn_state,
-		struct dpu_rm_rsvp *rsvp,
-		struct dpu_rm_requirements *reqs)
-{
-	int ret;
-	struct dpu_rm_topology_def topology;
-
-	/* Create reservation info, tag reserved blocks with it as we go */
-	rsvp->seq = ++rm->rsvp_next_seq;
-	rsvp->enc_id = enc->base.id;
-	rsvp->topology = reqs->topology->top_name;
-	list_add_tail(&rsvp->list, &rm->rsvps);
-
-	ret = _dpu_rm_reserve_lms(rm, rsvp, reqs);
-	if (ret) {
-		DPU_ERROR("unable to find appropriate mixers\n");
-		return ret;
-	}
+		id = i + INTF_0;
+		intf[i] = _dpu_rm_get_hw_id(rm, id, DPU_HW_BLK_INTF);
+		if (!intf[i])
+			return -EINVAL;
 
-	/*
-	 * Do assignment preferring to give away low-resource CTLs first:
-	 * - Check mixers without Split Display
-	 * - Only then allow to grab from CTLs with split display capability
-	 */
-	_dpu_rm_reserve_ctls(rm, rsvp, reqs->topology);
-	if (ret && !reqs->topology->needs_split_display) {
-		memcpy(&topology, reqs->topology, sizeof(topology));
-		topology.needs_split_display = true;
-		_dpu_rm_reserve_ctls(rm, rsvp, &topology);
-	}
-	if (ret) {
-		DPU_ERROR("unable to find appropriate CTL\n");
-		return ret;
+		/* Reserve other INTF related blocks if needed */
 	}
 
-	/* Assign INTFs and blks whose usage is tied to them: CTL & CDM */
-	ret = _dpu_rm_reserve_intf_related_hw(rm, rsvp, &reqs->hw_res);
-	if (ret)
-		return ret;
-
-	return ret;
-}
-
-static int _dpu_rm_populate_requirements(
-		struct dpu_rm *rm,
-		struct drm_encoder *enc,
-		struct drm_crtc_state *crtc_state,
-		struct drm_connector_state *conn_state,
-		struct dpu_rm_requirements *reqs,
-		struct msm_display_topology req_topology)
-{
-	const struct drm_display_mode *mode = &crtc_state->mode;
-	int i;
-
-	memset(reqs, 0, sizeof(*reqs));
-
-	dpu_encoder_get_hw_resources(enc, &reqs->hw_res, conn_state);
-
-	for (i = 0; i < DPU_RM_TOPOLOGY_MAX; i++) {
-		if (RM_IS_TOPOLOGY_MATCH(g_top_table[i],
-					req_topology)) {
-			reqs->topology = &g_top_table[i];
-			break;
-		}
-	}
+	for (i = 0; i < ARRAY_SIZE(hw_res->intfs); i++) {
+		if (!intf[i])
+			continue;
 
-	if (!reqs->topology) {
-		DPU_ERROR("invalid topology for the display\n");
-		return -EINVAL;
+		intf_drm_map[intf[i]->rm_id] = drm_id;
+		state->hw_intfs[intf_count++] =
+			(struct dpu_hw_intf *)intf[i]->hw;
 	}
 
-	/**
-	 * Set the requirement based on caps if not set from user space
-	 * This will ensure to select LM tied with DS blocks
-	 * Currently, DS blocks are tied with LM 0 and LM 1 (primary display)
-	 */
-	if (!RM_RQ_DS(reqs) && rm->hw_mdp->caps->has_dest_scaler &&
-		conn_state->connector->connector_type == DRM_MODE_CONNECTOR_DSI)
-		reqs->top_ctrl |= BIT(DPU_RM_TOPCTL_DS);
-
-	DPU_DEBUG("top_ctrl: 0x%llX\n", reqs->top_ctrl);
-	DPU_DEBUG("num_lm: %d num_ctl: %d topology: %d split_display: %d\n",
-			reqs->topology->num_lm, reqs->topology->num_ctl,
-			reqs->topology->top_name,
-			reqs->topology->needs_split_display);
-	DPU_EVT32(mode->hdisplay, rm->lm_max_width, reqs->topology->num_lm,
-			reqs->top_ctrl, reqs->topology->top_name,
-			reqs->topology->num_ctl);
+	state->num_intfs = intf_count;
 
 	return 0;
 }
 
-static struct dpu_rm_rsvp *_dpu_rm_get_rsvp(
+static int _dpu_rm_release_hw_blk(
 		struct dpu_rm *rm,
-		struct drm_encoder *enc)
+		struct dpu_crtc_state *state,
+		enum dpu_hw_blk_type type)
 {
-	struct dpu_rm_rsvp *i;
-
-	if (!rm || !enc) {
-		DPU_ERROR("invalid params\n");
-		return NULL;
-	}
-
-	if (list_empty(&rm->rsvps))
-		return NULL;
-
-	list_for_each_entry(i, &rm->rsvps, list)
-		if (i->enc_id == enc->base.id)
-			return i;
-
-	return NULL;
-}
+	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];
 
-static struct drm_connector *_dpu_rm_get_connector(
-		struct drm_encoder *enc)
-{
-	struct drm_connector *conn = NULL;
-	struct list_head *connector_list =
-			&enc->dev->mode_config.connector_list;
+	dpu_rm_init_hw_iter(&iter, drm_id, type);
+	while (_dpu_rm_get_hw_locked(rm, &iter)) {
+		drm_map[iter.blk->rm_id] = 0;
+		num_released++;
 
-	list_for_each_entry(conn, connector_list, head)
-		if (conn->encoder == enc)
-			return conn;
+		DPU_EVT32(iter.blk->type, drm_id, iter.blk->id);
+	}
 
-	return NULL;
+	return num_released;
 }
 
-/**
- * _dpu_rm_release_rsvp - release resources and release a reservation
- * @rm:	KMS handle
- * @rsvp:	RSVP pointer to release and release resources for
- */
-static void _dpu_rm_release_rsvp(
-		struct dpu_rm *rm,
-		struct dpu_rm_rsvp *rsvp,
-		struct drm_connector *conn)
+static int _dpu_rm_release_lms(struct dpu_rm *rm, struct dpu_crtc_state *state)
 {
-	struct dpu_rm_rsvp *rsvp_c, *rsvp_n;
-	struct dpu_rm_hw_blk *blk;
-	enum dpu_hw_blk_type type;
+	int num_lm, num_pp;
 
-	if (!rsvp)
-		return;
+	/* Release LM blocks */
+	num_lm = _dpu_rm_release_hw_blk(rm, state, DPU_HW_BLK_LM);
 
-	DPU_DEBUG("rel rsvp %d enc %d\n", rsvp->seq, rsvp->enc_id);
-
-	list_for_each_entry_safe(rsvp_c, rsvp_n, &rm->rsvps, list) {
-		if (rsvp == rsvp_c) {
-			list_del(&rsvp_c->list);
-			break;
-		}
-	}
-
-	for (type = 0; type < DPU_HW_BLK_MAX; type++) {
-		list_for_each_entry(blk, &rm->hw_blks[type], list) {
-			if (blk->rsvp == rsvp) {
-				blk->rsvp = NULL;
-				DPU_DEBUG("rel rsvp %d enc %d %d %d\n",
-						rsvp->seq, rsvp->enc_id,
-						blk->type, blk->id);
-			}
-			if (blk->rsvp_nxt == rsvp) {
-				blk->rsvp_nxt = NULL;
-				DPU_DEBUG("rel rsvp_nxt %d enc %d %d %d\n",
-						rsvp->seq, rsvp->enc_id,
-						blk->type, blk->id);
-			}
-		}
+	/* Rlease ping pong blocks */
+	num_pp = _dpu_rm_release_hw_blk(rm, state, DPU_HW_BLK_PINGPONG);
+	if (num_pp != num_lm) {
+		DPU_ERROR("lm chain count mismatch lm: %d pp:%d\n",
+				num_lm, num_pp);
+		return 0;
 	}
 
-	kfree(rsvp);
+	return num_lm;
 }
 
-void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc)
+int dpu_rm_reserve_crtc_res(struct dpu_rm *rm, struct dpu_crtc_state *state,
+	struct dpu_crtc_topology *topology)
 {
-	struct dpu_rm_rsvp *rsvp;
-	struct drm_connector *conn;
-
-	if (!rm || !enc) {
-		DPU_ERROR("invalid params\n");
-		return;
-	}
+	int rc = 0;
 
 	mutex_lock(&rm->rm_lock);
 
-	rsvp = _dpu_rm_get_rsvp(rm, enc);
-	if (!rsvp) {
-		DPU_ERROR("failed to find rsvp for enc %d\n", enc->base.id);
-		goto end;
+	rc = _dpu_rm_reserve_lms(rm, state, topology);
+	if (rc)  {
+		DPU_ERROR("unable to allocate lm for crtc: %d\n",
+				get_crtc_id(state));
+		goto reserve_done;
 	}
 
-	conn = _dpu_rm_get_connector(enc);
-	if (!conn) {
-		DPU_ERROR("failed to get connector for enc %d\n", enc->base.id);
-		goto end;
+	rc = _dpu_rm_reserve_ctls(rm, state, topology);
+	if (rc)  {
+		DPU_ERROR("unable to allocate ctl for crtc: %d\n",
+				get_crtc_id(state));
+		goto reserve_done;
 	}
 
-	_dpu_rm_release_rsvp(rm, rsvp, conn);
-end:
+reserve_done:
 	mutex_unlock(&rm->rm_lock);
+
+	return 0;
 }
 
-static int _dpu_rm_commit_rsvp(
-		struct dpu_rm *rm,
-		struct dpu_rm_rsvp *rsvp,
-		struct drm_connector_state *conn_state)
+
+int dpu_rm_release_crtc_res(struct dpu_rm *rm, struct dpu_crtc_state *state)
 {
-	struct dpu_rm_hw_blk *blk;
-	enum dpu_hw_blk_type type;
-	int ret = 0;
+	int rc = 0, num_released;
 
-	/* Swap next rsvp to be the active */
-	for (type = 0; type < DPU_HW_BLK_MAX; type++) {
-		list_for_each_entry(blk, &rm->hw_blks[type], list) {
-			if (blk->rsvp_nxt) {
-				blk->rsvp = blk->rsvp_nxt;
-				blk->rsvp_nxt = NULL;
-			}
-		}
+	mutex_lock(&rm->rm_lock);
+
+	num_released = _dpu_rm_release_lms(rm, state);
+	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);
+		rc = -EINVAL;
+		goto release_done;
 	}
 
-	if (!ret) {
-		DPU_DEBUG("rsrv enc %d topology %d\n", rsvp->enc_id,
-				rsvp->topology);
-		DPU_EVT32(rsvp->enc_id, rsvp->topology);
+	num_released = _dpu_rm_release_hw_blk(rm, state, 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);
+		rc = -EINVAL;
+		goto release_done;
 	}
+ release_done:
+	mutex_unlock(&rm->rm_lock);
 
-	return ret;
+	state->num_mixers = 0;
+	state->num_ctls = 0;
+	memset(&state->mixers, 0, sizeof(state->mixers));
+	memset(&state->hw_ctls, 0, sizeof(state->hw_ctls));
+
+	return rc;
 }
 
-int dpu_rm_reserve(
-		struct dpu_rm *rm,
-		struct drm_encoder *enc,
-		struct drm_crtc_state *crtc_state,
-		struct drm_connector_state *conn_state,
-		struct msm_display_topology topology,
-		bool test_only)
+int dpu_rm_reserve_encoder_res(
+	struct dpu_rm *rm, struct dpu_crtc_state *state,
+	struct dpu_encoder_hw_resources *hw_res)
 {
-	struct dpu_rm_rsvp *rsvp_cur, *rsvp_nxt;
-	struct dpu_rm_requirements reqs;
-	int ret;
-
-	if (!rm || !enc || !crtc_state || !conn_state) {
-		DPU_ERROR("invalid arguments\n");
-		return -EINVAL;
-	}
-
-	/* Check if this is just a page-flip */
-	if (!drm_atomic_crtc_needs_modeset(crtc_state))
-		return 0;
-
-	DPU_DEBUG("reserving hw for conn %d enc %d crtc %d test_only %d\n",
-			conn_state->connector->base.id, enc->base.id,
-			crtc_state->crtc->base.id, test_only);
-	DPU_EVT32(enc->base.id, conn_state->connector->base.id);
+	int rc = 0;
 
 	mutex_lock(&rm->rm_lock);
 
-	_dpu_rm_print_rsvps(rm, DPU_RM_STAGE_BEGIN);
+	rc = _dpu_rm_reserve_intf_related_hw(rm, state, hw_res);
+	if (rc)
+		DPU_ERROR("unable to allocate intf for crtc: %d\n",
+				get_crtc_id(state));
 
-	ret = _dpu_rm_populate_requirements(rm, enc, crtc_state,
-			conn_state, &reqs, topology);
-	if (ret) {
-		DPU_ERROR("failed to populate hw requirements\n");
-		goto end;
-	}
+	mutex_unlock(&rm->rm_lock);
 
-	/*
-	 * We only support one active reservation per-hw-block. But to implement
-	 * transactional semantics for test-only, and for allowing failure while
-	 * modifying your existing reservation, over the course of this
-	 * function we can have two reservations:
-	 * Current: Existing reservation
-	 * Next: Proposed reservation. The proposed reservation may fail, or may
-	 *       be discarded if in test-only mode.
-	 * If reservation is successful, and we're not in test-only, then we
-	 * replace the current with the next.
-	 */
-	rsvp_nxt = kzalloc(sizeof(*rsvp_nxt), GFP_KERNEL);
-	if (!rsvp_nxt) {
-		ret = -ENOMEM;
-		goto end;
-	}
+	return rc;
+}
 
-	rsvp_cur = _dpu_rm_get_rsvp(rm, enc);
-
-	/*
-	 * User can request that we clear out any reservation during the
-	 * atomic_check phase by using this CLEAR bit
-	 */
-	if (rsvp_cur && test_only && RM_RQ_CLEAR(&reqs)) {
-		DPU_DEBUG("test_only & CLEAR: clear rsvp[s%de%d]\n",
-				rsvp_cur->seq, rsvp_cur->enc_id);
-		_dpu_rm_release_rsvp(rm, rsvp_cur, conn_state->connector);
-		rsvp_cur = NULL;
-		_dpu_rm_print_rsvps(rm, DPU_RM_STAGE_AFTER_CLEAR);
-	}
+int dpu_rm_release_encoder_res(struct dpu_rm *rm, struct dpu_crtc_state *state)
+{
+	int num_released;
+	int rc = 0;
 
-	/* Check the proposed reservation, store it in hw's "next" field */
-	ret = _dpu_rm_make_next_rsvp(rm, enc, crtc_state, conn_state,
-			rsvp_nxt, &reqs);
-
-	_dpu_rm_print_rsvps(rm, DPU_RM_STAGE_AFTER_RSVPNEXT);
-
-	if (ret) {
-		DPU_ERROR("failed to reserve hw resources: %d\n", ret);
-		_dpu_rm_release_rsvp(rm, rsvp_nxt, conn_state->connector);
-	} else if (test_only && !RM_RQ_LOCK(&reqs)) {
-		/*
-		 * Normally, if test_only, test the reservation and then undo
-		 * However, if the user requests LOCK, then keep the reservation
-		 * made during the atomic_check phase.
-		 */
-		DPU_DEBUG("test_only: discard test rsvp[s%de%d]\n",
-				rsvp_nxt->seq, rsvp_nxt->enc_id);
-		_dpu_rm_release_rsvp(rm, rsvp_nxt, conn_state->connector);
-	} else {
-		if (test_only && RM_RQ_LOCK(&reqs))
-			DPU_DEBUG("test_only & LOCK: lock rsvp[s%de%d]\n",
-					rsvp_nxt->seq, rsvp_nxt->enc_id);
-
-		_dpu_rm_release_rsvp(rm, rsvp_cur, conn_state->connector);
-
-		ret = _dpu_rm_commit_rsvp(rm, rsvp_nxt, conn_state);
-	}
+	mutex_lock(&rm->rm_lock);
 
-	_dpu_rm_print_rsvps(rm, DPU_RM_STAGE_FINAL);
+	num_released = _dpu_rm_release_hw_blk(rm, state, 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);
+		rc = -EINVAL;
+	}
 
-end:
 	mutex_unlock(&rm->rm_lock);
 
-	return ret;
+	state->num_intfs = 0;
+	memset(&state->hw_intfs, 0, sizeof(state->hw_intfs));
+
+	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 05a718c..fa2cd70 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -16,61 +16,26 @@
 #define __DPU_RM_H__
 
 #include <linux/list.h>
-
 #include "msm_kms.h"
 #include "dpu_hw_top.h"
-
-/**
- * enum dpu_rm_topology_name - HW resource use case in use by connector
- * @DPU_RM_TOPOLOGY_NONE:                 No topology in use currently
- * @DPU_RM_TOPOLOGY_SINGLEPIPE:           1 LM, 1 PP, 1 INTF/WB
- * @DPU_RM_TOPOLOGY_DUALPIPE:             2 LM, 2 PP, 2 INTF/WB
- * @DPU_RM_TOPOLOGY_DUALPIPE_3DMERGE:     2 LM, 2 PP, 3DMux, 1 INTF/WB
- */
-enum dpu_rm_topology_name {
-	DPU_RM_TOPOLOGY_NONE = 0,
-	DPU_RM_TOPOLOGY_SINGLEPIPE,
-	DPU_RM_TOPOLOGY_DUALPIPE,
-	DPU_RM_TOPOLOGY_DUALPIPE_3DMERGE,
-	DPU_RM_TOPOLOGY_MAX,
-};
-
-/**
- * enum dpu_rm_topology_control - HW resource use case in use by connector
- * @DPU_RM_TOPCTL_RESERVE_LOCK: If set, in AtomicTest phase, after a successful
- *                              test, reserve the resources for this display.
- *                              Normal behavior would not impact the reservation
- *                              list during the AtomicTest phase.
- * @DPU_RM_TOPCTL_RESERVE_CLEAR: If set, in AtomicTest phase, before testing,
- *                               release any reservation held by this display.
- *                               Normal behavior would not impact the
- *                               reservation list during the AtomicTest phase.
- * @DPU_RM_TOPCTL_DS  : Require layer mixers with DS capabilities
- */
-enum dpu_rm_topology_control {
-	DPU_RM_TOPCTL_RESERVE_LOCK,
-	DPU_RM_TOPCTL_RESERVE_CLEAR,
-	DPU_RM_TOPCTL_DS,
-};
+#include "dpu_crtc.h"
+#include "dpu_encoder.h"
 
 /**
  * struct dpu_rm - DPU dynamic hardware resource manager
- * @dev: device handle for event logging purposes
- * @rsvps: list of hardware reservations by each crtc->encoder->connector
+ * @hw_blks_len - number of hw blocks per type
  * @hw_blks: array of lists of hardware resources present in the system, one
  *	list per type of hardware block
+ * @hw_drm_map - array to track each hw block type assignments
  * @hw_mdp: hardware object for mdp_top
  * @lm_max_width: cached layer mixer maximum width
- * @rsvp_next_seq: sequence number for next reservation for debugging purposes
  * @rm_lock: resource manager mutex
  */
 struct dpu_rm {
-	struct drm_device *dev;
-	struct list_head rsvps;
-	struct list_head hw_blks[DPU_HW_BLK_MAX];
+	uint32_t hw_blks_len[DPU_HW_BLK_MAX];
+	struct dpu_rm_hw_blk *hw_blks[DPU_HW_BLK_MAX][MAX_BLOCKS];
+	int hw_drm_map[DPU_HW_BLK_MAX][MAX_BLOCKS];
 	struct dpu_hw_mdp *hw_mdp;
-	uint32_t lm_max_width;
-	uint32_t rsvp_next_seq;
 	struct mutex rm_lock;
 };
 
@@ -90,23 +55,28 @@ struct dpu_rm {
 struct dpu_rm_hw_iter {
 	void *hw;
 	struct dpu_rm_hw_blk *blk;
-	uint32_t enc_id;
+	uint32_t drm_id;
 	enum dpu_hw_blk_type type;
+	uint32_t index;
 };
 
 /**
+ * dpu_rm_print_state - prints current RM state on resource pool
+ * @rm: DPU Resource Manager handle
+ */
+void dpu_rm_print_state(struct dpu_rm *rm);
+
+/**
  * dpu_rm_init - Read hardware catalog and create reservation tracking objects
  *	for all HW blocks.
  * @rm: DPU Resource Manager handle
  * @cat: Pointer to hardware catalog
  * @mmio: mapped register io address of MDP
- * @dev: device handle for event logging purposes
  * @Return: 0 on Success otherwise -ERROR
  */
 int dpu_rm_init(struct dpu_rm *rm,
 		struct dpu_mdss_cfg *cat,
-		void *mmio,
-		struct drm_device *dev);
+		void *mmio);
 
 /**
  * dpu_rm_destroy - Free all memory allocated by dpu_rm_init
@@ -116,75 +86,47 @@ int dpu_rm_init(struct dpu_rm *rm,
 int dpu_rm_destroy(struct dpu_rm *rm);
 
 /**
- * dpu_rm_reserve - Given a CRTC->Encoder->Connector display chain, analyze
- *	the use connections and user requirements, specified through related
- *	topology control properties, and reserve hardware blocks to that
- *	display chain.
- *	HW blocks can then be accessed through dpu_rm_get_* functions.
- *	HW Reservations should be released via dpu_rm_release_hw.
+ * dpu_rm_reserve_crtc_res - Reserve HW blocks for CRTC
  * @rm: DPU Resource Manager handle
- * @drm_enc: DRM Encoder handle
- * @crtc_state: Proposed Atomic DRM CRTC State handle
- * @conn_state: Proposed Atomic DRM Connector State handle
- * @topology: Pointer to topology info for the display
- * @test_only: Atomic-Test phase, discard results (unless property overrides)
- * @Return: 0 on Success otherwise -ERROR
+ * @state: DPU CRTC state to cache HW block handles
+ * @topology: topology requirement for the display
+ * @Return: 0 on Success otherwise - ERROR
  */
-int dpu_rm_reserve(struct dpu_rm *rm,
-		struct drm_encoder *drm_enc,
-		struct drm_crtc_state *crtc_state,
-		struct drm_connector_state *conn_state,
-		struct msm_display_topology topology,
-		bool test_only);
+int dpu_rm_reserve_crtc_res(struct dpu_rm *rm, struct dpu_crtc_state *state,
+		struct dpu_crtc_topology *topology);
 
 /**
- * dpu_rm_reserve - Given the encoder for the display chain, release any
- *	HW blocks previously reserved for that use case.
+ * dpu_rm_release_crtc_res - Release HW blocks of the CRTC
  * @rm: DPU Resource Manager handle
- * @enc: DRM Encoder handle
- * @Return: 0 on Success otherwise -ERROR
+ * @state: DPU CRTC state to cache HW block handles
+ * @Return: 0 on Success otherwise - ERROR
  */
-void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc);
+int dpu_rm_release_crtc_res(struct dpu_rm *rm, struct dpu_crtc_state *state);
 
 /**
- * dpu_rm_get_mdp - Retrieve HW block for MDP TOP.
- *	This is never reserved, and is usable by any display.
+ * dpu_rm_reserve_encoder_res - Reserve HW blocks for Encoder/Connector
  * @rm: DPU Resource Manager handle
- * @Return: Pointer to hw block or NULL
+ * @state: DPU CRTC state to cache HW block handles
+ * @hw_res: interface block related info
+ * @Return: 0 on Success otherwise - ERROR
  */
-struct dpu_hw_mdp *dpu_rm_get_mdp(struct dpu_rm *rm);
+int dpu_rm_reserve_encoder_res(struct dpu_rm *rm, struct dpu_crtc_state *state,
+		struct dpu_encoder_hw_resources *hw_res);
 
 /**
- * dpu_rm_init_hw_iter - setup given iterator for new iteration over hw list
- *	using dpu_rm_get_hw
- * @iter: iter object to initialize
- * @enc_id: DRM ID of Encoder client wishes to search for, or 0 for Any Encoder
- * @type: Hardware Block Type client wishes to search for.
- */
-void dpu_rm_init_hw_iter(
-		struct dpu_rm_hw_iter *iter,
-		uint32_t enc_id,
-		enum dpu_hw_blk_type type);
-/**
- * dpu_rm_get_hw - retrieve reserved hw object given encoder and hw type
- *	Meant to do a single pass through the hardware list to iteratively
- *	retrieve hardware blocks of a given type for a given encoder.
- *	Initialize an iterator object.
- *	Set hw block type of interest. Set encoder id of interest, 0 for any.
- *	Function returns first hw of type for that encoder.
- *	Subsequent calls will return the next reserved hw of that type in-order.
- *	Iterator HW pointer will be null on failure to find hw.
+ * dpu_rm_release_encoder_res - Release HW blocks of the Encoder/Connector
  * @rm: DPU Resource Manager handle
- * @iter: iterator object
- * @Return: true on match found, false on no match found
+ * @state: DPU CRTC state to cache HW block handles
+ * @Return: 0 on Success otherwise - ERROR
  */
-bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *iter);
+int dpu_rm_release_encoder_res(struct dpu_rm *rm, struct dpu_crtc_state *state);
 
 /**
- * dpu_rm_check_property_topctl - validate property bitmask before it is set
- * @val: user's proposed topology control bitmask
- * @Return: 0 on success or error
+ * dpu_rm_get_mdp - Retrieve HW block for MDP TOP.
+ *	This is never reserved, and is usable by any display.
+ * @rm: DPU Resource Manager handle
+ * @Return: Pointer to hw block or NULL
  */
-int dpu_rm_check_property_topctl(uint64_t val);
+struct dpu_hw_mdp *dpu_rm_get_mdp(struct dpu_rm *rm);
 
 #endif /* __DPU_RM_H__ */
