1254885Sdumbbell/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */
2254885Sdumbbell/*
3254885Sdumbbell * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
4254885Sdumbbell *
5254885Sdumbbell * The Weather Channel (TM) funded Tungsten Graphics to develop the
6254885Sdumbbell * initial release of the Radeon 8500 driver under the XFree86 license.
7254885Sdumbbell * This notice must be preserved.
8254885Sdumbbell *
9254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a
10254885Sdumbbell * copy of this software and associated documentation files (the "Software"),
11254885Sdumbbell * to deal in the Software without restriction, including without limitation
12254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the
14254885Sdumbbell * Software is furnished to do so, subject to the following conditions:
15254885Sdumbbell *
16254885Sdumbbell * The above copyright notice and this permission notice (including the next
17254885Sdumbbell * paragraph) shall be included in all copies or substantial portions of the
18254885Sdumbbell * Software.
19254885Sdumbbell *
20254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23254885Sdumbbell * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26254885Sdumbbell * DEALINGS IN THE SOFTWARE.
27254885Sdumbbell *
28254885Sdumbbell * Authors:
29254885Sdumbbell *    Keith Whitwell <keith@tungstengraphics.com>
30254885Sdumbbell *    Michel D���zer <michel@daenzer.net>
31254885Sdumbbell */
32254885Sdumbbell
33254885Sdumbbell#include <sys/cdefs.h>
34254885Sdumbbell__FBSDID("$FreeBSD: releng/10.2/sys/dev/drm2/radeon/radeon_irq.c 254885 2013-08-25 19:37:15Z dumbbell $");
35254885Sdumbbell
36254885Sdumbbell#include <dev/drm2/drmP.h>
37254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h>
38254885Sdumbbell#include "radeon_drv.h"
39254885Sdumbbell
40254885Sdumbbellvoid radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
41254885Sdumbbell{
42254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
43254885Sdumbbell
44254885Sdumbbell	if (state)
45254885Sdumbbell		dev_priv->irq_enable_reg |= mask;
46254885Sdumbbell	else
47254885Sdumbbell		dev_priv->irq_enable_reg &= ~mask;
48254885Sdumbbell
49254885Sdumbbell	if (dev->irq_enabled)
50254885Sdumbbell		RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
51254885Sdumbbell}
52254885Sdumbbell
53254885Sdumbbellstatic void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state)
54254885Sdumbbell{
55254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
56254885Sdumbbell
57254885Sdumbbell	if (state)
58254885Sdumbbell		dev_priv->r500_disp_irq_reg |= mask;
59254885Sdumbbell	else
60254885Sdumbbell		dev_priv->r500_disp_irq_reg &= ~mask;
61254885Sdumbbell
62254885Sdumbbell	if (dev->irq_enabled)
63254885Sdumbbell		RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
64254885Sdumbbell}
65254885Sdumbbell
66254885Sdumbbellint radeon_enable_vblank(struct drm_device *dev, int crtc)
67254885Sdumbbell{
68254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
69254885Sdumbbell
70254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
71254885Sdumbbell		switch (crtc) {
72254885Sdumbbell		case 0:
73254885Sdumbbell			r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 1);
74254885Sdumbbell			break;
75254885Sdumbbell		case 1:
76254885Sdumbbell			r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 1);
77254885Sdumbbell			break;
78254885Sdumbbell		default:
79254885Sdumbbell			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
80254885Sdumbbell				  crtc);
81254885Sdumbbell			return -EINVAL;
82254885Sdumbbell		}
83254885Sdumbbell	} else {
84254885Sdumbbell		switch (crtc) {
85254885Sdumbbell		case 0:
86254885Sdumbbell			radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
87254885Sdumbbell			break;
88254885Sdumbbell		case 1:
89254885Sdumbbell			radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
90254885Sdumbbell			break;
91254885Sdumbbell		default:
92254885Sdumbbell			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
93254885Sdumbbell				  crtc);
94254885Sdumbbell			return -EINVAL;
95254885Sdumbbell		}
96254885Sdumbbell	}
97254885Sdumbbell
98254885Sdumbbell	return 0;
99254885Sdumbbell}
100254885Sdumbbell
101254885Sdumbbellvoid radeon_disable_vblank(struct drm_device *dev, int crtc)
102254885Sdumbbell{
103254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
104254885Sdumbbell
105254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
106254885Sdumbbell		switch (crtc) {
107254885Sdumbbell		case 0:
108254885Sdumbbell			r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 0);
109254885Sdumbbell			break;
110254885Sdumbbell		case 1:
111254885Sdumbbell			r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 0);
112254885Sdumbbell			break;
113254885Sdumbbell		default:
114254885Sdumbbell			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
115254885Sdumbbell				  crtc);
116254885Sdumbbell			break;
117254885Sdumbbell		}
118254885Sdumbbell	} else {
119254885Sdumbbell		switch (crtc) {
120254885Sdumbbell		case 0:
121254885Sdumbbell			radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
122254885Sdumbbell			break;
123254885Sdumbbell		case 1:
124254885Sdumbbell			radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
125254885Sdumbbell			break;
126254885Sdumbbell		default:
127254885Sdumbbell			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
128254885Sdumbbell				  crtc);
129254885Sdumbbell			break;
130254885Sdumbbell		}
131254885Sdumbbell	}
132254885Sdumbbell}
133254885Sdumbbell
134254885Sdumbbellstatic u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int)
135254885Sdumbbell{
136254885Sdumbbell	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS);
137254885Sdumbbell	u32 irq_mask = RADEON_SW_INT_TEST;
138254885Sdumbbell
139254885Sdumbbell	*r500_disp_int = 0;
140254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
141254885Sdumbbell		/* vbl interrupts in a different place */
142254885Sdumbbell
143254885Sdumbbell		if (irqs & R500_DISPLAY_INT_STATUS) {
144254885Sdumbbell			/* if a display interrupt */
145254885Sdumbbell			u32 disp_irq;
146254885Sdumbbell
147254885Sdumbbell			disp_irq = RADEON_READ(R500_DISP_INTERRUPT_STATUS);
148254885Sdumbbell
149254885Sdumbbell			*r500_disp_int = disp_irq;
150254885Sdumbbell			if (disp_irq & R500_D1_VBLANK_INTERRUPT)
151254885Sdumbbell				RADEON_WRITE(R500_D1MODE_VBLANK_STATUS, R500_VBLANK_ACK);
152254885Sdumbbell			if (disp_irq & R500_D2_VBLANK_INTERRUPT)
153254885Sdumbbell				RADEON_WRITE(R500_D2MODE_VBLANK_STATUS, R500_VBLANK_ACK);
154254885Sdumbbell		}
155254885Sdumbbell		irq_mask |= R500_DISPLAY_INT_STATUS;
156254885Sdumbbell	} else
157254885Sdumbbell		irq_mask |= RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT;
158254885Sdumbbell
159254885Sdumbbell	irqs &=	irq_mask;
160254885Sdumbbell
161254885Sdumbbell	if (irqs)
162254885Sdumbbell		RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
163254885Sdumbbell
164254885Sdumbbell	return irqs;
165254885Sdumbbell}
166254885Sdumbbell
167254885Sdumbbell/* Interrupts - Used for device synchronization and flushing in the
168254885Sdumbbell * following circumstances:
169254885Sdumbbell *
170254885Sdumbbell * - Exclusive FB access with hw idle:
171254885Sdumbbell *    - Wait for GUI Idle (?) interrupt, then do normal flush.
172254885Sdumbbell *
173254885Sdumbbell * - Frame throttling, NV_fence:
174254885Sdumbbell *    - Drop marker irq's into command stream ahead of time.
175254885Sdumbbell *    - Wait on irq's with lock *not held*
176254885Sdumbbell *    - Check each for termination condition
177254885Sdumbbell *
178254885Sdumbbell * - Internally in cp_getbuffer, etc:
179254885Sdumbbell *    - as above, but wait with lock held???
180254885Sdumbbell *
181254885Sdumbbell * NOTE: These functions are misleadingly named -- the irq's aren't
182254885Sdumbbell * tied to dma at all, this is just a hangover from dri prehistory.
183254885Sdumbbell */
184254885Sdumbbell
185254885Sdumbbellirqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
186254885Sdumbbell{
187254885Sdumbbell	struct drm_device *dev = (struct drm_device *) arg;
188254885Sdumbbell	drm_radeon_private_t *dev_priv =
189254885Sdumbbell	    (drm_radeon_private_t *) dev->dev_private;
190254885Sdumbbell	u32 stat;
191254885Sdumbbell	u32 r500_disp_int;
192254885Sdumbbell
193254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
194254885Sdumbbell		return IRQ_NONE;
195254885Sdumbbell
196254885Sdumbbell	/* Only consider the bits we're interested in - others could be used
197254885Sdumbbell	 * outside the DRM
198254885Sdumbbell	 */
199254885Sdumbbell	stat = radeon_acknowledge_irqs(dev_priv, &r500_disp_int);
200254885Sdumbbell	if (!stat)
201254885Sdumbbell		return IRQ_NONE;
202254885Sdumbbell
203254885Sdumbbell	stat &= dev_priv->irq_enable_reg;
204254885Sdumbbell
205254885Sdumbbell	/* SW interrupt */
206254885Sdumbbell	if (stat & RADEON_SW_INT_TEST)
207254885Sdumbbell		DRM_WAKEUP(&dev_priv->swi_queue);
208254885Sdumbbell
209254885Sdumbbell	/* VBLANK interrupt */
210254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
211254885Sdumbbell		if (r500_disp_int & R500_D1_VBLANK_INTERRUPT)
212254885Sdumbbell			drm_handle_vblank(dev, 0);
213254885Sdumbbell		if (r500_disp_int & R500_D2_VBLANK_INTERRUPT)
214254885Sdumbbell			drm_handle_vblank(dev, 1);
215254885Sdumbbell	} else {
216254885Sdumbbell		if (stat & RADEON_CRTC_VBLANK_STAT)
217254885Sdumbbell			drm_handle_vblank(dev, 0);
218254885Sdumbbell		if (stat & RADEON_CRTC2_VBLANK_STAT)
219254885Sdumbbell			drm_handle_vblank(dev, 1);
220254885Sdumbbell	}
221254885Sdumbbell	return IRQ_HANDLED;
222254885Sdumbbell}
223254885Sdumbbell
224254885Sdumbbellstatic int radeon_emit_irq(struct drm_device * dev)
225254885Sdumbbell{
226254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
227254885Sdumbbell	unsigned int ret;
228254885Sdumbbell	RING_LOCALS;
229254885Sdumbbell
230254885Sdumbbell	atomic_inc(&dev_priv->swi_emitted);
231254885Sdumbbell	ret = atomic_read(&dev_priv->swi_emitted);
232254885Sdumbbell
233254885Sdumbbell	BEGIN_RING(4);
234254885Sdumbbell	OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
235254885Sdumbbell	OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
236254885Sdumbbell	ADVANCE_RING();
237254885Sdumbbell	COMMIT_RING();
238254885Sdumbbell
239254885Sdumbbell	return ret;
240254885Sdumbbell}
241254885Sdumbbell
242254885Sdumbbellstatic int radeon_wait_irq(struct drm_device * dev, int swi_nr)
243254885Sdumbbell{
244254885Sdumbbell	drm_radeon_private_t *dev_priv =
245254885Sdumbbell	    (drm_radeon_private_t *) dev->dev_private;
246254885Sdumbbell	int ret = 0;
247254885Sdumbbell
248254885Sdumbbell	if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr)
249254885Sdumbbell		return 0;
250254885Sdumbbell
251254885Sdumbbell	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
252254885Sdumbbell
253254885Sdumbbell	DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
254254885Sdumbbell		    RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
255254885Sdumbbell
256254885Sdumbbell	return ret;
257254885Sdumbbell}
258254885Sdumbbell
259254885Sdumbbellu32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
260254885Sdumbbell{
261254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
262254885Sdumbbell
263254885Sdumbbell	if (!dev_priv) {
264254885Sdumbbell		DRM_ERROR("called with no initialization\n");
265254885Sdumbbell		return -EINVAL;
266254885Sdumbbell	}
267254885Sdumbbell
268254885Sdumbbell	if (crtc < 0 || crtc > 1) {
269254885Sdumbbell		DRM_ERROR("Invalid crtc %d\n", crtc);
270254885Sdumbbell		return -EINVAL;
271254885Sdumbbell	}
272254885Sdumbbell
273254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
274254885Sdumbbell		if (crtc == 0)
275254885Sdumbbell			return RADEON_READ(R500_D1CRTC_FRAME_COUNT);
276254885Sdumbbell		else
277254885Sdumbbell			return RADEON_READ(R500_D2CRTC_FRAME_COUNT);
278254885Sdumbbell	} else {
279254885Sdumbbell		if (crtc == 0)
280254885Sdumbbell			return RADEON_READ(RADEON_CRTC_CRNT_FRAME);
281254885Sdumbbell		else
282254885Sdumbbell			return RADEON_READ(RADEON_CRTC2_CRNT_FRAME);
283254885Sdumbbell	}
284254885Sdumbbell}
285254885Sdumbbell
286254885Sdumbbell/* Needs the lock as it touches the ring.
287254885Sdumbbell */
288254885Sdumbbellint radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv)
289254885Sdumbbell{
290254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
291254885Sdumbbell	drm_radeon_irq_emit_t *emit = data;
292254885Sdumbbell	int result;
293254885Sdumbbell
294254885Sdumbbell	if (!dev_priv) {
295254885Sdumbbell		DRM_ERROR("called with no initialization\n");
296254885Sdumbbell		return -EINVAL;
297254885Sdumbbell	}
298254885Sdumbbell
299254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
300254885Sdumbbell		return -EINVAL;
301254885Sdumbbell
302254885Sdumbbell	LOCK_TEST_WITH_RETURN(dev, file_priv);
303254885Sdumbbell
304254885Sdumbbell	result = radeon_emit_irq(dev);
305254885Sdumbbell
306254885Sdumbbell	if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
307254885Sdumbbell		DRM_ERROR("copy_to_user\n");
308254885Sdumbbell		return -EFAULT;
309254885Sdumbbell	}
310254885Sdumbbell
311254885Sdumbbell	return 0;
312254885Sdumbbell}
313254885Sdumbbell
314254885Sdumbbell/* Doesn't need the hardware lock.
315254885Sdumbbell */
316254885Sdumbbellint radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv)
317254885Sdumbbell{
318254885Sdumbbell	drm_radeon_private_t *dev_priv = dev->dev_private;
319254885Sdumbbell	drm_radeon_irq_wait_t *irqwait = data;
320254885Sdumbbell
321254885Sdumbbell	if (!dev_priv) {
322254885Sdumbbell		DRM_ERROR("called with no initialization\n");
323254885Sdumbbell		return -EINVAL;
324254885Sdumbbell	}
325254885Sdumbbell
326254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
327254885Sdumbbell		return -EINVAL;
328254885Sdumbbell
329254885Sdumbbell	return radeon_wait_irq(dev, irqwait->irq_seq);
330254885Sdumbbell}
331254885Sdumbbell
332254885Sdumbbell/* drm_dma.h hooks
333254885Sdumbbell*/
334254885Sdumbbellvoid radeon_driver_irq_preinstall(struct drm_device * dev)
335254885Sdumbbell{
336254885Sdumbbell	drm_radeon_private_t *dev_priv =
337254885Sdumbbell	    (drm_radeon_private_t *) dev->dev_private;
338254885Sdumbbell	u32 dummy;
339254885Sdumbbell
340254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
341254885Sdumbbell		return;
342254885Sdumbbell
343254885Sdumbbell	/* Disable *all* interrupts */
344254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
345254885Sdumbbell		RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
346254885Sdumbbell	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
347254885Sdumbbell
348254885Sdumbbell	/* Clear bits if they're already high */
349254885Sdumbbell	radeon_acknowledge_irqs(dev_priv, &dummy);
350254885Sdumbbell}
351254885Sdumbbell
352254885Sdumbbellint radeon_driver_irq_postinstall(struct drm_device *dev)
353254885Sdumbbell{
354254885Sdumbbell	drm_radeon_private_t *dev_priv =
355254885Sdumbbell	    (drm_radeon_private_t *) dev->dev_private;
356254885Sdumbbell
357254885Sdumbbell	atomic_set(&dev_priv->swi_emitted, 0);
358254885Sdumbbell	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
359254885Sdumbbell
360254885Sdumbbell	dev->max_vblank_count = 0x001fffff;
361254885Sdumbbell
362254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
363254885Sdumbbell		return 0;
364254885Sdumbbell
365254885Sdumbbell	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
366254885Sdumbbell
367254885Sdumbbell	return 0;
368254885Sdumbbell}
369254885Sdumbbell
370254885Sdumbbellvoid radeon_driver_irq_uninstall(struct drm_device * dev)
371254885Sdumbbell{
372254885Sdumbbell	drm_radeon_private_t *dev_priv =
373254885Sdumbbell	    (drm_radeon_private_t *) dev->dev_private;
374254885Sdumbbell	if (!dev_priv)
375254885Sdumbbell		return;
376254885Sdumbbell
377254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
378254885Sdumbbell		return;
379254885Sdumbbell
380254885Sdumbbell	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
381254885Sdumbbell		RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
382254885Sdumbbell	/* Disable *all* interrupts */
383254885Sdumbbell	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
384254885Sdumbbell}
385254885Sdumbbell
386254885Sdumbbell
387254885Sdumbbellint radeon_vblank_crtc_get(struct drm_device *dev)
388254885Sdumbbell{
389254885Sdumbbell	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
390254885Sdumbbell
391254885Sdumbbell	return dev_priv->vblank_crtc;
392254885Sdumbbell}
393254885Sdumbbell
394254885Sdumbbellint radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
395254885Sdumbbell{
396254885Sdumbbell	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
397254885Sdumbbell	if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
398254885Sdumbbell		DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
399254885Sdumbbell		return -EINVAL;
400254885Sdumbbell	}
401254885Sdumbbell	dev_priv->vblank_crtc = (unsigned int)value;
402254885Sdumbbell	return 0;
403254885Sdumbbell}
404