aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/mga_irq.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2008-04-22 02:03:07 -0400
committerDave Airlie <airlied@linux.ie>2008-04-26 04:01:07 -0400
commitac741ab71bb39e6977694ac0cc26678d8673cda4 (patch)
treef82e08399a0da5accba930444744b269479185dd /drivers/char/drm/mga_irq.c
parent2c14f28be2a3f2a2e9861b156d64fbe2bc7000c3 (diff)
drm/vbl rework: rework how the drm deals with vblank.
Other Authors: Michel Dänzer <michel@tungstengraphics.com> mga: Ian Romanick <idr@us.ibm.com> via: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> This re-works the DRM internals to provide a better interface for drivers to expose vblank on multiple crtcs. It also includes work done by Michel on making i915 triple buffering and pageflipping work properly. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/char/drm/mga_irq.c')
-rw-r--r--drivers/char/drm/mga_irq.c69
1 files changed, 51 insertions, 18 deletions
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
index 9302cb8f0f83..06852fb4b278 100644
--- a/drivers/char/drm/mga_irq.c
+++ b/drivers/char/drm/mga_irq.c
@@ -35,6 +35,20 @@
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
38irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) 52irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
39{ 53{
40 struct drm_device *dev = (struct drm_device *) arg; 54 struct drm_device *dev = (struct drm_device *) arg;
@@ -47,9 +61,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
47 /* VBLANK interrupt */ 61 /* VBLANK interrupt */
48 if (status & MGA_VLINEPEN) { 62 if (status & MGA_VLINEPEN) {
49 MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); 63 MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
50 atomic_inc(&dev->vbl_received); 64 atomic_inc(&dev_priv->vbl_received);
51 DRM_WAKEUP(&dev->vbl_queue); 65 drm_handle_vblank(dev, 0);
52 drm_vbl_send_signals(dev);
53 handled = 1; 66 handled = 1;
54 } 67 }
55 68
@@ -78,22 +91,34 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
78 return IRQ_NONE; 91 return IRQ_NONE;
79} 92}
80 93
81int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) 94int mga_enable_vblank(struct drm_device *dev, int crtc)
82{ 95{
83 unsigned int cur_vblank; 96 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
84 int ret = 0;
85 97
86 /* Assume that the user has missed the current sequence number 98 if (crtc != 0) {
87 * by about a day rather than she wants to wait for years 99 DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
88 * using vertical blanks... 100 crtc);
89 */ 101 return 0;
90 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, 102 }
91 (((cur_vblank = atomic_read(&dev->vbl_received))
92 - *sequence) <= (1 << 23)));
93 103
94 *sequence = cur_vblank; 104 MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
105 return 0;
106}
95 107
96 return ret; 108
109void mga_disable_vblank(struct drm_device *dev, int crtc)
110{
111 if (crtc != 0) {
112 DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
113 crtc);
114 }
115
116 /* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have
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); */
97} 122}
98 123
99int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence) 124int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
@@ -125,14 +150,22 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
125 MGA_WRITE(MGA_ICLEAR, ~0); 150 MGA_WRITE(MGA_ICLEAR, ~0);
126} 151}
127 152
128void mga_driver_irq_postinstall(struct drm_device * dev) 153int mga_driver_irq_postinstall(struct drm_device * dev)
129{ 154{
130 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; 155 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;
131 161
132 DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); 162 DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
133 163
134 /* Turn on vertical blank interrupt and soft trap interrupt. */ 164 /* Turn on soft trap interrupt. Vertical blank interrupts are enabled
135 MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); 165 * in mga_enable_vblank.
166 */
167 MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
168 return 0;
136} 169}
137 170
138void mga_driver_irq_uninstall(struct drm_device * dev) 171void mga_driver_irq_uninstall(struct drm_device * dev)