aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/mdp4/mdp4_crtc.c')
-rw-r--r--drivers/gpu/drm/msm/mdp4/mdp4_crtc.c208
1 files changed, 138 insertions, 70 deletions
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
index de6bea297cda..019d530187ff 100644
--- a/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
@@ -26,6 +26,7 @@ struct mdp4_crtc {
26 struct drm_crtc base; 26 struct drm_crtc base;
27 char name[8]; 27 char name[8];
28 struct drm_plane *plane; 28 struct drm_plane *plane;
29 struct drm_plane *planes[8];
29 int id; 30 int id;
30 int ovlp; 31 int ovlp;
31 enum mdp4_dma dma; 32 enum mdp4_dma dma;
@@ -50,7 +51,11 @@ struct mdp4_crtc {
50 51
51 /* if there is a pending flip, these will be non-null: */ 52 /* if there is a pending flip, these will be non-null: */
52 struct drm_pending_vblank_event *event; 53 struct drm_pending_vblank_event *event;
53 struct work_struct pageflip_work; 54 struct msm_fence_cb pageflip_cb;
55
56#define PENDING_CURSOR 0x1
57#define PENDING_FLIP 0x2
58 atomic_t pending;
54 59
55 /* the fb that we currently hold a scanout ref to: */ 60 /* the fb that we currently hold a scanout ref to: */
56 struct drm_framebuffer *fb; 61 struct drm_framebuffer *fb;
@@ -92,7 +97,8 @@ static void update_fb(struct drm_crtc *crtc, bool async,
92 } 97 }
93} 98}
94 99
95static void complete_flip(struct drm_crtc *crtc, bool canceled) 100/* if file!=NULL, this is preclose potential cancel-flip path */
101static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
96{ 102{
97 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); 103 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
98 struct drm_device *dev = crtc->dev; 104 struct drm_device *dev = crtc->dev;
@@ -102,11 +108,14 @@ static void complete_flip(struct drm_crtc *crtc, bool canceled)
102 spin_lock_irqsave(&dev->event_lock, flags); 108 spin_lock_irqsave(&dev->event_lock, flags);
103 event = mdp4_crtc->event; 109 event = mdp4_crtc->event;
104 if (event) { 110 if (event) {
105 mdp4_crtc->event = NULL; 111 /* if regular vblank case (!file) or if cancel-flip from
106 if (canceled) 112 * preclose on file that requested flip, then send the
107 event->base.destroy(&event->base); 113 * event:
108 else 114 */
115 if (!file || (event->base.file_priv == file)) {
116 mdp4_crtc->event = NULL;
109 drm_send_vblank_event(dev, mdp4_crtc->id, event); 117 drm_send_vblank_event(dev, mdp4_crtc->id, event);
118 }
110 } 119 }
111 spin_unlock_irqrestore(&dev->event_lock, flags); 120 spin_unlock_irqrestore(&dev->event_lock, flags);
112} 121}
@@ -115,9 +124,15 @@ static void crtc_flush(struct drm_crtc *crtc)
115{ 124{
116 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); 125 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
117 struct mdp4_kms *mdp4_kms = get_kms(crtc); 126 struct mdp4_kms *mdp4_kms = get_kms(crtc);
118 uint32_t flush = 0; 127 uint32_t i, flush = 0;
119 128
120 flush |= pipe2flush(mdp4_plane_pipe(mdp4_crtc->plane)); 129 for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) {
130 struct drm_plane *plane = mdp4_crtc->planes[i];
131 if (plane) {
132 enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
133 flush |= pipe2flush(pipe_id);
134 }
135 }
121 flush |= ovlp2flush(mdp4_crtc->ovlp); 136 flush |= ovlp2flush(mdp4_crtc->ovlp);
122 137
123 DBG("%s: flush=%08x", mdp4_crtc->name, flush); 138 DBG("%s: flush=%08x", mdp4_crtc->name, flush);
@@ -125,17 +140,29 @@ static void crtc_flush(struct drm_crtc *crtc)
125 mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush); 140 mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush);
126} 141}
127 142
128static void pageflip_worker(struct work_struct *work) 143static void request_pending(struct drm_crtc *crtc, uint32_t pending)
144{
145 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
146
147 atomic_or(pending, &mdp4_crtc->pending);
148 mdp4_irq_register(get_kms(crtc), &mdp4_crtc->vblank);
149}
150
151static void pageflip_cb(struct msm_fence_cb *cb)
129{ 152{
130 struct mdp4_crtc *mdp4_crtc = 153 struct mdp4_crtc *mdp4_crtc =
131 container_of(work, struct mdp4_crtc, pageflip_work); 154 container_of(cb, struct mdp4_crtc, pageflip_cb);
132 struct drm_crtc *crtc = &mdp4_crtc->base; 155 struct drm_crtc *crtc = &mdp4_crtc->base;
156 struct drm_framebuffer *fb = crtc->fb;
133 157
134 mdp4_plane_set_scanout(mdp4_crtc->plane, crtc->fb); 158 if (!fb)
159 return;
160
161 mdp4_plane_set_scanout(mdp4_crtc->plane, fb);
135 crtc_flush(crtc); 162 crtc_flush(crtc);
136 163
137 /* enable vblank to complete flip: */ 164 /* enable vblank to complete flip: */
138 mdp4_irq_register(get_kms(crtc), &mdp4_crtc->vblank); 165 request_pending(crtc, PENDING_FLIP);
139} 166}
140 167
141static void unref_fb_worker(struct drm_flip_work *work, void *val) 168static void unref_fb_worker(struct drm_flip_work *work, void *val)
@@ -205,67 +232,69 @@ static void blend_setup(struct drm_crtc *crtc)
205 struct mdp4_kms *mdp4_kms = get_kms(crtc); 232 struct mdp4_kms *mdp4_kms = get_kms(crtc);
206 int i, ovlp = mdp4_crtc->ovlp; 233 int i, ovlp = mdp4_crtc->ovlp;
207 uint32_t mixer_cfg = 0; 234 uint32_t mixer_cfg = 0;
208 235 static const enum mdp4_mixer_stage_id stages[] = {
209 /* 236 STAGE_BASE, STAGE0, STAGE1, STAGE2, STAGE3,
210 * This probably would also need to be triggered by any attached 237 };
211 * plane when it changes.. for now since we are only using a single 238 /* statically (for now) map planes to mixer stage (z-order): */
212 * private plane, the configuration is hard-coded: 239 static const int idxs[] = {
213 */ 240 [VG1] = 1,
241 [VG2] = 2,
242 [RGB1] = 0,
243 [RGB2] = 0,
244 [RGB3] = 0,
245 [VG3] = 3,
246 [VG4] = 4,
247
248 };
249 bool alpha[4]= { false, false, false, false };
214 250
215 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW0(ovlp), 0); 251 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW0(ovlp), 0);
216 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW1(ovlp), 0); 252 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW1(ovlp), 0);
217 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0); 253 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0);
218 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0); 254 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0);
219 255
256 /* TODO single register for all CRTCs, so this won't work properly
257 * when multiple CRTCs are active..
258 */
259 for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) {
260 struct drm_plane *plane = mdp4_crtc->planes[i];
261 if (plane) {
262 enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
263 int idx = idxs[pipe_id];
264 if (idx > 0) {
265 const struct mdp4_format *format =
266 to_mdp4_format(msm_framebuffer_format(plane->fb));
267 alpha[idx-1] = format->alpha_enable;
268 }
269 mixer_cfg |= mixercfg(mdp4_crtc->mixer, pipe_id, stages[idx]);
270 }
271 }
272
273 /* this shouldn't happen.. and seems to cause underflow: */
274 WARN_ON(!mixer_cfg);
275
220 for (i = 0; i < 4; i++) { 276 for (i = 0; i < 4; i++) {
221 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_FG_ALPHA(ovlp, i), 0); 277 uint32_t op;
222 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_BG_ALPHA(ovlp, i), 0); 278
223 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_OP(ovlp, i), 279 if (alpha[i]) {
224 MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_CONST) | 280 op = MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_PIXEL) |
225 MDP4_OVLP_STAGE_OP_BG_ALPHA(BG_CONST)); 281 MDP4_OVLP_STAGE_OP_BG_ALPHA(FG_PIXEL) |
226 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_CO3(ovlp, i), 0); 282 MDP4_OVLP_STAGE_OP_BG_INV_ALPHA;
283 } else {
284 op = MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_CONST) |
285 MDP4_OVLP_STAGE_OP_BG_ALPHA(BG_CONST);
286 }
287
288 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_FG_ALPHA(ovlp, i), 0xff);
289 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_BG_ALPHA(ovlp, i), 0x00);
290 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_OP(ovlp, i), op);
291 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_CO3(ovlp, i), 1);
227 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW0(ovlp, i), 0); 292 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW0(ovlp, i), 0);
228 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW1(ovlp, i), 0); 293 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW1(ovlp, i), 0);
229 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH0(ovlp, i), 0); 294 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH0(ovlp, i), 0);
230 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp, i), 0); 295 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp, i), 0);
231 } 296 }
232 297
233 /* TODO single register for all CRTCs, so this won't work properly
234 * when multiple CRTCs are active..
235 */
236 switch (mdp4_plane_pipe(mdp4_crtc->plane)) {
237 case VG1:
238 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE0(STAGE_BASE) |
239 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1);
240 break;
241 case VG2:
242 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE1(STAGE_BASE) |
243 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1);
244 break;
245 case RGB1:
246 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE2(STAGE_BASE) |
247 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1);
248 break;
249 case RGB2:
250 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE3(STAGE_BASE) |
251 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1);
252 break;
253 case RGB3:
254 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE4(STAGE_BASE) |
255 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1);
256 break;
257 case VG3:
258 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE5(STAGE_BASE) |
259 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1);
260 break;
261 case VG4:
262 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE6(STAGE_BASE) |
263 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1);
264 break;
265 default:
266 WARN_ON("invalid pipe");
267 break;
268 }
269 mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg); 298 mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg);
270} 299}
271 300
@@ -377,6 +406,7 @@ static int mdp4_crtc_page_flip(struct drm_crtc *crtc,
377 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); 406 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
378 struct drm_device *dev = crtc->dev; 407 struct drm_device *dev = crtc->dev;
379 struct drm_gem_object *obj; 408 struct drm_gem_object *obj;
409 unsigned long flags;
380 410
381 if (mdp4_crtc->event) { 411 if (mdp4_crtc->event) {
382 dev_err(dev->dev, "already pending flip!\n"); 412 dev_err(dev->dev, "already pending flip!\n");
@@ -385,11 +415,13 @@ static int mdp4_crtc_page_flip(struct drm_crtc *crtc,
385 415
386 obj = msm_framebuffer_bo(new_fb, 0); 416 obj = msm_framebuffer_bo(new_fb, 0);
387 417
418 spin_lock_irqsave(&dev->event_lock, flags);
388 mdp4_crtc->event = event; 419 mdp4_crtc->event = event;
420 spin_unlock_irqrestore(&dev->event_lock, flags);
421
389 update_fb(crtc, true, new_fb); 422 update_fb(crtc, true, new_fb);
390 423
391 return msm_gem_queue_inactive_work(obj, 424 return msm_gem_queue_inactive_cb(obj, &mdp4_crtc->pageflip_cb);
392 &mdp4_crtc->pageflip_work);
393} 425}
394 426
395static int mdp4_crtc_set_property(struct drm_crtc *crtc, 427static int mdp4_crtc_set_property(struct drm_crtc *crtc,
@@ -498,6 +530,8 @@ static int mdp4_crtc_cursor_set(struct drm_crtc *crtc,
498 drm_gem_object_unreference_unlocked(old_bo); 530 drm_gem_object_unreference_unlocked(old_bo);
499 } 531 }
500 532
533 request_pending(crtc, PENDING_CURSOR);
534
501 return 0; 535 return 0;
502 536
503fail: 537fail:
@@ -542,13 +576,21 @@ static void mdp4_crtc_vblank_irq(struct mdp4_irq *irq, uint32_t irqstatus)
542 struct mdp4_crtc *mdp4_crtc = container_of(irq, struct mdp4_crtc, vblank); 576 struct mdp4_crtc *mdp4_crtc = container_of(irq, struct mdp4_crtc, vblank);
543 struct drm_crtc *crtc = &mdp4_crtc->base; 577 struct drm_crtc *crtc = &mdp4_crtc->base;
544 struct msm_drm_private *priv = crtc->dev->dev_private; 578 struct msm_drm_private *priv = crtc->dev->dev_private;
579 unsigned pending;
545 580
546 update_cursor(crtc);
547 complete_flip(crtc, false);
548 mdp4_irq_unregister(get_kms(crtc), &mdp4_crtc->vblank); 581 mdp4_irq_unregister(get_kms(crtc), &mdp4_crtc->vblank);
549 582
550 drm_flip_work_commit(&mdp4_crtc->unref_fb_work, priv->wq); 583 pending = atomic_xchg(&mdp4_crtc->pending, 0);
551 drm_flip_work_commit(&mdp4_crtc->unref_cursor_work, priv->wq); 584
585 if (pending & PENDING_FLIP) {
586 complete_flip(crtc, NULL);
587 drm_flip_work_commit(&mdp4_crtc->unref_fb_work, priv->wq);
588 }
589
590 if (pending & PENDING_CURSOR) {
591 update_cursor(crtc);
592 drm_flip_work_commit(&mdp4_crtc->unref_cursor_work, priv->wq);
593 }
552} 594}
553 595
554static void mdp4_crtc_err_irq(struct mdp4_irq *irq, uint32_t irqstatus) 596static void mdp4_crtc_err_irq(struct mdp4_irq *irq, uint32_t irqstatus)
@@ -565,9 +607,10 @@ uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc)
565 return mdp4_crtc->vblank.irqmask; 607 return mdp4_crtc->vblank.irqmask;
566} 608}
567 609
568void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc) 610void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
569{ 611{
570 complete_flip(crtc, true); 612 DBG("cancel: %p", file);
613 complete_flip(crtc, file);
571} 614}
572 615
573/* set dma config, ie. the format the encoder wants. */ 616/* set dma config, ie. the format the encoder wants. */
@@ -622,6 +665,32 @@ void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf)
622 mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel); 665 mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel);
623} 666}
624 667
668static void set_attach(struct drm_crtc *crtc, enum mdp4_pipe pipe_id,
669 struct drm_plane *plane)
670{
671 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
672
673 BUG_ON(pipe_id >= ARRAY_SIZE(mdp4_crtc->planes));
674
675 if (mdp4_crtc->planes[pipe_id] == plane)
676 return;
677
678 mdp4_crtc->planes[pipe_id] = plane;
679 blend_setup(crtc);
680 if (mdp4_crtc->enabled && (plane != mdp4_crtc->plane))
681 crtc_flush(crtc);
682}
683
684void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane)
685{
686 set_attach(crtc, mdp4_plane_pipe(plane), plane);
687}
688
689void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane)
690{
691 set_attach(crtc, mdp4_plane_pipe(plane), NULL);
692}
693
625static const char *dma_names[] = { 694static const char *dma_names[] = {
626 "DMA_P", "DMA_S", "DMA_E", 695 "DMA_P", "DMA_S", "DMA_E",
627}; 696};
@@ -644,7 +713,6 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
644 crtc = &mdp4_crtc->base; 713 crtc = &mdp4_crtc->base;
645 714
646 mdp4_crtc->plane = plane; 715 mdp4_crtc->plane = plane;
647 mdp4_crtc->plane->crtc = crtc;
648 716
649 mdp4_crtc->ovlp = ovlp_id; 717 mdp4_crtc->ovlp = ovlp_id;
650 mdp4_crtc->dma = dma_id; 718 mdp4_crtc->dma = dma_id;
@@ -668,7 +736,7 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
668 ret = drm_flip_work_init(&mdp4_crtc->unref_cursor_work, 64, 736 ret = drm_flip_work_init(&mdp4_crtc->unref_cursor_work, 64,
669 "unref cursor", unref_cursor_worker); 737 "unref cursor", unref_cursor_worker);
670 738
671 INIT_WORK(&mdp4_crtc->pageflip_work, pageflip_worker); 739 INIT_FENCE_CB(&mdp4_crtc->pageflip_cb, pageflip_cb);
672 740
673 drm_crtc_init(dev, crtc, &mdp4_crtc_funcs); 741 drm_crtc_init(dev, crtc, &mdp4_crtc_funcs);
674 drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs); 742 drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs);