aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_irq.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-05-28 20:09:59 -0400
committerDave Airlie <airlied@redhat.com>2008-07-13 20:45:01 -0400
commitc0e09200dc0813972442e550a5905a132768e56c (patch)
treed38e635a30ff8b0a2b98b9d7f97cab1501f8209e /drivers/gpu/drm/radeon/radeon_irq.c
parentbce7f793daec3e65ec5c5705d2457b81fe7b5725 (diff)
drm: reorganise drm tree to be more future proof.
With the coming of kernel based modesetting and the memory manager stuff, the everything in one directory approach was getting very ugly and starting to be unmanageable. This restructures the drm along the lines of other kernel components. It creates a drivers/gpu/drm directory and moves the hw drivers into subdirectores. It moves the includes into an include/drm, and sets up the unifdef for the userspace headers we should be exporting. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_irq.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq.c320
1 files changed, 320 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c
new file mode 100644
index 000000000000..ee40d197deb7
--- /dev/null
+++ b/drivers/gpu/drm/radeon/radeon_irq.c
@@ -0,0 +1,320 @@
1/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */
2/*
3 * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 *
5 * The Weather Channel (TM) funded Tungsten Graphics to develop the
6 * initial release of the Radeon 8500 driver under the XFree86 license.
7 * This notice must be preserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 * Michel Dänzer <michel@daenzer.net>
31 */
32
33#include "drmP.h"
34#include "drm.h"
35#include "radeon_drm.h"
36#include "radeon_drv.h"
37
38static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
39 u32 mask)
40{
41 u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
42 if (irqs)
43 RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
44 return irqs;
45}
46
47/* Interrupts - Used for device synchronization and flushing in the
48 * following circumstances:
49 *
50 * - Exclusive FB access with hw idle:
51 * - Wait for GUI Idle (?) interrupt, then do normal flush.
52 *
53 * - Frame throttling, NV_fence:
54 * - Drop marker irq's into command stream ahead of time.
55 * - Wait on irq's with lock *not held*
56 * - Check each for termination condition
57 *
58 * - Internally in cp_getbuffer, etc:
59 * - as above, but wait with lock held???
60 *
61 * NOTE: These functions are misleadingly named -- the irq's aren't
62 * tied to dma at all, this is just a hangover from dri prehistory.
63 */
64
65irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
66{
67 struct drm_device *dev = (struct drm_device *) arg;
68 drm_radeon_private_t *dev_priv =
69 (drm_radeon_private_t *) dev->dev_private;
70 u32 stat;
71
72 /* Only consider the bits we're interested in - others could be used
73 * outside the DRM
74 */
75 stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
76 RADEON_CRTC_VBLANK_STAT |
77 RADEON_CRTC2_VBLANK_STAT));
78 if (!stat)
79 return IRQ_NONE;
80
81 stat &= dev_priv->irq_enable_reg;
82
83 /* SW interrupt */
84 if (stat & RADEON_SW_INT_TEST) {
85 DRM_WAKEUP(&dev_priv->swi_queue);
86 }
87
88 /* VBLANK interrupt */
89 if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
90 int vblank_crtc = dev_priv->vblank_crtc;
91
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 }
108
109 return IRQ_HANDLED;
110}
111
112static int radeon_emit_irq(struct drm_device * dev)
113{
114 drm_radeon_private_t *dev_priv = dev->dev_private;
115 unsigned int ret;
116 RING_LOCALS;
117
118 atomic_inc(&dev_priv->swi_emitted);
119 ret = atomic_read(&dev_priv->swi_emitted);
120
121 BEGIN_RING(4);
122 OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
123 OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
124 ADVANCE_RING();
125 COMMIT_RING();
126
127 return ret;
128}
129
130static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
131{
132 drm_radeon_private_t *dev_priv =
133 (drm_radeon_private_t *) dev->dev_private;
134 int ret = 0;
135
136 if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr)
137 return 0;
138
139 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
140
141 DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
142 RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
143
144 return ret;
145}
146
147static int radeon_driver_vblank_do_wait(struct drm_device * dev,
148 unsigned int *sequence, int crtc)
149{
150 drm_radeon_private_t *dev_priv =
151 (drm_radeon_private_t *) dev->dev_private;
152 unsigned int cur_vblank;
153 int ret = 0;
154 int ack = 0;
155 atomic_t *counter;
156 if (!dev_priv) {
157 DRM_ERROR("called with no initialization\n");
158 return -EINVAL;
159 }
160
161 if (crtc == DRM_RADEON_VBLANK_CRTC1) {
162 counter = &dev->vbl_received;
163 ack |= RADEON_CRTC_VBLANK_STAT;
164 } else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
165 counter = &dev->vbl_received2;
166 ack |= RADEON_CRTC2_VBLANK_STAT;
167 } else
168 return -EINVAL;
169
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);
195}
196
197/* Needs the lock as it touches the ring.
198 */
199int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv)
200{
201 drm_radeon_private_t *dev_priv = dev->dev_private;
202 drm_radeon_irq_emit_t *emit = data;
203 int result;
204
205 LOCK_TEST_WITH_RETURN(dev, file_priv);
206
207 if (!dev_priv) {
208 DRM_ERROR("called with no initialization\n");
209 return -EINVAL;
210 }
211
212 result = radeon_emit_irq(dev);
213
214 if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
215 DRM_ERROR("copy_to_user\n");
216 return -EFAULT;
217 }
218
219 return 0;
220}
221
222/* Doesn't need the hardware lock.
223 */
224int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv)
225{
226 drm_radeon_private_t *dev_priv = dev->dev_private;
227 drm_radeon_irq_wait_t *irqwait = data;
228
229 if (!dev_priv) {
230 DRM_ERROR("called with no initialization\n");
231 return -EINVAL;
232 }
233
234 return radeon_wait_irq(dev, irqwait->irq_seq);
235}
236
237void 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
252/* drm_dma.h hooks
253*/
254void radeon_driver_irq_preinstall(struct drm_device * dev)
255{
256 drm_radeon_private_t *dev_priv =
257 (drm_radeon_private_t *) dev->dev_private;
258
259 /* Disable *all* interrupts */
260 RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
261
262 /* Clear bits if they're already high */
263 radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
264 RADEON_CRTC_VBLANK_STAT |
265 RADEON_CRTC2_VBLANK_STAT));
266}
267
268void radeon_driver_irq_postinstall(struct drm_device * dev)
269{
270 drm_radeon_private_t *dev_priv =
271 (drm_radeon_private_t *) dev->dev_private;
272
273 atomic_set(&dev_priv->swi_emitted, 0);
274 DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
275
276 radeon_enable_interrupt(dev);
277}
278
279void radeon_driver_irq_uninstall(struct drm_device * dev)
280{
281 drm_radeon_private_t *dev_priv =
282 (drm_radeon_private_t *) dev->dev_private;
283 if (!dev_priv)
284 return;
285
286 dev_priv->irq_enabled = 0;
287
288 /* Disable *all* interrupts */
289 RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
290}
291
292
293int radeon_vblank_crtc_get(struct drm_device *dev)
294{
295 drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
296 u32 flag;
297 u32 value;
298
299 flag = RADEON_READ(RADEON_GEN_INT_CNTL);
300 value = 0;
301
302 if (flag & RADEON_CRTC_VBLANK_MASK)
303 value |= DRM_RADEON_VBLANK_CRTC1;
304
305 if (flag & RADEON_CRTC2_VBLANK_MASK)
306 value |= DRM_RADEON_VBLANK_CRTC2;
307 return value;
308}
309
310int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
311{
312 drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
313 if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
314 DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
315 return -EINVAL;
316 }
317 dev_priv->vblank_crtc = (unsigned int)value;
318 radeon_enable_interrupt(dev);
319 return 0;
320}