diff options
Diffstat (limited to 'drivers/gpu/drm/msm/mdp4/mdp4_crtc.c')
-rw-r--r-- | drivers/gpu/drm/msm/mdp4/mdp4_crtc.c | 208 |
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 | ||
95 | static void complete_flip(struct drm_crtc *crtc, bool canceled) | 100 | /* if file!=NULL, this is preclose potential cancel-flip path */ |
101 | static 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 | ||
128 | static void pageflip_worker(struct work_struct *work) | 143 | static 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 | |||
151 | static 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 | ||
141 | static void unref_fb_worker(struct drm_flip_work *work, void *val) | 168 | static 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 | ||
395 | static int mdp4_crtc_set_property(struct drm_crtc *crtc, | 427 | static 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 | ||
503 | fail: | 537 | fail: |
@@ -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 | ||
554 | static void mdp4_crtc_err_irq(struct mdp4_irq *irq, uint32_t irqstatus) | 596 | static 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 | ||
568 | void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc) | 610 | void 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 | ||
668 | static 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 | |||
684 | void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane) | ||
685 | { | ||
686 | set_attach(crtc, mdp4_plane_pipe(plane), plane); | ||
687 | } | ||
688 | |||
689 | void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane) | ||
690 | { | ||
691 | set_attach(crtc, mdp4_plane_pipe(plane), NULL); | ||
692 | } | ||
693 | |||
625 | static const char *dma_names[] = { | 694 | static 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); |