LUT updates
[platform/upstream/libdrm.git] / shared-core / radeon_ms_irq.c
1 /*
2  * Copyright 2007 Jérôme Glisse
3  * Copyright 2007 Alex Deucher
4  * Copyright 2007 Dave Airlie
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  *
26  * Authors:
27  *    Jerome Glisse <glisse@freedesktop.org>
28  */
29 #include "drmP.h"
30 #include "drm.h"
31 #include "radeon_ms.h"
32
33 static uint32_t radeon_ack_irqs(struct drm_radeon_private *dev_priv,
34                                 uint32_t mask)
35 {
36         uint32_t irqs;
37
38         irqs = MMIO_R(GEN_INT_STATUS);
39         if (irqs) {
40                 MMIO_W(GEN_INT_STATUS, irqs);
41         }
42         if (irqs & (~mask)) {
43                 /* reprogram irq */
44                 MMIO_W(GEN_INT_CNTL, dev_priv->driver_state.gen_int_cntl);
45         }
46         return irqs;
47 }
48
49 void radeon_ms_irq_emit(struct drm_device *dev)
50 {
51         struct drm_radeon_private *dev_priv = dev->dev_private;
52         uint32_t cmd[4];
53         int i, ret;
54
55         cmd[0] = CP_PACKET0(GEN_INT_CNTL, 1);
56         cmd[1] = dev_priv->driver_state.gen_int_cntl | GEN_INT_CNTL__SW_INT_EN;
57         cmd[2] = GEN_INT_STATUS__SW_INT_SET;
58         /* try to wait but if we timeout we likely are in bad situation */
59         for (i = 0; i < dev_priv->usec_timeout; i++) {
60                 ret = radeon_ms_ring_emit(dev, cmd, 3);
61                 if (!ret) {
62                         break;
63                 }
64         }
65 }
66
67 static void radeon_ms_irq_enable(struct drm_device *dev)
68 {
69         struct drm_radeon_private *dev_priv = dev->dev_private;
70         struct radeon_state *state = &dev_priv->driver_state;
71
72         state->gen_int_cntl = GEN_INT_CNTL__SW_INT_EN;
73         radeon_ms_irq_restore(dev, state);
74 }
75
76 irqreturn_t radeon_ms_irq_handler(DRM_IRQ_ARGS)
77 {
78         struct drm_device *dev = (struct drm_device *)arg;
79         struct drm_radeon_private *dev_priv = dev->dev_private;
80         uint32_t status, mask;
81
82         /* Only consider the bits we're interested in - others could be used
83          * outside the DRM
84          */
85         mask = GEN_INT_STATUS__SW_INT |
86                GEN_INT_STATUS__CRTC_VBLANK_STAT |
87                GEN_INT_STATUS__CRTC2_VBLANK_STAT;
88         status = radeon_ack_irqs(dev_priv, mask);
89         if (!status) {
90                 return IRQ_NONE;
91         }
92
93         /* SW interrupt */
94         if (GEN_INT_STATUS__SW_INT & status) {
95                 r3xx_fence_handler(dev);
96         }
97         r3xx_fence_handler(dev);
98         return IRQ_HANDLED;
99 }
100
101 void radeon_ms_irq_preinstall(struct drm_device * dev)
102 {
103         struct drm_radeon_private *dev_priv = dev->dev_private;
104         struct radeon_state *state = &dev_priv->driver_state;
105         uint32_t mask;
106
107         /* Disable *all* interrupts */
108         state->gen_int_cntl = 0;
109         radeon_ms_irq_restore(dev, state);
110
111         /* Clear bits if they're already high */
112         mask = GEN_INT_STATUS__SW_INT |
113                GEN_INT_STATUS__CRTC_VBLANK_STAT |
114                GEN_INT_STATUS__CRTC2_VBLANK_STAT;
115         radeon_ack_irqs(dev_priv, mask);
116 }
117
118 int radeon_ms_irq_postinstall(struct drm_device * dev)
119 {
120         radeon_ms_irq_enable(dev);
121         return 0;
122 }
123
124 int radeon_ms_irq_init(struct drm_device *dev)
125 {
126         struct drm_radeon_private *dev_priv = dev->dev_private;
127         struct radeon_state *state = &dev_priv->driver_state;
128
129         /* Disable *all* interrupts */
130         state->gen_int_cntl = 0;
131         radeon_ms_irq_restore(dev, state);
132         return 0;
133 }
134
135 void radeon_ms_irq_restore(struct drm_device *dev, struct radeon_state *state)
136 {
137         struct drm_radeon_private *dev_priv = dev->dev_private;
138
139         MMIO_W(GEN_INT_CNTL, state->gen_int_cntl);
140 }
141
142 void radeon_ms_irq_save(struct drm_device *dev, struct radeon_state *state)
143 {
144         struct drm_radeon_private *dev_priv = dev->dev_private;
145
146         state->gen_int_cntl = MMIO_R(GEN_INT_CNTL);
147 }
148
149 void radeon_ms_irq_uninstall(struct drm_device * dev)
150 {
151         struct drm_radeon_private *dev_priv = dev->dev_private;
152         struct radeon_state *state = &dev_priv->driver_state;
153
154         if (dev_priv == NULL) {
155                 return;
156         }
157
158         /* Disable *all* interrupts */
159         state->gen_int_cntl = 0;
160         radeon_ms_irq_restore(dev, state);
161 }