aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2008-09-30 15:14:26 -0400
committerDave Airlie <airlied@linux.ie>2008-10-17 17:10:11 -0400
commit0a3e67a4caac273a3bfc4ced3da364830b1ab241 (patch)
tree02a2e5e76d9dffcb556d09b0eee4d34ebe5d81cb /drivers/gpu/drm/i915/i915_irq.c
parent2df68b439fcb97a4c55f81516206ef4ee325e28d (diff)
drm: Rework vblank-wait handling to allow interrupt reduction.
Previously, drivers supporting vblank interrupt waits would run the interrupt all the time, or all the time that any 3d client was running, preventing the CPU from sleeping for long when the system was otherwise idle. Now, interrupts are disabled any time that no client is waiting on a vblank event. The new method uses vblank counters on the chipsets when the interrupts are turned off, rather than counting interrupts, so that we can continue to present accurate vblank numbers. Co-author: Michel Dänzer <michel@tungstengraphics.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c395
1 files changed, 265 insertions, 130 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index ae7d3a82a6d1..f8759597233b 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -35,9 +35,8 @@
35 35
36/** These are the interrupts used by the driver */ 36/** These are the interrupts used by the driver */
37#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \ 37#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \
38 I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | \
39 I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT | \
40 I915_ASLE_INTERRUPT | \ 38 I915_ASLE_INTERRUPT | \
39 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
41 I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) 40 I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
42 41
43void 42void
@@ -61,6 +60,64 @@ i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
61} 60}
62 61
63/** 62/**
63 * i915_get_pipe - return the the pipe associated with a given plane
64 * @dev: DRM device
65 * @plane: plane to look for
66 *
67 * The Intel Mesa & 2D drivers call the vblank routines with a plane number
68 * rather than a pipe number, since they may not always be equal. This routine
69 * maps the given @plane back to a pipe number.
70 */
71static int
72i915_get_pipe(struct drm_device *dev, int plane)
73{
74 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
75 u32 dspcntr;
76
77 dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
78
79 return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
80}
81
82/**
83 * i915_get_plane - return the the plane associated with a given pipe
84 * @dev: DRM device
85 * @pipe: pipe to look for
86 *
87 * The Intel Mesa & 2D drivers call the vblank routines with a plane number
88 * rather than a plane number, since they may not always be equal. This routine
89 * maps the given @pipe back to a plane number.
90 */
91static int
92i915_get_plane(struct drm_device *dev, int pipe)
93{
94 if (i915_get_pipe(dev, 0) == pipe)
95 return 0;
96 return 1;
97}
98
99/**
100 * i915_pipe_enabled - check if a pipe is enabled
101 * @dev: DRM device
102 * @pipe: pipe to check
103 *
104 * Reading certain registers when the pipe is disabled can hang the chip.
105 * Use this routine to make sure the PLL is running and the pipe is active
106 * before reading such registers if unsure.
107 */
108static int
109i915_pipe_enabled(struct drm_device *dev, int pipe)
110{
111 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
112 unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
113
114 if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
115 return 1;
116
117 return 0;
118}
119
120/**
64 * Emit blits for scheduled buffer swaps. 121 * Emit blits for scheduled buffer swaps.
65 * 122 *
66 * This function will be called with the HW lock held. 123 * This function will be called with the HW lock held.
@@ -71,8 +128,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
71 unsigned long irqflags; 128 unsigned long irqflags;
72 struct list_head *list, *tmp, hits, *hit; 129 struct list_head *list, *tmp, hits, *hit;
73 int nhits, nrects, slice[2], upper[2], lower[2], i; 130 int nhits, nrects, slice[2], upper[2], lower[2], i;
74 unsigned counter[2] = { atomic_read(&dev->vbl_received), 131 unsigned counter[2];
75 atomic_read(&dev->vbl_received2) };
76 struct drm_drawable_info *drw; 132 struct drm_drawable_info *drw;
77 drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; 133 drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
78 u32 cpp = dev_priv->cpp; 134 u32 cpp = dev_priv->cpp;
@@ -94,6 +150,9 @@ static void i915_vblank_tasklet(struct drm_device *dev)
94 src_pitch >>= 2; 150 src_pitch >>= 2;
95 } 151 }
96 152
153 counter[0] = drm_vblank_count(dev, 0);
154 counter[1] = drm_vblank_count(dev, 1);
155
97 DRM_DEBUG("\n"); 156 DRM_DEBUG("\n");
98 157
99 INIT_LIST_HEAD(&hits); 158 INIT_LIST_HEAD(&hits);
@@ -106,12 +165,14 @@ static void i915_vblank_tasklet(struct drm_device *dev)
106 list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { 165 list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
107 drm_i915_vbl_swap_t *vbl_swap = 166 drm_i915_vbl_swap_t *vbl_swap =
108 list_entry(list, drm_i915_vbl_swap_t, head); 167 list_entry(list, drm_i915_vbl_swap_t, head);
168 int pipe = i915_get_pipe(dev, vbl_swap->plane);
109 169
110 if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23)) 170 if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
111 continue; 171 continue;
112 172
113 list_del(list); 173 list_del(list);
114 dev_priv->swaps_pending--; 174 dev_priv->swaps_pending--;
175 drm_vblank_put(dev, pipe);
115 176
116 spin_unlock(&dev_priv->swaps_lock); 177 spin_unlock(&dev_priv->swaps_lock);
117 spin_lock(&dev->drw_lock); 178 spin_lock(&dev->drw_lock);
@@ -204,7 +265,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
204 drm_i915_vbl_swap_t *swap_hit = 265 drm_i915_vbl_swap_t *swap_hit =
205 list_entry(hit, drm_i915_vbl_swap_t, head); 266 list_entry(hit, drm_i915_vbl_swap_t, head);
206 struct drm_clip_rect *rect; 267 struct drm_clip_rect *rect;
207 int num_rects, pipe; 268 int num_rects, plane;
208 unsigned short top, bottom; 269 unsigned short top, bottom;
209 270
210 drw = drm_get_drawable_info(dev, swap_hit->drw_id); 271 drw = drm_get_drawable_info(dev, swap_hit->drw_id);
@@ -213,9 +274,9 @@ static void i915_vblank_tasklet(struct drm_device *dev)
213 continue; 274 continue;
214 275
215 rect = drw->rects; 276 rect = drw->rects;
216 pipe = swap_hit->pipe; 277 plane = swap_hit->plane;
217 top = upper[pipe]; 278 top = upper[plane];
218 bottom = lower[pipe]; 279 bottom = lower[plane];
219 280
220 for (num_rects = drw->num_rects; num_rects--; rect++) { 281 for (num_rects = drw->num_rects; num_rects--; rect++) {
221 int y1 = max(rect->y1, top); 282 int y1 = max(rect->y1, top);
@@ -252,22 +313,54 @@ static void i915_vblank_tasklet(struct drm_device *dev)
252 } 313 }
253} 314}
254 315
316u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
317{
318 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
319 unsigned long high_frame;
320 unsigned long low_frame;
321 u32 high1, high2, low, count;
322 int pipe;
323
324 pipe = i915_get_pipe(dev, plane);
325 high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
326 low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
327
328 if (!i915_pipe_enabled(dev, pipe)) {
329 DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
330 return 0;
331 }
332
333 /*
334 * High & low register fields aren't synchronized, so make sure
335 * we get a low value that's stable across two reads of the high
336 * register.
337 */
338 do {
339 high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
340 PIPE_FRAME_HIGH_SHIFT);
341 low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
342 PIPE_FRAME_LOW_SHIFT);
343 high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
344 PIPE_FRAME_HIGH_SHIFT);
345 } while (high1 != high2);
346
347 count = (high1 << 8) | low;
348
349 return count;
350}
351
255irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) 352irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
256{ 353{
257 struct drm_device *dev = (struct drm_device *) arg; 354 struct drm_device *dev = (struct drm_device *) arg;
258 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 355 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
259 u32 pipea_stats, pipeb_stats;
260 u32 iir; 356 u32 iir;
261 357 u32 pipea_stats, pipeb_stats;
262 pipea_stats = I915_READ(PIPEASTAT); 358 int vblank = 0;
263 pipeb_stats = I915_READ(PIPEBSTAT);
264 359
265 if (dev->pdev->msi_enabled) 360 if (dev->pdev->msi_enabled)
266 I915_WRITE(IMR, ~0); 361 I915_WRITE(IMR, ~0);
267 iir = I915_READ(IIR); 362 iir = I915_READ(IIR);
268 363
269 DRM_DEBUG("iir=%08x\n", iir);
270
271 if (iir == 0) { 364 if (iir == 0) {
272 if (dev->pdev->msi_enabled) { 365 if (dev->pdev->msi_enabled) {
273 I915_WRITE(IMR, dev_priv->irq_mask_reg); 366 I915_WRITE(IMR, dev_priv->irq_mask_reg);
@@ -276,48 +369,56 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
276 return IRQ_NONE; 369 return IRQ_NONE;
277 } 370 }
278 371
279 I915_WRITE(PIPEASTAT, pipea_stats); 372 /*
280 I915_WRITE(PIPEBSTAT, pipeb_stats); 373 * Clear the PIPE(A|B)STAT regs before the IIR otherwise
281 374 * we may get extra interrupts.
282 I915_WRITE(IIR, iir); 375 */
283 if (dev->pdev->msi_enabled) 376 if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
284 I915_WRITE(IMR, dev_priv->irq_mask_reg); 377 pipea_stats = I915_READ(PIPEASTAT);
285 (void) I915_READ(IIR); /* Flush posted writes */ 378 if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A))
286 379 pipea_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
287 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); 380 PIPE_VBLANK_INTERRUPT_ENABLE);
288 381 else if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
289 if (iir & I915_USER_INTERRUPT) 382 PIPE_VBLANK_INTERRUPT_STATUS)) {
290 DRM_WAKEUP(&dev_priv->irq_queue); 383 vblank++;
291 384 drm_handle_vblank(dev, i915_get_plane(dev, 0));
292 if (iir & (I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | 385 }
293 I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)) {
294 int vblank_pipe = dev_priv->vblank_pipe;
295
296 if ((vblank_pipe &
297 (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
298 == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
299 if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
300 atomic_inc(&dev->vbl_received);
301 if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
302 atomic_inc(&dev->vbl_received2);
303 } else if (((iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) &&
304 (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
305 ((iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) &&
306 (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
307 atomic_inc(&dev->vbl_received);
308 386
309 DRM_WAKEUP(&dev->vbl_queue); 387 I915_WRITE(PIPEASTAT, pipea_stats);
310 drm_vbl_send_signals(dev); 388 }
389 if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
390 pipeb_stats = I915_READ(PIPEBSTAT);
391 /* Ack the event */
392 I915_WRITE(PIPEBSTAT, pipeb_stats);
393
394 /* The vblank interrupt gets enabled even if we didn't ask for
395 it, so make sure it's shut down again */
396 if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
397 pipeb_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
398 PIPE_VBLANK_INTERRUPT_ENABLE);
399 else if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
400 PIPE_VBLANK_INTERRUPT_STATUS)) {
401 vblank++;
402 drm_handle_vblank(dev, i915_get_plane(dev, 1));
403 }
311 404
312 if (dev_priv->swaps_pending > 0) 405 if (pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS)
313 drm_locked_tasklet(dev, i915_vblank_tasklet); 406 opregion_asle_intr(dev);
407 I915_WRITE(PIPEBSTAT, pipeb_stats);
314 } 408 }
315 409
316 if (iir & I915_ASLE_INTERRUPT) 410 if (iir & I915_ASLE_INTERRUPT)
317 opregion_asle_intr(dev); 411 opregion_asle_intr(dev);
318 412
319 if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) 413 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
320 opregion_asle_intr(dev); 414
415 if (dev->pdev->msi_enabled)
416 I915_WRITE(IMR, dev_priv->irq_mask_reg);
417 I915_WRITE(IIR, iir);
418 (void) I915_READ(IIR);
419
420 if (vblank && dev_priv->swaps_pending > 0)
421 drm_locked_tasklet(dev, i915_vblank_tasklet);
321 422
322 return IRQ_HANDLED; 423 return IRQ_HANDLED;
323} 424}
@@ -358,7 +459,7 @@ static void i915_user_irq_get(struct drm_device *dev)
358 spin_unlock(&dev_priv->user_irq_lock); 459 spin_unlock(&dev_priv->user_irq_lock);
359} 460}
360 461
361static void i915_user_irq_put(struct drm_device *dev) 462void i915_user_irq_put(struct drm_device *dev)
362{ 463{
363 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 464 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
364 465
@@ -395,41 +496,10 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
395 } 496 }
396 497
397 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); 498 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
398 return ret;
399}
400
401static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
402 atomic_t *counter)
403{
404 drm_i915_private_t *dev_priv = dev->dev_private;
405 unsigned int cur_vblank;
406 int ret = 0;
407
408 if (!dev_priv) {
409 DRM_ERROR("called with no initialization\n");
410 return -EINVAL;
411 }
412
413 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
414 (((cur_vblank = atomic_read(counter))
415 - *sequence) <= (1<<23)));
416
417 *sequence = cur_vblank;
418 499
419 return ret; 500 return ret;
420} 501}
421 502
422
423int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
424{
425 return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
426}
427
428int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
429{
430 return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
431}
432
433/* Needs the lock as it touches the ring. 503/* Needs the lock as it touches the ring.
434 */ 504 */
435int i915_irq_emit(struct drm_device *dev, void *data, 505int i915_irq_emit(struct drm_device *dev, void *data,
@@ -472,40 +542,88 @@ int i915_irq_wait(struct drm_device *dev, void *data,
472 return i915_wait_irq(dev, irqwait->irq_seq); 542 return i915_wait_irq(dev, irqwait->irq_seq);
473} 543}
474 544
545int i915_enable_vblank(struct drm_device *dev, int plane)
546{
547 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
548 int pipe = i915_get_pipe(dev, plane);
549 u32 pipestat_reg = 0;
550 u32 pipestat;
551
552 switch (pipe) {
553 case 0:
554 pipestat_reg = PIPEASTAT;
555 i915_enable_irq(dev_priv, I915_DISPLAY_PIPE_A_EVENT_INTERRUPT);
556 break;
557 case 1:
558 pipestat_reg = PIPEBSTAT;
559 i915_enable_irq(dev_priv, I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
560 break;
561 default:
562 DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
563 pipe);
564 break;
565 }
566
567 if (pipestat_reg) {
568 pipestat = I915_READ(pipestat_reg);
569 if (IS_I965G(dev))
570 pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE;
571 else
572 pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE;
573 /* Clear any stale interrupt status */
574 pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
575 PIPE_VBLANK_INTERRUPT_STATUS);
576 I915_WRITE(pipestat_reg, pipestat);
577 }
578
579 return 0;
580}
581
582void i915_disable_vblank(struct drm_device *dev, int plane)
583{
584 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
585 int pipe = i915_get_pipe(dev, plane);
586 u32 pipestat_reg = 0;
587 u32 pipestat;
588
589 switch (pipe) {
590 case 0:
591 pipestat_reg = PIPEASTAT;
592 i915_disable_irq(dev_priv, I915_DISPLAY_PIPE_A_EVENT_INTERRUPT);
593 break;
594 case 1:
595 pipestat_reg = PIPEBSTAT;
596 i915_disable_irq(dev_priv, I915_DISPLAY_PIPE_B_EVENT_INTERRUPT);
597 break;
598 default:
599 DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
600 pipe);
601 break;
602 }
603
604 if (pipestat_reg) {
605 pipestat = I915_READ(pipestat_reg);
606 pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
607 PIPE_VBLANK_INTERRUPT_ENABLE);
608 /* Clear any stale interrupt status */
609 pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
610 PIPE_VBLANK_INTERRUPT_STATUS);
611 I915_WRITE(pipestat_reg, pipestat);
612 }
613}
614
475/* Set the vblank monitor pipe 615/* Set the vblank monitor pipe
476 */ 616 */
477int i915_vblank_pipe_set(struct drm_device *dev, void *data, 617int i915_vblank_pipe_set(struct drm_device *dev, void *data,
478 struct drm_file *file_priv) 618 struct drm_file *file_priv)
479{ 619{
480 drm_i915_private_t *dev_priv = dev->dev_private; 620 drm_i915_private_t *dev_priv = dev->dev_private;
481 drm_i915_vblank_pipe_t *pipe = data;
482 u32 enable_mask = 0, disable_mask = 0;
483 621
484 if (!dev_priv) { 622 if (!dev_priv) {
485 DRM_ERROR("called with no initialization\n"); 623 DRM_ERROR("called with no initialization\n");
486 return -EINVAL; 624 return -EINVAL;
487 } 625 }
488 626
489 if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
490 DRM_ERROR("called with invalid pipe 0x%x\n", pipe->pipe);
491 return -EINVAL;
492 }
493
494 if (pipe->pipe & DRM_I915_VBLANK_PIPE_A)
495 enable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
496 else
497 disable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
498
499 if (pipe->pipe & DRM_I915_VBLANK_PIPE_B)
500 enable_mask |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
501 else
502 disable_mask |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
503
504 i915_enable_irq(dev_priv, enable_mask);
505 i915_disable_irq(dev_priv, disable_mask);
506
507 dev_priv->vblank_pipe = pipe->pipe;
508
509 return 0; 627 return 0;
510} 628}
511 629
@@ -514,19 +632,13 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
514{ 632{
515 drm_i915_private_t *dev_priv = dev->dev_private; 633 drm_i915_private_t *dev_priv = dev->dev_private;
516 drm_i915_vblank_pipe_t *pipe = data; 634 drm_i915_vblank_pipe_t *pipe = data;
517 u16 flag;
518 635
519 if (!dev_priv) { 636 if (!dev_priv) {
520 DRM_ERROR("called with no initialization\n"); 637 DRM_ERROR("called with no initialization\n");
521 return -EINVAL; 638 return -EINVAL;
522 } 639 }
523 640
524 flag = I915_READ(IMR); 641 pipe->pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
525 pipe->pipe = 0;
526 if (flag & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT)
527 pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
528 if (flag & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
529 pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
530 642
531 return 0; 643 return 0;
532} 644}
@@ -540,9 +652,10 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
540 drm_i915_private_t *dev_priv = dev->dev_private; 652 drm_i915_private_t *dev_priv = dev->dev_private;
541 drm_i915_vblank_swap_t *swap = data; 653 drm_i915_vblank_swap_t *swap = data;
542 drm_i915_vbl_swap_t *vbl_swap; 654 drm_i915_vbl_swap_t *vbl_swap;
543 unsigned int pipe, seqtype, curseq; 655 unsigned int pipe, seqtype, curseq, plane;
544 unsigned long irqflags; 656 unsigned long irqflags;
545 struct list_head *list; 657 struct list_head *list;
658 int ret;
546 659
547 if (!dev_priv) { 660 if (!dev_priv) {
548 DRM_ERROR("%s called with no initialization\n", __func__); 661 DRM_ERROR("%s called with no initialization\n", __func__);
@@ -560,7 +673,8 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
560 return -EINVAL; 673 return -EINVAL;
561 } 674 }
562 675
563 pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; 676 plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
677 pipe = i915_get_pipe(dev, plane);
564 678
565 seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); 679 seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
566 680
@@ -579,7 +693,14 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
579 693
580 spin_unlock_irqrestore(&dev->drw_lock, irqflags); 694 spin_unlock_irqrestore(&dev->drw_lock, irqflags);
581 695
582 curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received); 696 /*
697 * We take the ref here and put it when the swap actually completes
698 * in the tasklet.
699 */
700 ret = drm_vblank_get(dev, pipe);
701 if (ret)
702 return ret;
703 curseq = drm_vblank_count(dev, pipe);
583 704
584 if (seqtype == _DRM_VBLANK_RELATIVE) 705 if (seqtype == _DRM_VBLANK_RELATIVE)
585 swap->sequence += curseq; 706 swap->sequence += curseq;
@@ -589,6 +710,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
589 swap->sequence = curseq + 1; 710 swap->sequence = curseq + 1;
590 } else { 711 } else {
591 DRM_DEBUG("Missed target sequence\n"); 712 DRM_DEBUG("Missed target sequence\n");
713 drm_vblank_put(dev, pipe);
592 return -EINVAL; 714 return -EINVAL;
593 } 715 }
594 } 716 }
@@ -599,7 +721,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
599 vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); 721 vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
600 722
601 if (vbl_swap->drw_id == swap->drawable && 723 if (vbl_swap->drw_id == swap->drawable &&
602 vbl_swap->pipe == pipe && 724 vbl_swap->plane == plane &&
603 vbl_swap->sequence == swap->sequence) { 725 vbl_swap->sequence == swap->sequence) {
604 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); 726 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
605 DRM_DEBUG("Already scheduled\n"); 727 DRM_DEBUG("Already scheduled\n");
@@ -611,6 +733,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
611 733
612 if (dev_priv->swaps_pending >= 100) { 734 if (dev_priv->swaps_pending >= 100) {
613 DRM_DEBUG("Too many swaps queued\n"); 735 DRM_DEBUG("Too many swaps queued\n");
736 drm_vblank_put(dev, pipe);
614 return -EBUSY; 737 return -EBUSY;
615 } 738 }
616 739
@@ -618,13 +741,14 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
618 741
619 if (!vbl_swap) { 742 if (!vbl_swap) {
620 DRM_ERROR("Failed to allocate memory to queue swap\n"); 743 DRM_ERROR("Failed to allocate memory to queue swap\n");
744 drm_vblank_put(dev, pipe);
621 return -ENOMEM; 745 return -ENOMEM;
622 } 746 }
623 747
624 DRM_DEBUG("\n"); 748 DRM_DEBUG("\n");
625 749
626 vbl_swap->drw_id = swap->drawable; 750 vbl_swap->drw_id = swap->drawable;
627 vbl_swap->pipe = pipe; 751 vbl_swap->plane = plane;
628 vbl_swap->sequence = swap->sequence; 752 vbl_swap->sequence = swap->sequence;
629 753
630 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); 754 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
@@ -643,28 +767,32 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
643{ 767{
644 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 768 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
645 769
646 I915_WRITE(HWSTAM, 0xfffe); 770 I915_WRITE(HWSTAM, 0xeffe);
647 I915_WRITE(IMR, 0x0); 771 I915_WRITE(IMR, 0xffffffff);
648 I915_WRITE(IER, 0x0); 772 I915_WRITE(IER, 0x0);
649} 773}
650 774
651void i915_driver_irq_postinstall(struct drm_device * dev) 775int i915_driver_irq_postinstall(struct drm_device *dev)
652{ 776{
653 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 777 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
778 int ret, num_pipes = 2;
654 779
655 spin_lock_init(&dev_priv->swaps_lock); 780 spin_lock_init(&dev_priv->swaps_lock);
656 INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); 781 INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
657 dev_priv->swaps_pending = 0; 782 dev_priv->swaps_pending = 0;
658 783
659 if (!dev_priv->vblank_pipe)
660 dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
661
662 /* Set initial unmasked IRQs to just the selected vblank pipes. */ 784 /* Set initial unmasked IRQs to just the selected vblank pipes. */
663 dev_priv->irq_mask_reg = ~0; 785 dev_priv->irq_mask_reg = ~0;
664 if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A) 786
665 dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; 787 ret = drm_vblank_init(dev, num_pipes);
666 if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) 788 if (ret)
667 dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; 789 return ret;
790
791 dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
792 dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
793 dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
794
795 dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
668 796
669 dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK; 797 dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK;
670 798
@@ -673,22 +801,29 @@ void i915_driver_irq_postinstall(struct drm_device * dev)
673 (void) I915_READ(IER); 801 (void) I915_READ(IER);
674 802
675 opregion_enable_asle(dev); 803 opregion_enable_asle(dev);
676
677 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); 804 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
805
806 return 0;
678} 807}
679 808
680void i915_driver_irq_uninstall(struct drm_device * dev) 809void i915_driver_irq_uninstall(struct drm_device * dev)
681{ 810{
682 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 811 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
683 u16 temp; 812 u32 temp;
684 813
685 if (!dev_priv) 814 if (!dev_priv)
686 return; 815 return;
687 816
688 I915_WRITE(HWSTAM, 0xffff); 817 dev_priv->vblank_pipe = 0;
689 I915_WRITE(IMR, 0xffff); 818
819 I915_WRITE(HWSTAM, 0xffffffff);
820 I915_WRITE(IMR, 0xffffffff);
690 I915_WRITE(IER, 0x0); 821 I915_WRITE(IER, 0x0);
691 822
823 temp = I915_READ(PIPEASTAT);
824 I915_WRITE(PIPEASTAT, temp);
825 temp = I915_READ(PIPEBSTAT);
826 I915_WRITE(PIPEBSTAT, temp);
692 temp = I915_READ(IIR); 827 temp = I915_READ(IIR);
693 I915_WRITE(IIR, temp); 828 I915_WRITE(IIR, temp);
694} 829}