diff mbox

[06/24] drm/msm/mdp5: Clean up interface assignment

Message ID 20170323102817.15017-7-architt@codeaurora.org (mailing list archive)
State Not Applicable, archived
Delegated to: Andy Gross
Headers show

Commit Message

Archit Taneja March 23, 2017, 10:27 a.m. UTC
mdp5_interface struct contains data corresponding to a INTF
instance in MDP5 hardware. This sturct is memcpy'd to the
mdp5_encoder struct, and then later to the mdp5_ctl struct.

Instead of copying around interface data, create mdp5_interface
instances in mdp5_init, like how it's done currently done for
pipes and layer mixers. Pass around the interface pointers to
mdp5_encoder and mdp5_ctl. This simplifies the code, and allows
us to decouple encoders from INTFs in the future if needed.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c |  8 +--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c         | 21 ++----
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c     | 37 +++++------
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c         | 85 +++++++++++++++++--------
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h         |  6 +-
 5 files changed, 93 insertions(+), 64 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
index fd3cb45976f3..18c967107bc4 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
@@ -145,7 +145,7 @@  void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder,
 			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);
 }
 
@@ -153,7 +153,7 @@  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_interface *intf = mdp5_cmd_enc->intf;
 
 	if (WARN_ON(!mdp5_cmd_enc->enabled))
 		return;
@@ -172,7 +172,7 @@  void mdp5_cmd_encoder_enable(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_interface *intf = mdp5_cmd_enc->intf;
 
 	if (WARN_ON(mdp5_cmd_enc->enabled))
 		return;
@@ -200,7 +200,7 @@  int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder,
 		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
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
index fa4f27a1a551..ed184e5491b4 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
@@ -33,7 +33,7 @@ 
 #define CTL_STAT_BOOKED	0x2
 
 struct op_mode {
-	struct mdp5_interface intf;
+	struct mdp5_interface *intf;
 
 	bool encoder_enabled;
 	uint32_t start_mask;
@@ -180,16 +180,8 @@  int mdp5_ctl_set_pipeline(struct mdp5_ctl *ctl, struct mdp5_interface *intf,
 	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);
@@ -210,11 +202,11 @@  static bool start_signal_needed(struct mdp5_ctl *ctl)
 	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;
 	}
@@ -239,7 +231,7 @@  static void send_start_signal(struct mdp5_ctl *ctl)
 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);
 
@@ -265,7 +257,7 @@  int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl, bool enabled)
 		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);
@@ -621,7 +613,6 @@  struct mdp5_ctl *mdp5_ctlm_request(struct mdp5_ctl_manager *ctl_mgr,
 
 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;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index c2c204e6ea3b..2994841eb00c 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -109,7 +109,7 @@  static void mdp5_vid_encoder_mode_set(struct drm_encoder *encoder,
 	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;
@@ -130,7 +130,7 @@  static void mdp5_vid_encoder_mode_set(struct drm_encoder *encoder,
 	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)
@@ -175,7 +175,7 @@  static void mdp5_vid_encoder_mode_set(struct drm_encoder *encoder,
 	 * 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;
 	}
@@ -206,8 +206,8 @@  static void mdp5_vid_encoder_mode_set(struct drm_encoder *encoder,
 
 	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)
@@ -216,8 +216,8 @@  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))
@@ -250,8 +250,8 @@  static void mdp5_vid_encoder_enable(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_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))
@@ -273,7 +273,7 @@  static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
 				  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);
@@ -284,7 +284,7 @@  static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
 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);
@@ -295,7 +295,7 @@  static void mdp5_encoder_disable(struct drm_encoder *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);
@@ -313,7 +313,7 @@  int mdp5_encoder_get_linecount(struct drm_encoder *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));
 }
@@ -322,7 +322,7 @@  u32 mdp5_encoder_get_framecount(struct drm_encoder *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_FRAME_COUNT(intf));
 }
@@ -340,7 +340,7 @@  int mdp5_vid_encoder_set_split_display(struct drm_encoder *encoder,
 		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.
@@ -369,7 +369,7 @@  int mdp5_vid_encoder_set_split_display(struct drm_encoder *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) {
@@ -385,7 +385,8 @@  void mdp5_encoder_set_intf_mode(struct drm_encoder *encoder, bool 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;
@@ -399,9 +400,9 @@  struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
 		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);
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 1c6fbe7bc0ae..9dcd893a5c06 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -308,19 +308,14 @@  int mdp5_enable(struct mdp5_kms *mdp5_kms)
 }
 
 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;
@@ -349,32 +344,28 @@  static int get_dsi_id_from_intf(const struct mdp5_cfg_hw *hw_cfg, int intf_num)
 	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;
@@ -386,13 +377,13 @@  static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)
 		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;
@@ -402,11 +393,13 @@  static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)
 		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;
 		}
@@ -414,13 +407,13 @@  static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)
 		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;
@@ -430,7 +423,7 @@  static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)
 		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;
 	}
@@ -454,8 +447,8 @@  static int modeset_init(struct mdp5_kms *mdp5_kms)
 	 * 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;
 	}
@@ -786,6 +779,7 @@  struct msm_kms *mdp5_kms_init(struct drm_device *dev)
 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);
@@ -794,6 +788,9 @@  static void mdp5_destroy(struct platform_device *pdev)
 	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);
 
@@ -901,6 +898,38 @@  static int hwmixer_init(struct mdp5_kms *mdp5_kms)
 	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;
@@ -1017,6 +1046,10 @@  static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
 	if (ret)
 		goto fail;
 
+	ret = interface_init(mdp5_kms);
+	if (ret)
+		goto fail;
+
 	/* set uninit-ed kms */
 	priv->kms = &mdp5_kms->base.base;
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 041c131ae563..6452fc115030 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -43,6 +43,9 @@  struct mdp5_kms {
 	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) */
 
@@ -131,6 +134,7 @@  enum mdp5_intf_mode {
 };
 
 struct mdp5_interface {
+	int idx;
 	int num; /* display interface number */
 	enum mdp5_intf_type type;
 	enum mdp5_intf_mode mode;
@@ -138,11 +142,11 @@  struct mdp5_interface {
 
 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)