aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephane Viau <sviau@codeaurora.org>2015-03-13 15:49:32 -0400
committerRob Clark <robdclark@gmail.com>2015-04-01 19:29:34 -0400
commitd145dd78d7e72ac07c84f6919283569e6b45a5c3 (patch)
tree31881cd0904e3115b136b5ee4a3d84f31c4e76b7
parenta13cebabc81d709e1649c8d8475f0c0f66c0dd24 (diff)
drm/msm/mdp5: Enhance operation mode for pipeline configuration
DSI and WB interfaces need a more complex pipeline configuration than the current mdp5_ctl_set_intf(). For example, memory output connections need to be selected for WB. Interface mode (Video vs. Command modes) also need to be configured for DSI. This change takes care of configuring the whole pipeline as far as operation mode goes. DSI and WB interfaces will be added later. v2: rename macro to mdp5_cfg_intf_is_virtual() [pointed by Archit] Signed-off-by: Stephane Viau <sviau@codeaurora.org> [Remove temp bisectability hack -Rob] Signed-off-by: Rob Clark <robdclark@gmail.com>
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c39
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c91
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h3
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c29
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c16
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h51
7 files changed, 159 insertions, 74 deletions
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
index dba4d52cceeb..4e90740c9749 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
@@ -84,6 +84,10 @@ const struct mdp5_cfg_hw *mdp5_cfg_get_hw_config(struct mdp5_cfg_handler *cfg_hn
84struct mdp5_cfg *mdp5_cfg_get_config(struct mdp5_cfg_handler *cfg_hnd); 84struct mdp5_cfg *mdp5_cfg_get_config(struct mdp5_cfg_handler *cfg_hnd);
85int mdp5_cfg_get_hw_rev(struct mdp5_cfg_handler *cfg_hnd); 85int mdp5_cfg_get_hw_rev(struct mdp5_cfg_handler *cfg_hnd);
86 86
87#define mdp5_cfg_intf_is_virtual(intf_type) ({ \
88 typeof(intf_type) __val = (intf_type); \
89 (__val) >= INTF_VIRTUAL ? true : false; })
90
87struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms, 91struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms,
88 uint32_t major, uint32_t minor); 92 uint32_t major, uint32_t minor);
89void mdp5_cfg_destroy(struct mdp5_cfg_handler *cfg_hnd); 93void mdp5_cfg_destroy(struct mdp5_cfg_handler *cfg_hnd);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index bfba236daaa6..15136f17f8ce 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -611,48 +611,17 @@ void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
611} 611}
612 612
613/* set interface for routing crtc->encoder: */ 613/* set interface for routing crtc->encoder: */
614void mdp5_crtc_set_intf(struct drm_crtc *crtc, int intf, 614void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf)
615 enum mdp5_intf intf_id)
616{ 615{
617 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); 616 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
618 struct mdp5_kms *mdp5_kms = get_kms(crtc); 617 struct mdp5_kms *mdp5_kms = get_kms(crtc);
619 uint32_t intf_sel; 618 int lm = mdp5_crtc_get_lm(crtc);
620 unsigned long flags;
621 619
622 /* now that we know what irq's we want: */ 620 /* now that we know what irq's we want: */
623 mdp5_crtc->err.irqmask = intf2err(intf); 621 mdp5_crtc->err.irqmask = intf2err(intf->num);
624 mdp5_crtc->vblank.irqmask = intf2vblank(intf); 622 mdp5_crtc->vblank.irqmask = intf2vblank(lm, intf);
625 mdp_irq_update(&mdp5_kms->base); 623 mdp_irq_update(&mdp5_kms->base);
626 624
627 spin_lock_irqsave(&mdp5_kms->resource_lock, flags);
628 intf_sel = mdp5_read(mdp5_kms, REG_MDP5_DISP_INTF_SEL);
629
630 switch (intf) {
631 case 0:
632 intf_sel &= ~MDP5_DISP_INTF_SEL_INTF0__MASK;
633 intf_sel |= MDP5_DISP_INTF_SEL_INTF0(intf_id);
634 break;
635 case 1:
636 intf_sel &= ~MDP5_DISP_INTF_SEL_INTF1__MASK;
637 intf_sel |= MDP5_DISP_INTF_SEL_INTF1(intf_id);
638 break;
639 case 2:
640 intf_sel &= ~MDP5_DISP_INTF_SEL_INTF2__MASK;
641 intf_sel |= MDP5_DISP_INTF_SEL_INTF2(intf_id);
642 break;
643 case 3:
644 intf_sel &= ~MDP5_DISP_INTF_SEL_INTF3__MASK;
645 intf_sel |= MDP5_DISP_INTF_SEL_INTF3(intf_id);
646 break;
647 default:
648 BUG();
649 break;
650 }
651
652 mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, intf_sel);
653 spin_unlock_irqrestore(&mdp5_kms->resource_lock, flags);
654
655 DBG("%s: intf_sel=%08x", mdp5_crtc->name, intf_sel);
656 mdp5_ctl_set_intf(mdp5_crtc->ctl, intf); 625 mdp5_ctl_set_intf(mdp5_crtc->ctl, intf);
657} 626}
658 627
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
index 151129032d16..a548113a8f68 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
@@ -33,6 +33,16 @@
33 * requested by the client (in mdp5_crtc_mode_set()). 33 * requested by the client (in mdp5_crtc_mode_set()).
34 */ 34 */
35 35
36struct op_mode {
37 struct mdp5_interface intf;
38 /*
39 * TODO: add a state variable to control the pipeline
40 *
41 * eg: WB interface needs both buffer addresses to be committed +
42 * output buffers ready to be written into, before we can START.
43 */
44};
45
36struct mdp5_ctl { 46struct mdp5_ctl {
37 struct mdp5_ctl_manager *ctlm; 47 struct mdp5_ctl_manager *ctlm;
38 48
@@ -41,8 +51,8 @@ struct mdp5_ctl {
41 /* whether this CTL has been allocated or not: */ 51 /* whether this CTL has been allocated or not: */
42 bool busy; 52 bool busy;
43 53
44 /* memory output connection (@see mdp5_ctl_mode): */ 54 /* Operation Mode Configuration for the Pipeline */
45 u32 mode; 55 struct op_mode pipeline;
46 56
47 /* REG_MDP5_CTL_*(<id>) registers access info + lock: */ 57 /* REG_MDP5_CTL_*(<id>) registers access info + lock: */
48 spinlock_t hw_lock; 58 spinlock_t hw_lock;
@@ -94,19 +104,81 @@ u32 ctl_read(struct mdp5_ctl *ctl, u32 reg)
94 return mdp5_read(mdp5_kms, reg); 104 return mdp5_read(mdp5_kms, reg);
95} 105}
96 106
107static void set_display_intf(struct mdp5_kms *mdp5_kms,
108 struct mdp5_interface *intf)
109{
110 unsigned long flags;
111 u32 intf_sel;
112
113 spin_lock_irqsave(&mdp5_kms->resource_lock, flags);
114 intf_sel = mdp5_read(mdp5_kms, REG_MDP5_DISP_INTF_SEL);
115
116 switch (intf->num) {
117 case 0:
118 intf_sel &= ~MDP5_DISP_INTF_SEL_INTF0__MASK;
119 intf_sel |= MDP5_DISP_INTF_SEL_INTF0(intf->type);
120 break;
121 case 1:
122 intf_sel &= ~MDP5_DISP_INTF_SEL_INTF1__MASK;
123 intf_sel |= MDP5_DISP_INTF_SEL_INTF1(intf->type);
124 break;
125 case 2:
126 intf_sel &= ~MDP5_DISP_INTF_SEL_INTF2__MASK;
127 intf_sel |= MDP5_DISP_INTF_SEL_INTF2(intf->type);
128 break;
129 case 3:
130 intf_sel &= ~MDP5_DISP_INTF_SEL_INTF3__MASK;
131 intf_sel |= MDP5_DISP_INTF_SEL_INTF3(intf->type);
132 break;
133 default:
134 BUG();
135 break;
136 }
137
138 mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, intf_sel);
139 spin_unlock_irqrestore(&mdp5_kms->resource_lock, flags);
140}
97 141
98int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, int intf) 142static void set_ctl_op(struct mdp5_ctl *ctl, struct mdp5_interface *intf)
99{ 143{
100 unsigned long flags; 144 unsigned long flags;
101 static const enum mdp5_intfnum intfnum[] = { 145 u32 ctl_op = 0;
102 INTF0, INTF1, INTF2, INTF3, 146
103 }; 147 if (!mdp5_cfg_intf_is_virtual(intf->type))
148 ctl_op |= MDP5_CTL_OP_INTF_NUM(INTF0 + intf->num);
149
150 switch (intf->type) {
151 case INTF_DSI:
152 if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
153 ctl_op |= MDP5_CTL_OP_CMD_MODE;
154 break;
155
156 case INTF_WB:
157 if (intf->mode == MDP5_INTF_WB_MODE_LINE)
158 ctl_op |= MDP5_CTL_OP_MODE(MODE_WB_2_LINE);
159 break;
160
161 default:
162 break;
163 }
104 164
105 spin_lock_irqsave(&ctl->hw_lock, flags); 165 spin_lock_irqsave(&ctl->hw_lock, flags);
106 ctl_write(ctl, REG_MDP5_CTL_OP(ctl->id), 166 ctl_write(ctl, REG_MDP5_CTL_OP(ctl->id), ctl_op);
107 MDP5_CTL_OP_MODE(ctl->mode) |
108 MDP5_CTL_OP_INTF_NUM(intfnum[intf]));
109 spin_unlock_irqrestore(&ctl->hw_lock, flags); 167 spin_unlock_irqrestore(&ctl->hw_lock, flags);
168}
169
170int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, struct mdp5_interface *intf)
171{
172 struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
173 struct mdp5_kms *mdp5_kms = get_kms(ctl_mgr);
174
175 memcpy(&ctl->pipeline.intf, intf, sizeof(*intf));
176
177 /* Virtual interfaces need not set a display intf (e.g.: Writeback) */
178 if (!mdp5_cfg_intf_is_virtual(intf->type))
179 set_display_intf(mdp5_kms, intf);
180
181 set_ctl_op(ctl, intf);
110 182
111 return 0; 183 return 0;
112} 184}
@@ -303,7 +375,6 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev,
303 } 375 }
304 ctl->ctlm = ctl_mgr; 376 ctl->ctlm = ctl_mgr;
305 ctl->id = c; 377 ctl->id = c;
306 ctl->mode = MODE_NONE;
307 ctl->reg_offset = ctl_cfg->base[c]; 378 ctl->reg_offset = ctl_cfg->base[c];
308 ctl->flush_mask = MDP5_CTL_FLUSH_CTL; 379 ctl->flush_mask = MDP5_CTL_FLUSH_CTL;
309 ctl->busy = false; 380 ctl->busy = false;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
index ad48788efeea..271d5ac429be 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
@@ -34,7 +34,8 @@ void mdp5_ctlm_destroy(struct mdp5_ctl_manager *ctlm);
34 */ 34 */
35struct mdp5_ctl *mdp5_ctlm_request(struct mdp5_ctl_manager *ctlm, struct drm_crtc *crtc); 35struct mdp5_ctl *mdp5_ctlm_request(struct mdp5_ctl_manager *ctlm, struct drm_crtc *crtc);
36 36
37int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, int intf); 37struct mdp5_interface;
38int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, struct mdp5_interface *intf);
38 39
39int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, bool enable); 40int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, bool enable);
40 41
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index af0e02fa4f48..b18b381502a3 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -23,8 +23,7 @@
23 23
24struct mdp5_encoder { 24struct mdp5_encoder {
25 struct drm_encoder base; 25 struct drm_encoder base;
26 int intf; 26 struct mdp5_interface intf;
27 enum mdp5_intf intf_id;
28 spinlock_t intf_lock; /* protect REG_MDP5_INTF_* registers */ 27 spinlock_t intf_lock; /* protect REG_MDP5_INTF_* registers */
29 bool enabled; 28 bool enabled;
30 uint32_t bsc; 29 uint32_t bsc;
@@ -126,7 +125,7 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
126 struct mdp5_kms *mdp5_kms = get_kms(encoder); 125 struct mdp5_kms *mdp5_kms = get_kms(encoder);
127 struct drm_device *dev = encoder->dev; 126 struct drm_device *dev = encoder->dev;
128 struct drm_connector *connector; 127 struct drm_connector *connector;
129 int intf = mdp5_encoder->intf; 128 int intf = mdp5_encoder->intf.num;
130 uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol; 129 uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
131 uint32_t display_v_start, display_v_end; 130 uint32_t display_v_start, display_v_end;
132 uint32_t hsync_start_x, hsync_end_x; 131 uint32_t hsync_start_x, hsync_end_x;
@@ -188,7 +187,7 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
188 * DISPLAY_V_START = (VBP * HCYCLE) + HBP 187 * DISPLAY_V_START = (VBP * HCYCLE) + HBP
189 * DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP 188 * DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP
190 */ 189 */
191 if (mdp5_encoder->intf_id == INTF_eDP) { 190 if (mdp5_encoder->intf.type == INTF_eDP) {
192 display_v_start += mode->htotal - mode->hsync_start; 191 display_v_start += mode->htotal - mode->hsync_start;
193 display_v_end -= mode->hsync_start - mode->hdisplay; 192 display_v_end -= mode->hsync_start - mode->hdisplay;
194 } 193 }
@@ -224,14 +223,16 @@ static void mdp5_encoder_disable(struct drm_encoder *encoder)
224{ 223{
225 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); 224 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
226 struct mdp5_kms *mdp5_kms = get_kms(encoder); 225 struct mdp5_kms *mdp5_kms = get_kms(encoder);
227 int intf = mdp5_encoder->intf; 226 int lm = mdp5_crtc_get_lm(encoder->crtc);
227 struct mdp5_interface *intf = &mdp5_encoder->intf;
228 int intfn = mdp5_encoder->intf.num;
228 unsigned long flags; 229 unsigned long flags;
229 230
230 if (WARN_ON(!mdp5_encoder->enabled)) 231 if (WARN_ON(!mdp5_encoder->enabled))
231 return; 232 return;
232 233
233 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); 234 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
234 mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 0); 235 mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 0);
235 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); 236 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
236 237
237 /* 238 /*
@@ -242,7 +243,7 @@ static void mdp5_encoder_disable(struct drm_encoder *encoder)
242 * the settings changes for the new modeset (like new 243 * the settings changes for the new modeset (like new
243 * scanout buffer) don't latch properly.. 244 * scanout buffer) don't latch properly..
244 */ 245 */
245 mdp_irq_wait(&mdp5_kms->base, intf2vblank(intf)); 246 mdp_irq_wait(&mdp5_kms->base, intf2vblank(lm, intf));
246 247
247 bs_set(mdp5_encoder, 0); 248 bs_set(mdp5_encoder, 0);
248 249
@@ -253,18 +254,17 @@ static void mdp5_encoder_enable(struct drm_encoder *encoder)
253{ 254{
254 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); 255 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
255 struct mdp5_kms *mdp5_kms = get_kms(encoder); 256 struct mdp5_kms *mdp5_kms = get_kms(encoder);
256 int intf = mdp5_encoder->intf; 257 int intfn = mdp5_encoder->intf.num;
257 unsigned long flags; 258 unsigned long flags;
258 259
259 if (WARN_ON(mdp5_encoder->enabled)) 260 if (WARN_ON(mdp5_encoder->enabled))
260 return; 261 return;
261 262
262 mdp5_crtc_set_intf(encoder->crtc, mdp5_encoder->intf, 263 mdp5_crtc_set_intf(encoder->crtc, &mdp5_encoder->intf);
263 mdp5_encoder->intf_id);
264 264
265 bs_set(mdp5_encoder, 1); 265 bs_set(mdp5_encoder, 1);
266 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); 266 spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
267 mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1); 267 mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 1);
268 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); 268 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
269 269
270 mdp5_encoder->enabled = true; 270 mdp5_encoder->enabled = true;
@@ -278,8 +278,8 @@ static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = {
278}; 278};
279 279
280/* initialize encoder */ 280/* initialize encoder */
281struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, int intf, 281struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
282 enum mdp5_intf intf_id) 282 struct mdp5_interface *intf)
283{ 283{
284 struct drm_encoder *encoder = NULL; 284 struct drm_encoder *encoder = NULL;
285 struct mdp5_encoder *mdp5_encoder; 285 struct mdp5_encoder *mdp5_encoder;
@@ -291,8 +291,7 @@ struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, int intf,
291 goto fail; 291 goto fail;
292 } 292 }
293 293
294 mdp5_encoder->intf = intf; 294 memcpy(&mdp5_encoder->intf, intf, sizeof(mdp5_encoder->intf));
295 mdp5_encoder->intf_id = intf_id;
296 encoder = &mdp5_encoder->base; 295 encoder = &mdp5_encoder->base;
297 296
298 spin_lock_init(&mdp5_encoder->intf_lock); 297 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 92b61db5754c..390d9d2b6882 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -223,8 +223,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
223 } 223 }
224 224
225 if (priv->hdmi) { 225 if (priv->hdmi) {
226 struct mdp5_interface intf = {
227 .num = 3,
228 .type = INTF_HDMI,
229 .mode = MDP5_INTF_MODE_NONE,
230 };
231
226 /* Construct encoder for HDMI: */ 232 /* Construct encoder for HDMI: */
227 encoder = mdp5_encoder_init(dev, 3, INTF_HDMI); 233 encoder = mdp5_encoder_init(dev, &intf);
228 if (IS_ERR(encoder)) { 234 if (IS_ERR(encoder)) {
229 dev_err(dev->dev, "failed to construct encoder\n"); 235 dev_err(dev->dev, "failed to construct encoder\n");
230 ret = PTR_ERR(encoder); 236 ret = PTR_ERR(encoder);
@@ -242,8 +248,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
242 } 248 }
243 249
244 if (priv->edp) { 250 if (priv->edp) {
251 struct mdp5_interface intf = {
252 .num = 0,
253 .type = INTF_eDP,
254 .mode = MDP5_INTF_MODE_NONE,
255 };
256
245 /* Construct encoder for eDP: */ 257 /* Construct encoder for eDP: */
246 encoder = mdp5_encoder_init(dev, 0, INTF_eDP); 258 encoder = mdp5_encoder_init(dev, &intf);
247 if (IS_ERR(encoder)) { 259 if (IS_ERR(encoder)) {
248 dev_err(dev->dev, "failed to construct eDP encoder\n"); 260 dev_err(dev->dev, "failed to construct eDP encoder\n");
249 ret = PTR_ERR(encoder); 261 ret = PTR_ERR(encoder);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index f30a700d04bf..1a6aa494d92f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -26,9 +26,6 @@
26#include "mdp5_ctl.h" 26#include "mdp5_ctl.h"
27#include "mdp5_smp.h" 27#include "mdp5_smp.h"
28 28
29/* temporary compat for enum name change: */
30#define mdp5_intf mdp5_intf_type
31
32struct mdp5_kms { 29struct mdp5_kms {
33 struct mdp_kms base; 30 struct mdp_kms base;
34 31
@@ -97,6 +94,24 @@ struct mdp5_plane_state {
97#define to_mdp5_plane_state(x) \ 94#define to_mdp5_plane_state(x) \
98 container_of(x, struct mdp5_plane_state, base) 95 container_of(x, struct mdp5_plane_state, base)
99 96
97enum mdp5_intf_mode {
98 MDP5_INTF_MODE_NONE = 0,
99
100 /* Modes used for DSI interface (INTF_DSI type): */
101 MDP5_INTF_DSI_MODE_VIDEO,
102 MDP5_INTF_DSI_MODE_COMMAND,
103
104 /* Modes used for WB interface (INTF_WB type): */
105 MDP5_INTF_WB_MODE_BLOCK,
106 MDP5_INTF_WB_MODE_LINE,
107};
108
109struct mdp5_interface {
110 int num; /* display interface number */
111 enum mdp5_intf_type type;
112 enum mdp5_intf_mode mode;
113};
114
100static inline void mdp5_write(struct mdp5_kms *mdp5_kms, u32 reg, u32 data) 115static inline void mdp5_write(struct mdp5_kms *mdp5_kms, u32 reg, u32 data)
101{ 116{
102 msm_writel(data, mdp5_kms->mmio + reg); 117 msm_writel(data, mdp5_kms->mmio + reg);
@@ -133,9 +148,9 @@ static inline int pipe2nclients(enum mdp5_pipe pipe)
133 } 148 }
134} 149}
135 150
136static inline uint32_t intf2err(int intf) 151static inline uint32_t intf2err(int intf_num)
137{ 152{
138 switch (intf) { 153 switch (intf_num) {
139 case 0: return MDP5_IRQ_INTF0_UNDER_RUN; 154 case 0: return MDP5_IRQ_INTF0_UNDER_RUN;
140 case 1: return MDP5_IRQ_INTF1_UNDER_RUN; 155 case 1: return MDP5_IRQ_INTF1_UNDER_RUN;
141 case 2: return MDP5_IRQ_INTF2_UNDER_RUN; 156 case 2: return MDP5_IRQ_INTF2_UNDER_RUN;
@@ -144,9 +159,24 @@ static inline uint32_t intf2err(int intf)
144 } 159 }
145} 160}
146 161
147static inline uint32_t intf2vblank(int intf) 162static inline uint32_t intf2vblank(int lm, struct mdp5_interface *intf)
148{ 163{
149 switch (intf) { 164#define GET_PING_PONG_ID(layer_mixer) ((layer_mixer == 5) ? 3 : layer_mixer)
165
166 /*
167 * In case of DSI Command Mode, the Ping Pong's read pointer IRQ
168 * acts as a Vblank signal. The Ping Pong buffer used is bound to
169 * layer mixer.
170 */
171
172 if ((intf->type == INTF_DSI) &&
173 (intf->mode == MDP5_INTF_DSI_MODE_COMMAND))
174 return MDP5_IRQ_PING_PONG_0_RD_PTR << GET_PING_PONG_ID(lm);
175
176 if (intf->type == INTF_WB)
177 return MDP5_IRQ_WB_2_DONE;
178
179 switch (intf->num) {
150 case 0: return MDP5_IRQ_INTF0_VSYNC; 180 case 0: return MDP5_IRQ_INTF0_VSYNC;
151 case 1: return MDP5_IRQ_INTF1_VSYNC; 181 case 1: return MDP5_IRQ_INTF1_VSYNC;
152 case 2: return MDP5_IRQ_INTF2_VSYNC; 182 case 2: return MDP5_IRQ_INTF2_VSYNC;
@@ -201,12 +231,11 @@ uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
201 231
202int mdp5_crtc_get_lm(struct drm_crtc *crtc); 232int mdp5_crtc_get_lm(struct drm_crtc *crtc);
203void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file); 233void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
204void mdp5_crtc_set_intf(struct drm_crtc *crtc, int intf, 234void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf);
205 enum mdp5_intf intf_id);
206struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, 235struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
207 struct drm_plane *plane, int id); 236 struct drm_plane *plane, int id);
208 237
209struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, int intf, 238struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
210 enum mdp5_intf intf_id); 239 struct mdp5_interface *intf);
211 240
212#endif /* __MDP5_KMS_H__ */ 241#endif /* __MDP5_KMS_H__ */