diff options
Diffstat (limited to 'drivers/char/drm/via_irq.c')
-rw-r--r-- | drivers/char/drm/via_irq.c | 81 |
1 files changed, 47 insertions, 34 deletions
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c index c6bb978a1106..f1ab6fc7c07e 100644 --- a/drivers/char/drm/via_irq.c +++ b/drivers/char/drm/via_irq.c | |||
@@ -92,8 +92,17 @@ static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; | |||
92 | static unsigned time_diff(struct timeval *now, struct timeval *then) | 92 | static 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 | |||
99 | u32 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); | ||
97 | } | 106 | } |
98 | 107 | ||
99 | irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) | 108 | irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) |
@@ -108,8 +117,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) | |||
108 | 117 | ||
109 | status = VIA_READ(VIA_REG_INTERRUPT); | 118 | status = VIA_READ(VIA_REG_INTERRUPT); |
110 | if (status & VIA_IRQ_VBLANK_PENDING) { | 119 | if (status & VIA_IRQ_VBLANK_PENDING) { |
111 | atomic_inc(&dev->vbl_received); | 120 | atomic_inc(&dev_priv->vbl_received); |
112 | if (!(atomic_read(&dev->vbl_received) & 0x0F)) { | 121 | if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) { |
113 | do_gettimeofday(&cur_vblank); | 122 | do_gettimeofday(&cur_vblank); |
114 | if (dev_priv->last_vblank_valid) { | 123 | if (dev_priv->last_vblank_valid) { |
115 | dev_priv->usec_per_vblank = | 124 | dev_priv->usec_per_vblank = |
@@ -119,12 +128,11 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) | |||
119 | dev_priv->last_vblank = cur_vblank; | 128 | dev_priv->last_vblank = cur_vblank; |
120 | dev_priv->last_vblank_valid = 1; | 129 | dev_priv->last_vblank_valid = 1; |
121 | } | 130 | } |
122 | if (!(atomic_read(&dev->vbl_received) & 0xFF)) { | 131 | if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) { |
123 | DRM_DEBUG("US per vblank is: %u\n", | 132 | DRM_DEBUG("US per vblank is: %u\n", |
124 | dev_priv->usec_per_vblank); | 133 | dev_priv->usec_per_vblank); |
125 | } | 134 | } |
126 | DRM_WAKEUP(&dev->vbl_queue); | 135 | drm_handle_vblank(dev, 0); |
127 | drm_vbl_send_signals(dev); | ||
128 | handled = 1; | 136 | handled = 1; |
129 | } | 137 | } |
130 | 138 | ||
@@ -163,31 +171,34 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv) | |||
163 | } | 171 | } |
164 | } | 172 | } |
165 | 173 | ||
166 | int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) | 174 | int via_enable_vblank(struct drm_device *dev, int crtc) |
167 | { | 175 | { |
168 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | 176 | drm_via_private_t *dev_priv = dev->dev_private; |
169 | unsigned int cur_vblank; | 177 | u32 status; |
170 | int ret = 0; | ||
171 | 178 | ||
172 | DRM_DEBUG("\n"); | 179 | if (crtc != 0) { |
173 | if (!dev_priv) { | 180 | DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); |
174 | DRM_ERROR("called with no initialization\n"); | ||
175 | return -EINVAL; | 181 | return -EINVAL; |
176 | } | 182 | } |
177 | 183 | ||
178 | viadrv_acknowledge_irqs(dev_priv); | 184 | status = VIA_READ(VIA_REG_INTERRUPT); |
185 | VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE); | ||
179 | 186 | ||
180 | /* Assume that the user has missed the current sequence number | 187 | VIA_WRITE8(0x83d4, 0x11); |
181 | * by about a day rather than she wants to wait for years | 188 | VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); |
182 | * using vertical blanks... | ||
183 | */ | ||
184 | 189 | ||
185 | DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, | 190 | return 0; |
186 | (((cur_vblank = atomic_read(&dev->vbl_received)) - | 191 | } |
187 | *sequence) <= (1 << 23))); | ||
188 | 192 | ||
189 | *sequence = cur_vblank; | 193 | void via_disable_vblank(struct drm_device *dev, int crtc) |
190 | return ret; | 194 | { |
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); | ||
191 | } | 202 | } |
192 | 203 | ||
193 | static int | 204 | static int |
@@ -292,23 +303,25 @@ void via_driver_irq_preinstall(struct drm_device * dev) | |||
292 | } | 303 | } |
293 | } | 304 | } |
294 | 305 | ||
295 | void via_driver_irq_postinstall(struct drm_device * dev) | 306 | int via_driver_irq_postinstall(struct drm_device * dev) |
296 | { | 307 | { |
297 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | 308 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; |
298 | u32 status; | 309 | u32 status; |
299 | 310 | ||
300 | DRM_DEBUG("\n"); | 311 | DRM_DEBUG("via_driver_irq_postinstall\n"); |
301 | if (dev_priv) { | 312 | if (!dev_priv) |
302 | status = VIA_READ(VIA_REG_INTERRUPT); | 313 | return -EINVAL; |
303 | VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL | ||
304 | | dev_priv->irq_enable_mask); | ||
305 | 314 | ||
306 | /* Some magic, oh for some data sheets ! */ | 315 | drm_vblank_init(dev, 1); |
316 | status = VIA_READ(VIA_REG_INTERRUPT); | ||
317 | VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL | ||
318 | | dev_priv->irq_enable_mask); | ||
307 | 319 | ||
308 | VIA_WRITE8(0x83d4, 0x11); | 320 | /* Some magic, oh for some data sheets ! */ |
309 | VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); | 321 | VIA_WRITE8(0x83d4, 0x11); |
322 | VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); | ||
310 | 323 | ||
311 | } | 324 | return 0; |
312 | } | 325 | } |
313 | 326 | ||
314 | void via_driver_irq_uninstall(struct drm_device * dev) | 327 | void via_driver_irq_uninstall(struct drm_device * dev) |