aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm
diff options
context:
space:
mode:
authorHai Li <hali@codeaurora.org>2015-06-26 16:03:25 -0400
committerRob Clark <robdclark@gmail.com>2015-08-15 18:27:16 -0400
commitc71716b17bc772e9c38f85a4b496bbfac0dd32f0 (patch)
tree06b551c9d06a7edad0d12841b094e99a20855198 /drivers/gpu/drm/msm
parent129877819c0a5f8d419fe67ae08a8a7c811afa5e (diff)
drm/msm/mdp5: Allocate CTL for each display interface
In MDP5, CTL contains information of the whole pipeline whose output goes down to a display interface. In various cases, one interface may require 2 CRTCs, but only one CTL. Some interfaces also require to use certain CTLs. Instead of allocating CTL for each active CRTC, this change is to associate a CTL with each interface. Signed-off-by: Hai Li <hali@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm')
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c12
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c25
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c53
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h9
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c12
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c36
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h12
7 files changed, 80 insertions, 79 deletions
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 ee31b16fe7ea..8e6c9b598a57 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
@@ -21,6 +21,8 @@ struct mdp5_cmd_encoder {
21 struct mdp5_interface intf; 21 struct mdp5_interface intf;
22 bool enabled; 22 bool enabled;
23 uint32_t bsc; 23 uint32_t bsc;
24
25 struct mdp5_ctl *ctl;
24}; 26};
25#define to_mdp5_cmd_encoder(x) container_of(x, struct mdp5_cmd_encoder, base) 27#define to_mdp5_cmd_encoder(x) container_of(x, struct mdp5_cmd_encoder, base)
26 28
@@ -210,13 +212,14 @@ static void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder,
210 mode->vsync_end, mode->vtotal, 212 mode->vsync_end, mode->vtotal,
211 mode->type, mode->flags); 213 mode->type, mode->flags);
212 pingpong_tearcheck_setup(encoder, mode); 214 pingpong_tearcheck_setup(encoder, mode);
213 mdp5_crtc_set_intf(encoder->crtc, &mdp5_cmd_enc->intf); 215 mdp5_crtc_set_pipeline(encoder->crtc, &mdp5_cmd_enc->intf,
216 mdp5_cmd_enc->ctl);
214} 217}
215 218
216static void mdp5_cmd_encoder_disable(struct drm_encoder *encoder) 219static void mdp5_cmd_encoder_disable(struct drm_encoder *encoder)
217{ 220{
218 struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder); 221 struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
219 struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc); 222 struct mdp5_ctl *ctl = mdp5_cmd_enc->ctl;
220 struct mdp5_interface *intf = &mdp5_cmd_enc->intf; 223 struct mdp5_interface *intf = &mdp5_cmd_enc->intf;
221 224
222 if (WARN_ON(!mdp5_cmd_enc->enabled)) 225 if (WARN_ON(!mdp5_cmd_enc->enabled))
@@ -235,7 +238,7 @@ static void mdp5_cmd_encoder_disable(struct drm_encoder *encoder)
235static void mdp5_cmd_encoder_enable(struct drm_encoder *encoder) 238static void mdp5_cmd_encoder_enable(struct drm_encoder *encoder)
236{ 239{
237 struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder); 240 struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
238 struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc); 241 struct mdp5_ctl *ctl = mdp5_cmd_enc->ctl;
239 struct mdp5_interface *intf = &mdp5_cmd_enc->intf; 242 struct mdp5_interface *intf = &mdp5_cmd_enc->intf;
240 243
241 if (WARN_ON(mdp5_cmd_enc->enabled)) 244 if (WARN_ON(mdp5_cmd_enc->enabled))
@@ -300,7 +303,7 @@ int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder,
300 303
301/* initialize command mode encoder */ 304/* initialize command mode encoder */
302struct drm_encoder *mdp5_cmd_encoder_init(struct drm_device *dev, 305struct drm_encoder *mdp5_cmd_encoder_init(struct drm_device *dev,
303 struct mdp5_interface *intf) 306 struct mdp5_interface *intf, struct mdp5_ctl *ctl)
304{ 307{
305 struct drm_encoder *encoder = NULL; 308 struct drm_encoder *encoder = NULL;
306 struct mdp5_cmd_encoder *mdp5_cmd_enc; 309 struct mdp5_cmd_encoder *mdp5_cmd_enc;
@@ -320,6 +323,7 @@ struct drm_encoder *mdp5_cmd_encoder_init(struct drm_device *dev,
320 323
321 memcpy(&mdp5_cmd_enc->intf, intf, sizeof(mdp5_cmd_enc->intf)); 324 memcpy(&mdp5_cmd_enc->intf, intf, sizeof(mdp5_cmd_enc->intf));
322 encoder = &mdp5_cmd_enc->base; 325 encoder = &mdp5_cmd_enc->base;
326 mdp5_cmd_enc->ctl = ctl;
323 327
324 drm_encoder_init(dev, encoder, &mdp5_cmd_encoder_funcs, 328 drm_encoder_init(dev, encoder, &mdp5_cmd_encoder_funcs,
325 DRM_MODE_ENCODER_DSI); 329 DRM_MODE_ENCODER_DSI);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 572f57927595..7f9f4ac88029 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -160,8 +160,7 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
160 160
161 if (mdp5_crtc->ctl && !crtc->state->enable) { 161 if (mdp5_crtc->ctl && !crtc->state->enable) {
162 /* set STAGE_UNUSED for all layers */ 162 /* set STAGE_UNUSED for all layers */
163 mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, NULL, 0, 0); 163 mdp5_ctl_blend(mdp5_crtc->ctl, NULL, 0, 0);
164 mdp5_ctl_release(mdp5_crtc->ctl);
165 mdp5_crtc->ctl = NULL; 164 mdp5_crtc->ctl = NULL;
166 } 165 }
167} 166}
@@ -289,7 +288,7 @@ static void blend_setup(struct drm_crtc *crtc)
289 blender(i)), bg_alpha); 288 blender(i)), bg_alpha);
290 } 289 }
291 290
292 mdp5_ctl_blend(mdp5_crtc->ctl, lm, stage, plane_cnt, ctl_blend_flags); 291 mdp5_ctl_blend(mdp5_crtc->ctl, stage, plane_cnt, ctl_blend_flags);
293 292
294out: 293out:
295 spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags); 294 spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags);
@@ -386,13 +385,6 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
386 385
387 DBG("%s: check", mdp5_crtc->name); 386 DBG("%s: check", mdp5_crtc->name);
388 387
389 /* request a free CTL, if none is already allocated for this CRTC */
390 if (state->enable && !mdp5_crtc->ctl) {
391 mdp5_crtc->ctl = mdp5_ctlm_request(mdp5_kms->ctlm, crtc);
392 if (WARN_ON(!mdp5_crtc->ctl))
393 return -EINVAL;
394 }
395
396 /* verify that there are not too many planes attached to crtc 388 /* verify that there are not too many planes attached to crtc
397 * and that we don't have conflicting mixer stages: 389 * and that we don't have conflicting mixer stages:
398 */ 390 */
@@ -735,8 +727,8 @@ void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
735 complete_flip(crtc, file); 727 complete_flip(crtc, file);
736} 728}
737 729
738/* set interface for routing crtc->encoder: */ 730void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,
739void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf) 731 struct mdp5_interface *intf, struct mdp5_ctl *ctl)
740{ 732{
741 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); 733 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
742 struct mdp5_kms *mdp5_kms = get_kms(crtc); 734 struct mdp5_kms *mdp5_kms = get_kms(crtc);
@@ -759,7 +751,8 @@ void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf)
759 751
760 mdp_irq_update(&mdp5_kms->base); 752 mdp_irq_update(&mdp5_kms->base);
761 753
762 mdp5_ctl_set_intf(mdp5_crtc->ctl, intf); 754 mdp5_crtc->ctl = ctl;
755 mdp5_ctl_set_pipeline(ctl, intf, lm);
763} 756}
764 757
765int mdp5_crtc_get_lm(struct drm_crtc *crtc) 758int mdp5_crtc_get_lm(struct drm_crtc *crtc)
@@ -768,12 +761,6 @@ int mdp5_crtc_get_lm(struct drm_crtc *crtc)
768 return WARN_ON(!crtc) ? -EINVAL : mdp5_crtc->lm; 761 return WARN_ON(!crtc) ? -EINVAL : mdp5_crtc->lm;
769} 762}
770 763
771struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc)
772{
773 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
774 return WARN_ON(!crtc) ? NULL : mdp5_crtc->ctl;
775}
776
777void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc) 764void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc)
778{ 765{
779 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); 766 struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
index 622849bbc346..9cf987bb0b09 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
@@ -60,8 +60,6 @@ struct mdp5_ctl {
60 u32 pending_ctl_trigger; 60 u32 pending_ctl_trigger;
61 61
62 bool cursor_on; 62 bool cursor_on;
63
64 struct drm_crtc *crtc;
65}; 63};
66 64
67struct mdp5_ctl_manager { 65struct mdp5_ctl_manager {
@@ -168,11 +166,21 @@ static void set_ctl_op(struct mdp5_ctl *ctl, struct mdp5_interface *intf)
168 spin_unlock_irqrestore(&ctl->hw_lock, flags); 166 spin_unlock_irqrestore(&ctl->hw_lock, flags);
169} 167}
170 168
171int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, struct mdp5_interface *intf) 169int mdp5_ctl_set_pipeline(struct mdp5_ctl *ctl,
170 struct mdp5_interface *intf, int lm)
172{ 171{
173 struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm; 172 struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
174 struct mdp5_kms *mdp5_kms = get_kms(ctl_mgr); 173 struct mdp5_kms *mdp5_kms = get_kms(ctl_mgr);
175 174
175 if (unlikely(WARN_ON(intf->num != ctl->pipeline.intf.num))) {
176 dev_err(mdp5_kms->dev->dev,
177 "CTL %d is allocated by INTF %d, but used by INTF %d\n",
178 ctl->id, ctl->pipeline.intf.num, intf->num);
179 return -EINVAL;
180 }
181
182 ctl->lm = lm;
183
176 memcpy(&ctl->pipeline.intf, intf, sizeof(*intf)); 184 memcpy(&ctl->pipeline.intf, intf, sizeof(*intf));
177 185
178 ctl->pipeline.start_mask = mdp_ctl_flush_mask_lm(ctl->lm) | 186 ctl->pipeline.start_mask = mdp_ctl_flush_mask_lm(ctl->lm) |
@@ -335,7 +343,7 @@ static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe,
335 } 343 }
336} 344}
337 345
338int mdp5_ctl_blend(struct mdp5_ctl *ctl, u32 lm, u8 *stage, u32 stage_cnt, 346int mdp5_ctl_blend(struct mdp5_ctl *ctl, u8 *stage, u32 stage_cnt,
339 u32 ctl_blend_op_flags) 347 u32 ctl_blend_op_flags)
340{ 348{
341 unsigned long flags; 349 unsigned long flags;
@@ -358,13 +366,13 @@ int mdp5_ctl_blend(struct mdp5_ctl *ctl, u32 lm, u8 *stage, u32 stage_cnt,
358 if (ctl->cursor_on) 366 if (ctl->cursor_on)
359 blend_cfg |= MDP5_CTL_LAYER_REG_CURSOR_OUT; 367 blend_cfg |= MDP5_CTL_LAYER_REG_CURSOR_OUT;
360 368
361 ctl_write(ctl, REG_MDP5_CTL_LAYER_REG(ctl->id, lm), blend_cfg); 369 ctl_write(ctl, REG_MDP5_CTL_LAYER_REG(ctl->id, ctl->lm), blend_cfg);
362 ctl_write(ctl, REG_MDP5_CTL_LAYER_EXT_REG(ctl->id, lm), blend_ext_cfg); 370 ctl_write(ctl, REG_MDP5_CTL_LAYER_EXT_REG(ctl->id, ctl->lm), blend_ext_cfg);
363 spin_unlock_irqrestore(&ctl->hw_lock, flags); 371 spin_unlock_irqrestore(&ctl->hw_lock, flags);
364 372
365 ctl->pending_ctl_trigger = mdp_ctl_flush_mask_lm(lm); 373 ctl->pending_ctl_trigger = mdp_ctl_flush_mask_lm(ctl->lm);
366 374
367 DBG("lm%d: blend config = 0x%08x. ext_cfg = 0x%08x", lm, 375 DBG("lm%d: blend config = 0x%08x. ext_cfg = 0x%08x", ctl->lm,
368 blend_cfg, blend_ext_cfg); 376 blend_cfg, blend_ext_cfg);
369 377
370 return 0; 378 return 0;
@@ -490,38 +498,18 @@ u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl)
490 return ctl_read(ctl, REG_MDP5_CTL_FLUSH(ctl->id)); 498 return ctl_read(ctl, REG_MDP5_CTL_FLUSH(ctl->id));
491} 499}
492 500
493void mdp5_ctl_release(struct mdp5_ctl *ctl)
494{
495 struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
496 unsigned long flags;
497
498 if (unlikely(WARN_ON(ctl->id >= MAX_CTL) || !ctl->busy)) {
499 dev_err(ctl_mgr->dev->dev, "CTL %d in bad state (%d)",
500 ctl->id, ctl->busy);
501 return;
502 }
503
504 spin_lock_irqsave(&ctl_mgr->pool_lock, flags);
505 ctl->busy = false;
506 spin_unlock_irqrestore(&ctl_mgr->pool_lock, flags);
507
508 DBG("CTL %d released", ctl->id);
509}
510
511int mdp5_ctl_get_ctl_id(struct mdp5_ctl *ctl) 501int mdp5_ctl_get_ctl_id(struct mdp5_ctl *ctl)
512{ 502{
513 return WARN_ON(!ctl) ? -EINVAL : ctl->id; 503 return WARN_ON(!ctl) ? -EINVAL : ctl->id;
514} 504}
515 505
516/* 506/*
517 * mdp5_ctl_request() - CTL dynamic allocation 507 * mdp5_ctl_request() - CTL allocation
518 *
519 * Note: Current implementation considers that we can only have one CRTC per CTL
520 * 508 *
521 * @return first free CTL 509 * @return first free CTL
522 */ 510 */
523struct mdp5_ctl *mdp5_ctlm_request(struct mdp5_ctl_manager *ctl_mgr, 511struct mdp5_ctl *mdp5_ctlm_request(struct mdp5_ctl_manager *ctl_mgr,
524 struct drm_crtc *crtc) 512 int intf_num)
525{ 513{
526 struct mdp5_ctl *ctl = NULL; 514 struct mdp5_ctl *ctl = NULL;
527 unsigned long flags; 515 unsigned long flags;
@@ -539,9 +527,8 @@ struct mdp5_ctl *mdp5_ctlm_request(struct mdp5_ctl_manager *ctl_mgr,
539 } 527 }
540 528
541 ctl = &ctl_mgr->ctls[c]; 529 ctl = &ctl_mgr->ctls[c];
542 530 ctl->pipeline.intf.num = intf_num;
543 ctl->lm = mdp5_crtc_get_lm(crtc); 531 ctl->lm = -1;
544 ctl->crtc = crtc;
545 ctl->busy = true; 532 ctl->busy = true;
546 ctl->pending_ctl_trigger = 0; 533 ctl->pending_ctl_trigger = 0;
547 DBG("CTL %d allocated", ctl->id); 534 DBG("CTL %d allocated", ctl->id);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
index ab52675d2bd0..5f473fa3aa50 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
@@ -32,11 +32,12 @@ void mdp5_ctlm_destroy(struct mdp5_ctl_manager *ctlm);
32 * mdp5_ctl_request(ctlm, ...) returns a ctl (CTL resource) handler, 32 * mdp5_ctl_request(ctlm, ...) returns a ctl (CTL resource) handler,
33 * which is then used to call the other mdp5_ctl_*(ctl, ...) functions. 33 * which is then used to call the other mdp5_ctl_*(ctl, ...) functions.
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, int intf_num);
36int mdp5_ctl_get_ctl_id(struct mdp5_ctl *ctl); 36int mdp5_ctl_get_ctl_id(struct mdp5_ctl *ctl);
37 37
38struct mdp5_interface; 38struct mdp5_interface;
39int mdp5_ctl_set_intf(struct mdp5_ctl *ctl, struct mdp5_interface *intf); 39int mdp5_ctl_set_pipeline(struct mdp5_ctl *ctl, struct mdp5_interface *intf,
40 int lm);
40int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl, bool enabled); 41int mdp5_ctl_set_encoder_state(struct mdp5_ctl *ctl, bool enabled);
41 42
42int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, int cursor_id, bool enable); 43int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, int cursor_id, bool enable);
@@ -53,7 +54,7 @@ int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, int cursor_id, bool enable);
53 * (call mdp5_ctl_commit() with mdp_ctl_flush_mask_ctl() mask) 54 * (call mdp5_ctl_commit() with mdp_ctl_flush_mask_ctl() mask)
54 */ 55 */
55#define MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT BIT(0) 56#define MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT BIT(0)
56int mdp5_ctl_blend(struct mdp5_ctl *ctl, u32 lm, u8 *stage, u32 stage_cnt, 57int mdp5_ctl_blend(struct mdp5_ctl *ctl, u8 *stage, u32 stage_cnt,
57 u32 ctl_blend_op_flags); 58 u32 ctl_blend_op_flags);
58 59
59/** 60/**
@@ -71,8 +72,6 @@ u32 mdp_ctl_flush_mask_encoder(struct mdp5_interface *intf);
71u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask); 72u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask);
72u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl); 73u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl);
73 74
74void mdp5_ctl_release(struct mdp5_ctl *ctl);
75
76 75
77 76
78#endif /* __MDP5_CTL_H__ */ 77#endif /* __MDP5_CTL_H__ */
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index de97c08f3f1f..3fa19138b388 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -27,6 +27,8 @@ struct mdp5_encoder {
27 spinlock_t intf_lock; /* protect REG_MDP5_INTF_* registers */ 27 spinlock_t intf_lock; /* protect REG_MDP5_INTF_* registers */
28 bool enabled; 28 bool enabled;
29 uint32_t bsc; 29 uint32_t bsc;
30
31 struct mdp5_ctl *ctl;
30}; 32};
31#define to_mdp5_encoder(x) container_of(x, struct mdp5_encoder, base) 33#define to_mdp5_encoder(x) container_of(x, struct mdp5_encoder, base)
32 34
@@ -222,14 +224,15 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
222 224
223 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); 225 spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
224 226
225 mdp5_crtc_set_intf(encoder->crtc, &mdp5_encoder->intf); 227 mdp5_crtc_set_pipeline(encoder->crtc, &mdp5_encoder->intf,
228 mdp5_encoder->ctl);
226} 229}
227 230
228static void mdp5_encoder_disable(struct drm_encoder *encoder) 231static void mdp5_encoder_disable(struct drm_encoder *encoder)
229{ 232{
230 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); 233 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
231 struct mdp5_kms *mdp5_kms = get_kms(encoder); 234 struct mdp5_kms *mdp5_kms = get_kms(encoder);
232 struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc); 235 struct mdp5_ctl *ctl = mdp5_encoder->ctl;
233 int lm = mdp5_crtc_get_lm(encoder->crtc); 236 int lm = mdp5_crtc_get_lm(encoder->crtc);
234 struct mdp5_interface *intf = &mdp5_encoder->intf; 237 struct mdp5_interface *intf = &mdp5_encoder->intf;
235 int intfn = mdp5_encoder->intf.num; 238 int intfn = mdp5_encoder->intf.num;
@@ -264,7 +267,7 @@ static void mdp5_encoder_enable(struct drm_encoder *encoder)
264{ 267{
265 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); 268 struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
266 struct mdp5_kms *mdp5_kms = get_kms(encoder); 269 struct mdp5_kms *mdp5_kms = get_kms(encoder);
267 struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc); 270 struct mdp5_ctl *ctl = mdp5_encoder->ctl;
268 struct mdp5_interface *intf = &mdp5_encoder->intf; 271 struct mdp5_interface *intf = &mdp5_encoder->intf;
269 int intfn = mdp5_encoder->intf.num; 272 int intfn = mdp5_encoder->intf.num;
270 unsigned long flags; 273 unsigned long flags;
@@ -329,7 +332,7 @@ int mdp5_encoder_set_split_display(struct drm_encoder *encoder,
329 332
330/* initialize encoder */ 333/* initialize encoder */
331struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, 334struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
332 struct mdp5_interface *intf) 335 struct mdp5_interface *intf, struct mdp5_ctl *ctl)
333{ 336{
334 struct drm_encoder *encoder = NULL; 337 struct drm_encoder *encoder = NULL;
335 struct mdp5_encoder *mdp5_encoder; 338 struct mdp5_encoder *mdp5_encoder;
@@ -345,6 +348,7 @@ struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
345 348
346 memcpy(&mdp5_encoder->intf, intf, sizeof(mdp5_encoder->intf)); 349 memcpy(&mdp5_encoder->intf, intf, sizeof(mdp5_encoder->intf));
347 encoder = &mdp5_encoder->base; 350 encoder = &mdp5_encoder->base;
351 mdp5_encoder->ctl = ctl;
348 352
349 spin_lock_init(&mdp5_encoder->intf_lock); 353 spin_lock_init(&mdp5_encoder->intf_lock);
350 354
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 97d9da2175b4..cd587a6dfbd0 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -198,7 +198,7 @@ int mdp5_enable(struct mdp5_kms *mdp5_kms)
198 198
199static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms, 199static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms,
200 enum mdp5_intf_type intf_type, int intf_num, 200 enum mdp5_intf_type intf_type, int intf_num,
201 enum mdp5_intf_mode intf_mode) 201 enum mdp5_intf_mode intf_mode, struct mdp5_ctl *ctl)
202{ 202{
203 struct drm_device *dev = mdp5_kms->dev; 203 struct drm_device *dev = mdp5_kms->dev;
204 struct msm_drm_private *priv = dev->dev_private; 204 struct msm_drm_private *priv = dev->dev_private;
@@ -211,9 +211,9 @@ static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms,
211 211
212 if ((intf_type == INTF_DSI) && 212 if ((intf_type == INTF_DSI) &&
213 (intf_mode == MDP5_INTF_DSI_MODE_COMMAND)) 213 (intf_mode == MDP5_INTF_DSI_MODE_COMMAND))
214 encoder = mdp5_cmd_encoder_init(dev, &intf); 214 encoder = mdp5_cmd_encoder_init(dev, &intf, ctl);
215 else 215 else
216 encoder = mdp5_encoder_init(dev, &intf); 216 encoder = mdp5_encoder_init(dev, &intf, ctl);
217 217
218 if (IS_ERR(encoder)) { 218 if (IS_ERR(encoder)) {
219 dev_err(dev->dev, "failed to construct encoder\n"); 219 dev_err(dev->dev, "failed to construct encoder\n");
@@ -251,6 +251,8 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)
251 const struct mdp5_cfg_hw *hw_cfg = 251 const struct mdp5_cfg_hw *hw_cfg =
252 mdp5_cfg_get_hw_config(mdp5_kms->cfg); 252 mdp5_cfg_get_hw_config(mdp5_kms->cfg);
253 enum mdp5_intf_type intf_type = hw_cfg->intf.connect[intf_num]; 253 enum mdp5_intf_type intf_type = hw_cfg->intf.connect[intf_num];
254 struct mdp5_ctl_manager *ctlm = mdp5_kms->ctlm;
255 struct mdp5_ctl *ctl;
254 struct drm_encoder *encoder; 256 struct drm_encoder *encoder;
255 int ret = 0; 257 int ret = 0;
256 258
@@ -261,8 +263,14 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)
261 if (!priv->edp) 263 if (!priv->edp)
262 break; 264 break;
263 265
266 ctl = mdp5_ctlm_request(ctlm, intf_num);
267 if (!ctl) {
268 ret = -EINVAL;
269 break;
270 }
271
264 encoder = construct_encoder(mdp5_kms, INTF_eDP, intf_num, 272 encoder = construct_encoder(mdp5_kms, INTF_eDP, intf_num,
265 MDP5_INTF_MODE_NONE); 273 MDP5_INTF_MODE_NONE, ctl);
266 if (IS_ERR(encoder)) { 274 if (IS_ERR(encoder)) {
267 ret = PTR_ERR(encoder); 275 ret = PTR_ERR(encoder);
268 break; 276 break;
@@ -274,8 +282,14 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)
274 if (!priv->hdmi) 282 if (!priv->hdmi)
275 break; 283 break;
276 284
285 ctl = mdp5_ctlm_request(ctlm, intf_num);
286 if (!ctl) {
287 ret = -EINVAL;
288 break;
289 }
290
277 encoder = construct_encoder(mdp5_kms, INTF_HDMI, intf_num, 291 encoder = construct_encoder(mdp5_kms, INTF_HDMI, intf_num,
278 MDP5_INTF_MODE_NONE); 292 MDP5_INTF_MODE_NONE, ctl);
279 if (IS_ERR(encoder)) { 293 if (IS_ERR(encoder)) {
280 ret = PTR_ERR(encoder); 294 ret = PTR_ERR(encoder);
281 break; 295 break;
@@ -300,14 +314,20 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num)
300 if (!priv->dsi[dsi_id]) 314 if (!priv->dsi[dsi_id])
301 break; 315 break;
302 316
317 ctl = mdp5_ctlm_request(ctlm, intf_num);
318 if (!ctl) {
319 ret = -EINVAL;
320 break;
321 }
322
303 for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) { 323 for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) {
304 mode = (i == MSM_DSI_CMD_ENCODER_ID) ? 324 mode = (i == MSM_DSI_CMD_ENCODER_ID) ?
305 MDP5_INTF_DSI_MODE_COMMAND : 325 MDP5_INTF_DSI_MODE_COMMAND :
306 MDP5_INTF_DSI_MODE_VIDEO; 326 MDP5_INTF_DSI_MODE_VIDEO;
307 dsi_encs[i] = construct_encoder(mdp5_kms, INTF_DSI, 327 dsi_encs[i] = construct_encoder(mdp5_kms, INTF_DSI,
308 intf_num, mode); 328 intf_num, mode, ctl);
309 if (IS_ERR(dsi_encs)) { 329 if (IS_ERR(dsi_encs[i])) {
310 ret = PTR_ERR(dsi_encs); 330 ret = PTR_ERR(dsi_encs[i]);
311 break; 331 break;
312 } 332 }
313 } 333 }
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 776b84b828e3..dc94c8f29404 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -228,26 +228,26 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
228uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc); 228uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
229 229
230int mdp5_crtc_get_lm(struct drm_crtc *crtc); 230int mdp5_crtc_get_lm(struct drm_crtc *crtc);
231struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc);
232void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file); 231void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
233void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf); 232void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,
233 struct mdp5_interface *intf, struct mdp5_ctl *ctl);
234void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc); 234void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc);
235struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, 235struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
236 struct drm_plane *plane, int id); 236 struct drm_plane *plane, int id);
237 237
238struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, 238struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
239 struct mdp5_interface *intf); 239 struct mdp5_interface *intf, struct mdp5_ctl *ctl);
240int mdp5_encoder_set_split_display(struct drm_encoder *encoder, 240int mdp5_encoder_set_split_display(struct drm_encoder *encoder,
241 struct drm_encoder *slave_encoder); 241 struct drm_encoder *slave_encoder);
242 242
243#ifdef CONFIG_DRM_MSM_DSI 243#ifdef CONFIG_DRM_MSM_DSI
244struct drm_encoder *mdp5_cmd_encoder_init(struct drm_device *dev, 244struct drm_encoder *mdp5_cmd_encoder_init(struct drm_device *dev,
245 struct mdp5_interface *intf); 245 struct mdp5_interface *intf, struct mdp5_ctl *ctl);
246int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder, 246int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder,
247 struct drm_encoder *slave_encoder); 247 struct drm_encoder *slave_encoder);
248#else 248#else
249static inline struct drm_encoder *mdp5_cmd_encoder_init( 249static inline struct drm_encoder *mdp5_cmd_encoder_init(struct drm_device *dev,
250 struct drm_device *dev, struct mdp5_interface *intf) 250 struct mdp5_interface *intf, struct mdp5_ctl *ctl)
251{ 251{
252 return ERR_PTR(-EINVAL); 252 return ERR_PTR(-EINVAL);
253} 253}