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_crtc_set_pipeline(encoder->crtc, mdp5_cmd_enc->intf,
                                mdp5_cmd_enc->ctl);
 }
 
 {
        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_interface *intf = mdp5_cmd_enc->intf;
 
        if (WARN_ON(!mdp5_cmd_enc->enabled))
                return;
 {
        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_interface *intf = mdp5_cmd_enc->intf;
 
        if (WARN_ON(mdp5_cmd_enc->enabled))
                return;
                return -EINVAL;
 
        mdp5_kms = get_kms(encoder);
-       intf_num = mdp5_cmd_enc->intf.num;
+       intf_num = mdp5_cmd_enc->intf->num;
 
        /* Switch slave encoder's trigger MUX, to use the master's
         * start signal for the slave encoder
 
 #define CTL_STAT_BOOKED        0x2
 
 struct op_mode {
-       struct mdp5_interface intf;
+       struct mdp5_interface *intf;
 
        bool encoder_enabled;
        uint32_t start_mask;
        struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
        struct mdp5_kms *mdp5_kms = get_kms(ctl_mgr);
 
-       if (unlikely(WARN_ON(intf->num != ctl->pipeline.intf.num))) {
-               dev_err(mdp5_kms->dev->dev,
-                       "CTL %d is allocated by INTF %d, but used by INTF %d\n",
-                       ctl->id, ctl->pipeline.intf.num, intf->num);
-               return -EINVAL;
-       }
-
        ctl->mixer = mixer;
-
-       memcpy(&ctl->pipeline.intf, intf, sizeof(*intf));
+       ctl->pipeline.intf = intf;
 
        ctl->pipeline.start_mask = mdp_ctl_flush_mask_lm(mixer->lm) |
                                   mdp_ctl_flush_mask_encoder(intf);
        if (!pipeline->encoder_enabled || pipeline->start_mask != 0)
                return false;
 
-       switch (pipeline->intf.type) {
+       switch (pipeline->intf->type) {
        case INTF_WB:
                return true;
        case INTF_DSI:
-               return pipeline->intf.mode == MDP5_INTF_DSI_MODE_COMMAND;
+               return pipeline->intf->mode == MDP5_INTF_DSI_MODE_COMMAND;
        default:
                return false;
        }
 static void refill_start_mask(struct mdp5_ctl *ctl)
 {
        struct op_mode *pipeline = &ctl->pipeline;
-       struct mdp5_interface *intf = &ctl->pipeline.intf;
+       struct mdp5_interface *intf = pipeline->intf;
 
        pipeline->start_mask = mdp_ctl_flush_mask_lm(ctl->mixer->lm);
 
                return -EINVAL;
 
        ctl->pipeline.encoder_enabled = enabled;
-       DBG("intf_%d: %s", ctl->pipeline.intf.num, enabled ? "on" : "off");
+       DBG("intf_%d: %s", ctl->pipeline.intf->num, enabled ? "on" : "off");
 
        if (start_signal_needed(ctl)) {
                send_start_signal(ctl);
 
 found:
        ctl = &ctl_mgr->ctls[c];
-       ctl->pipeline.intf.num = intf_num;
        ctl->mixer = NULL;
        ctl->status |= CTL_STAT_BUSY;
        ctl->pending_ctl_trigger = 0;
 
        struct mdp5_kms *mdp5_kms = get_kms(encoder);
        struct drm_device *dev = encoder->dev;
        struct drm_connector *connector;
-       int intf = mdp5_encoder->intf.num;
+       int intf = mdp5_encoder->intf->num;
        uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
        uint32_t display_v_start, display_v_end;
        uint32_t hsync_start_x, hsync_end_x;
        ctrl_pol = 0;
 
        /* DSI controller cannot handle active-low sync signals. */
-       if (mdp5_encoder->intf.type != INTF_DSI) {
+       if (mdp5_encoder->intf->type != INTF_DSI) {
                if (mode->flags & DRM_MODE_FLAG_NHSYNC)
                        ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW;
                if (mode->flags & DRM_MODE_FLAG_NVSYNC)
         * DISPLAY_V_START = (VBP * HCYCLE) + HBP
         * DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP
         */
-       if (mdp5_encoder->intf.type == INTF_eDP) {
+       if (mdp5_encoder->intf->type == INTF_eDP) {
                display_v_start += mode->htotal - mode->hsync_start;
                display_v_end -= mode->hsync_start - mode->hdisplay;
        }
 
        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, mdp5_encoder->intf,
+                              mdp5_encoder->ctl);
 }
 
 static void mdp5_vid_encoder_disable(struct drm_encoder *encoder)
        struct mdp5_kms *mdp5_kms = get_kms(encoder);
        struct mdp5_ctl *ctl = mdp5_encoder->ctl;
        struct mdp5_hw_mixer *mixer = mdp5_crtc_get_mixer(encoder->crtc);
-       struct mdp5_interface *intf = &mdp5_encoder->intf;
-       int intfn = mdp5_encoder->intf.num;
+       struct mdp5_interface *intf = mdp5_encoder->intf;
+       int intfn = mdp5_encoder->intf->num;
        unsigned long flags;
 
        if (WARN_ON(!mdp5_encoder->enabled))
        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_interface *intf = &mdp5_encoder->intf;
-       int intfn = mdp5_encoder->intf.num;
+       struct mdp5_interface *intf = mdp5_encoder->intf;
+       int intfn = intf->num;
        unsigned long flags;
 
        if (WARN_ON(mdp5_encoder->enabled))
                                  struct drm_display_mode *adjusted_mode)
 {
        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
-       struct mdp5_interface *intf = &mdp5_encoder->intf;
+       struct mdp5_interface *intf = mdp5_encoder->intf;
 
        if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
                mdp5_cmd_encoder_mode_set(encoder, mode, adjusted_mode);
 static void mdp5_encoder_disable(struct drm_encoder *encoder)
 {
        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
-       struct mdp5_interface *intf = &mdp5_encoder->intf;
+       struct mdp5_interface *intf = mdp5_encoder->intf;
 
        if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
                mdp5_cmd_encoder_disable(encoder);
 static void mdp5_encoder_enable(struct drm_encoder *encoder)
 {
        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
-       struct mdp5_interface *intf = &mdp5_encoder->intf;
+       struct mdp5_interface *intf = mdp5_encoder->intf;
 
        if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
                mdp5_cmd_encoder_disable(encoder);
 {
        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
        struct mdp5_kms *mdp5_kms = get_kms(encoder);
-       int intf = mdp5_encoder->intf.num;
+       int intf = mdp5_encoder->intf->num;
 
        return mdp5_read(mdp5_kms, REG_MDP5_INTF_LINE_COUNT(intf));
 }
 {
        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
        struct mdp5_kms *mdp5_kms = get_kms(encoder);
-       int intf = mdp5_encoder->intf.num;
+       int intf = mdp5_encoder->intf->num;
 
        return mdp5_read(mdp5_kms, REG_MDP5_INTF_FRAME_COUNT(intf));
 }
                return -EINVAL;
 
        mdp5_kms = get_kms(encoder);
-       intf_num = mdp5_encoder->intf.num;
+       intf_num = mdp5_encoder->intf->num;
 
        /* Switch slave encoder's TimingGen Sync mode,
         * to use the master's enable signal for the slave encoder.
 void mdp5_encoder_set_intf_mode(struct drm_encoder *encoder, bool cmd_mode)
 {
        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
-       struct mdp5_interface *intf = &mdp5_encoder->intf;
+       struct mdp5_interface *intf = mdp5_encoder->intf;
 
        /* TODO: Expand this to set writeback modes too */
        if (cmd_mode) {
 
 /* initialize encoder */
 struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
-                       struct mdp5_interface *intf, struct mdp5_ctl *ctl)
+                                     struct mdp5_interface *intf,
+                                     struct mdp5_ctl *ctl)
 {
        struct drm_encoder *encoder = NULL;
        struct mdp5_encoder *mdp5_encoder;
                goto fail;
        }
 
-       memcpy(&mdp5_encoder->intf, intf, sizeof(mdp5_encoder->intf));
        encoder = &mdp5_encoder->base;
        mdp5_encoder->ctl = ctl;
+       mdp5_encoder->intf = intf;
 
        spin_lock_init(&mdp5_encoder->intf_lock);
 
 
 }
 
 static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms,
-               enum mdp5_intf_type intf_type, int intf_num,
-               struct mdp5_ctl *ctl)
+                                            struct mdp5_interface *intf,
+                                            struct mdp5_ctl *ctl)
 {
        struct drm_device *dev = mdp5_kms->dev;
        struct msm_drm_private *priv = dev->dev_private;
        struct drm_encoder *encoder;
-       struct mdp5_interface intf = {
-                       .num    = intf_num,
-                       .type   = intf_type,
-                       .mode   = MDP5_INTF_MODE_NONE,
-       };
 
-       encoder = mdp5_encoder_init(dev, &intf, ctl);
+       encoder = mdp5_encoder_init(dev, intf, ctl);
        if (IS_ERR(encoder)) {
                dev_err(dev->dev, "failed to construct encoder\n");
                return encoder;
        return -EINVAL;
 }
 
-static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)
+static int modeset_init_intf(struct mdp5_kms *mdp5_kms,
+                            struct mdp5_interface *intf)
 {
        struct drm_device *dev = mdp5_kms->dev;
        struct msm_drm_private *priv = dev->dev_private;
-       const struct mdp5_cfg_hw *hw_cfg =
-                                       mdp5_cfg_get_hw_config(mdp5_kms->cfg);
-       enum mdp5_intf_type intf_type = hw_cfg->intf.connect[intf_num];
        struct mdp5_ctl_manager *ctlm = mdp5_kms->ctlm;
        struct mdp5_ctl *ctl;
        struct drm_encoder *encoder;
        int ret = 0;
 
-       switch (intf_type) {
-       case INTF_DISABLED:
-               break;
+       switch (intf->type) {
        case INTF_eDP:
                if (!priv->edp)
                        break;
 
-               ctl = mdp5_ctlm_request(ctlm, intf_num);
+               ctl = mdp5_ctlm_request(ctlm, intf->num);
                if (!ctl) {
                        ret = -EINVAL;
                        break;
                }
 
-               encoder = construct_encoder(mdp5_kms, INTF_eDP, intf_num, ctl);
+               encoder = construct_encoder(mdp5_kms, intf, ctl);
                if (IS_ERR(encoder)) {
                        ret = PTR_ERR(encoder);
                        break;
                if (!priv->hdmi)
                        break;
 
-               ctl = mdp5_ctlm_request(ctlm, intf_num);
+               ctl = mdp5_ctlm_request(ctlm, intf->num);
                if (!ctl) {
                        ret = -EINVAL;
                        break;
                }
 
-               encoder = construct_encoder(mdp5_kms, INTF_HDMI, intf_num, ctl);
+               encoder = construct_encoder(mdp5_kms, intf, ctl);
                if (IS_ERR(encoder)) {
                        ret = PTR_ERR(encoder);
                        break;
                break;
        case INTF_DSI:
        {
-               int dsi_id = get_dsi_id_from_intf(hw_cfg, intf_num);
+               const struct mdp5_cfg_hw *hw_cfg =
+                                       mdp5_cfg_get_hw_config(mdp5_kms->cfg);
+               int dsi_id = get_dsi_id_from_intf(hw_cfg, intf->num);
 
                if ((dsi_id >= ARRAY_SIZE(priv->dsi)) || (dsi_id < 0)) {
                        dev_err(dev->dev, "failed to find dsi from intf %d\n",
-                               intf_num);
+                               intf->num);
                        ret = -EINVAL;
                        break;
                }
                if (!priv->dsi[dsi_id])
                        break;
 
-               ctl = mdp5_ctlm_request(ctlm, intf_num);
+               ctl = mdp5_ctlm_request(ctlm, intf->num);
                if (!ctl) {
                        ret = -EINVAL;
                        break;
                }
 
-               encoder = construct_encoder(mdp5_kms, INTF_DSI, intf_num, ctl);
+               encoder = construct_encoder(mdp5_kms, intf, ctl);
                if (IS_ERR(encoder)) {
                        ret = PTR_ERR(encoder);
                        break;
                break;
        }
        default:
-               dev_err(dev->dev, "unknown intf: %d\n", intf_type);
+               dev_err(dev->dev, "unknown intf: %d\n", intf->type);
                ret = -EINVAL;
                break;
        }
         * Construct encoders and modeset initialize connector devices
         * for each external display interface.
         */
-       for (i = 0; i < ARRAY_SIZE(hw_cfg->intf.connect); i++) {
-               ret = modeset_init_intf(mdp5_kms, i);
+       for (i = 0; i < mdp5_kms->num_intfs; i++) {
+               ret = modeset_init_intf(mdp5_kms, mdp5_kms->intfs[i]);
                if (ret)
                        goto fail;
        }
 static void mdp5_destroy(struct platform_device *pdev)
 {
        struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev);
+       int i;
 
        if (mdp5_kms->ctlm)
                mdp5_ctlm_destroy(mdp5_kms->ctlm);
        if (mdp5_kms->cfg)
                mdp5_cfg_destroy(mdp5_kms->cfg);
 
+       for (i = 0; i < mdp5_kms->num_intfs; i++)
+               kfree(mdp5_kms->intfs[i]);
+
        if (mdp5_kms->rpm_enabled)
                pm_runtime_disable(&pdev->dev);
 
        return 0;
 }
 
+static int interface_init(struct mdp5_kms *mdp5_kms)
+{
+       struct drm_device *dev = mdp5_kms->dev;
+       const struct mdp5_cfg_hw *hw_cfg;
+       const enum mdp5_intf_type *intf_types;
+       int i;
+
+       hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
+       intf_types = hw_cfg->intf.connect;
+
+       for (i = 0; i < ARRAY_SIZE(hw_cfg->intf.connect); i++) {
+               struct mdp5_interface *intf;
+
+               if (intf_types[i] == INTF_DISABLED)
+                       continue;
+
+               intf = kzalloc(sizeof(*intf), GFP_KERNEL);
+               if (!intf) {
+                       dev_err(dev->dev, "failed to construct INTF%d\n", i);
+                       return -ENOMEM;
+               }
+
+               intf->num = i;
+               intf->type = intf_types[i];
+               intf->mode = MDP5_INTF_MODE_NONE;
+               intf->idx = mdp5_kms->num_intfs;
+               mdp5_kms->intfs[mdp5_kms->num_intfs++] = intf;
+       }
+
+       return 0;
+}
+
 static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
 {
        struct msm_drm_private *priv = dev->dev_private;
        if (ret)
                goto fail;
 
+       ret = interface_init(mdp5_kms);
+       if (ret)
+               goto fail;
+
        /* set uninit-ed kms */
        priv->kms = &mdp5_kms->base.base;
 
 
        unsigned num_hwmixers;
        struct mdp5_hw_mixer *hwmixers[8];
 
+       unsigned num_intfs;
+       struct mdp5_interface *intfs[5];
+
        struct mdp5_cfg_handler *cfg;
        uint32_t caps;  /* MDP capabilities (MDP_CAP_XXX bits) */
 
 };
 
 struct mdp5_interface {
+       int idx;
        int num; /* display interface number */
        enum mdp5_intf_type type;
        enum mdp5_intf_mode mode;
 
 struct mdp5_encoder {
        struct drm_encoder base;
-       struct mdp5_interface intf;
        spinlock_t intf_lock;   /* protect REG_MDP5_INTF_* registers */
        bool enabled;
        uint32_t bsc;
 
+       struct mdp5_interface *intf;
        struct mdp5_ctl *ctl;
 };
 #define to_mdp5_encoder(x) container_of(x, struct mdp5_encoder, base)