xref: /gfx-drm/usr/src/uts/intel/io/radeon/radeon_irq.c (revision 47dc10d7)
1 
2 /*
3  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
4  * Use is subject to license terms.
5  */
6 /* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */
7 /*
8  * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
9  *
10  * The Weather Channel (TM) funded Tungsten Graphics to develop the
11  * initial release of the Radeon 8500 driver under the XFree86 license.
12  * This notice must be preserved.
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the "Software"),
16  * to deal in the Software without restriction, including without limitation
17  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18  * and/or sell copies of the Software, and to permit persons to whom the
19  * Software is furnished to do so, subject to the following conditions:
20  *
21  * The above copyright notice and this permission notice (including the next
22  * paragraph) shall be included in all copies or substantial portions of the
23  * Software.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
28  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
29  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31  * DEALINGS IN THE SOFTWARE.
32  *
33  * Authors:
34  *    Keith Whitwell <keith@tungstengraphics.com>
35  *    Michel D�zer <michel@daenzer.net>
36  */
37 
38 #include "drmP.h"
39 #include "radeon_drm.h"
40 #include "radeon_drv.h"
41 #include "radeon_io32.h"
42 
43 static inline u32
radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,u32 mask)44 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 mask)
45 {
46 	uint32_t irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
47 	if (irqs)
48 		RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
49 	return (irqs);
50 }
51 
52 /*
53  * Interrupts - Used for device synchronization and flushing in the
54  * following circumstances:
55  *
56  * - Exclusive FB access with hw idle:
57  *    - Wait for GUI Idle (?) interrupt, then do normal flush.
58  *
59  * - Frame throttling, NV_fence:
60  *    - Drop marker irq's into command stream ahead of time.
61  *    - Wait on irq's with lock *not held*
62  *    - Check each for termination condition
63  *
64  * - Internally in cp_getbuffer, etc:
65  *    - as above, but wait with lock held???
66  *
67  * NOTE: These functions are misleadingly named -- the irq's aren't
68  * tied to dma at all, this is just a hangover from dri prehistory.
69  */
70 
71 irqreturn_t
radeon_driver_irq_handler(DRM_IRQ_ARGS)72 radeon_driver_irq_handler(DRM_IRQ_ARGS)
73 {
74 	drm_device_t *dev = (drm_device_t *)(uintptr_t)arg;
75 	drm_radeon_private_t *dev_priv =
76 	    (drm_radeon_private_t *)dev->dev_private;
77 	u32 stat;
78 
79 	/*
80 	 * Only consider the bits we're interested in - others could be used
81 	 * outside the DRM
82 	 */
83 	stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
84 	    RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT));
85 	if (!stat)
86 		return (IRQ_NONE);
87 
88 	stat &= dev_priv->irq_enable_reg;
89 
90 	/* SW interrupt */
91 	if (stat & RADEON_SW_INT_TEST) {
92 		DRM_WAKEUP(&dev_priv->swi_queue);
93 	}
94 
95 	/* VBLANK interrupt */
96 	if (stat & (RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT)) {
97 		int vblank_crtc = dev_priv->vblank_crtc;
98 
99 		if ((vblank_crtc &
100 		    (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
101 		    (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
102 			if (stat & RADEON_CRTC_VBLANK_STAT)
103 				atomic_inc(&dev->vbl_received);
104 			if (stat & RADEON_CRTC2_VBLANK_STAT)
105 				atomic_inc(&dev->vbl_received2);
106 		} else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
107 		    (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
108 		    ((stat & RADEON_CRTC2_VBLANK_STAT) &&
109 		    (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
110 			atomic_inc(&dev->vbl_received);
111 
112 		DRM_WAKEUP(&dev->vbl_queue);
113 		drm_vbl_send_signals(dev);
114 	}
115 
116 	return (IRQ_HANDLED);
117 }
118 
radeon_emit_irq(drm_device_t * dev)119 static int radeon_emit_irq(drm_device_t *dev)
120 {
121 	drm_radeon_private_t *dev_priv = dev->dev_private;
122 	unsigned int ret;
123 	RING_LOCALS;
124 
125 	atomic_inc(&dev_priv->swi_emitted);
126 	ret = atomic_read(&dev_priv->swi_emitted);
127 
128 	BEGIN_RING(4);
129 	OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
130 	OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
131 	ADVANCE_RING();
132 	COMMIT_RING();
133 
134 	return (ret);
135 }
136 
radeon_wait_irq(drm_device_t * dev,int swi_nr)137 static int radeon_wait_irq(drm_device_t *dev, int swi_nr)
138 {
139 	drm_radeon_private_t *dev_priv =
140 	    (drm_radeon_private_t *)dev->dev_private;
141 	int ret = 0;
142 
143 	if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr)
144 		return (0);
145 
146 	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
147 
148 	DRM_WAIT_ON(ret, &dev_priv->swi_queue, 3 * DRM_HZ,
149 	    RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
150 
151 	return (ret);
152 }
153 
radeon_driver_vblank_do_wait(struct drm_device * dev,unsigned int * sequence,int crtc)154 static int radeon_driver_vblank_do_wait(struct drm_device *dev,
155 					unsigned int *sequence, int crtc)
156 {
157 	drm_radeon_private_t *dev_priv =
158 	    (drm_radeon_private_t *)dev->dev_private;
159 	unsigned int cur_vblank;
160 	int ret = 0;
161 	atomic_t *counter;
162 	if (!dev_priv) {
163 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
164 		return (EINVAL);
165 	}
166 
167 	/*
168 	 * I don't know why reset Intr Status Register here,
169 	 * it might miss intr. So, I remove the code which
170 	 * exists in open source, and changes as follows:
171 	 */
172 
173 	if (crtc == DRM_RADEON_VBLANK_CRTC1) {
174 		counter = &dev->vbl_received;
175 	} else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
176 		counter = &dev->vbl_received2;
177 	} else
178 		return (EINVAL);
179 
180 	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
181 
182 	/*
183 	 * Assume that the user has missed the current sequence number
184 	 * by about a day rather than she wants to wait for years
185 	 * using vertical blanks...
186 	 */
187 	DRM_WAIT_ON(ret, &dev->vbl_queue, 3 * DRM_HZ,
188 	    (((cur_vblank = atomic_read(counter)) - *sequence) <= (1 << 23)));
189 
190 	*sequence = cur_vblank;
191 
192 	return (ret);
193 }
194 
195 int
radeon_driver_vblank_wait(struct drm_device * dev,unsigned int * sequence)196 radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
197 {
198 	return (radeon_driver_vblank_do_wait(dev, sequence,
199 	    DRM_RADEON_VBLANK_CRTC1));
200 }
201 
202 int
radeon_driver_vblank_wait2(struct drm_device * dev,unsigned int * sequence)203 radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
204 {
205 	return (radeon_driver_vblank_do_wait(dev, sequence,
206 	    DRM_RADEON_VBLANK_CRTC2));
207 }
208 
209 /*
210  * Needs the lock as it touches the ring.
211  */
212 /*ARGSUSED*/
213 int
radeon_irq_emit(DRM_IOCTL_ARGS)214 radeon_irq_emit(DRM_IOCTL_ARGS)
215 {
216 	DRM_DEVICE;
217 	drm_radeon_private_t *dev_priv = dev->dev_private;
218 	drm_radeon_irq_emit_t emit;
219 	int result;
220 
221 	LOCK_TEST_WITH_RETURN(dev, fpriv);
222 
223 	if (!dev_priv) {
224 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
225 		return (EINVAL);
226 	}
227 
228 #ifdef _MULTI_DATAMODEL
229 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
230 		drm_radeon_irq_emit_32_t emit32;
231 
232 		DRM_COPYFROM_WITH_RETURN(&emit32, (void *) data,
233 		    sizeof (emit32));
234 		emit.irq_seq = (void *)(uintptr_t)(emit32.irq_seq);
235 	} else {
236 #endif
237 
238 		DRM_COPYFROM_WITH_RETURN(&emit, (void *) data, sizeof (emit));
239 #ifdef _MULTI_DATAMODEL
240 }
241 #endif
242 
243 	result = radeon_emit_irq(dev);
244 
245 	if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof (int))) {
246 		DRM_ERROR("copy_to_user\n");
247 		return (EFAULT);
248 	}
249 
250 	return (0);
251 }
252 
253 /*
254  * Doesn't need the hardware lock.
255  */
256 /*ARGSUSED*/
257 int
radeon_irq_wait(DRM_IOCTL_ARGS)258 radeon_irq_wait(DRM_IOCTL_ARGS)
259 {
260 	DRM_DEVICE;
261 	drm_radeon_private_t *dev_priv = dev->dev_private;
262 	drm_radeon_irq_wait_t irqwait;
263 
264 	if (!dev_priv) {
265 		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
266 		return (EINVAL);
267 	}
268 
269 	DRM_COPYFROM_WITH_RETURN(&irqwait, (void *) data, sizeof (irqwait));
270 
271 	return (radeon_wait_irq(dev, irqwait.irq_seq));
272 }
273 
radeon_enable_interrupt(struct drm_device * dev)274 static void radeon_enable_interrupt(struct drm_device *dev)
275 {
276 	drm_radeon_private_t *dev_priv;
277 
278 	dev_priv = (drm_radeon_private_t *)dev->dev_private;
279 	dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
280 
281 	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1) {
282 		dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
283 	}
284 
285 	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2) {
286 		dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
287 	}
288 
289 	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
290 	dev_priv->irq_enabled = 1;
291 }
292 
293 
294 /*
295  * drm_dma.h hooks
296  */
297 int
radeon_driver_irq_preinstall(drm_device_t * dev)298 radeon_driver_irq_preinstall(drm_device_t *dev)
299 {
300 	drm_radeon_private_t *dev_priv =
301 	    (drm_radeon_private_t *)dev->dev_private;
302 
303 	if (!dev_priv->mmio)
304 		return (EINVAL);
305 
306 	/* Disable *all* interrupts */
307 	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
308 
309 	/* Clear bits if they're already high */
310 	(void) radeon_acknowledge_irqs(dev_priv,
311 	    (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT |
312 	    RADEON_CRTC2_VBLANK_STAT));
313 
314 	return (0);
315 }
316 
317 void
radeon_driver_irq_postinstall(drm_device_t * dev)318 radeon_driver_irq_postinstall(drm_device_t *dev)
319 {
320 	drm_radeon_private_t *dev_priv =
321 	    (drm_radeon_private_t *)dev->dev_private;
322 
323 	atomic_set(&dev_priv->swi_emitted, 0);
324 	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue, DRM_INTR_PRI(dev));
325 
326 	radeon_enable_interrupt(dev);
327 }
328 
329 void
radeon_driver_irq_uninstall(drm_device_t * dev)330 radeon_driver_irq_uninstall(drm_device_t *dev)
331 {
332 	drm_radeon_private_t *dev_priv =
333 	    (drm_radeon_private_t *)dev->dev_private;
334 	if (!dev_priv)
335 		return;
336 
337 	/* Disable *all* interrupts */
338 	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
339 	DRM_FINI_WAITQUEUE(&dev_priv->swi_queue);
340 }
341 
342 int
radeon_vblank_crtc_get(drm_device_t * dev)343 radeon_vblank_crtc_get(drm_device_t *dev)
344 {
345 	drm_radeon_private_t *dev_priv;
346 	u32 flag;
347 	u32 value;
348 
349 	dev_priv = (drm_radeon_private_t *)dev->dev_private;
350 	flag = RADEON_READ(RADEON_GEN_INT_CNTL);
351 	value = 0;
352 
353 	if (flag & RADEON_CRTC_VBLANK_MASK)
354 		value |= DRM_RADEON_VBLANK_CRTC1;
355 
356 	if (flag & RADEON_CRTC2_VBLANK_MASK)
357 		value |= DRM_RADEON_VBLANK_CRTC2;
358 	return (value);
359 }
360 
361 int
radeon_vblank_crtc_set(drm_device_t * dev,int64_t value)362 radeon_vblank_crtc_set(drm_device_t *dev, int64_t value)
363 {
364 	drm_radeon_private_t *dev_priv;
365 
366 	dev_priv = (drm_radeon_private_t *)dev->dev_private;
367 	if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
368 		DRM_ERROR("called with invalid crtc 0x%x\n",
369 		    (unsigned int)value);
370 		return (EINVAL);
371 	}
372 	dev_priv->vblank_crtc = (unsigned int)value;
373 	radeon_enable_interrupt(dev);
374 	return (0);
375 }
376