diff options
author | Dave Airlie <airlied@linux.ie> | 2007-07-10 22:16:01 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2007-07-10 22:16:01 -0400 |
commit | ddbee33328dcfb892cd91f2d57a1822f4d6f70d9 (patch) | |
tree | 6db71299d2cf09f22201a44487d925e222facb33 /drivers/char/drm/radeon_irq.c | |
parent | 7c158acef8f0e51c3a5f71133aaf402628370a64 (diff) |
radeon: add support for vblank on crtc2
This adds support for CRTC2 vblank on radeon similiar to the i915.
Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm/radeon_irq.c')
-rw-r--r-- | drivers/char/drm/radeon_irq.c | 106 |
1 files changed, 95 insertions, 11 deletions
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c index 3ff0baa2fbfa..a4be86e38121 100644 --- a/drivers/char/drm/radeon_irq.c +++ b/drivers/char/drm/radeon_irq.c | |||
@@ -73,18 +73,35 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) | |||
73 | * outside the DRM | 73 | * outside the DRM |
74 | */ | 74 | */ |
75 | stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | | 75 | stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | |
76 | RADEON_CRTC_VBLANK_STAT)); | 76 | RADEON_CRTC_VBLANK_STAT | |
77 | RADEON_CRTC2_VBLANK_STAT)); | ||
77 | if (!stat) | 78 | if (!stat) |
78 | return IRQ_NONE; | 79 | return IRQ_NONE; |
79 | 80 | ||
81 | stat &= dev_priv->irq_enable_reg; | ||
82 | |||
80 | /* SW interrupt */ | 83 | /* SW interrupt */ |
81 | if (stat & RADEON_SW_INT_TEST) { | 84 | if (stat & RADEON_SW_INT_TEST) { |
82 | DRM_WAKEUP(&dev_priv->swi_queue); | 85 | DRM_WAKEUP(&dev_priv->swi_queue); |
83 | } | 86 | } |
84 | 87 | ||
85 | /* VBLANK interrupt */ | 88 | /* VBLANK interrupt */ |
86 | if (stat & RADEON_CRTC_VBLANK_STAT) { | 89 | if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) { |
87 | atomic_inc(&dev->vbl_received); | 90 | int vblank_crtc = dev_priv->vblank_crtc; |
91 | |||
92 | if ((vblank_crtc & | ||
93 | (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) == | ||
94 | (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { | ||
95 | if (stat & RADEON_CRTC_VBLANK_STAT) | ||
96 | atomic_inc(&dev->vbl_received); | ||
97 | if (stat & RADEON_CRTC2_VBLANK_STAT) | ||
98 | atomic_inc(&dev->vbl_received2); | ||
99 | } else if (((stat & RADEON_CRTC_VBLANK_STAT) && | ||
100 | (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) || | ||
101 | ((stat & RADEON_CRTC2_VBLANK_STAT) && | ||
102 | (vblank_crtc & DRM_RADEON_VBLANK_CRTC2))) | ||
103 | atomic_inc(&dev->vbl_received); | ||
104 | |||
88 | DRM_WAKEUP(&dev->vbl_queue); | 105 | DRM_WAKEUP(&dev->vbl_queue); |
89 | drm_vbl_send_signals(dev); | 106 | drm_vbl_send_signals(dev); |
90 | } | 107 | } |
@@ -127,19 +144,30 @@ static int radeon_wait_irq(drm_device_t * dev, int swi_nr) | |||
127 | return ret; | 144 | return ret; |
128 | } | 145 | } |
129 | 146 | ||
130 | int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) | 147 | int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence, |
148 | int crtc) | ||
131 | { | 149 | { |
132 | drm_radeon_private_t *dev_priv = | 150 | drm_radeon_private_t *dev_priv = |
133 | (drm_radeon_private_t *) dev->dev_private; | 151 | (drm_radeon_private_t *) dev->dev_private; |
134 | unsigned int cur_vblank; | 152 | unsigned int cur_vblank; |
135 | int ret = 0; | 153 | int ret = 0; |
136 | 154 | int ack = 0; | |
155 | atomic_t *counter; | ||
137 | if (!dev_priv) { | 156 | if (!dev_priv) { |
138 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | 157 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); |
139 | return DRM_ERR(EINVAL); | 158 | return DRM_ERR(EINVAL); |
140 | } | 159 | } |
141 | 160 | ||
142 | radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT); | 161 | if (crtc == DRM_RADEON_VBLANK_CRTC1) { |
162 | counter = &dev->vbl_received; | ||
163 | ack |= RADEON_CRTC_VBLANK_STAT; | ||
164 | } else if (crtc == DRM_RADEON_VBLANK_CRTC2) { | ||
165 | counter = &dev->vbl_received2; | ||
166 | ack |= RADEON_CRTC2_VBLANK_STAT; | ||
167 | } else | ||
168 | return DRM_ERR(EINVAL); | ||
169 | |||
170 | radeon_acknowledge_irqs(dev_priv, ack); | ||
143 | 171 | ||
144 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | 172 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; |
145 | 173 | ||
@@ -148,7 +176,7 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) | |||
148 | * using vertical blanks... | 176 | * using vertical blanks... |
149 | */ | 177 | */ |
150 | DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, | 178 | DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, |
151 | (((cur_vblank = atomic_read(&dev->vbl_received)) | 179 | (((cur_vblank = atomic_read(counter)) |
152 | - *sequence) <= (1 << 23))); | 180 | - *sequence) <= (1 << 23))); |
153 | 181 | ||
154 | *sequence = cur_vblank; | 182 | *sequence = cur_vblank; |
@@ -156,6 +184,16 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) | |||
156 | return ret; | 184 | return ret; |
157 | } | 185 | } |
158 | 186 | ||
187 | int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) | ||
188 | { | ||
189 | return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1); | ||
190 | } | ||
191 | |||
192 | int radeon_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence) | ||
193 | { | ||
194 | return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2); | ||
195 | } | ||
196 | |||
159 | /* Needs the lock as it touches the ring. | 197 | /* Needs the lock as it touches the ring. |
160 | */ | 198 | */ |
161 | int radeon_irq_emit(DRM_IOCTL_ARGS) | 199 | int radeon_irq_emit(DRM_IOCTL_ARGS) |
@@ -204,6 +242,21 @@ int radeon_irq_wait(DRM_IOCTL_ARGS) | |||
204 | return radeon_wait_irq(dev, irqwait.irq_seq); | 242 | return radeon_wait_irq(dev, irqwait.irq_seq); |
205 | } | 243 | } |
206 | 244 | ||
245 | static void radeon_enable_interrupt(drm_device_t *dev) | ||
246 | { | ||
247 | drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; | ||
248 | |||
249 | dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE; | ||
250 | if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1) | ||
251 | dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK; | ||
252 | |||
253 | if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2) | ||
254 | dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK; | ||
255 | |||
256 | RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); | ||
257 | dev_priv->irq_enabled = 1; | ||
258 | } | ||
259 | |||
207 | /* drm_dma.h hooks | 260 | /* drm_dma.h hooks |
208 | */ | 261 | */ |
209 | void radeon_driver_irq_preinstall(drm_device_t * dev) | 262 | void radeon_driver_irq_preinstall(drm_device_t * dev) |
@@ -216,7 +269,8 @@ void radeon_driver_irq_preinstall(drm_device_t * dev) | |||
216 | 269 | ||
217 | /* Clear bits if they're already high */ | 270 | /* Clear bits if they're already high */ |
218 | radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | | 271 | radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | |
219 | RADEON_CRTC_VBLANK_STAT)); | 272 | RADEON_CRTC_VBLANK_STAT | |
273 | RADEON_CRTC2_VBLANK_STAT)); | ||
220 | } | 274 | } |
221 | 275 | ||
222 | void radeon_driver_irq_postinstall(drm_device_t * dev) | 276 | void radeon_driver_irq_postinstall(drm_device_t * dev) |
@@ -227,9 +281,7 @@ void radeon_driver_irq_postinstall(drm_device_t * dev) | |||
227 | atomic_set(&dev_priv->swi_emitted, 0); | 281 | atomic_set(&dev_priv->swi_emitted, 0); |
228 | DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); | 282 | DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); |
229 | 283 | ||
230 | /* Turn on SW and VBL ints */ | 284 | radeon_enable_interrupt(dev); |
231 | RADEON_WRITE(RADEON_GEN_INT_CNTL, | ||
232 | RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE); | ||
233 | } | 285 | } |
234 | 286 | ||
235 | void radeon_driver_irq_uninstall(drm_device_t * dev) | 287 | void radeon_driver_irq_uninstall(drm_device_t * dev) |
@@ -239,6 +291,38 @@ void radeon_driver_irq_uninstall(drm_device_t * dev) | |||
239 | if (!dev_priv) | 291 | if (!dev_priv) |
240 | return; | 292 | return; |
241 | 293 | ||
294 | dev_priv->irq_enabled = 0; | ||
295 | |||
242 | /* Disable *all* interrupts */ | 296 | /* Disable *all* interrupts */ |
243 | RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); | 297 | RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); |
244 | } | 298 | } |
299 | |||
300 | |||
301 | int radeon_vblank_crtc_get(drm_device_t *dev) | ||
302 | { | ||
303 | drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; | ||
304 | u32 flag; | ||
305 | u32 value; | ||
306 | |||
307 | flag = RADEON_READ(RADEON_GEN_INT_CNTL); | ||
308 | value = 0; | ||
309 | |||
310 | if (flag & RADEON_CRTC_VBLANK_MASK) | ||
311 | value |= DRM_RADEON_VBLANK_CRTC1; | ||
312 | |||
313 | if (flag & RADEON_CRTC2_VBLANK_MASK) | ||
314 | value |= DRM_RADEON_VBLANK_CRTC2; | ||
315 | return value; | ||
316 | } | ||
317 | |||
318 | int radeon_vblank_crtc_set(drm_device_t *dev, int64_t value) | ||
319 | { | ||
320 | drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; | ||
321 | if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { | ||
322 | DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value); | ||
323 | return DRM_ERR(EINVAL); | ||
324 | } | ||
325 | dev_priv->vblank_crtc = (unsigned int)value; | ||
326 | radeon_enable_interrupt(dev); | ||
327 | return 0; | ||
328 | } | ||