diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/char/drm/radeon_irq.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/char/drm/radeon_irq.c')
-rw-r--r-- | drivers/char/drm/radeon_irq.c | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c new file mode 100644 index 000000000000..5b18bee6492e --- /dev/null +++ b/drivers/char/drm/radeon_irq.c | |||
@@ -0,0 +1,251 @@ | |||
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�zer <michel@daenzer.net> | ||
31 | */ | ||
32 | |||
33 | #include "drmP.h" | ||
34 | #include "drm.h" | ||
35 | #include "radeon_drm.h" | ||
36 | #include "radeon_drv.h" | ||
37 | |||
38 | /* Interrupts - Used for device synchronization and flushing in the | ||
39 | * following circumstances: | ||
40 | * | ||
41 | * - Exclusive FB access with hw idle: | ||
42 | * - Wait for GUI Idle (?) interrupt, then do normal flush. | ||
43 | * | ||
44 | * - Frame throttling, NV_fence: | ||
45 | * - Drop marker irq's into command stream ahead of time. | ||
46 | * - Wait on irq's with lock *not held* | ||
47 | * - Check each for termination condition | ||
48 | * | ||
49 | * - Internally in cp_getbuffer, etc: | ||
50 | * - as above, but wait with lock held??? | ||
51 | * | ||
52 | * NOTE: These functions are misleadingly named -- the irq's aren't | ||
53 | * tied to dma at all, this is just a hangover from dri prehistory. | ||
54 | */ | ||
55 | |||
56 | irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS ) | ||
57 | { | ||
58 | drm_device_t *dev = (drm_device_t *) arg; | ||
59 | drm_radeon_private_t *dev_priv = | ||
60 | (drm_radeon_private_t *)dev->dev_private; | ||
61 | u32 stat; | ||
62 | |||
63 | /* Only consider the bits we're interested in - others could be used | ||
64 | * outside the DRM | ||
65 | */ | ||
66 | stat = RADEON_READ(RADEON_GEN_INT_STATUS) | ||
67 | & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT); | ||
68 | if (!stat) | ||
69 | return IRQ_NONE; | ||
70 | |||
71 | /* SW interrupt */ | ||
72 | if (stat & RADEON_SW_INT_TEST) { | ||
73 | DRM_WAKEUP( &dev_priv->swi_queue ); | ||
74 | } | ||
75 | |||
76 | /* VBLANK interrupt */ | ||
77 | if (stat & RADEON_CRTC_VBLANK_STAT) { | ||
78 | atomic_inc(&dev->vbl_received); | ||
79 | DRM_WAKEUP(&dev->vbl_queue); | ||
80 | drm_vbl_send_signals( dev ); | ||
81 | } | ||
82 | |||
83 | /* Acknowledge interrupts we handle */ | ||
84 | RADEON_WRITE(RADEON_GEN_INT_STATUS, stat); | ||
85 | return IRQ_HANDLED; | ||
86 | } | ||
87 | |||
88 | static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv) | ||
89 | { | ||
90 | u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS ) | ||
91 | & (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT); | ||
92 | if (tmp) | ||
93 | RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp ); | ||
94 | } | ||
95 | |||
96 | static int radeon_emit_irq(drm_device_t *dev) | ||
97 | { | ||
98 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
99 | unsigned int ret; | ||
100 | RING_LOCALS; | ||
101 | |||
102 | atomic_inc(&dev_priv->swi_emitted); | ||
103 | ret = atomic_read(&dev_priv->swi_emitted); | ||
104 | |||
105 | BEGIN_RING( 4 ); | ||
106 | OUT_RING_REG( RADEON_LAST_SWI_REG, ret ); | ||
107 | OUT_RING_REG( RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE ); | ||
108 | ADVANCE_RING(); | ||
109 | COMMIT_RING(); | ||
110 | |||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | |||
115 | static int radeon_wait_irq(drm_device_t *dev, int swi_nr) | ||
116 | { | ||
117 | drm_radeon_private_t *dev_priv = | ||
118 | (drm_radeon_private_t *)dev->dev_private; | ||
119 | int ret = 0; | ||
120 | |||
121 | if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr) | ||
122 | return 0; | ||
123 | |||
124 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | ||
125 | |||
126 | /* This is a hack to work around mysterious freezes on certain | ||
127 | * systems: | ||
128 | */ | ||
129 | radeon_acknowledge_irqs( dev_priv ); | ||
130 | |||
131 | DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ, | ||
132 | RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr ); | ||
133 | |||
134 | return ret; | ||
135 | } | ||
136 | |||
137 | int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) | ||
138 | { | ||
139 | drm_radeon_private_t *dev_priv = | ||
140 | (drm_radeon_private_t *)dev->dev_private; | ||
141 | unsigned int cur_vblank; | ||
142 | int ret = 0; | ||
143 | |||
144 | if ( !dev_priv ) { | ||
145 | DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); | ||
146 | return DRM_ERR(EINVAL); | ||
147 | } | ||
148 | |||
149 | radeon_acknowledge_irqs( dev_priv ); | ||
150 | |||
151 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | ||
152 | |||
153 | /* Assume that the user has missed the current sequence number | ||
154 | * by about a day rather than she wants to wait for years | ||
155 | * using vertical blanks... | ||
156 | */ | ||
157 | DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, | ||
158 | ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) | ||
159 | - *sequence ) <= (1<<23) ) ); | ||
160 | |||
161 | *sequence = cur_vblank; | ||
162 | |||
163 | return ret; | ||
164 | } | ||
165 | |||
166 | |||
167 | /* Needs the lock as it touches the ring. | ||
168 | */ | ||
169 | int radeon_irq_emit( DRM_IOCTL_ARGS ) | ||
170 | { | ||
171 | DRM_DEVICE; | ||
172 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
173 | drm_radeon_irq_emit_t emit; | ||
174 | int result; | ||
175 | |||
176 | LOCK_TEST_WITH_RETURN( dev, filp ); | ||
177 | |||
178 | if ( !dev_priv ) { | ||
179 | DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); | ||
180 | return DRM_ERR(EINVAL); | ||
181 | } | ||
182 | |||
183 | DRM_COPY_FROM_USER_IOCTL( emit, (drm_radeon_irq_emit_t __user *)data, | ||
184 | sizeof(emit) ); | ||
185 | |||
186 | result = radeon_emit_irq( dev ); | ||
187 | |||
188 | if ( DRM_COPY_TO_USER( emit.irq_seq, &result, sizeof(int) ) ) { | ||
189 | DRM_ERROR( "copy_to_user\n" ); | ||
190 | return DRM_ERR(EFAULT); | ||
191 | } | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | |||
197 | /* Doesn't need the hardware lock. | ||
198 | */ | ||
199 | int radeon_irq_wait( DRM_IOCTL_ARGS ) | ||
200 | { | ||
201 | DRM_DEVICE; | ||
202 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
203 | drm_radeon_irq_wait_t irqwait; | ||
204 | |||
205 | if ( !dev_priv ) { | ||
206 | DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); | ||
207 | return DRM_ERR(EINVAL); | ||
208 | } | ||
209 | |||
210 | DRM_COPY_FROM_USER_IOCTL( irqwait, (drm_radeon_irq_wait_t __user*)data, | ||
211 | sizeof(irqwait) ); | ||
212 | |||
213 | return radeon_wait_irq( dev, irqwait.irq_seq ); | ||
214 | } | ||
215 | |||
216 | |||
217 | /* drm_dma.h hooks | ||
218 | */ | ||
219 | void radeon_driver_irq_preinstall( drm_device_t *dev ) { | ||
220 | drm_radeon_private_t *dev_priv = | ||
221 | (drm_radeon_private_t *)dev->dev_private; | ||
222 | |||
223 | /* Disable *all* interrupts */ | ||
224 | RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); | ||
225 | |||
226 | /* Clear bits if they're already high */ | ||
227 | radeon_acknowledge_irqs( dev_priv ); | ||
228 | } | ||
229 | |||
230 | void radeon_driver_irq_postinstall( drm_device_t *dev ) { | ||
231 | drm_radeon_private_t *dev_priv = | ||
232 | (drm_radeon_private_t *)dev->dev_private; | ||
233 | |||
234 | atomic_set(&dev_priv->swi_emitted, 0); | ||
235 | DRM_INIT_WAITQUEUE( &dev_priv->swi_queue ); | ||
236 | |||
237 | /* Turn on SW and VBL ints */ | ||
238 | RADEON_WRITE( RADEON_GEN_INT_CNTL, | ||
239 | RADEON_CRTC_VBLANK_MASK | | ||
240 | RADEON_SW_INT_ENABLE ); | ||
241 | } | ||
242 | |||
243 | void radeon_driver_irq_uninstall( drm_device_t *dev ) { | ||
244 | drm_radeon_private_t *dev_priv = | ||
245 | (drm_radeon_private_t *)dev->dev_private; | ||
246 | if (!dev_priv) | ||
247 | return; | ||
248 | |||
249 | /* Disable *all* interrupts */ | ||
250 | RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); | ||
251 | } | ||