aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2008-05-06 22:15:39 -0400
committerDave Airlie <airlied@linux.ie>2008-05-06 22:15:39 -0400
commitaf6061af0d9f84a4665f88186dc1ff9e4fb78330 (patch)
tree90281b9188338cc702f92329ed3725313d248eea /drivers
parentc0a18111e571138747a98af18b3a2124df56a0d1 (diff)
Revert "drm/vbl rework: rework how the drm deals with vblank."
This reverts commit ac741ab71bb39e6977694ac0cc26678d8673cda4. Okay this looks like wasn't as fully baked as I'd led myself to believe. Revert for now for further baking. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/drm/drm.h17
-rw-r--r--drivers/char/drm/drmP.h91
-rw-r--r--drivers/char/drm/drm_irq.c381
-rw-r--r--drivers/char/drm/i915_dma.c160
-rw-r--r--drivers/char/drm/i915_drm.h45
-rw-r--r--drivers/char/drm/i915_drv.c8
-rw-r--r--drivers/char/drm/i915_drv.h101
-rw-r--r--drivers/char/drm/i915_irq.c597
-rw-r--r--drivers/char/drm/mga_drv.c7
-rw-r--r--drivers/char/drm/mga_drv.h6
-rw-r--r--drivers/char/drm/mga_irq.c69
-rw-r--r--drivers/char/drm/r128_drv.c7
-rw-r--r--drivers/char/drm/r128_drv.h9
-rw-r--r--drivers/char/drm/r128_irq.c55
-rw-r--r--drivers/char/drm/radeon_drv.c8
-rw-r--r--drivers/char/drm/radeon_drv.h19
-rw-r--r--drivers/char/drm/radeon_irq.c171
-rw-r--r--drivers/char/drm/via_drv.c6
-rw-r--r--drivers/char/drm/via_drv.h7
-rw-r--r--drivers/char/drm/via_irq.c81
20 files changed, 473 insertions, 1372 deletions
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index 6874f31ca8ca..3a05c6d5ebe1 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -471,7 +471,6 @@ struct drm_irq_busid {
471enum drm_vblank_seq_type { 471enum drm_vblank_seq_type {
472 _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ 472 _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
473 _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ 473 _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
474 _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */
475 _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ 474 _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
476 _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ 475 _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
477 _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */ 476 _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
@@ -504,21 +503,6 @@ union drm_wait_vblank {
504 struct drm_wait_vblank_reply reply; 503 struct drm_wait_vblank_reply reply;
505}; 504};
506 505
507enum drm_modeset_ctl_cmd {
508 _DRM_PRE_MODESET = 1,
509 _DRM_POST_MODESET = 2,
510};
511
512/**
513 * DRM_IOCTL_MODESET_CTL ioctl argument type
514 *
515 * \sa drmModesetCtl().
516 */
517struct drm_modeset_ctl {
518 unsigned long arg;
519 enum drm_modeset_ctl_cmd cmd;
520};
521
522/** 506/**
523 * DRM_IOCTL_AGP_ENABLE ioctl argument type. 507 * DRM_IOCTL_AGP_ENABLE ioctl argument type.
524 * 508 *
@@ -603,7 +587,6 @@ struct drm_set_version {
603#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) 587#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client)
604#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) 588#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)
605#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) 589#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)
606#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)
607 590
608#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) 591#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique)
609#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) 592#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth)
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 213b3ca3468e..0764b662b339 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -100,8 +100,10 @@ struct drm_device;
100#define DRIVER_HAVE_DMA 0x20 100#define DRIVER_HAVE_DMA 0x20
101#define DRIVER_HAVE_IRQ 0x40 101#define DRIVER_HAVE_IRQ 0x40
102#define DRIVER_IRQ_SHARED 0x80 102#define DRIVER_IRQ_SHARED 0x80
103#define DRIVER_IRQ_VBL 0x100
103#define DRIVER_DMA_QUEUE 0x200 104#define DRIVER_DMA_QUEUE 0x200
104#define DRIVER_FB_DMA 0x400 105#define DRIVER_FB_DMA 0x400
106#define DRIVER_IRQ_VBL2 0x800
105 107
106/***********************************************************************/ 108/***********************************************************************/
107/** \name Begin the DRM... */ 109/** \name Begin the DRM... */
@@ -577,52 +579,10 @@ struct drm_driver {
577 int (*context_dtor) (struct drm_device *dev, int context); 579 int (*context_dtor) (struct drm_device *dev, int context);
578 int (*kernel_context_switch) (struct drm_device *dev, int old, 580 int (*kernel_context_switch) (struct drm_device *dev, int old,
579 int new); 581 int new);
580 void (*kernel_context_switch_unlock) (struct drm_device * dev); 582 void (*kernel_context_switch_unlock) (struct drm_device *dev);
581 /** 583 int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
582 * get_vblank_counter - get raw hardware vblank counter 584 int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
583 * @dev: DRM device 585 int (*dri_library_name) (struct drm_device *dev, char *buf);
584 * @crtc: counter to fetch
585 *
586 * Driver callback for fetching a raw hardware vblank counter
587 * for @crtc. If a device doesn't have a hardware counter, the
588 * driver can simply return the value of drm_vblank_count and
589 * make the enable_vblank() and disable_vblank() hooks into no-ops,
590 * leaving interrupts enabled at all times.
591 *
592 * Wraparound handling and loss of events due to modesetting is dealt
593 * with in the DRM core code.
594 *
595 * RETURNS
596 * Raw vblank counter value.
597 */
598 u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
599
600 /**
601 * enable_vblank - enable vblank interrupt events
602 * @dev: DRM device
603 * @crtc: which irq to enable
604 *
605 * Enable vblank interrupts for @crtc. If the device doesn't have
606 * a hardware vblank counter, this routine should be a no-op, since
607 * interrupts will have to stay on to keep the count accurate.
608 *
609 * RETURNS
610 * Zero on success, appropriate errno if the given @crtc's vblank
611 * interrupt cannot be enabled.
612 */
613 int (*enable_vblank) (struct drm_device *dev, int crtc);
614
615 /**
616 * disable_vblank - disable vblank interrupt events
617 * @dev: DRM device
618 * @crtc: which irq to enable
619 *
620 * Disable vblank interrupts for @crtc. If the device doesn't have
621 * a hardware vblank counter, this routine should be a no-op, since
622 * interrupts will have to stay on to keep the count accurate.
623 */
624 void (*disable_vblank) (struct drm_device *dev, int crtc);
625 int (*dri_library_name) (struct drm_device *dev, char * buf);
626 586
627 /** 587 /**
628 * Called by \c drm_device_is_agp. Typically used to determine if a 588 * Called by \c drm_device_is_agp. Typically used to determine if a
@@ -641,7 +601,7 @@ struct drm_driver {
641 601
642 irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); 602 irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
643 void (*irq_preinstall) (struct drm_device *dev); 603 void (*irq_preinstall) (struct drm_device *dev);
644 int (*irq_postinstall) (struct drm_device *dev); 604 void (*irq_postinstall) (struct drm_device *dev);
645 void (*irq_uninstall) (struct drm_device *dev); 605 void (*irq_uninstall) (struct drm_device *dev);
646 void (*reclaim_buffers) (struct drm_device *dev, 606 void (*reclaim_buffers) (struct drm_device *dev,
647 struct drm_file * file_priv); 607 struct drm_file * file_priv);
@@ -770,21 +730,13 @@ struct drm_device {
770 /** \name VBLANK IRQ support */ 730 /** \name VBLANK IRQ support */
771 /*@{ */ 731 /*@{ */
772 732
773 wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */ 733 wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
774 atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */ 734 atomic_t vbl_received;
735 atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */
775 spinlock_t vbl_lock; 736 spinlock_t vbl_lock;
776 struct list_head *vbl_sigs; /**< signal list to send on VBLANK */ 737 struct list_head vbl_sigs; /**< signal list to send on VBLANK */
777 atomic_t vbl_signal_pending; /* number of signals pending on all crtcs*/ 738 struct list_head vbl_sigs2; /**< signals to send on secondary VBLANK */
778 atomic_t *vblank_refcount; /* number of users of vblank interrupts per crtc */ 739 unsigned int vbl_pending;
779 u32 *last_vblank; /* protected by dev->vbl_lock, used */
780 /* for wraparound handling */
781 u32 *vblank_offset; /* used to track how many vblanks */
782 int *vblank_enabled; /* so we don't call enable more than
783 once per disable */
784 u32 *vblank_premodeset; /* were lost during modeset */
785 struct timer_list vblank_disable_timer;
786
787 unsigned long max_vblank_count; /**< size of vblank counter register */
788 spinlock_t tasklet_lock; /**< For drm_locked_tasklet */ 740 spinlock_t tasklet_lock; /**< For drm_locked_tasklet */
789 void (*locked_tasklet_func)(struct drm_device *dev); 741 void (*locked_tasklet_func)(struct drm_device *dev);
790 742
@@ -804,7 +756,6 @@ struct drm_device {
804#ifdef __alpha__ 756#ifdef __alpha__
805 struct pci_controller *hose; 757 struct pci_controller *hose;
806#endif 758#endif
807 int num_crtcs; /**< Number of CRTCs on this device */
808 struct drm_sg_mem *sg; /**< Scatter gather memory */ 759 struct drm_sg_mem *sg; /**< Scatter gather memory */
809 void *dev_private; /**< device private data */ 760 void *dev_private; /**< device private data */
810 struct drm_sigdata sigdata; /**< For block_all_signals */ 761 struct drm_sigdata sigdata; /**< For block_all_signals */
@@ -1039,19 +990,11 @@ extern void drm_driver_irq_preinstall(struct drm_device *dev);
1039extern void drm_driver_irq_postinstall(struct drm_device *dev); 990extern void drm_driver_irq_postinstall(struct drm_device *dev);
1040extern void drm_driver_irq_uninstall(struct drm_device *dev); 991extern void drm_driver_irq_uninstall(struct drm_device *dev);
1041 992
1042extern int drm_vblank_init(struct drm_device *dev, int num_crtcs); 993extern int drm_wait_vblank(struct drm_device *dev, void *data,
1043extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *filp);
1044extern int drm_vblank_wait(struct drm_device * dev, unsigned int *vbl_seq);
1045extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
1046extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
1047extern void drm_update_vblank_count(struct drm_device *dev, int crtc);
1048extern void drm_handle_vblank(struct drm_device *dev, int crtc);
1049extern int drm_vblank_get(struct drm_device *dev, int crtc);
1050extern void drm_vblank_put(struct drm_device *dev, int crtc);
1051
1052 /* Modesetting support */
1053extern int drm_modeset_ctl(struct drm_device *dev, void *data,
1054 struct drm_file *file_priv); 994 struct drm_file *file_priv);
995extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
996extern void drm_vbl_send_signals(struct drm_device *dev);
997extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
1055 998
1056 /* AGP/GART support (drm_agpsupport.h) */ 999 /* AGP/GART support (drm_agpsupport.h) */
1057extern struct drm_agp_head *drm_agp_init(struct drm_device *dev); 1000extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index 286f9d61e7d5..089c015c01d1 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -71,117 +71,6 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
71 return 0; 71 return 0;
72} 72}
73 73
74static void vblank_disable_fn(unsigned long arg)
75{
76 struct drm_device *dev = (struct drm_device *)arg;
77 unsigned long irqflags;
78 int i;
79
80 for (i = 0; i < dev->num_crtcs; i++) {
81 spin_lock_irqsave(&dev->vbl_lock, irqflags);
82 if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
83 dev->vblank_enabled[i]) {
84 dev->driver->disable_vblank(dev, i);
85 dev->vblank_enabled[i] = 0;
86 }
87 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
88 }
89}
90
91static void drm_vblank_cleanup(struct drm_device *dev)
92{
93 /* Bail if the driver didn't call drm_vblank_init() */
94 if (dev->num_crtcs == 0)
95 return;
96
97 del_timer(&dev->vblank_disable_timer);
98
99 vblank_disable_fn((unsigned long)dev);
100
101 drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
102 DRM_MEM_DRIVER);
103 drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
104 DRM_MEM_DRIVER);
105 drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
106 dev->num_crtcs, DRM_MEM_DRIVER);
107 drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
108 dev->num_crtcs, DRM_MEM_DRIVER);
109 drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
110 dev->num_crtcs, DRM_MEM_DRIVER);
111 drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
112 DRM_MEM_DRIVER);
113 drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
114 dev->num_crtcs, DRM_MEM_DRIVER);
115 drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs,
116 DRM_MEM_DRIVER);
117
118 dev->num_crtcs = 0;
119}
120
121int drm_vblank_init(struct drm_device *dev, int num_crtcs)
122{
123 int i, ret = -ENOMEM;
124
125 setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
126 (unsigned long)dev);
127 spin_lock_init(&dev->vbl_lock);
128 atomic_set(&dev->vbl_signal_pending, 0);
129 dev->num_crtcs = num_crtcs;
130
131 dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
132 DRM_MEM_DRIVER);
133 if (!dev->vbl_queue)
134 goto err;
135
136 dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
137 DRM_MEM_DRIVER);
138 if (!dev->vbl_sigs)
139 goto err;
140
141 dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
142 DRM_MEM_DRIVER);
143 if (!dev->_vblank_count)
144 goto err;
145
146 dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
147 DRM_MEM_DRIVER);
148 if (!dev->vblank_refcount)
149 goto err;
150
151 dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
152 DRM_MEM_DRIVER);
153 if (!dev->vblank_enabled)
154 goto err;
155
156 dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
157 if (!dev->last_vblank)
158 goto err;
159
160 dev->vblank_premodeset = drm_calloc(num_crtcs, sizeof(u32),
161 DRM_MEM_DRIVER);
162 if (!dev->vblank_premodeset)
163 goto err;
164
165 dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
166 if (!dev->vblank_offset)
167 goto err;
168
169 /* Zero per-crtc vblank stuff */
170 for (i = 0; i < num_crtcs; i++) {
171 init_waitqueue_head(&dev->vbl_queue[i]);
172 INIT_LIST_HEAD(&dev->vbl_sigs[i]);
173 atomic_set(&dev->_vblank_count[i], 0);
174 atomic_set(&dev->vblank_refcount[i], 0);
175 }
176
177 return 0;
178
179err:
180 drm_vblank_cleanup(dev);
181 return ret;
182}
183EXPORT_SYMBOL(drm_vblank_init);
184
185/** 74/**
186 * Install IRQ handler. 75 * Install IRQ handler.
187 * 76 *
@@ -220,6 +109,17 @@ static int drm_irq_install(struct drm_device * dev)
220 109
221 DRM_DEBUG("irq=%d\n", dev->irq); 110 DRM_DEBUG("irq=%d\n", dev->irq);
222 111
112 if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
113 init_waitqueue_head(&dev->vbl_queue);
114
115 spin_lock_init(&dev->vbl_lock);
116
117 INIT_LIST_HEAD(&dev->vbl_sigs);
118 INIT_LIST_HEAD(&dev->vbl_sigs2);
119
120 dev->vbl_pending = 0;
121 }
122
223 /* Before installing handler */ 123 /* Before installing handler */
224 dev->driver->irq_preinstall(dev); 124 dev->driver->irq_preinstall(dev);
225 125
@@ -237,14 +137,9 @@ static int drm_irq_install(struct drm_device * dev)
237 } 137 }
238 138
239 /* After installing handler */ 139 /* After installing handler */
240 ret = dev->driver->irq_postinstall(dev); 140 dev->driver->irq_postinstall(dev);
241 if (ret < 0) {
242 mutex_lock(&dev->struct_mutex);
243 dev->irq_enabled = 0;
244 mutex_unlock(&dev->struct_mutex);
245 }
246 141
247 return ret; 142 return 0;
248} 143}
249 144
250/** 145/**
@@ -275,8 +170,6 @@ int drm_irq_uninstall(struct drm_device * dev)
275 170
276 free_irq(dev->irq, dev); 171 free_irq(dev->irq, dev);
277 172
278 drm_vblank_cleanup(dev);
279
280 dev->locked_tasklet_func = NULL; 173 dev->locked_tasklet_func = NULL;
281 174
282 return 0; 175 return 0;
@@ -321,148 +214,6 @@ int drm_control(struct drm_device *dev, void *data,
321} 214}
322 215
323/** 216/**
324 * drm_vblank_count - retrieve "cooked" vblank counter value
325 * @dev: DRM device
326 * @crtc: which counter to retrieve
327 *
328 * Fetches the "cooked" vblank count value that represents the number of
329 * vblank events since the system was booted, including lost events due to
330 * modesetting activity.
331 */
332u32 drm_vblank_count(struct drm_device *dev, int crtc)
333{
334 return atomic_read(&dev->_vblank_count[crtc]) +
335 dev->vblank_offset[crtc];
336}
337EXPORT_SYMBOL(drm_vblank_count);
338
339/**
340 * drm_update_vblank_count - update the master vblank counter
341 * @dev: DRM device
342 * @crtc: counter to update
343 *
344 * Call back into the driver to update the appropriate vblank counter
345 * (specified by @crtc). Deal with wraparound, if it occurred, and
346 * update the last read value so we can deal with wraparound on the next
347 * call if necessary.
348 */
349void drm_update_vblank_count(struct drm_device *dev, int crtc)
350{
351 unsigned long irqflags;
352 u32 cur_vblank, diff;
353
354 /*
355 * Interrupts were disabled prior to this call, so deal with counter
356 * wrap if needed.
357 * NOTE! It's possible we lost a full dev->max_vblank_count events
358 * here if the register is small or we had vblank interrupts off for
359 * a long time.
360 */
361 cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
362 spin_lock_irqsave(&dev->vbl_lock, irqflags);
363 if (cur_vblank < dev->last_vblank[crtc]) {
364 diff = dev->max_vblank_count -
365 dev->last_vblank[crtc];
366 diff += cur_vblank;
367 } else {
368 diff = cur_vblank - dev->last_vblank[crtc];
369 }
370 dev->last_vblank[crtc] = cur_vblank;
371 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
372
373 atomic_add(diff, &dev->_vblank_count[crtc]);
374}
375EXPORT_SYMBOL(drm_update_vblank_count);
376
377/**
378 * drm_vblank_get - get a reference count on vblank events
379 * @dev: DRM device
380 * @crtc: which CRTC to own
381 *
382 * Acquire a reference count on vblank events to avoid having them disabled
383 * while in use. Note callers will probably want to update the master counter
384 * using drm_update_vblank_count() above before calling this routine so that
385 * wakeups occur on the right vblank event.
386 *
387 * RETURNS
388 * Zero on success, nonzero on failure.
389 */
390int drm_vblank_get(struct drm_device *dev, int crtc)
391{
392 unsigned long irqflags;
393 int ret = 0;
394
395 spin_lock_irqsave(&dev->vbl_lock, irqflags);
396 /* Going from 0->1 means we have to enable interrupts again */
397 if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
398 !dev->vblank_enabled[crtc]) {
399 ret = dev->driver->enable_vblank(dev, crtc);
400 if (ret)
401 atomic_dec(&dev->vblank_refcount[crtc]);
402 else
403 dev->vblank_enabled[crtc] = 1;
404 }
405 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
406
407 return ret;
408}
409EXPORT_SYMBOL(drm_vblank_get);
410
411/**
412 * drm_vblank_put - give up ownership of vblank events
413 * @dev: DRM device
414 * @crtc: which counter to give up
415 *
416 * Release ownership of a given vblank counter, turning off interrupts
417 * if possible.
418 */
419void drm_vblank_put(struct drm_device *dev, int crtc)
420{
421 /* Last user schedules interrupt disable */
422 if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
423 mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
424}
425EXPORT_SYMBOL(drm_vblank_put);
426
427/**
428 * drm_modeset_ctl - handle vblank event counter changes across mode switch
429 * @DRM_IOCTL_ARGS: standard ioctl arguments
430 *
431 * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
432 * ioctls around modesetting so that any lost vblank events are accounted for.
433 */
434int drm_modeset_ctl(struct drm_device *dev, void *data,
435 struct drm_file *file_priv)
436{
437 struct drm_modeset_ctl *modeset = data;
438 int crtc, ret = 0;
439 u32 new;
440
441 crtc = modeset->arg;
442 if (crtc >= dev->num_crtcs) {
443 ret = -EINVAL;
444 goto out;
445 }
446
447 switch (modeset->cmd) {
448 case _DRM_PRE_MODESET:
449 dev->vblank_premodeset[crtc] =
450 dev->driver->get_vblank_counter(dev, crtc);
451 break;
452 case _DRM_POST_MODESET:
453 new = dev->driver->get_vblank_counter(dev, crtc);
454 dev->vblank_offset[crtc] = dev->vblank_premodeset[crtc] - new;
455 break;
456 default:
457 ret = -EINVAL;
458 break;
459 }
460
461out:
462 return ret;
463}
464
465/**
466 * Wait for VBLANK. 217 * Wait for VBLANK.
467 * 218 *
468 * \param inode device inode. 219 * \param inode device inode.
@@ -481,13 +232,12 @@ out:
481 * 232 *
482 * If a signal is not requested, then calls vblank_wait(). 233 * If a signal is not requested, then calls vblank_wait().
483 */ 234 */
484int drm_wait_vblank(struct drm_device *dev, void *data, 235int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
485 struct drm_file *file_priv)
486{ 236{
487 union drm_wait_vblank *vblwait = data; 237 union drm_wait_vblank *vblwait = data;
488 struct timeval now; 238 struct timeval now;
489 int ret = 0; 239 int ret = 0;
490 unsigned int flags, seq, crtc; 240 unsigned int flags, seq;
491 241
492 if ((!dev->irq) || (!dev->irq_enabled)) 242 if ((!dev->irq) || (!dev->irq_enabled))
493 return -EINVAL; 243 return -EINVAL;
@@ -501,13 +251,13 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
501 } 251 }
502 252
503 flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; 253 flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
504 crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
505 254
506 if (crtc >= dev->num_crtcs) 255 if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
256 DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
507 return -EINVAL; 257 return -EINVAL;
508 258
509 drm_update_vblank_count(dev, crtc); 259 seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
510 seq = drm_vblank_count(dev, crtc); 260 : &dev->vbl_received);
511 261
512 switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { 262 switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
513 case _DRM_VBLANK_RELATIVE: 263 case _DRM_VBLANK_RELATIVE:
@@ -526,7 +276,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
526 276
527 if (flags & _DRM_VBLANK_SIGNAL) { 277 if (flags & _DRM_VBLANK_SIGNAL) {
528 unsigned long irqflags; 278 unsigned long irqflags;
529 struct list_head *vbl_sigs = &dev->vbl_sigs[crtc]; 279 struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
280 ? &dev->vbl_sigs2 : &dev->vbl_sigs;
530 struct drm_vbl_sig *vbl_sig; 281 struct drm_vbl_sig *vbl_sig;
531 282
532 spin_lock_irqsave(&dev->vbl_lock, irqflags); 283 spin_lock_irqsave(&dev->vbl_lock, irqflags);
@@ -547,26 +298,22 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
547 } 298 }
548 } 299 }
549 300
550 if (atomic_read(&dev->vbl_signal_pending) >= 100) { 301 if (dev->vbl_pending >= 100) {
551 spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 302 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
552 return -EBUSY; 303 return -EBUSY;
553 } 304 }
554 305
306 dev->vbl_pending++;
307
555 spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 308 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
556 309
557 vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig), 310 if (!
558 DRM_MEM_DRIVER); 311 (vbl_sig =
559 if (!vbl_sig) 312 drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
560 return -ENOMEM; 313 return -ENOMEM;
561
562 ret = drm_vblank_get(dev, crtc);
563 if (ret) {
564 drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
565 DRM_MEM_DRIVER);
566 return ret;
567 } 314 }
568 315
569 atomic_inc(&dev->vbl_signal_pending); 316 memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
570 317
571 vbl_sig->sequence = vblwait->request.sequence; 318 vbl_sig->sequence = vblwait->request.sequence;
572 vbl_sig->info.si_signo = vblwait->request.signal; 319 vbl_sig->info.si_signo = vblwait->request.signal;
@@ -580,20 +327,17 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
580 327
581 vblwait->reply.sequence = seq; 328 vblwait->reply.sequence = seq;
582 } else { 329 } else {
583 unsigned long cur_vblank; 330 if (flags & _DRM_VBLANK_SECONDARY) {
584 331 if (dev->driver->vblank_wait2)
585 ret = drm_vblank_get(dev, crtc); 332 ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
586 if (ret) 333 } else if (dev->driver->vblank_wait)
587 return ret; 334 ret =
588 DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, 335 dev->driver->vblank_wait(dev,
589 (((cur_vblank = drm_vblank_count(dev, crtc)) 336 &vblwait->request.sequence);
590 - vblwait->request.sequence) <= (1 << 23)));
591 drm_vblank_put(dev, crtc);
592 do_gettimeofday(&now);
593 337
338 do_gettimeofday(&now);
594 vblwait->reply.tval_sec = now.tv_sec; 339 vblwait->reply.tval_sec = now.tv_sec;
595 vblwait->reply.tval_usec = now.tv_usec; 340 vblwait->reply.tval_usec = now.tv_usec;
596 vblwait->reply.sequence = cur_vblank;
597 } 341 }
598 342
599 done: 343 done:
@@ -604,57 +348,44 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
604 * Send the VBLANK signals. 348 * Send the VBLANK signals.
605 * 349 *
606 * \param dev DRM device. 350 * \param dev DRM device.
607 * \param crtc CRTC where the vblank event occurred
608 * 351 *
609 * Sends a signal for each task in drm_device::vbl_sigs and empties the list. 352 * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
610 * 353 *
611 * If a signal is not requested, then calls vblank_wait(). 354 * If a signal is not requested, then calls vblank_wait().
612 */ 355 */
613static void drm_vbl_send_signals(struct drm_device * dev, int crtc) 356void drm_vbl_send_signals(struct drm_device * dev)
614{ 357{
615 struct drm_vbl_sig *vbl_sig, *tmp;
616 struct list_head *vbl_sigs;
617 unsigned int vbl_seq;
618 unsigned long flags; 358 unsigned long flags;
359 int i;
619 360
620 spin_lock_irqsave(&dev->vbl_lock, flags); 361 spin_lock_irqsave(&dev->vbl_lock, flags);
621 362
622 vbl_sigs = &dev->vbl_sigs[crtc]; 363 for (i = 0; i < 2; i++) {
623 vbl_seq = drm_vblank_count(dev, crtc); 364 struct drm_vbl_sig *vbl_sig, *tmp;
365 struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
366 unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
367 &dev->vbl_received);
624 368
625 list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) { 369 list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
626 if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { 370 if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
627 vbl_sig->info.si_code = vbl_seq; 371 vbl_sig->info.si_code = vbl_seq;
628 send_sig_info(vbl_sig->info.si_signo, 372 send_sig_info(vbl_sig->info.si_signo,
629 &vbl_sig->info, vbl_sig->task); 373 &vbl_sig->info, vbl_sig->task);
630 374
631 list_del(&vbl_sig->head); 375 list_del(&vbl_sig->head);
632 376
633 drm_free(vbl_sig, sizeof(*vbl_sig), 377 drm_free(vbl_sig, sizeof(*vbl_sig),
634 DRM_MEM_DRIVER); 378 DRM_MEM_DRIVER);
635 atomic_dec(&dev->vbl_signal_pending); 379
636 drm_vblank_put(dev, crtc); 380 dev->vbl_pending--;
637 } 381 }
382 }
638 } 383 }
639 384
640 spin_unlock_irqrestore(&dev->vbl_lock, flags); 385 spin_unlock_irqrestore(&dev->vbl_lock, flags);
641} 386}
642 387
643/** 388EXPORT_SYMBOL(drm_vbl_send_signals);
644 * drm_handle_vblank - handle a vblank event
645 * @dev: DRM device
646 * @crtc: where this event occurred
647 *
648 * Drivers should call this routine in their vblank interrupt handlers to
649 * update the vblank counter and send any signals that may be pending.
650 */
651void drm_handle_vblank(struct drm_device *dev, int crtc)
652{
653 drm_update_vblank_count(dev, crtc);
654 DRM_WAKEUP(&dev->vbl_queue[crtc]);
655 drm_vbl_send_signals(dev, crtc);
656}
657EXPORT_SYMBOL(drm_handle_vblank);
658 389
659/** 390/**
660 * Tasklet wrapper function. 391 * Tasklet wrapper function.
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index f47e46e3529f..88974342933c 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -415,13 +415,10 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
415 drm_i915_private_t *dev_priv = dev->dev_private; 415 drm_i915_private_t *dev_priv = dev->dev_private;
416 RING_LOCALS; 416 RING_LOCALS;
417 417
418 if (++dev_priv->counter > BREADCRUMB_MASK) { 418 dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
419 dev_priv->counter = 1;
420 DRM_DEBUG("Breadcrumb counter wrapped around\n");
421 }
422 419
423 if (dev_priv->sarea_priv) 420 if (dev_priv->counter > 0x7FFFFFFFUL)
424 dev_priv->sarea_priv->last_enqueue = dev_priv->counter; 421 dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
425 422
426 BEGIN_LP_RING(4); 423 BEGIN_LP_RING(4);
427 OUT_RING(CMD_STORE_DWORD_IDX); 424 OUT_RING(CMD_STORE_DWORD_IDX);
@@ -431,26 +428,6 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
431 ADVANCE_LP_RING(); 428 ADVANCE_LP_RING();
432} 429}
433 430
434int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush)
435{
436 drm_i915_private_t *dev_priv = dev->dev_private;
437 uint32_t flush_cmd = CMD_MI_FLUSH;
438 RING_LOCALS;
439
440 flush_cmd |= flush;
441
442 i915_kernel_lost_context(dev);
443
444 BEGIN_LP_RING(4);
445 OUT_RING(flush_cmd);
446 OUT_RING(0);
447 OUT_RING(0);
448 OUT_RING(0);
449 ADVANCE_LP_RING();
450
451 return 0;
452}
453
454static int i915_dispatch_cmdbuffer(struct drm_device * dev, 431static int i915_dispatch_cmdbuffer(struct drm_device * dev,
455 drm_i915_cmdbuffer_t * cmd) 432 drm_i915_cmdbuffer_t * cmd)
456{ 433{
@@ -534,74 +511,52 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
534 return 0; 511 return 0;
535} 512}
536 513
537static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync) 514static int i915_dispatch_flip(struct drm_device * dev)
538{ 515{
539 drm_i915_private_t *dev_priv = dev->dev_private; 516 drm_i915_private_t *dev_priv = dev->dev_private;
540 u32 num_pages, current_page, next_page, dspbase;
541 int shift = 2 * plane, x, y;
542 RING_LOCALS; 517 RING_LOCALS;
543 518
544 /* Calculate display base offset */ 519 DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
545 num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2; 520 __FUNCTION__,
546 current_page = (dev_priv->sarea_priv->pf_current_page >> shift) & 0x3; 521 dev_priv->current_page,
547 next_page = (current_page + 1) % num_pages; 522 dev_priv->sarea_priv->pf_current_page);
548 523
549 switch (next_page) { 524 i915_kernel_lost_context(dev);
550 default: 525
551 case 0: 526 BEGIN_LP_RING(2);
552 dspbase = dev_priv->sarea_priv->front_offset; 527 OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
553 break; 528 OUT_RING(0);
554 case 1: 529 ADVANCE_LP_RING();
555 dspbase = dev_priv->sarea_priv->back_offset;
556 break;
557 case 2:
558 dspbase = dev_priv->sarea_priv->third_offset;
559 break;
560 }
561 530
562 if (plane == 0) { 531 BEGIN_LP_RING(6);
563 x = dev_priv->sarea_priv->planeA_x; 532 OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
564 y = dev_priv->sarea_priv->planeA_y; 533 OUT_RING(0);
534 if (dev_priv->current_page == 0) {
535 OUT_RING(dev_priv->back_offset);
536 dev_priv->current_page = 1;
565 } else { 537 } else {
566 x = dev_priv->sarea_priv->planeB_x; 538 OUT_RING(dev_priv->front_offset);
567 y = dev_priv->sarea_priv->planeB_y; 539 dev_priv->current_page = 0;
568 } 540 }
541 OUT_RING(0);
542 ADVANCE_LP_RING();
569 543
570 dspbase += (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp; 544 BEGIN_LP_RING(2);
545 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
546 OUT_RING(0);
547 ADVANCE_LP_RING();
571 548
572 DRM_DEBUG("plane=%d current_page=%d dspbase=0x%x\n", plane, current_page, 549 dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
573 dspbase);
574 550
575 BEGIN_LP_RING(4); 551 BEGIN_LP_RING(4);
576 OUT_RING(sync ? 0 : 552 OUT_RING(CMD_STORE_DWORD_IDX);
577 (MI_WAIT_FOR_EVENT | (plane ? MI_WAIT_FOR_PLANE_B_FLIP : 553 OUT_RING(20);
578 MI_WAIT_FOR_PLANE_A_FLIP))); 554 OUT_RING(dev_priv->counter);
579 OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) | 555 OUT_RING(0);
580 (plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A));
581 OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp);
582 OUT_RING(dspbase);
583 ADVANCE_LP_RING(); 556 ADVANCE_LP_RING();
584 557
585 dev_priv->sarea_priv->pf_current_page &= ~(0x3 << shift); 558 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
586 dev_priv->sarea_priv->pf_current_page |= next_page << shift; 559 return 0;
587}
588
589void i915_dispatch_flip(struct drm_device * dev, int planes, int sync)
590{
591 drm_i915_private_t *dev_priv = dev->dev_private;
592 int i;
593
594 DRM_DEBUG("planes=0x%x pfCurrentPage=%d\n",
595 planes, dev_priv->sarea_priv->pf_current_page);
596
597 i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH);
598
599 for (i = 0; i < 2; i++)
600 if (planes & (1 << i))
601 i915_do_dispatch_flip(dev, i, sync);
602
603 i915_emit_breadcrumb(dev);
604
605} 560}
606 561
607static int i915_quiescent(struct drm_device * dev) 562static int i915_quiescent(struct drm_device * dev)
@@ -624,6 +579,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
624 struct drm_file *file_priv) 579 struct drm_file *file_priv)
625{ 580{
626 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 581 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
582 u32 *hw_status = dev_priv->hw_status_page;
627 drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) 583 drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
628 dev_priv->sarea_priv; 584 dev_priv->sarea_priv;
629 drm_i915_batchbuffer_t *batch = data; 585 drm_i915_batchbuffer_t *batch = data;
@@ -646,7 +602,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
646 602
647 ret = i915_dispatch_batchbuffer(dev, batch); 603 ret = i915_dispatch_batchbuffer(dev, batch);
648 604
649 sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); 605 sarea_priv->last_dispatch = (int)hw_status[5];
650 return ret; 606 return ret;
651} 607}
652 608
@@ -654,6 +610,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
654 struct drm_file *file_priv) 610 struct drm_file *file_priv)
655{ 611{
656 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 612 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
613 u32 *hw_status = dev_priv->hw_status_page;
657 drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) 614 drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
658 dev_priv->sarea_priv; 615 dev_priv->sarea_priv;
659 drm_i915_cmdbuffer_t *cmdbuf = data; 616 drm_i915_cmdbuffer_t *cmdbuf = data;
@@ -678,51 +635,18 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
678 return ret; 635 return ret;
679 } 636 }
680 637
681 sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); 638 sarea_priv->last_dispatch = (int)hw_status[5];
682 return 0;
683}
684
685static int i915_do_cleanup_pageflip(struct drm_device * dev)
686{
687 drm_i915_private_t *dev_priv = dev->dev_private;
688 int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
689
690 DRM_DEBUG("\n");
691
692 for (i = 0, planes = 0; i < 2; i++)
693 if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) {
694 dev_priv->sarea_priv->pf_current_page =
695 (dev_priv->sarea_priv->pf_current_page &
696 ~(0x3 << (2 * i))) | ((num_pages - 1) << (2 * i));
697
698 planes |= 1 << i;
699 }
700
701 if (planes)
702 i915_dispatch_flip(dev, planes, 0);
703
704 return 0; 639 return 0;
705} 640}
706 641
707static int i915_flip_bufs(struct drm_device *dev, void *data, 642static int i915_flip_bufs(struct drm_device *dev, void *data,
708 struct drm_file *file_priv) 643 struct drm_file *file_priv)
709{ 644{
710 drm_i915_flip_t *param = data; 645 DRM_DEBUG("%s\n", __FUNCTION__);
711
712 DRM_DEBUG("\n");
713 646
714 LOCK_TEST_WITH_RETURN(dev, file_priv); 647 LOCK_TEST_WITH_RETURN(dev, file_priv);
715 648
716 /* This is really planes */ 649 return i915_dispatch_flip(dev);
717 if (param->pipes & ~0x3) {
718 DRM_ERROR("Invalid planes 0x%x, only <= 0x3 is valid\n",
719 param->pipes);
720 return -EINVAL;
721 }
722
723 i915_dispatch_flip(dev, param->pipes, 0);
724
725 return 0;
726} 650}
727 651
728static int i915_getparam(struct drm_device *dev, void *data, 652static int i915_getparam(struct drm_device *dev, void *data,
@@ -883,8 +807,6 @@ void i915_driver_lastclose(struct drm_device * dev)
883 if (!dev_priv) 807 if (!dev_priv)
884 return; 808 return;
885 809
886 if (drm_getsarea(dev) && dev_priv->sarea_priv)
887 i915_do_cleanup_pageflip(dev);
888 if (dev_priv->agp_heap) 810 if (dev_priv->agp_heap)
889 i915_mem_takedown(&(dev_priv->agp_heap)); 811 i915_mem_takedown(&(dev_priv->agp_heap));
890 812
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 0431c00e2289..05c66cf03a9e 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -105,29 +105,14 @@ typedef struct _drm_i915_sarea {
105 unsigned int rotated_tiled; 105 unsigned int rotated_tiled;
106 unsigned int rotated2_tiled; 106 unsigned int rotated2_tiled;
107 107
108 int planeA_x; 108 int pipeA_x;
109 int planeA_y; 109 int pipeA_y;
110 int planeA_w; 110 int pipeA_w;
111 int planeA_h; 111 int pipeA_h;
112 int planeB_x; 112 int pipeB_x;
113 int planeB_y; 113 int pipeB_y;
114 int planeB_w; 114 int pipeB_w;
115 int planeB_h; 115 int pipeB_h;
116
117 /* Triple buffering */
118 drm_handle_t third_handle;
119 int third_offset;
120 int third_size;
121 unsigned int third_tiled;
122
123 /* buffer object handles for the static buffers. May change
124 * over the lifetime of the client, though it doesn't in our current
125 * implementation.
126 */
127 unsigned int front_bo_handle;
128 unsigned int back_bo_handle;
129 unsigned int third_bo_handle;
130 unsigned int depth_bo_handle;
131} drm_i915_sarea_t; 116} drm_i915_sarea_t;
132 117
133/* Flags for perf_boxes 118/* Flags for perf_boxes
@@ -161,7 +146,7 @@ typedef struct _drm_i915_sarea {
161 146
162#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) 147#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
163#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) 148#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
164#define DRM_IOCTL_I915_FLIP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FLIP, drm_i915_flip_t) 149#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
165#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t) 150#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
166#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t) 151#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
167#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t) 152#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
@@ -176,18 +161,6 @@ typedef struct _drm_i915_sarea {
176#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) 161#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
177#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) 162#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
178 163
179/* Asynchronous page flipping:
180 */
181typedef struct drm_i915_flip {
182 /*
183 * This is really talking about planes, and we could rename it
184 * except for the fact that some of the duplicated i915_drm.h files
185 * out there check for HAVE_I915_FLIP and so might pick up this
186 * version.
187 */
188 int pipes;
189} drm_i915_flip_t;
190
191/* Allow drivers to submit batchbuffers directly to hardware, relying 164/* Allow drivers to submit batchbuffers directly to hardware, relying
192 * on the security mechanisms provided by hardware. 165 * on the security mechanisms provided by hardware.
193 */ 166 */
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
index bb8f1b2fb383..b2b451dc4460 100644
--- a/drivers/char/drm/i915_drv.c
+++ b/drivers/char/drm/i915_drv.c
@@ -533,7 +533,8 @@ static struct drm_driver driver = {
533 */ 533 */
534 .driver_features = 534 .driver_features =
535 DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/ 535 DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
536 DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, 536 DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
537 DRIVER_IRQ_VBL2,
537 .load = i915_driver_load, 538 .load = i915_driver_load,
538 .unload = i915_driver_unload, 539 .unload = i915_driver_unload,
539 .lastclose = i915_driver_lastclose, 540 .lastclose = i915_driver_lastclose,
@@ -541,9 +542,8 @@ static struct drm_driver driver = {
541 .suspend = i915_suspend, 542 .suspend = i915_suspend,
542 .resume = i915_resume, 543 .resume = i915_resume,
543 .device_is_agp = i915_driver_device_is_agp, 544 .device_is_agp = i915_driver_device_is_agp,
544 .get_vblank_counter = i915_get_vblank_counter, 545 .vblank_wait = i915_driver_vblank_wait,
545 .enable_vblank = i915_enable_vblank, 546 .vblank_wait2 = i915_driver_vblank_wait2,
546 .disable_vblank = i915_disable_vblank,
547 .irq_preinstall = i915_driver_irq_preinstall, 547 .irq_preinstall = i915_driver_irq_preinstall,
548 .irq_postinstall = i915_driver_irq_postinstall, 548 .irq_postinstall = i915_driver_irq_postinstall,
549 .irq_uninstall = i915_driver_irq_uninstall, 549 .irq_uninstall = i915_driver_irq_uninstall,
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index db7001f22561..2be7e1d72836 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -76,9 +76,8 @@ struct mem_block {
76typedef struct _drm_i915_vbl_swap { 76typedef struct _drm_i915_vbl_swap {
77 struct list_head head; 77 struct list_head head;
78 drm_drawable_t drw_id; 78 drm_drawable_t drw_id;
79 unsigned int plane; 79 unsigned int pipe;
80 unsigned int sequence; 80 unsigned int sequence;
81 int flip;
82} drm_i915_vbl_swap_t; 81} drm_i915_vbl_swap_t;
83 82
84typedef struct drm_i915_private { 83typedef struct drm_i915_private {
@@ -91,7 +90,7 @@ typedef struct drm_i915_private {
91 drm_dma_handle_t *status_page_dmah; 90 drm_dma_handle_t *status_page_dmah;
92 void *hw_status_page; 91 void *hw_status_page;
93 dma_addr_t dma_status_page; 92 dma_addr_t dma_status_page;
94 uint32_t counter; 93 unsigned long counter;
95 unsigned int status_gfx_addr; 94 unsigned int status_gfx_addr;
96 drm_local_map_t hws_map; 95 drm_local_map_t hws_map;
97 96
@@ -104,18 +103,13 @@ typedef struct drm_i915_private {
104 103
105 wait_queue_head_t irq_queue; 104 wait_queue_head_t irq_queue;
106 atomic_t irq_received; 105 atomic_t irq_received;
107 atomic_t irq_emited; 106 atomic_t irq_emitted;
108 107
109 int tex_lru_log_granularity; 108 int tex_lru_log_granularity;
110 int allow_batchbuffer; 109 int allow_batchbuffer;
111 struct mem_block *agp_heap; 110 struct mem_block *agp_heap;
112 unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; 111 unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
113 int vblank_pipe; 112 int vblank_pipe;
114 spinlock_t user_irq_lock;
115 int user_irq_refcount;
116 int fence_irq_on;
117 uint32_t irq_enable_reg;
118 int irq_enabled;
119 113
120 spinlock_t swaps_lock; 114 spinlock_t swaps_lock;
121 drm_i915_vbl_swap_t vbl_swaps; 115 drm_i915_vbl_swap_t vbl_swaps;
@@ -222,7 +216,7 @@ extern void i915_driver_preclose(struct drm_device *dev,
222extern int i915_driver_device_is_agp(struct drm_device * dev); 216extern int i915_driver_device_is_agp(struct drm_device * dev);
223extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, 217extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
224 unsigned long arg); 218 unsigned long arg);
225extern void i915_dispatch_flip(struct drm_device * dev, int pipes, int sync); 219
226/* i915_irq.c */ 220/* i915_irq.c */
227extern int i915_irq_emit(struct drm_device *dev, void *data, 221extern int i915_irq_emit(struct drm_device *dev, void *data,
228 struct drm_file *file_priv); 222 struct drm_file *file_priv);
@@ -233,7 +227,7 @@ extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequenc
233extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence); 227extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
234extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); 228extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
235extern void i915_driver_irq_preinstall(struct drm_device * dev); 229extern void i915_driver_irq_preinstall(struct drm_device * dev);
236extern int i915_driver_irq_postinstall(struct drm_device * dev); 230extern void i915_driver_irq_postinstall(struct drm_device * dev);
237extern void i915_driver_irq_uninstall(struct drm_device * dev); 231extern void i915_driver_irq_uninstall(struct drm_device * dev);
238extern int i915_vblank_pipe_set(struct drm_device *dev, void *data, 232extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
239 struct drm_file *file_priv); 233 struct drm_file *file_priv);
@@ -241,9 +235,6 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
241 struct drm_file *file_priv); 235 struct drm_file *file_priv);
242extern int i915_vblank_swap(struct drm_device *dev, void *data, 236extern int i915_vblank_swap(struct drm_device *dev, void *data,
243 struct drm_file *file_priv); 237 struct drm_file *file_priv);
244extern int i915_enable_vblank(struct drm_device *dev, int crtc);
245extern void i915_disable_vblank(struct drm_device *dev, int crtc);
246extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
247 238
248/* i915_mem.c */ 239/* i915_mem.c */
249extern int i915_mem_alloc(struct drm_device *dev, void *data, 240extern int i915_mem_alloc(struct drm_device *dev, void *data,
@@ -388,91 +379,21 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
388 379
389/* Interrupt bits: 380/* Interrupt bits:
390 */ 381 */
391#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) 382#define USER_INT_FLAG (1<<1)
392#define I915_DISPLAY_PORT_INTERRUPT (1<<17) 383#define VSYNC_PIPEB_FLAG (1<<5)
393#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15) 384#define VSYNC_PIPEA_FLAG (1<<7)
394#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14) 385#define HWB_OOM_FLAG (1<<13) /* binner out of memory */
395#define I915_HWB_OOM_INTERRUPT (1<<13) /* binner out of memory */
396#define I915_SYNC_STATUS_INTERRUPT (1<<12)
397#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11)
398#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10)
399#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT (1<<9)
400#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8)
401#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT (1<<7)
402#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT (1<<6)
403#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT (1<<5)
404#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4)
405#define I915_DEBUG_INTERRUPT (1<<2)
406#define I915_USER_INTERRUPT (1<<1)
407
408 386
409#define I915REG_HWSTAM 0x02098 387#define I915REG_HWSTAM 0x02098
410#define I915REG_INT_IDENTITY_R 0x020a4 388#define I915REG_INT_IDENTITY_R 0x020a4
411#define I915REG_INT_MASK_R 0x020a8 389#define I915REG_INT_MASK_R 0x020a8
412#define I915REG_INT_ENABLE_R 0x020a0 390#define I915REG_INT_ENABLE_R 0x020a0
413#define I915REG_INSTPM 0x020c0
414
415#define PIPEADSL 0x70000
416#define PIPEBDSL 0x71000
417 391
418#define I915REG_PIPEASTAT 0x70024 392#define I915REG_PIPEASTAT 0x70024
419#define I915REG_PIPEBSTAT 0x71024 393#define I915REG_PIPEBSTAT 0x71024
420/*
421 * The two pipe frame counter registers are not synchronized, so
422 * reading a stable value is somewhat tricky. The following code
423 * should work:
424 *
425 * do {
426 * high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
427 * PIPE_FRAME_HIGH_SHIFT;
428 * low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
429 * PIPE_FRAME_LOW_SHIFT);
430 * high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
431 * PIPE_FRAME_HIGH_SHIFT);
432 * } while (high1 != high2);
433 * frame = (high1 << 8) | low1;
434 */
435#define PIPEAFRAMEHIGH 0x70040
436#define PIPEBFRAMEHIGH 0x71040
437#define PIPE_FRAME_HIGH_MASK 0x0000ffff
438#define PIPE_FRAME_HIGH_SHIFT 0
439#define PIPEAFRAMEPIXEL 0x70044
440#define PIPEBFRAMEPIXEL 0x71044
441 394
442#define PIPE_FRAME_LOW_MASK 0xff000000 395#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
443#define PIPE_FRAME_LOW_SHIFT 24 396#define I915_VBLANK_CLEAR (1UL<<1)
444/*
445 * Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register
446 * and is 24 bits wide.
447 */
448#define PIPE_PIXEL_MASK 0x00ffffff
449#define PIPE_PIXEL_SHIFT 0
450
451#define I915_FIFO_UNDERRUN_STATUS (1UL<<31)
452#define I915_CRC_ERROR_ENABLE (1UL<<29)
453#define I915_CRC_DONE_ENABLE (1UL<<28)
454#define I915_GMBUS_EVENT_ENABLE (1UL<<27)
455#define I915_VSYNC_INTERRUPT_ENABLE (1UL<<25)
456#define I915_DISPLAY_LINE_COMPARE_ENABLE (1UL<<24)
457#define I915_DPST_EVENT_ENABLE (1UL<<23)
458#define I915_LEGACY_BLC_EVENT_ENABLE (1UL<<22)
459#define I915_ODD_FIELD_INTERRUPT_ENABLE (1UL<<21)
460#define I915_EVEN_FIELD_INTERRUPT_ENABLE (1UL<<20)
461#define I915_START_VBLANK_INTERRUPT_ENABLE (1UL<<18) /* 965 or later */
462#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
463#define I915_OVERLAY_UPDATED_ENABLE (1UL<<16)
464#define I915_CRC_ERROR_INTERRUPT_STATUS (1UL<<13)
465#define I915_CRC_DONE_INTERRUPT_STATUS (1UL<<12)
466#define I915_GMBUS_INTERRUPT_STATUS (1UL<<11)
467#define I915_VSYNC_INTERRUPT_STATUS (1UL<<9)
468#define I915_DISPLAY_LINE_COMPARE_STATUS (1UL<<8)
469#define I915_DPST_EVENT_STATUS (1UL<<7)
470#define I915_LEGACY_BLC_EVENT_STATUS (1UL<<6)
471#define I915_ODD_FIELD_INTERRUPT_STATUS (1UL<<5)
472#define I915_EVEN_FIELD_INTERRUPT_STATUS (1UL<<4)
473#define I915_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */
474#define I915_VBLANK_INTERRUPT_STATUS (1UL<<1)
475#define I915_OVERLAY_UPDATED_STATUS (1UL<<0)
476 397
477#define SRX_INDEX 0x3c4 398#define SRX_INDEX 0x3c4
478#define SRX_DATA 0x3c5 399#define SRX_DATA 0x3c5
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index 023ce66ef3ab..f7f16e7a8bf3 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -38,109 +38,6 @@
38#define MAX_NOPID ((u32)~0) 38#define MAX_NOPID ((u32)~0)
39 39
40/** 40/**
41 * i915_get_pipe - return the the pipe associated with a given plane
42 * @dev: DRM device
43 * @plane: plane to look for
44 *
45 * The Intel Mesa & 2D drivers call the vblank routines with a plane number
46 * rather than a pipe number, since they may not always be equal. This routine
47 * maps the given @plane back to a pipe number.
48 */
49static int
50i915_get_pipe(struct drm_device *dev, int plane)
51{
52 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
53 u32 dspcntr;
54
55 dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
56
57 return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
58}
59
60/**
61 * i915_get_plane - return the the plane associated with a given pipe
62 * @dev: DRM device
63 * @pipe: pipe to look for
64 *
65 * The Intel Mesa & 2D drivers call the vblank routines with a plane number
66 * rather than a plane number, since they may not always be equal. This routine
67 * maps the given @pipe back to a plane number.
68 */
69static int
70i915_get_plane(struct drm_device *dev, int pipe)
71{
72 if (i915_get_pipe(dev, 0) == pipe)
73 return 0;
74 return 1;
75}
76
77/**
78 * i915_pipe_enabled - check if a pipe is enabled
79 * @dev: DRM device
80 * @pipe: pipe to check
81 *
82 * Reading certain registers when the pipe is disabled can hang the chip.
83 * Use this routine to make sure the PLL is running and the pipe is active
84 * before reading such registers if unsure.
85 */
86static int
87i915_pipe_enabled(struct drm_device *dev, int pipe)
88{
89 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
90 unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
91
92 if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
93 return 1;
94
95 return 0;
96}
97
98/**
99 * Emit a synchronous flip.
100 *
101 * This function must be called with the drawable spinlock held.
102 */
103static void
104i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw,
105 int plane)
106{
107 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
108 drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
109 u16 x1, y1, x2, y2;
110 int pf_planes = 1 << plane;
111
112 /* If the window is visible on the other plane, we have to flip on that
113 * plane as well.
114 */
115 if (plane == 1) {
116 x1 = sarea_priv->planeA_x;
117 y1 = sarea_priv->planeA_y;
118 x2 = x1 + sarea_priv->planeA_w;
119 y2 = y1 + sarea_priv->planeA_h;
120 } else {
121 x1 = sarea_priv->planeB_x;
122 y1 = sarea_priv->planeB_y;
123 x2 = x1 + sarea_priv->planeB_w;
124 y2 = y1 + sarea_priv->planeB_h;
125 }
126
127 if (x2 > 0 && y2 > 0) {
128 int i, num_rects = drw->num_rects;
129 struct drm_clip_rect *rect = drw->rects;
130
131 for (i = 0; i < num_rects; i++)
132 if (!(rect[i].x1 >= x2 || rect[i].y1 >= y2 ||
133 rect[i].x2 <= x1 || rect[i].y2 <= y1)) {
134 pf_planes = 0x3;
135
136 break;
137 }
138 }
139
140 i915_dispatch_flip(dev, pf_planes, 1);
141}
142
143/**
144 * Emit blits for scheduled buffer swaps. 41 * Emit blits for scheduled buffer swaps.
145 * 42 *
146 * This function will be called with the HW lock held. 43 * This function will be called with the HW lock held.
@@ -148,19 +45,20 @@ i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw,
148static void i915_vblank_tasklet(struct drm_device *dev) 45static void i915_vblank_tasklet(struct drm_device *dev)
149{ 46{
150 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 47 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
48 unsigned long irqflags;
151 struct list_head *list, *tmp, hits, *hit; 49 struct list_head *list, *tmp, hits, *hit;
152 int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages; 50 int nhits, nrects, slice[2], upper[2], lower[2], i;
153 unsigned counter[2]; 51 unsigned counter[2] = { atomic_read(&dev->vbl_received),
52 atomic_read(&dev->vbl_received2) };
154 struct drm_drawable_info *drw; 53 struct drm_drawable_info *drw;
155 drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; 54 drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
156 u32 cpp = dev_priv->cpp, offsets[3]; 55 u32 cpp = dev_priv->cpp;
157 u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD | 56 u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
158 XY_SRC_COPY_BLT_WRITE_ALPHA | 57 XY_SRC_COPY_BLT_WRITE_ALPHA |
159 XY_SRC_COPY_BLT_WRITE_RGB) 58 XY_SRC_COPY_BLT_WRITE_RGB)
160 : XY_SRC_COPY_BLT_CMD; 59 : XY_SRC_COPY_BLT_CMD;
161 u32 src_pitch = sarea_priv->pitch * cpp; 60 u32 src_pitch = sarea_priv->pitch * cpp;
162 u32 dst_pitch = sarea_priv->pitch * cpp; 61 u32 dst_pitch = sarea_priv->pitch * cpp;
163 /* COPY rop (0xcc), map cpp to magic color depth constants */
164 u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24); 62 u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24);
165 RING_LOCALS; 63 RING_LOCALS;
166 64
@@ -173,34 +71,24 @@ static void i915_vblank_tasklet(struct drm_device *dev)
173 src_pitch >>= 2; 71 src_pitch >>= 2;
174 } 72 }
175 73
176 counter[0] = drm_vblank_count(dev, 0);
177 counter[1] = drm_vblank_count(dev, 1);
178
179 DRM_DEBUG("\n"); 74 DRM_DEBUG("\n");
180 75
181 INIT_LIST_HEAD(&hits); 76 INIT_LIST_HEAD(&hits);
182 77
183 nhits = nrects = 0; 78 nhits = nrects = 0;
184 79
185 /* No irqsave/restore necessary. This tasklet may be run in an 80 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
186 * interrupt context or normal context, but we don't have to worry
187 * about getting interrupted by something acquiring the lock, because
188 * we are the interrupt context thing that acquires the lock.
189 */
190 spin_lock(&dev_priv->swaps_lock);
191 81
192 /* Find buffer swaps scheduled for this vertical blank */ 82 /* Find buffer swaps scheduled for this vertical blank */
193 list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { 83 list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
194 drm_i915_vbl_swap_t *vbl_swap = 84 drm_i915_vbl_swap_t *vbl_swap =
195 list_entry(list, drm_i915_vbl_swap_t, head); 85 list_entry(list, drm_i915_vbl_swap_t, head);
196 int pipe = i915_get_pipe(dev, vbl_swap->plane);
197 86
198 if ((counter[pipe] - vbl_swap->sequence) > (1<<23)) 87 if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
199 continue; 88 continue;
200 89
201 list_del(list); 90 list_del(list);
202 dev_priv->swaps_pending--; 91 dev_priv->swaps_pending--;
203 drm_vblank_put(dev, pipe);
204 92
205 spin_unlock(&dev_priv->swaps_lock); 93 spin_unlock(&dev_priv->swaps_lock);
206 spin_lock(&dev->drw_lock); 94 spin_lock(&dev->drw_lock);
@@ -238,23 +126,43 @@ static void i915_vblank_tasklet(struct drm_device *dev)
238 spin_lock(&dev_priv->swaps_lock); 126 spin_lock(&dev_priv->swaps_lock);
239 } 127 }
240 128
241 spin_unlock(&dev_priv->swaps_lock); 129 if (nhits == 0) {
242 130 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
243 if (nhits == 0)
244 return; 131 return;
132 }
133
134 spin_unlock(&dev_priv->swaps_lock);
245 135
246 i915_kernel_lost_context(dev); 136 i915_kernel_lost_context(dev);
247 137
248 upper[0] = upper[1] = 0; 138 if (IS_I965G(dev)) {
249 slice[0] = max(sarea_priv->planeA_h / nhits, 1); 139 BEGIN_LP_RING(4);
250 slice[1] = max(sarea_priv->planeB_h / nhits, 1); 140
251 lower[0] = sarea_priv->planeA_y + slice[0]; 141 OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
252 lower[1] = sarea_priv->planeB_y + slice[0]; 142 OUT_RING(0);
143 OUT_RING(((sarea_priv->width - 1) & 0xffff) | ((sarea_priv->height - 1) << 16));
144 OUT_RING(0);
145 ADVANCE_LP_RING();
146 } else {
147 BEGIN_LP_RING(6);
253 148
254 offsets[0] = sarea_priv->front_offset; 149 OUT_RING(GFX_OP_DRAWRECT_INFO);
255 offsets[1] = sarea_priv->back_offset; 150 OUT_RING(0);
256 offsets[2] = sarea_priv->third_offset; 151 OUT_RING(0);
257 num_pages = sarea_priv->third_handle ? 3 : 2; 152 OUT_RING(sarea_priv->width | sarea_priv->height << 16);
153 OUT_RING(sarea_priv->width | sarea_priv->height << 16);
154 OUT_RING(0);
155
156 ADVANCE_LP_RING();
157 }
158
159 sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
160
161 upper[0] = upper[1] = 0;
162 slice[0] = max(sarea_priv->pipeA_h / nhits, 1);
163 slice[1] = max(sarea_priv->pipeB_h / nhits, 1);
164 lower[0] = sarea_priv->pipeA_y + slice[0];
165 lower[1] = sarea_priv->pipeB_y + slice[0];
258 166
259 spin_lock(&dev->drw_lock); 167 spin_lock(&dev->drw_lock);
260 168
@@ -266,8 +174,6 @@ static void i915_vblank_tasklet(struct drm_device *dev)
266 for (i = 0; i++ < nhits; 174 for (i = 0; i++ < nhits;
267 upper[0] = lower[0], lower[0] += slice[0], 175 upper[0] = lower[0], lower[0] += slice[0],
268 upper[1] = lower[1], lower[1] += slice[1]) { 176 upper[1] = lower[1], lower[1] += slice[1]) {
269 int init_drawrect = 1;
270
271 if (i == nhits) 177 if (i == nhits)
272 lower[0] = lower[1] = sarea_priv->height; 178 lower[0] = lower[1] = sarea_priv->height;
273 179
@@ -275,7 +181,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
275 drm_i915_vbl_swap_t *swap_hit = 181 drm_i915_vbl_swap_t *swap_hit =
276 list_entry(hit, drm_i915_vbl_swap_t, head); 182 list_entry(hit, drm_i915_vbl_swap_t, head);
277 struct drm_clip_rect *rect; 183 struct drm_clip_rect *rect;
278 int num_rects, plane, front, back; 184 int num_rects, pipe;
279 unsigned short top, bottom; 185 unsigned short top, bottom;
280 186
281 drw = drm_get_drawable_info(dev, swap_hit->drw_id); 187 drw = drm_get_drawable_info(dev, swap_hit->drw_id);
@@ -283,50 +189,10 @@ static void i915_vblank_tasklet(struct drm_device *dev)
283 if (!drw) 189 if (!drw)
284 continue; 190 continue;
285 191
286 plane = swap_hit->plane;
287
288 if (swap_hit->flip) {
289 i915_dispatch_vsync_flip(dev, drw, plane);
290 continue;
291 }
292
293 if (init_drawrect) {
294 int width = sarea_priv->width;
295 int height = sarea_priv->height;
296 if (IS_I965G(dev)) {
297 BEGIN_LP_RING(4);
298
299 OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
300 OUT_RING(0);
301 OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
302 OUT_RING(0);
303
304 ADVANCE_LP_RING();
305 } else {
306 BEGIN_LP_RING(6);
307
308 OUT_RING(GFX_OP_DRAWRECT_INFO);
309 OUT_RING(0);
310 OUT_RING(0);
311 OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
312 OUT_RING(0);
313 OUT_RING(0);
314
315 ADVANCE_LP_RING();
316 }
317
318 sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
319
320 init_drawrect = 0;
321 }
322
323 rect = drw->rects; 192 rect = drw->rects;
324 top = upper[plane]; 193 pipe = swap_hit->pipe;
325 bottom = lower[plane]; 194 top = upper[pipe];
326 195 bottom = lower[pipe];
327 front = (dev_priv->sarea_priv->pf_current_page >>
328 (2 * plane)) & 0x3;
329 back = (front + 1) % num_pages;
330 196
331 for (num_rects = drw->num_rects; num_rects--; rect++) { 197 for (num_rects = drw->num_rects; num_rects--; rect++) {
332 int y1 = max(rect->y1, top); 198 int y1 = max(rect->y1, top);
@@ -341,17 +207,17 @@ static void i915_vblank_tasklet(struct drm_device *dev)
341 OUT_RING(ropcpp | dst_pitch); 207 OUT_RING(ropcpp | dst_pitch);
342 OUT_RING((y1 << 16) | rect->x1); 208 OUT_RING((y1 << 16) | rect->x1);
343 OUT_RING((y2 << 16) | rect->x2); 209 OUT_RING((y2 << 16) | rect->x2);
344 OUT_RING(offsets[front]); 210 OUT_RING(sarea_priv->front_offset);
345 OUT_RING((y1 << 16) | rect->x1); 211 OUT_RING((y1 << 16) | rect->x1);
346 OUT_RING(src_pitch); 212 OUT_RING(src_pitch);
347 OUT_RING(offsets[back]); 213 OUT_RING(sarea_priv->back_offset);
348 214
349 ADVANCE_LP_RING(); 215 ADVANCE_LP_RING();
350 } 216 }
351 } 217 }
352 } 218 }
353 219
354 spin_unlock(&dev->drw_lock); 220 spin_unlock_irqrestore(&dev->drw_lock, irqflags);
355 221
356 list_for_each_safe(hit, tmp, &hits) { 222 list_for_each_safe(hit, tmp, &hits) {
357 drm_i915_vbl_swap_t *swap_hit = 223 drm_i915_vbl_swap_t *swap_hit =
@@ -363,112 +229,67 @@ static void i915_vblank_tasklet(struct drm_device *dev)
363 } 229 }
364} 230}
365 231
366u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
367{
368 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
369 unsigned long high_frame;
370 unsigned long low_frame;
371 u32 high1, high2, low, count;
372 int pipe;
373
374 pipe = i915_get_pipe(dev, plane);
375 high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
376 low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
377
378 if (!i915_pipe_enabled(dev, pipe)) {
379 printk(KERN_ERR "trying to get vblank count for disabled "
380 "pipe %d\n", pipe);
381 return 0;
382 }
383
384 /*
385 * High & low register fields aren't synchronized, so make sure
386 * we get a low value that's stable across two reads of the high
387 * register.
388 */
389 do {
390 high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
391 PIPE_FRAME_HIGH_SHIFT);
392 low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
393 PIPE_FRAME_LOW_SHIFT);
394 high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
395 PIPE_FRAME_HIGH_SHIFT);
396 } while (high1 != high2);
397
398 count = (high1 << 8) | low;
399
400 /* count may be reset by other driver(e.g. 2D driver),
401 we have no way to know if it is wrapped or resetted
402 when count is zero. do a rough guess.
403 */
404 if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2)
405 dev->last_vblank[pipe] = 0;
406
407 return count;
408}
409
410irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) 232irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
411{ 233{
412 struct drm_device *dev = (struct drm_device *) arg; 234 struct drm_device *dev = (struct drm_device *) arg;
413 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 235 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
414 u32 iir; 236 u16 temp;
415 u32 pipea_stats, pipeb_stats; 237 u32 pipea_stats, pipeb_stats;
416 int vblank = 0;
417
418 iir = I915_READ(I915REG_INT_IDENTITY_R);
419 if (iir == 0) {
420 DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n",
421 iir,
422 I915_READ(I915REG_INT_MASK_R),
423 I915_READ(I915REG_INT_ENABLE_R),
424 I915_READ(I915REG_PIPEASTAT),
425 I915_READ(I915REG_PIPEBSTAT));
426 return IRQ_NONE;
427 }
428 238
429 /* 239 pipea_stats = I915_READ(I915REG_PIPEASTAT);
430 * Clear the PIPE(A|B)STAT regs before the IIR otherwise 240 pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
431 * we may get extra interrupts.
432 */
433 if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
434 pipea_stats = I915_READ(I915REG_PIPEASTAT);
435 if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
436 I915_VBLANK_INTERRUPT_STATUS))
437 {
438 vblank++;
439 drm_handle_vblank(dev, i915_get_plane(dev, 0));
440 }
441 I915_WRITE(I915REG_PIPEASTAT, pipea_stats);
442 }
443 if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
444 pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
445 if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
446 I915_VBLANK_INTERRUPT_STATUS))
447 {
448 vblank++;
449 drm_handle_vblank(dev, i915_get_plane(dev, 1));
450 }
451 I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats);
452 }
453 241
454 if (dev_priv->sarea_priv) 242 temp = I915_READ16(I915REG_INT_IDENTITY_R);
455 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
456 243
457 I915_WRITE(I915REG_INT_IDENTITY_R, iir); 244 temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
458 (void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */
459 245
460 if (iir & I915_USER_INTERRUPT) { 246 DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
247
248 if (temp == 0)
249 return IRQ_NONE;
250
251 I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
252 (void) I915_READ16(I915REG_INT_IDENTITY_R);
253 DRM_READMEMORYBARRIER();
254
255 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
256
257 if (temp & USER_INT_FLAG)
461 DRM_WAKEUP(&dev_priv->irq_queue); 258 DRM_WAKEUP(&dev_priv->irq_queue);
462 } 259
463 if (vblank) { 260 if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
261 int vblank_pipe = dev_priv->vblank_pipe;
262
263 if ((vblank_pipe &
264 (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
265 == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
266 if (temp & VSYNC_PIPEA_FLAG)
267 atomic_inc(&dev->vbl_received);
268 if (temp & VSYNC_PIPEB_FLAG)
269 atomic_inc(&dev->vbl_received2);
270 } else if (((temp & VSYNC_PIPEA_FLAG) &&
271 (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
272 ((temp & VSYNC_PIPEB_FLAG) &&
273 (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
274 atomic_inc(&dev->vbl_received);
275
276 DRM_WAKEUP(&dev->vbl_queue);
277 drm_vbl_send_signals(dev);
278
464 if (dev_priv->swaps_pending > 0) 279 if (dev_priv->swaps_pending > 0)
465 drm_locked_tasklet(dev, i915_vblank_tasklet); 280 drm_locked_tasklet(dev, i915_vblank_tasklet);
281 I915_WRITE(I915REG_PIPEASTAT,
282 pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
283 I915_VBLANK_CLEAR);
284 I915_WRITE(I915REG_PIPEBSTAT,
285 pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
286 I915_VBLANK_CLEAR);
466 } 287 }
467 288
468 return IRQ_HANDLED; 289 return IRQ_HANDLED;
469} 290}
470 291
471static int i915_emit_irq(struct drm_device *dev) 292static int i915_emit_irq(struct drm_device * dev)
472{ 293{
473 drm_i915_private_t *dev_priv = dev->dev_private; 294 drm_i915_private_t *dev_priv = dev->dev_private;
474 RING_LOCALS; 295 RING_LOCALS;
@@ -515,12 +336,42 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
515 READ_BREADCRUMB(dev_priv), (int)dev_priv->counter); 336 READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
516 } 337 }
517 338
518 if (dev_priv->sarea_priv) 339 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
519 dev_priv->sarea_priv->last_dispatch =
520 READ_BREADCRUMB(dev_priv);
521 return ret; 340 return ret;
522} 341}
523 342
343static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
344 atomic_t *counter)
345{
346 drm_i915_private_t *dev_priv = dev->dev_private;
347 unsigned int cur_vblank;
348 int ret = 0;
349
350 if (!dev_priv) {
351 DRM_ERROR("called with no initialization\n");
352 return -EINVAL;
353 }
354
355 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
356 (((cur_vblank = atomic_read(counter))
357 - *sequence) <= (1<<23)));
358
359 *sequence = cur_vblank;
360
361 return ret;
362}
363
364
365int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
366{
367 return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
368}
369
370int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
371{
372 return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
373}
374
524/* Needs the lock as it touches the ring. 375/* Needs the lock as it touches the ring.
525 */ 376 */
526int i915_irq_emit(struct drm_device *dev, void *data, 377int i915_irq_emit(struct drm_device *dev, void *data,
@@ -563,96 +414,18 @@ int i915_irq_wait(struct drm_device *dev, void *data,
563 return i915_wait_irq(dev, irqwait->irq_seq); 414 return i915_wait_irq(dev, irqwait->irq_seq);
564} 415}
565 416
566int i915_enable_vblank(struct drm_device *dev, int plane)
567{
568 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
569 int pipe = i915_get_pipe(dev, plane);
570 u32 pipestat_reg = 0;
571 u32 pipestat;
572
573 switch (pipe) {
574 case 0:
575 pipestat_reg = I915REG_PIPEASTAT;
576 dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
577 break;
578 case 1:
579 pipestat_reg = I915REG_PIPEBSTAT;
580 dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
581 break;
582 default:
583 DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
584 pipe);
585 break;
586 }
587
588 if (pipestat_reg)
589 {
590 pipestat = I915_READ (pipestat_reg);
591 /*
592 * Older chips didn't have the start vblank interrupt,
593 * but
594 */
595 if (IS_I965G (dev))
596 pipestat |= I915_START_VBLANK_INTERRUPT_ENABLE;
597 else
598 pipestat |= I915_VBLANK_INTERRUPT_ENABLE;
599 /*
600 * Clear any pending status
601 */
602 pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
603 I915_VBLANK_INTERRUPT_STATUS);
604 I915_WRITE(pipestat_reg, pipestat);
605 }
606 I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
607
608 return 0;
609}
610
611void i915_disable_vblank(struct drm_device *dev, int plane)
612{
613 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
614 int pipe = i915_get_pipe(dev, plane);
615 u32 pipestat_reg = 0;
616 u32 pipestat;
617
618 switch (pipe) {
619 case 0:
620 pipestat_reg = I915REG_PIPEASTAT;
621 dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
622 break;
623 case 1:
624 pipestat_reg = I915REG_PIPEBSTAT;
625 dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
626 break;
627 default:
628 DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
629 pipe);
630 break;
631 }
632
633 I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
634 if (pipestat_reg)
635 {
636 pipestat = I915_READ (pipestat_reg);
637 pipestat &= ~(I915_START_VBLANK_INTERRUPT_ENABLE |
638 I915_VBLANK_INTERRUPT_ENABLE);
639 /*
640 * Clear any pending status
641 */
642 pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
643 I915_VBLANK_INTERRUPT_STATUS);
644 I915_WRITE(pipestat_reg, pipestat);
645 }
646}
647
648static void i915_enable_interrupt (struct drm_device *dev) 417static void i915_enable_interrupt (struct drm_device *dev)
649{ 418{
650 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 419 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
420 u16 flag;
651 421
652 dev_priv->irq_enable_reg |= I915_USER_INTERRUPT; 422 flag = 0;
423 if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
424 flag |= VSYNC_PIPEA_FLAG;
425 if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
426 flag |= VSYNC_PIPEB_FLAG;
653 427
654 I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); 428 I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
655 dev_priv->irq_enabled = 1;
656} 429}
657 430
658/* Set the vblank monitor pipe 431/* Set the vblank monitor pipe
@@ -675,6 +448,8 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,
675 448
676 dev_priv->vblank_pipe = pipe->pipe; 449 dev_priv->vblank_pipe = pipe->pipe;
677 450
451 i915_enable_interrupt (dev);
452
678 return 0; 453 return 0;
679} 454}
680 455
@@ -692,9 +467,9 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
692 467
693 flag = I915_READ(I915REG_INT_ENABLE_R); 468 flag = I915_READ(I915REG_INT_ENABLE_R);
694 pipe->pipe = 0; 469 pipe->pipe = 0;
695 if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) 470 if (flag & VSYNC_PIPEA_FLAG)
696 pipe->pipe |= DRM_I915_VBLANK_PIPE_A; 471 pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
697 if (flag & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) 472 if (flag & VSYNC_PIPEB_FLAG)
698 pipe->pipe |= DRM_I915_VBLANK_PIPE_B; 473 pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
699 474
700 return 0; 475 return 0;
@@ -709,30 +484,27 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
709 drm_i915_private_t *dev_priv = dev->dev_private; 484 drm_i915_private_t *dev_priv = dev->dev_private;
710 drm_i915_vblank_swap_t *swap = data; 485 drm_i915_vblank_swap_t *swap = data;
711 drm_i915_vbl_swap_t *vbl_swap; 486 drm_i915_vbl_swap_t *vbl_swap;
712 unsigned int pipe, seqtype, curseq, plane; 487 unsigned int pipe, seqtype, curseq;
713 unsigned long irqflags; 488 unsigned long irqflags;
714 struct list_head *list; 489 struct list_head *list;
715 int ret;
716 490
717 if (!dev_priv) { 491 if (!dev_priv) {
718 DRM_ERROR("%s called with no initialization\n", __func__); 492 DRM_ERROR("%s called with no initialization\n", __func__);
719 return -EINVAL; 493 return -EINVAL;
720 } 494 }
721 495
722 if (!dev_priv->sarea_priv || dev_priv->sarea_priv->rotation) { 496 if (dev_priv->sarea_priv->rotation) {
723 DRM_DEBUG("Rotation not supported\n"); 497 DRM_DEBUG("Rotation not supported\n");
724 return -EINVAL; 498 return -EINVAL;
725 } 499 }
726 500
727 if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE | 501 if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
728 _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS | 502 _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
729 _DRM_VBLANK_FLIP)) {
730 DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype); 503 DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype);
731 return -EINVAL; 504 return -EINVAL;
732 } 505 }
733 506
734 plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; 507 pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
735 pipe = i915_get_pipe(dev, plane);
736 508
737 seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); 509 seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
738 510
@@ -743,11 +515,6 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
743 515
744 spin_lock_irqsave(&dev->drw_lock, irqflags); 516 spin_lock_irqsave(&dev->drw_lock, irqflags);
745 517
746 /* It makes no sense to schedule a swap for a drawable that doesn't have
747 * valid information at this point. E.g. this could mean that the X
748 * server is too old to push drawable information to the DRM, in which
749 * case all such swaps would become ineffective.
750 */
751 if (!drm_get_drawable_info(dev, swap->drawable)) { 518 if (!drm_get_drawable_info(dev, swap->drawable)) {
752 spin_unlock_irqrestore(&dev->drw_lock, irqflags); 519 spin_unlock_irqrestore(&dev->drw_lock, irqflags);
753 DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable); 520 DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable);
@@ -756,8 +523,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
756 523
757 spin_unlock_irqrestore(&dev->drw_lock, irqflags); 524 spin_unlock_irqrestore(&dev->drw_lock, irqflags);
758 525
759 drm_update_vblank_count(dev, pipe); 526 curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
760 curseq = drm_vblank_count(dev, pipe);
761 527
762 if (seqtype == _DRM_VBLANK_RELATIVE) 528 if (seqtype == _DRM_VBLANK_RELATIVE)
763 swap->sequence += curseq; 529 swap->sequence += curseq;
@@ -771,43 +537,14 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
771 } 537 }
772 } 538 }
773 539
774 if (swap->seqtype & _DRM_VBLANK_FLIP) {
775 swap->sequence--;
776
777 if ((curseq - swap->sequence) <= (1<<23)) {
778 struct drm_drawable_info *drw;
779
780 LOCK_TEST_WITH_RETURN(dev, file_priv);
781
782 spin_lock_irqsave(&dev->drw_lock, irqflags);
783
784 drw = drm_get_drawable_info(dev, swap->drawable);
785
786 if (!drw) {
787 spin_unlock_irqrestore(&dev->drw_lock,
788 irqflags);
789 DRM_DEBUG("Invalid drawable ID %d\n",
790 swap->drawable);
791 return -EINVAL;
792 }
793
794 i915_dispatch_vsync_flip(dev, drw, plane);
795
796 spin_unlock_irqrestore(&dev->drw_lock, irqflags);
797
798 return 0;
799 }
800 }
801
802 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); 540 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
803 541
804 list_for_each(list, &dev_priv->vbl_swaps.head) { 542 list_for_each(list, &dev_priv->vbl_swaps.head) {
805 vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); 543 vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
806 544
807 if (vbl_swap->drw_id == swap->drawable && 545 if (vbl_swap->drw_id == swap->drawable &&
808 vbl_swap->plane == plane && 546 vbl_swap->pipe == pipe &&
809 vbl_swap->sequence == swap->sequence) { 547 vbl_swap->sequence == swap->sequence) {
810 vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
811 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); 548 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
812 DRM_DEBUG("Already scheduled\n"); 549 DRM_DEBUG("Already scheduled\n");
813 return 0; 550 return 0;
@@ -830,19 +567,9 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
830 567
831 DRM_DEBUG("\n"); 568 DRM_DEBUG("\n");
832 569
833 ret = drm_vblank_get(dev, pipe);
834 if (ret) {
835 drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
836 return ret;
837 }
838
839 vbl_swap->drw_id = swap->drawable; 570 vbl_swap->drw_id = swap->drawable;
840 vbl_swap->plane = plane; 571 vbl_swap->pipe = pipe;
841 vbl_swap->sequence = swap->sequence; 572 vbl_swap->sequence = swap->sequence;
842 vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
843
844 if (vbl_swap->flip)
845 swap->sequence++;
846 573
847 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); 574 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
848 575
@@ -860,57 +587,37 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
860{ 587{
861 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 588 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
862 589
863 I915_WRITE16(I915REG_HWSTAM, 0xeffe); 590 I915_WRITE16(I915REG_HWSTAM, 0xfffe);
864 I915_WRITE16(I915REG_INT_MASK_R, 0x0); 591 I915_WRITE16(I915REG_INT_MASK_R, 0x0);
865 I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); 592 I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
866} 593}
867 594
868int i915_driver_irq_postinstall(struct drm_device * dev) 595void i915_driver_irq_postinstall(struct drm_device * dev)
869{ 596{
870 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 597 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
871 int ret, num_pipes = 2;
872 598
873 spin_lock_init(&dev_priv->swaps_lock); 599 spin_lock_init(&dev_priv->swaps_lock);
874 INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); 600 INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
875 dev_priv->swaps_pending = 0; 601 dev_priv->swaps_pending = 0;
876 602
877 dev_priv->user_irq_refcount = 0; 603 if (!dev_priv->vblank_pipe)
878 dev_priv->irq_enable_reg = 0; 604 dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
879
880 ret = drm_vblank_init(dev, num_pipes);
881 if (ret)
882 return ret;
883
884 dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
885
886 i915_enable_interrupt(dev); 605 i915_enable_interrupt(dev);
887 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); 606 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
888
889 /*
890 * Initialize the hardware status page IRQ location.
891 */
892
893 I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21));
894 return 0;
895} 607}
896 608
897void i915_driver_irq_uninstall(struct drm_device * dev) 609void i915_driver_irq_uninstall(struct drm_device * dev)
898{ 610{
899 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 611 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
900 u32 temp; 612 u16 temp;
901 613
902 if (!dev_priv) 614 if (!dev_priv)
903 return; 615 return;
904 616
905 dev_priv->irq_enabled = 0; 617 I915_WRITE16(I915REG_HWSTAM, 0xffff);
906 I915_WRITE(I915REG_HWSTAM, 0xffffffff); 618 I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
907 I915_WRITE(I915REG_INT_MASK_R, 0xffffffff); 619 I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
908 I915_WRITE(I915REG_INT_ENABLE_R, 0x0); 620
909 621 temp = I915_READ16(I915REG_INT_IDENTITY_R);
910 temp = I915_READ(I915REG_PIPEASTAT); 622 I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
911 I915_WRITE(I915REG_PIPEASTAT, temp);
912 temp = I915_READ(I915REG_PIPEBSTAT);
913 I915_WRITE(I915REG_PIPEBSTAT, temp);
914 temp = I915_READ(I915REG_INT_IDENTITY_R);
915 I915_WRITE(I915REG_INT_IDENTITY_R, temp);
916} 623}
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index 6b3790939e76..5572939fc7d1 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -45,16 +45,15 @@ static struct pci_device_id pciidlist[] = {
45static struct drm_driver driver = { 45static struct drm_driver driver = {
46 .driver_features = 46 .driver_features =
47 DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | 47 DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
48 DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, 48 DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
49 DRIVER_IRQ_VBL,
49 .dev_priv_size = sizeof(drm_mga_buf_priv_t), 50 .dev_priv_size = sizeof(drm_mga_buf_priv_t),
50 .load = mga_driver_load, 51 .load = mga_driver_load,
51 .unload = mga_driver_unload, 52 .unload = mga_driver_unload,
52 .lastclose = mga_driver_lastclose, 53 .lastclose = mga_driver_lastclose,
53 .dma_quiescent = mga_driver_dma_quiescent, 54 .dma_quiescent = mga_driver_dma_quiescent,
54 .device_is_agp = mga_driver_device_is_agp, 55 .device_is_agp = mga_driver_device_is_agp,
55 .get_vblank_counter = mga_get_vblank_counter, 56 .vblank_wait = mga_driver_vblank_wait,
56 .enable_vblank = mga_enable_vblank,
57 .disable_vblank = mga_disable_vblank,
58 .irq_preinstall = mga_driver_irq_preinstall, 57 .irq_preinstall = mga_driver_irq_preinstall,
59 .irq_postinstall = mga_driver_irq_postinstall, 58 .irq_postinstall = mga_driver_irq_postinstall,
60 .irq_uninstall = mga_driver_irq_uninstall, 59 .irq_uninstall = mga_driver_irq_uninstall,
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index 8f7291f36363..f6ebd24bd587 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -120,7 +120,6 @@ typedef struct drm_mga_private {
120 u32 clear_cmd; 120 u32 clear_cmd;
121 u32 maccess; 121 u32 maccess;
122 122
123 atomic_t vbl_received; /**< Number of vblanks received. */
124 wait_queue_head_t fence_queue; 123 wait_queue_head_t fence_queue;
125 atomic_t last_fence_retired; 124 atomic_t last_fence_retired;
126 u32 next_fence_to_post; 125 u32 next_fence_to_post;
@@ -182,14 +181,11 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
182extern int mga_warp_init(drm_mga_private_t * dev_priv); 181extern int mga_warp_init(drm_mga_private_t * dev_priv);
183 182
184 /* mga_irq.c */ 183 /* mga_irq.c */
185extern int mga_enable_vblank(struct drm_device *dev, int crtc);
186extern void mga_disable_vblank(struct drm_device *dev, int crtc);
187extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
188extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence); 184extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
189extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence); 185extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
190extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS); 186extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
191extern void mga_driver_irq_preinstall(struct drm_device * dev); 187extern void mga_driver_irq_preinstall(struct drm_device * dev);
192extern int mga_driver_irq_postinstall(struct drm_device * dev); 188extern void mga_driver_irq_postinstall(struct drm_device * dev);
193extern void mga_driver_irq_uninstall(struct drm_device * dev); 189extern void mga_driver_irq_uninstall(struct drm_device * dev);
194extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, 190extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
195 unsigned long arg); 191 unsigned long arg);
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
index 06852fb4b278..9302cb8f0f83 100644
--- a/drivers/char/drm/mga_irq.c
+++ b/drivers/char/drm/mga_irq.c
@@ -35,20 +35,6 @@
35#include "mga_drm.h" 35#include "mga_drm.h"
36#include "mga_drv.h" 36#include "mga_drv.h"
37 37
38u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
39{
40 const drm_mga_private_t *const dev_priv =
41 (drm_mga_private_t *) dev->dev_private;
42
43 if (crtc != 0) {
44 return 0;
45 }
46
47
48 return atomic_read(&dev_priv->vbl_received);
49}
50
51
52irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) 38irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
53{ 39{
54 struct drm_device *dev = (struct drm_device *) arg; 40 struct drm_device *dev = (struct drm_device *) arg;
@@ -61,8 +47,9 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
61 /* VBLANK interrupt */ 47 /* VBLANK interrupt */
62 if (status & MGA_VLINEPEN) { 48 if (status & MGA_VLINEPEN) {
63 MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); 49 MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
64 atomic_inc(&dev_priv->vbl_received); 50 atomic_inc(&dev->vbl_received);
65 drm_handle_vblank(dev, 0); 51 DRM_WAKEUP(&dev->vbl_queue);
52 drm_vbl_send_signals(dev);
66 handled = 1; 53 handled = 1;
67 } 54 }
68 55
@@ -91,34 +78,22 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
91 return IRQ_NONE; 78 return IRQ_NONE;
92} 79}
93 80
94int mga_enable_vblank(struct drm_device *dev, int crtc) 81int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
95{ 82{
96 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; 83 unsigned int cur_vblank;
97 84 int ret = 0;
98 if (crtc != 0) {
99 DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
100 crtc);
101 return 0;
102 }
103
104 MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
105 return 0;
106}
107 85
86 /* Assume that the user has missed the current sequence number
87 * by about a day rather than she wants to wait for years
88 * using vertical blanks...
89 */
90 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
91 (((cur_vblank = atomic_read(&dev->vbl_received))
92 - *sequence) <= (1 << 23)));
108 93
109void mga_disable_vblank(struct drm_device *dev, int crtc) 94 *sequence = cur_vblank;
110{
111 if (crtc != 0) {
112 DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
113 crtc);
114 }
115 95
116 /* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have 96 return ret;
117 * a nice hardware counter that tracks the number of refreshes when
118 * the interrupt is disabled, and the kernel doesn't know the refresh
119 * rate to calculate an estimate.
120 */
121 /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
122} 97}
123 98
124int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence) 99int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
@@ -150,22 +125,14 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
150 MGA_WRITE(MGA_ICLEAR, ~0); 125 MGA_WRITE(MGA_ICLEAR, ~0);
151} 126}
152 127
153int mga_driver_irq_postinstall(struct drm_device * dev) 128void mga_driver_irq_postinstall(struct drm_device * dev)
154{ 129{
155 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; 130 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
156 int ret;
157
158 ret = drm_vblank_init(dev, 1);
159 if (ret)
160 return ret;
161 131
162 DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); 132 DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
163 133
164 /* Turn on soft trap interrupt. Vertical blank interrupts are enabled 134 /* Turn on vertical blank interrupt and soft trap interrupt. */
165 * in mga_enable_vblank. 135 MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
166 */
167 MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
168 return 0;
169} 136}
170 137
171void mga_driver_irq_uninstall(struct drm_device * dev) 138void mga_driver_irq_uninstall(struct drm_device * dev)
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
index 2888aa01ebc7..6108e7587e12 100644
--- a/drivers/char/drm/r128_drv.c
+++ b/drivers/char/drm/r128_drv.c
@@ -43,13 +43,12 @@ static struct pci_device_id pciidlist[] = {
43static struct drm_driver driver = { 43static struct drm_driver driver = {
44 .driver_features = 44 .driver_features =
45 DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | 45 DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
46 DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, 46 DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
47 DRIVER_IRQ_VBL,
47 .dev_priv_size = sizeof(drm_r128_buf_priv_t), 48 .dev_priv_size = sizeof(drm_r128_buf_priv_t),
48 .preclose = r128_driver_preclose, 49 .preclose = r128_driver_preclose,
49 .lastclose = r128_driver_lastclose, 50 .lastclose = r128_driver_lastclose,
50 .get_vblank_counter = r128_get_vblank_counter, 51 .vblank_wait = r128_driver_vblank_wait,
51 .enable_vblank = r128_enable_vblank,
52 .disable_vblank = r128_disable_vblank,
53 .irq_preinstall = r128_driver_irq_preinstall, 52 .irq_preinstall = r128_driver_irq_preinstall,
54 .irq_postinstall = r128_driver_irq_postinstall, 53 .irq_postinstall = r128_driver_irq_postinstall,
55 .irq_uninstall = r128_driver_irq_uninstall, 54 .irq_uninstall = r128_driver_irq_uninstall,
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index 80af9e09e75d..011105e51ac6 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -97,8 +97,6 @@ typedef struct drm_r128_private {
97 u32 crtc_offset; 97 u32 crtc_offset;
98 u32 crtc_offset_cntl; 98 u32 crtc_offset_cntl;
99 99
100 atomic_t vbl_received;
101
102 u32 color_fmt; 100 u32 color_fmt;
103 unsigned int front_offset; 101 unsigned int front_offset;
104 unsigned int front_pitch; 102 unsigned int front_pitch;
@@ -151,12 +149,11 @@ extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
151extern int r128_do_cce_idle(drm_r128_private_t * dev_priv); 149extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
152extern int r128_do_cleanup_cce(struct drm_device * dev); 150extern int r128_do_cleanup_cce(struct drm_device * dev);
153 151
154extern int r128_enable_vblank(struct drm_device *dev, int crtc); 152extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
155extern void r128_disable_vblank(struct drm_device *dev, int crtc); 153
156extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
157extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS); 154extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
158extern void r128_driver_irq_preinstall(struct drm_device * dev); 155extern void r128_driver_irq_preinstall(struct drm_device * dev);
159extern int r128_driver_irq_postinstall(struct drm_device * dev); 156extern void r128_driver_irq_postinstall(struct drm_device * dev);
160extern void r128_driver_irq_uninstall(struct drm_device * dev); 157extern void r128_driver_irq_uninstall(struct drm_device * dev);
161extern void r128_driver_lastclose(struct drm_device * dev); 158extern void r128_driver_lastclose(struct drm_device * dev);
162extern void r128_driver_preclose(struct drm_device * dev, 159extern void r128_driver_preclose(struct drm_device * dev,
diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
index 5b95bd898f95..c76fdca7662d 100644
--- a/drivers/char/drm/r128_irq.c
+++ b/drivers/char/drm/r128_irq.c
@@ -35,16 +35,6 @@
35#include "r128_drm.h" 35#include "r128_drm.h"
36#include "r128_drv.h" 36#include "r128_drv.h"
37 37
38u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
39{
40 const drm_r128_private_t *dev_priv = dev->dev_private;
41
42 if (crtc != 0)
43 return 0;
44
45 return atomic_read(&dev_priv->vbl_received);
46}
47
48irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS) 38irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
49{ 39{
50 struct drm_device *dev = (struct drm_device *) arg; 40 struct drm_device *dev = (struct drm_device *) arg;
@@ -56,38 +46,30 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
56 /* VBLANK interrupt */ 46 /* VBLANK interrupt */
57 if (status & R128_CRTC_VBLANK_INT) { 47 if (status & R128_CRTC_VBLANK_INT) {
58 R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); 48 R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
59 atomic_inc(&dev_priv->vbl_received); 49 atomic_inc(&dev->vbl_received);
60 drm_handle_vblank(dev, 0); 50 DRM_WAKEUP(&dev->vbl_queue);
51 drm_vbl_send_signals(dev);
61 return IRQ_HANDLED; 52 return IRQ_HANDLED;
62 } 53 }
63 return IRQ_NONE; 54 return IRQ_NONE;
64} 55}
65 56
66int r128_enable_vblank(struct drm_device *dev, int crtc) 57int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
67{ 58{
68 drm_r128_private_t *dev_priv = dev->dev_private; 59 unsigned int cur_vblank;
69 60 int ret = 0;
70 if (crtc != 0) {
71 DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
72 return -EINVAL;
73 }
74 61
75 R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN); 62 /* Assume that the user has missed the current sequence number
76 return 0; 63 * by about a day rather than she wants to wait for years
77} 64 * using vertical blanks...
65 */
66 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
67 (((cur_vblank = atomic_read(&dev->vbl_received))
68 - *sequence) <= (1 << 23)));
78 69
79void r128_disable_vblank(struct drm_device *dev, int crtc) 70 *sequence = cur_vblank;
80{
81 if (crtc != 0)
82 DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
83 71
84 /* 72 return ret;
85 * FIXME: implement proper interrupt disable by using the vblank
86 * counter register (if available)
87 *
88 * R128_WRITE(R128_GEN_INT_CNTL,
89 * R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN);
90 */
91} 73}
92 74
93void r128_driver_irq_preinstall(struct drm_device * dev) 75void r128_driver_irq_preinstall(struct drm_device * dev)
@@ -100,9 +82,12 @@ void r128_driver_irq_preinstall(struct drm_device * dev)
100 R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); 82 R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
101} 83}
102 84
103int r128_driver_irq_postinstall(struct drm_device * dev) 85void r128_driver_irq_postinstall(struct drm_device * dev)
104{ 86{
105 return drm_vblank_init(dev, 1); 87 drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
88
89 /* Turn on VBL interrupt */
90 R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
106} 91}
107 92
108void r128_driver_irq_uninstall(struct drm_device * dev) 93void r128_driver_irq_uninstall(struct drm_device * dev)
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index a2610319624d..349ac3d3b848 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -59,7 +59,8 @@ static struct pci_device_id pciidlist[] = {
59static struct drm_driver driver = { 59static struct drm_driver driver = {
60 .driver_features = 60 .driver_features =
61 DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | 61 DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
62 DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED, 62 DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
63 DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
63 .dev_priv_size = sizeof(drm_radeon_buf_priv_t), 64 .dev_priv_size = sizeof(drm_radeon_buf_priv_t),
64 .load = radeon_driver_load, 65 .load = radeon_driver_load,
65 .firstopen = radeon_driver_firstopen, 66 .firstopen = radeon_driver_firstopen,
@@ -68,9 +69,8 @@ static struct drm_driver driver = {
68 .postclose = radeon_driver_postclose, 69 .postclose = radeon_driver_postclose,
69 .lastclose = radeon_driver_lastclose, 70 .lastclose = radeon_driver_lastclose,
70 .unload = radeon_driver_unload, 71 .unload = radeon_driver_unload,
71 .get_vblank_counter = radeon_get_vblank_counter, 72 .vblank_wait = radeon_driver_vblank_wait,
72 .enable_vblank = radeon_enable_vblank, 73 .vblank_wait2 = radeon_driver_vblank_wait2,
73 .disable_vblank = radeon_disable_vblank,
74 .dri_library_name = dri_library_name, 74 .dri_library_name = dri_library_name,
75 .irq_preinstall = radeon_driver_irq_preinstall, 75 .irq_preinstall = radeon_driver_irq_preinstall,
76 .irq_postinstall = radeon_driver_irq_postinstall, 76 .irq_postinstall = radeon_driver_irq_postinstall,
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index b791420bd3d9..173ae620223a 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -304,9 +304,6 @@ typedef struct drm_radeon_private {
304 304
305 u32 scratch_ages[5]; 305 u32 scratch_ages[5];
306 306
307 unsigned int crtc_last_cnt;
308 unsigned int crtc2_last_cnt;
309
310 /* starting from here on, data is preserved accross an open */ 307 /* starting from here on, data is preserved accross an open */
311 uint32_t flags; /* see radeon_chip_flags */ 308 uint32_t flags; /* see radeon_chip_flags */
312 unsigned long fb_aper_offset; 309 unsigned long fb_aper_offset;
@@ -377,13 +374,13 @@ extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *
377extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); 374extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
378 375
379extern void radeon_do_release(struct drm_device * dev); 376extern void radeon_do_release(struct drm_device * dev);
380extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc); 377extern int radeon_driver_vblank_wait(struct drm_device * dev,
381extern int radeon_enable_vblank(struct drm_device *dev, int crtc); 378 unsigned int *sequence);
382extern void radeon_disable_vblank(struct drm_device *dev, int crtc); 379extern int radeon_driver_vblank_wait2(struct drm_device * dev,
383extern void radeon_do_release(struct drm_device * dev); 380 unsigned int *sequence);
384extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS); 381extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
385extern void radeon_driver_irq_preinstall(struct drm_device * dev); 382extern void radeon_driver_irq_preinstall(struct drm_device * dev);
386extern int radeon_driver_irq_postinstall(struct drm_device * dev); 383extern void radeon_driver_irq_postinstall(struct drm_device * dev);
387extern void radeon_driver_irq_uninstall(struct drm_device * dev); 384extern void radeon_driver_irq_uninstall(struct drm_device * dev);
388extern int radeon_vblank_crtc_get(struct drm_device *dev); 385extern int radeon_vblank_crtc_get(struct drm_device *dev);
389extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value); 386extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
@@ -561,12 +558,6 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
561 ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \ 558 ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
562 : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) 559 : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
563 560
564#define RADEON_CRTC_CRNT_FRAME 0x0214
565#define RADEON_CRTC2_CRNT_FRAME 0x0314
566
567#define RADEON_CRTC_STATUS 0x005c
568#define RADEON_CRTC2_STATUS 0x03fc
569
570#define RADEON_GEN_INT_CNTL 0x0040 561#define RADEON_GEN_INT_CNTL 0x0040
571# define RADEON_CRTC_VBLANK_MASK (1 << 0) 562# define RADEON_CRTC_VBLANK_MASK (1 << 0)
572# define RADEON_CRTC2_VBLANK_MASK (1 << 9) 563# define RADEON_CRTC2_VBLANK_MASK (1 << 9)
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index 507d6b747a13..009af3814b6f 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -35,61 +35,12 @@
35#include "radeon_drm.h" 35#include "radeon_drm.h"
36#include "radeon_drv.h" 36#include "radeon_drv.h"
37 37
38static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state) 38static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
39 u32 mask)
39{ 40{
40 drm_radeon_private_t *dev_priv = dev->dev_private; 41 u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
41
42 if (state)
43 dev_priv->irq_enable_reg |= mask;
44 else
45 dev_priv->irq_enable_reg &= ~mask;
46
47 RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
48}
49
50int radeon_enable_vblank(struct drm_device *dev, int crtc)
51{
52 switch (crtc) {
53 case 0:
54 radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
55 break;
56 case 1:
57 radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
58 break;
59 default:
60 DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
61 crtc);
62 return EINVAL;
63 }
64
65 return 0;
66}
67
68void radeon_disable_vblank(struct drm_device *dev, int crtc)
69{
70 switch (crtc) {
71 case 0:
72 radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
73 break;
74 case 1:
75 radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
76 break;
77 default:
78 DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
79 crtc);
80 break;
81 }
82}
83
84static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv)
85{
86 u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) &
87 (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
88 RADEON_CRTC2_VBLANK_STAT);
89
90 if (irqs) 42 if (irqs)
91 RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); 43 RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
92
93 return irqs; 44 return irqs;
94} 45}
95 46
@@ -121,21 +72,39 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
121 /* Only consider the bits we're interested in - others could be used 72 /* Only consider the bits we're interested in - others could be used
122 * outside the DRM 73 * outside the DRM
123 */ 74 */
124 stat = radeon_acknowledge_irqs(dev_priv); 75 stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
76 RADEON_CRTC_VBLANK_STAT |
77 RADEON_CRTC2_VBLANK_STAT));
125 if (!stat) 78 if (!stat)
126 return IRQ_NONE; 79 return IRQ_NONE;
127 80
128 stat &= dev_priv->irq_enable_reg; 81 stat &= dev_priv->irq_enable_reg;
129 82
130 /* SW interrupt */ 83 /* SW interrupt */
131 if (stat & RADEON_SW_INT_TEST) 84 if (stat & RADEON_SW_INT_TEST) {
132 DRM_WAKEUP(&dev_priv->swi_queue); 85 DRM_WAKEUP(&dev_priv->swi_queue);
86 }
133 87
134 /* VBLANK interrupt */ 88 /* VBLANK interrupt */
135 if (stat & RADEON_CRTC_VBLANK_STAT) 89 if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
136 drm_handle_vblank(dev, 0); 90 int vblank_crtc = dev_priv->vblank_crtc;
137 if (stat & RADEON_CRTC2_VBLANK_STAT) 91
138 drm_handle_vblank(dev, 1); 92 if ((vblank_crtc &
93 (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
94 (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
95 if (stat & RADEON_CRTC_VBLANK_STAT)
96 atomic_inc(&dev->vbl_received);
97 if (stat & RADEON_CRTC2_VBLANK_STAT)
98 atomic_inc(&dev->vbl_received2);
99 } else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
100 (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
101 ((stat & RADEON_CRTC2_VBLANK_STAT) &&
102 (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
103 atomic_inc(&dev->vbl_received);
104
105 DRM_WAKEUP(&dev->vbl_queue);
106 drm_vbl_send_signals(dev);
107 }
139 108
140 return IRQ_HANDLED; 109 return IRQ_HANDLED;
141} 110}
@@ -175,27 +144,54 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
175 return ret; 144 return ret;
176} 145}
177 146
178u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc) 147static int radeon_driver_vblank_do_wait(struct drm_device * dev,
148 unsigned int *sequence, int crtc)
179{ 149{
180 drm_radeon_private_t *dev_priv = dev->dev_private; 150 drm_radeon_private_t *dev_priv =
181 u32 crtc_cnt_reg, crtc_status_reg; 151 (drm_radeon_private_t *) dev->dev_private;
182 152 unsigned int cur_vblank;
153 int ret = 0;
154 int ack = 0;
155 atomic_t *counter;
183 if (!dev_priv) { 156 if (!dev_priv) {
184 DRM_ERROR("called with no initialization\n"); 157 DRM_ERROR("called with no initialization\n");
185 return -EINVAL; 158 return -EINVAL;
186 } 159 }
187 160
188 if (crtc == 0) { 161 if (crtc == DRM_RADEON_VBLANK_CRTC1) {
189 crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME; 162 counter = &dev->vbl_received;
190 crtc_status_reg = RADEON_CRTC_STATUS; 163 ack |= RADEON_CRTC_VBLANK_STAT;
191 } else if (crtc == 1) { 164 } else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
192 crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME; 165 counter = &dev->vbl_received2;
193 crtc_status_reg = RADEON_CRTC2_STATUS; 166 ack |= RADEON_CRTC2_VBLANK_STAT;
194 } else { 167 } else
195 return -EINVAL; 168 return -EINVAL;
196 }
197 169
198 return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1); 170 radeon_acknowledge_irqs(dev_priv, ack);
171
172 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
173
174 /* Assume that the user has missed the current sequence number
175 * by about a day rather than she wants to wait for years
176 * using vertical blanks...
177 */
178 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
179 (((cur_vblank = atomic_read(counter))
180 - *sequence) <= (1 << 23)));
181
182 *sequence = cur_vblank;
183
184 return ret;
185}
186
187int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
188{
189 return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
190}
191
192int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
193{
194 return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
199} 195}
200 196
201/* Needs the lock as it touches the ring. 197/* Needs the lock as it touches the ring.
@@ -238,6 +234,21 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr
238 return radeon_wait_irq(dev, irqwait->irq_seq); 234 return radeon_wait_irq(dev, irqwait->irq_seq);
239} 235}
240 236
237static void radeon_enable_interrupt(struct drm_device *dev)
238{
239 drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
240
241 dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
242 if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
243 dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
244
245 if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
246 dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
247
248 RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
249 dev_priv->irq_enabled = 1;
250}
251
241/* drm_dma.h hooks 252/* drm_dma.h hooks
242*/ 253*/
243void radeon_driver_irq_preinstall(struct drm_device * dev) 254void radeon_driver_irq_preinstall(struct drm_device * dev)
@@ -249,27 +260,20 @@ void radeon_driver_irq_preinstall(struct drm_device * dev)
249 RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); 260 RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
250 261
251 /* Clear bits if they're already high */ 262 /* Clear bits if they're already high */
252 radeon_acknowledge_irqs(dev_priv); 263 radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
264 RADEON_CRTC_VBLANK_STAT |
265 RADEON_CRTC2_VBLANK_STAT));
253} 266}
254 267
255int radeon_driver_irq_postinstall(struct drm_device * dev) 268void radeon_driver_irq_postinstall(struct drm_device * dev)
256{ 269{
257 drm_radeon_private_t *dev_priv = 270 drm_radeon_private_t *dev_priv =
258 (drm_radeon_private_t *) dev->dev_private; 271 (drm_radeon_private_t *) dev->dev_private;
259 int ret;
260 272
261 atomic_set(&dev_priv->swi_emitted, 0); 273 atomic_set(&dev_priv->swi_emitted, 0);
262 DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); 274 DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
263 275
264 ret = drm_vblank_init(dev, 2); 276 radeon_enable_interrupt(dev);
265 if (ret)
266 return ret;
267
268 dev->max_vblank_count = 0x001fffff;
269
270 radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
271
272 return 0;
273} 277}
274 278
275void radeon_driver_irq_uninstall(struct drm_device * dev) 279void radeon_driver_irq_uninstall(struct drm_device * dev)
@@ -311,5 +315,6 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
311 return -EINVAL; 315 return -EINVAL;
312 } 316 }
313 dev_priv->vblank_crtc = (unsigned int)value; 317 dev_priv->vblank_crtc = (unsigned int)value;
318 radeon_enable_interrupt(dev);
314 return 0; 319 return 0;
315} 320}
diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c
index 37870a4a3dc7..80c01cdfa37d 100644
--- a/drivers/char/drm/via_drv.c
+++ b/drivers/char/drm/via_drv.c
@@ -40,13 +40,11 @@ static struct pci_device_id pciidlist[] = {
40static struct drm_driver driver = { 40static struct drm_driver driver = {
41 .driver_features = 41 .driver_features =
42 DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | 42 DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
43 DRIVER_IRQ_SHARED, 43 DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
44 .load = via_driver_load, 44 .load = via_driver_load,
45 .unload = via_driver_unload, 45 .unload = via_driver_unload,
46 .context_dtor = via_final_context, 46 .context_dtor = via_final_context,
47 .get_vblank_counter = via_get_vblank_counter, 47 .vblank_wait = via_driver_vblank_wait,
48 .enable_vblank = via_enable_vblank,
49 .disable_vblank = via_disable_vblank,
50 .irq_preinstall = via_driver_irq_preinstall, 48 .irq_preinstall = via_driver_irq_preinstall,
51 .irq_postinstall = via_driver_irq_postinstall, 49 .irq_postinstall = via_driver_irq_postinstall,
52 .irq_uninstall = via_driver_irq_uninstall, 50 .irq_uninstall = via_driver_irq_uninstall,
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index fe67030e39ac..2daae81874cd 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -75,7 +75,6 @@ typedef struct drm_via_private {
75 struct timeval last_vblank; 75 struct timeval last_vblank;
76 int last_vblank_valid; 76 int last_vblank_valid;
77 unsigned usec_per_vblank; 77 unsigned usec_per_vblank;
78 atomic_t vbl_received;
79 drm_via_state_t hc_state; 78 drm_via_state_t hc_state;
80 char pci_buf[VIA_PCI_BUF_SIZE]; 79 char pci_buf[VIA_PCI_BUF_SIZE];
81 const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; 80 const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
@@ -131,13 +130,11 @@ extern int via_init_context(struct drm_device * dev, int context);
131extern int via_final_context(struct drm_device * dev, int context); 130extern int via_final_context(struct drm_device * dev, int context);
132 131
133extern int via_do_cleanup_map(struct drm_device * dev); 132extern int via_do_cleanup_map(struct drm_device * dev);
134extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc); 133extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
135extern int via_enable_vblank(struct drm_device *dev, int crtc);
136extern void via_disable_vblank(struct drm_device *dev, int crtc);
137 134
138extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS); 135extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
139extern void via_driver_irq_preinstall(struct drm_device * dev); 136extern void via_driver_irq_preinstall(struct drm_device * dev);
140extern int via_driver_irq_postinstall(struct drm_device * dev); 137extern void via_driver_irq_postinstall(struct drm_device * dev);
141extern void via_driver_irq_uninstall(struct drm_device * dev); 138extern void via_driver_irq_uninstall(struct drm_device * dev);
142 139
143extern int via_dma_cleanup(struct drm_device * dev); 140extern int via_dma_cleanup(struct drm_device * dev);
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index f1ab6fc7c07e..c6bb978a1106 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -92,17 +92,8 @@ static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
92static unsigned time_diff(struct timeval *now, struct timeval *then) 92static unsigned time_diff(struct timeval *now, struct timeval *then)
93{ 93{
94 return (now->tv_usec >= then->tv_usec) ? 94 return (now->tv_usec >= then->tv_usec) ?
95 now->tv_usec - then->tv_usec : 95 now->tv_usec - then->tv_usec :
96 1000000 - (then->tv_usec - now->tv_usec); 96 1000000 - (then->tv_usec - now->tv_usec);
97}
98
99u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
100{
101 drm_via_private_t *dev_priv = dev->dev_private;
102 if (crtc != 0)
103 return 0;
104
105 return atomic_read(&dev_priv->vbl_received);
106} 97}
107 98
108irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) 99irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
@@ -117,8 +108,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
117 108
118 status = VIA_READ(VIA_REG_INTERRUPT); 109 status = VIA_READ(VIA_REG_INTERRUPT);
119 if (status & VIA_IRQ_VBLANK_PENDING) { 110 if (status & VIA_IRQ_VBLANK_PENDING) {
120 atomic_inc(&dev_priv->vbl_received); 111 atomic_inc(&dev->vbl_received);
121 if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) { 112 if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
122 do_gettimeofday(&cur_vblank); 113 do_gettimeofday(&cur_vblank);
123 if (dev_priv->last_vblank_valid) { 114 if (dev_priv->last_vblank_valid) {
124 dev_priv->usec_per_vblank = 115 dev_priv->usec_per_vblank =
@@ -128,11 +119,12 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
128 dev_priv->last_vblank = cur_vblank; 119 dev_priv->last_vblank = cur_vblank;
129 dev_priv->last_vblank_valid = 1; 120 dev_priv->last_vblank_valid = 1;
130 } 121 }
131 if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) { 122 if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
132 DRM_DEBUG("US per vblank is: %u\n", 123 DRM_DEBUG("US per vblank is: %u\n",
133 dev_priv->usec_per_vblank); 124 dev_priv->usec_per_vblank);
134 } 125 }
135 drm_handle_vblank(dev, 0); 126 DRM_WAKEUP(&dev->vbl_queue);
127 drm_vbl_send_signals(dev);
136 handled = 1; 128 handled = 1;
137 } 129 }
138 130
@@ -171,34 +163,31 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
171 } 163 }
172} 164}
173 165
174int via_enable_vblank(struct drm_device *dev, int crtc) 166int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
175{ 167{
176 drm_via_private_t *dev_priv = dev->dev_private; 168 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
177 u32 status; 169 unsigned int cur_vblank;
170 int ret = 0;
178 171
179 if (crtc != 0) { 172 DRM_DEBUG("\n");
180 DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); 173 if (!dev_priv) {
174 DRM_ERROR("called with no initialization\n");
181 return -EINVAL; 175 return -EINVAL;
182 } 176 }
183 177
184 status = VIA_READ(VIA_REG_INTERRUPT); 178 viadrv_acknowledge_irqs(dev_priv);
185 VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
186 179
187 VIA_WRITE8(0x83d4, 0x11); 180 /* Assume that the user has missed the current sequence number
188 VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); 181 * by about a day rather than she wants to wait for years
182 * using vertical blanks...
183 */
189 184
190 return 0; 185 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
191} 186 (((cur_vblank = atomic_read(&dev->vbl_received)) -
187 *sequence) <= (1 << 23)));
192 188
193void via_disable_vblank(struct drm_device *dev, int crtc) 189 *sequence = cur_vblank;
194{ 190 return ret;
195 drm_via_private_t *dev_priv = dev->dev_private;
196
197 VIA_WRITE8(0x83d4, 0x11);
198 VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
199
200 if (crtc != 0)
201 DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
202} 191}
203 192
204static int 193static int
@@ -303,25 +292,23 @@ void via_driver_irq_preinstall(struct drm_device * dev)
303 } 292 }
304} 293}
305 294
306int via_driver_irq_postinstall(struct drm_device * dev) 295void via_driver_irq_postinstall(struct drm_device * dev)
307{ 296{
308 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 297 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
309 u32 status; 298 u32 status;
310 299
311 DRM_DEBUG("via_driver_irq_postinstall\n"); 300 DRM_DEBUG("\n");
312 if (!dev_priv) 301 if (dev_priv) {
313 return -EINVAL; 302 status = VIA_READ(VIA_REG_INTERRUPT);
303 VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
304 | dev_priv->irq_enable_mask);
314 305
315 drm_vblank_init(dev, 1); 306 /* Some magic, oh for some data sheets ! */
316 status = VIA_READ(VIA_REG_INTERRUPT);
317 VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
318 | dev_priv->irq_enable_mask);
319 307
320 /* Some magic, oh for some data sheets ! */ 308 VIA_WRITE8(0x83d4, 0x11);
321 VIA_WRITE8(0x83d4, 0x11); 309 VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
322 VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
323 310
324 return 0; 311 }
325} 312}
326 313
327void via_driver_irq_uninstall(struct drm_device * dev) 314void via_driver_irq_uninstall(struct drm_device * dev)