struct drm_display_mode *mode,
                               struct drm_display_mode *adjusted_mode)
 {
-       struct mdp5_encoder *mdp5_cmd_enc = to_mdp5_encoder(encoder);
-
        mode = adjusted_mode;
 
        DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
                        mode->vsync_end, mode->vtotal,
                        mode->type, mode->flags);
        pingpong_tearcheck_setup(encoder, mode);
-       mdp5_crtc_set_pipeline(encoder->crtc, mdp5_cmd_enc->intf,
-                               mdp5_cmd_enc->ctl);
+       mdp5_crtc_set_pipeline(encoder->crtc);
 }
 
 void mdp5_cmd_encoder_disable(struct drm_encoder *encoder)
        struct mdp5_encoder *mdp5_cmd_enc = to_mdp5_encoder(encoder);
        struct mdp5_ctl *ctl = mdp5_cmd_enc->ctl;
        struct mdp5_interface *intf = mdp5_cmd_enc->intf;
+       struct mdp5_pipeline *pipeline = mdp5_crtc_get_pipeline(encoder->crtc);
 
        if (WARN_ON(!mdp5_cmd_enc->enabled))
                return;
 
        pingpong_tearcheck_disable(encoder);
 
-       mdp5_ctl_set_encoder_state(ctl, false);
-       mdp5_ctl_commit(ctl, mdp_ctl_flush_mask_encoder(intf));
+       mdp5_ctl_set_encoder_state(ctl, pipeline, false);
+       mdp5_ctl_commit(ctl, pipeline, mdp_ctl_flush_mask_encoder(intf));
 
        bs_set(mdp5_cmd_enc, 0);
 
        struct mdp5_encoder *mdp5_cmd_enc = to_mdp5_encoder(encoder);
        struct mdp5_ctl *ctl = mdp5_cmd_enc->ctl;
        struct mdp5_interface *intf = mdp5_cmd_enc->intf;
+       struct mdp5_pipeline *pipeline = mdp5_crtc_get_pipeline(encoder->crtc);
 
        if (WARN_ON(mdp5_cmd_enc->enabled))
                return;
        if (pingpong_tearcheck_enable(encoder))
                return;
 
-       mdp5_ctl_commit(ctl, mdp_ctl_flush_mask_encoder(intf));
+       mdp5_ctl_commit(ctl, pipeline, mdp_ctl_flush_mask_encoder(intf));
 
-       mdp5_ctl_set_encoder_state(ctl, true);
+       mdp5_ctl_set_encoder_state(ctl, pipeline, true);
 
        mdp5_cmd_enc->enabled = true;
 }
 
 {
        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
        struct mdp5_ctl *ctl = mdp5_cstate->ctl;
+       struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
 
        DBG("%s: flush=%08x", crtc->name, flush_mask);
-       return mdp5_ctl_commit(ctl, flush_mask);
+       return mdp5_ctl_commit(ctl, pipeline, flush_mask);
 }
 
 /*
 static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
 {
        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
+       struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
        struct mdp5_ctl *ctl = mdp5_cstate->ctl;
        struct drm_device *dev = crtc->dev;
 
        if (ctl && !crtc->state->enable) {
                /* set STAGE_UNUSED for all layers */
-               mdp5_ctl_blend(ctl, NULL, 0, 0);
+               mdp5_ctl_blend(ctl, pipeline, NULL, 0, 0);
                /* XXX: What to do here? */
                /* mdp5_crtc->ctl = NULL; */
        }
 {
        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
+       struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
        struct mdp5_kms *mdp5_kms = get_kms(crtc);
        struct drm_plane *plane;
        const struct mdp5_cfg_hw *hw_cfg;
        struct mdp5_plane_state *pstate, *pstates[STAGE_MAX + 1] = {NULL};
        const struct mdp_format *format;
-       struct mdp5_hw_mixer *mixer = mdp5_cstate->pipeline.mixer;
+       struct mdp5_hw_mixer *mixer = pipeline->mixer;
        uint32_t lm = mixer->lm;
        struct mdp5_ctl *ctl = mdp5_cstate->ctl;
        uint32_t blend_op, fg_alpha, bg_alpha, ctl_blend_flags = 0;
 
        mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(lm), mixer_op_mode);
 
-       mdp5_ctl_blend(ctl, stage, plane_cnt, ctl_blend_flags);
+       mdp5_ctl_blend(ctl, pipeline, stage, plane_cnt, ctl_blend_flags);
 
 out:
        spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags);
 {
        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
+       struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
        struct drm_device *dev = crtc->dev;
        struct mdp5_kms *mdp5_kms = get_kms(crtc);
        struct drm_gem_object *cursor_bo, *old_bo = NULL;
        spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
 
 set_cursor:
-       ret = mdp5_ctl_set_cursor(ctl, 0, cursor_enable);
+       ret = mdp5_ctl_set_cursor(ctl, pipeline, 0, cursor_enable);
        if (ret) {
                dev_err(dev->dev, "failed to %sable cursor: %d\n",
                                cursor_enable ? "en" : "dis", ret);
        return mdp5_crtc->vblank.irqmask;
 }
 
-void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,
-               struct mdp5_interface *intf, struct mdp5_ctl *ctl)
+void mdp5_crtc_set_pipeline(struct drm_crtc *crtc)
 {
        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
-       struct mdp5_hw_mixer *mixer = mdp5_cstate->pipeline.mixer;
        struct mdp5_kms *mdp5_kms = get_kms(crtc);
 
        /* should this be done elsewhere ? */
        mdp_irq_update(&mdp5_kms->base);
 
-       mdp5_ctl_set_pipeline(ctl, intf, mixer);
+       mdp5_ctl_set_pipeline(mdp5_cstate->ctl, &mdp5_cstate->pipeline);
 }
 
 struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc)
                ERR_PTR(-EINVAL) : mdp5_cstate->pipeline.mixer;
 }
 
+struct mdp5_pipeline *mdp5_crtc_get_pipeline(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc_state *mdp5_cstate;
+
+       if (WARN_ON(!crtc))
+               return ERR_PTR(-EINVAL);
+
+       mdp5_cstate = to_mdp5_crtc_state(crtc->state);
+
+       return &mdp5_cstate->pipeline;
+}
+
 void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc)
 {
        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
 
        struct mdp5_ctl_manager *ctlm;
 
        u32 id;
-       struct mdp5_hw_mixer *mixer;
 
        /* CTL status bitmask */
        u32 status;
 
-       /* Operation Mode Configuration for the Pipeline */
-       struct mdp5_interface *intf;
-
        bool encoder_enabled;
        uint32_t start_mask;
 
        spin_unlock_irqrestore(&ctl->hw_lock, flags);
 }
 
-int mdp5_ctl_set_pipeline(struct mdp5_ctl *ctl, struct mdp5_interface *intf,
-                         struct mdp5_hw_mixer *mixer)
+int mdp5_ctl_set_pipeline(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline)
 {
        struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
        struct mdp5_kms *mdp5_kms = get_kms(ctl_mgr);
-
-       ctl->mixer = mixer;
-       ctl->intf = intf;
+       struct mdp5_interface *intf = pipeline->intf;
+       struct mdp5_hw_mixer *mixer = pipeline->mixer;
 
        ctl->start_mask = mdp_ctl_flush_mask_lm(mixer->lm) |
                          mdp_ctl_flush_mask_encoder(intf);
        return 0;
 }
 
-static bool start_signal_needed(struct mdp5_ctl *ctl)
+static bool start_signal_needed(struct mdp5_ctl *ctl,
+                               struct mdp5_pipeline *pipeline)
 {
+       struct mdp5_interface *intf = pipeline->intf;
+
        if (!ctl->encoder_enabled || ctl->start_mask != 0)
                return false;
 
-       switch (ctl->intf->type) {
+       switch (intf->type) {
        case INTF_WB:
                return true;
        case INTF_DSI:
-               return ctl->intf->mode == MDP5_INTF_DSI_MODE_COMMAND;
+               return intf->mode == MDP5_INTF_DSI_MODE_COMMAND;
        default:
                return false;
        }
        spin_unlock_irqrestore(&ctl->hw_lock, flags);
 }
 
-static void refill_start_mask(struct mdp5_ctl *ctl)
+static void refill_start_mask(struct mdp5_ctl *ctl,
+                             struct mdp5_pipeline *pipeline)
 {
-       struct mdp5_interface *intf = ctl->intf;
+       struct mdp5_interface *intf = pipeline->intf;
+       struct mdp5_hw_mixer *mixer = pipeline->mixer;
 
-       ctl->start_mask = mdp_ctl_flush_mask_lm(ctl->mixer->lm);
+       ctl->start_mask = mdp_ctl_flush_mask_lm(mixer->lm);
 
        /*
         * Writeback encoder needs to program & flush
  * Note:
  * This encoder state is needed to trigger START signal (data path kickoff).
  */
-int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl, bool enabled)
+int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl,
+                              struct mdp5_pipeline *pipeline,
+                              bool enabled)
 {
+       struct mdp5_interface *intf = pipeline->intf;
+
        if (WARN_ON(!ctl))
                return -EINVAL;
 
        ctl->encoder_enabled = enabled;
-       DBG("intf_%d: %s", ctl->intf->num, enabled ? "on" : "off");
+       DBG("intf_%d: %s", intf->num, enabled ? "on" : "off");
 
-       if (start_signal_needed(ctl)) {
+       if (start_signal_needed(ctl, pipeline)) {
                send_start_signal(ctl);
-               refill_start_mask(ctl);
+               refill_start_mask(ctl, pipeline);
        }
 
        return 0;
  * CTL registers need to be flushed after calling this function
  * (call mdp5_ctl_commit() with mdp_ctl_flush_mask_ctl() mask)
  */
-int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, int cursor_id, bool enable)
+int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline,
+                       int cursor_id, bool enable)
 {
        struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
        unsigned long flags;
        u32 blend_cfg;
-       struct mdp5_hw_mixer *mixer = ctl->mixer;
+       struct mdp5_hw_mixer *mixer = pipeline->mixer;
 
        if (unlikely(WARN_ON(!mixer))) {
                dev_err(ctl_mgr->dev->dev, "CTL %d cannot find LM",
        }
 }
 
-int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt,
-                  u32 ctl_blend_op_flags)
+int mdp5_ctl_blend(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline,
+                  enum mdp5_pipe *stage, u32 stage_cnt, u32 ctl_blend_op_flags)
 {
-       struct mdp5_hw_mixer *mixer = ctl->mixer;
+       struct mdp5_hw_mixer *mixer = pipeline->mixer;
        unsigned long flags;
        u32 blend_cfg = 0, blend_ext_cfg = 0;
        int i, start_stage;
        }
 }
 
-static u32 fix_sw_flush(struct mdp5_ctl *ctl, u32 flush_mask)
+static u32 fix_sw_flush(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline,
+                       u32 flush_mask)
 {
        struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
        u32 sw_mask = 0;
 
        /* for some targets, cursor bit is the same as LM bit */
        if (BIT_NEEDS_SW_FIX(MDP5_CTL_FLUSH_CURSOR_0))
-               sw_mask |= mdp_ctl_flush_mask_lm(ctl->mixer->lm);
+               sw_mask |= mdp_ctl_flush_mask_lm(pipeline->mixer->lm);
 
        return sw_mask;
 }
  *
  * Return H/W flushed bit mask.
  */
-u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask)
+u32 mdp5_ctl_commit(struct mdp5_ctl *ctl,
+                   struct mdp5_pipeline *pipeline,
+                   u32 flush_mask)
 {
        struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
        unsigned long flags;
                ctl->pending_ctl_trigger = 0;
        }
 
-       flush_mask |= fix_sw_flush(ctl, flush_mask);
+       flush_mask |= fix_sw_flush(ctl, pipeline, flush_mask);
 
        flush_mask &= ctl_mgr->flush_hw_mask;
 
                spin_unlock_irqrestore(&ctl->hw_lock, flags);
        }
 
-       if (start_signal_needed(ctl)) {
+       if (start_signal_needed(ctl, pipeline)) {
                send_start_signal(ctl);
-               refill_start_mask(ctl);
+               refill_start_mask(ctl, pipeline);
        }
 
        return curr_ctl_flush_mask;
 
 found:
        ctl = &ctl_mgr->ctls[c];
-       ctl->mixer = NULL;
        ctl->status |= CTL_STAT_BUSY;
        ctl->pending_ctl_trigger = 0;
        DBG("CTL %d allocated", ctl->id);
 
 int mdp5_ctl_get_ctl_id(struct mdp5_ctl *ctl);
 
 struct mdp5_interface;
-int mdp5_ctl_set_pipeline(struct mdp5_ctl *ctl, struct mdp5_interface *intf,
-                         struct mdp5_hw_mixer *lm);
-int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl, bool enabled);
+struct mdp5_pipeline;
+int mdp5_ctl_set_pipeline(struct mdp5_ctl *ctl, struct mdp5_pipeline *p);
+int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl, struct mdp5_pipeline *p,
+                              bool enabled);
 
-int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, int cursor_id, bool enable);
+int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline,
+                       int cursor_id, bool enable);
 int mdp5_ctl_pair(struct mdp5_ctl *ctlx, struct mdp5_ctl *ctly, bool enable);
 
 /*
  * (call mdp5_ctl_commit() with mdp_ctl_flush_mask_ctl() mask)
  */
 #define MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT      BIT(0)
-int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt,
+int mdp5_ctl_blend(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline,
+                  enum mdp5_pipe *stage, u32 stage_cnt,
                   u32 ctl_blend_op_flags);
 
 /**
 u32 mdp_ctl_flush_mask_encoder(struct mdp5_interface *intf);
 
 /* @flush_mask: see CTL flush masks definitions below */
-u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask);
+u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline,
+                   u32 flush_mask);
 u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl);
 
 
 
 
        spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
 
-       mdp5_crtc_set_pipeline(encoder->crtc, mdp5_encoder->intf,
-                              mdp5_encoder->ctl);
+       mdp5_crtc_set_pipeline(encoder->crtc);
 }
 
 static void mdp5_vid_encoder_disable(struct drm_encoder *encoder)
        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
        struct mdp5_kms *mdp5_kms = get_kms(encoder);
        struct mdp5_ctl *ctl = mdp5_encoder->ctl;
+       struct mdp5_pipeline *pipeline = mdp5_crtc_get_pipeline(encoder->crtc);
        struct mdp5_hw_mixer *mixer = mdp5_crtc_get_mixer(encoder->crtc);
        struct mdp5_interface *intf = mdp5_encoder->intf;
        int intfn = mdp5_encoder->intf->num;
        if (WARN_ON(!mdp5_encoder->enabled))
                return;
 
-       mdp5_ctl_set_encoder_state(ctl, false);
+       mdp5_ctl_set_encoder_state(ctl, pipeline, false);
 
        spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
        mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 0);
        spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
-       mdp5_ctl_commit(ctl, mdp_ctl_flush_mask_encoder(intf));
+       mdp5_ctl_commit(ctl, pipeline, mdp_ctl_flush_mask_encoder(intf));
 
        /*
         * Wait for a vsync so we know the ENABLE=0 latched before
        struct mdp5_kms *mdp5_kms = get_kms(encoder);
        struct mdp5_ctl *ctl = mdp5_encoder->ctl;
        struct mdp5_interface *intf = mdp5_encoder->intf;
+       struct mdp5_pipeline *pipeline = mdp5_crtc_get_pipeline(encoder->crtc);
        int intfn = intf->num;
        unsigned long flags;
 
        spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
        mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 1);
        spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
-       mdp5_ctl_commit(ctl, mdp_ctl_flush_mask_encoder(intf));
+       mdp5_ctl_commit(ctl, pipeline, mdp_ctl_flush_mask_encoder(intf));
 
-       mdp5_ctl_set_encoder_state(ctl, true);
+       mdp5_ctl_set_encoder_state(ctl, pipeline, true);
 
        mdp5_encoder->enabled = true;
 }
 
 uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
 
 struct mdp5_hw_mixer *mdp5_crtc_get_mixer(struct drm_crtc *crtc);
-void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,
-               struct mdp5_interface *intf, struct mdp5_ctl *ctl);
+struct mdp5_pipeline *mdp5_crtc_get_pipeline(struct drm_crtc *crtc);
+void mdp5_crtc_set_pipeline(struct drm_crtc *crtc);
 void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc);
 struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
                                struct drm_plane *plane,
 
 
        if (new_plane_state->visible) {
                struct mdp5_ctl *ctl;
+               struct mdp5_pipeline *pipeline = mdp5_crtc_get_pipeline(crtc);
 
                ret = mdp5_plane_mode_set(plane, crtc, fb,
                                          &new_plane_state->src,
 
                ctl = mdp5_crtc_get_ctl(crtc);
 
-               mdp5_ctl_commit(ctl, mdp5_plane_get_flush(plane));
+               mdp5_ctl_commit(ctl, pipeline, mdp5_plane_get_flush(plane));
        }
 
        *to_mdp5_plane_state(plane_state) =