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 <sys/cdefs.h>
34__FBSDID("$FreeBSD: stable/11/sys/dev/drm2/radeon/radeon_irq.c 342691 2019-01-02 16:28:56Z markj $");
35
36#include <dev/drm2/drmP.h>
37#include <dev/drm2/radeon/radeon_drm.h>
38#include "radeon_drv.h"
39
40void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
41{
42	drm_radeon_private_t *dev_priv = dev->dev_private;
43
44	if (state)
45		dev_priv->irq_enable_reg |= mask;
46	else
47		dev_priv->irq_enable_reg &= ~mask;
48
49	if (dev->irq_enabled)
50		RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
51}
52
53static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state)
54{
55	drm_radeon_private_t *dev_priv = dev->dev_private;
56
57	if (state)
58		dev_priv->r500_disp_irq_reg |= mask;
59	else
60		dev_priv->r500_disp_irq_reg &= ~mask;
61
62	if (dev->irq_enabled)
63		RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
64}
65
66int radeon_enable_vblank(struct drm_device *dev, int crtc)
67{
68	drm_radeon_private_t *dev_priv = dev->dev_private;
69
70	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
71		switch (crtc) {
72		case 0:
73			r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 1);
74			break;
75		case 1:
76			r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 1);
77			break;
78		default:
79			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
80				  crtc);
81			return -EINVAL;
82		}
83	} else {
84		switch (crtc) {
85		case 0:
86			radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
87			break;
88		case 1:
89			radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
90			break;
91		default:
92			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
93				  crtc);
94			return -EINVAL;
95		}
96	}
97
98	return 0;
99}
100
101void radeon_disable_vblank(struct drm_device *dev, int crtc)
102{
103	drm_radeon_private_t *dev_priv = dev->dev_private;
104
105	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
106		switch (crtc) {
107		case 0:
108			r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 0);
109			break;
110		case 1:
111			r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 0);
112			break;
113		default:
114			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
115				  crtc);
116			break;
117		}
118	} else {
119		switch (crtc) {
120		case 0:
121			radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
122			break;
123		case 1:
124			radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
125			break;
126		default:
127			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
128				  crtc);
129			break;
130		}
131	}
132}
133
134static u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int)
135{
136	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS);
137	u32 irq_mask = RADEON_SW_INT_TEST;
138
139	*r500_disp_int = 0;
140	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
141		/* vbl interrupts in a different place */
142
143		if (irqs & R500_DISPLAY_INT_STATUS) {
144			/* if a display interrupt */
145			u32 disp_irq;
146
147			disp_irq = RADEON_READ(R500_DISP_INTERRUPT_STATUS);
148
149			*r500_disp_int = disp_irq;
150			if (disp_irq & R500_D1_VBLANK_INTERRUPT)
151				RADEON_WRITE(R500_D1MODE_VBLANK_STATUS, R500_VBLANK_ACK);
152			if (disp_irq & R500_D2_VBLANK_INTERRUPT)
153				RADEON_WRITE(R500_D2MODE_VBLANK_STATUS, R500_VBLANK_ACK);
154		}
155		irq_mask |= R500_DISPLAY_INT_STATUS;
156	} else
157		irq_mask |= RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT;
158
159	irqs &=	irq_mask;
160
161	if (irqs)
162		RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
163
164	return irqs;
165}
166
167/* Interrupts - Used for device synchronization and flushing in the
168 * following circumstances:
169 *
170 * - Exclusive FB access with hw idle:
171 *    - Wait for GUI Idle (?) interrupt, then do normal flush.
172 *
173 * - Frame throttling, NV_fence:
174 *    - Drop marker irq's into command stream ahead of time.
175 *    - Wait on irq's with lock *not held*
176 *    - Check each for termination condition
177 *
178 * - Internally in cp_getbuffer, etc:
179 *    - as above, but wait with lock held???
180 *
181 * NOTE: These functions are misleadingly named -- the irq's aren't
182 * tied to dma at all, this is just a hangover from dri prehistory.
183 */
184
185irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
186{
187	struct drm_device *dev = (struct drm_device *) arg;
188	drm_radeon_private_t *dev_priv =
189	    (drm_radeon_private_t *) dev->dev_private;
190	u32 stat;
191	u32 r500_disp_int;
192
193	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
194		return IRQ_NONE;
195
196	/* Only consider the bits we're interested in - others could be used
197	 * outside the DRM
198	 */
199	stat = radeon_acknowledge_irqs(dev_priv, &r500_disp_int);
200	if (!stat)
201		return IRQ_NONE;
202
203	stat &= dev_priv->irq_enable_reg;
204
205	/* SW interrupt */
206	if (stat & RADEON_SW_INT_TEST)
207		DRM_WAKEUP(&dev_priv->swi_queue);
208
209	/* VBLANK interrupt */
210	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
211		if (r500_disp_int & R500_D1_VBLANK_INTERRUPT)
212			drm_handle_vblank(dev, 0);
213		if (r500_disp_int & R500_D2_VBLANK_INTERRUPT)
214			drm_handle_vblank(dev, 1);
215	} else {
216		if (stat & RADEON_CRTC_VBLANK_STAT)
217			drm_handle_vblank(dev, 0);
218		if (stat & RADEON_CRTC2_VBLANK_STAT)
219			drm_handle_vblank(dev, 1);
220	}
221	return IRQ_HANDLED;
222}
223
224u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
225{
226	drm_radeon_private_t *dev_priv = dev->dev_private;
227
228	if (!dev_priv) {
229		DRM_ERROR("called with no initialization\n");
230		return -EINVAL;
231	}
232
233	if (crtc < 0 || crtc > 1) {
234		DRM_ERROR("Invalid crtc %d\n", crtc);
235		return -EINVAL;
236	}
237
238	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
239		if (crtc == 0)
240			return RADEON_READ(R500_D1CRTC_FRAME_COUNT);
241		else
242			return RADEON_READ(R500_D2CRTC_FRAME_COUNT);
243	} else {
244		if (crtc == 0)
245			return RADEON_READ(RADEON_CRTC_CRNT_FRAME);
246		else
247			return RADEON_READ(RADEON_CRTC2_CRNT_FRAME);
248	}
249}
250
251/* drm_dma.h hooks
252*/
253void radeon_driver_irq_preinstall(struct drm_device * dev)
254{
255	drm_radeon_private_t *dev_priv =
256	    (drm_radeon_private_t *) dev->dev_private;
257	u32 dummy;
258
259	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
260		return;
261
262	/* Disable *all* interrupts */
263	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
264		RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
265	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
266
267	/* Clear bits if they're already high */
268	radeon_acknowledge_irqs(dev_priv, &dummy);
269}
270
271int radeon_driver_irq_postinstall(struct drm_device *dev)
272{
273	drm_radeon_private_t *dev_priv =
274	    (drm_radeon_private_t *) dev->dev_private;
275
276	atomic_set(&dev_priv->swi_emitted, 0);
277	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
278
279	dev->max_vblank_count = 0x001fffff;
280
281	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
282		return 0;
283
284	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
285
286	return 0;
287}
288
289void radeon_driver_irq_uninstall(struct drm_device * dev)
290{
291	drm_radeon_private_t *dev_priv =
292	    (drm_radeon_private_t *) dev->dev_private;
293	if (!dev_priv)
294		return;
295
296	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
297		return;
298
299	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
300		RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
301	/* Disable *all* interrupts */
302	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
303}
304
305
306int radeon_vblank_crtc_get(struct drm_device *dev)
307{
308	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
309
310	return dev_priv->vblank_crtc;
311}
312
313int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
314{
315	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
316	if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
317		DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
318		return -EINVAL;
319	}
320	dev_priv->vblank_crtc = (unsigned int)value;
321	return 0;
322}
323