diff options
Diffstat (limited to 'drivers/char/drm/radeon_irq.c')
| -rw-r--r-- | drivers/char/drm/radeon_irq.c | 171 |
1 files changed, 88 insertions, 83 deletions
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c index 507d6b747a13..009af3814b6f 100644 --- a/drivers/char/drm/radeon_irq.c +++ b/drivers/char/drm/radeon_irq.c | |||
| @@ -35,61 +35,12 @@ | |||
| 35 | #include "radeon_drm.h" | 35 | #include "radeon_drm.h" |
| 36 | #include "radeon_drv.h" | 36 | #include "radeon_drv.h" |
| 37 | 37 | ||
| 38 | static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state) | 38 | static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv, |
| 39 | u32 mask) | ||
| 39 | { | 40 | { |
| 40 | drm_radeon_private_t *dev_priv = dev->dev_private; | 41 | u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask; |
| 41 | |||
| 42 | if (state) | ||
| 43 | dev_priv->irq_enable_reg |= mask; | ||
| 44 | else | ||
| 45 | dev_priv->irq_enable_reg &= ~mask; | ||
| 46 | |||
| 47 | RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); | ||
| 48 | } | ||
| 49 | |||
| 50 | int radeon_enable_vblank(struct drm_device *dev, int crtc) | ||
| 51 | { | ||
| 52 | switch (crtc) { | ||
| 53 | case 0: | ||
| 54 | radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1); | ||
| 55 | break; | ||
| 56 | case 1: | ||
| 57 | radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1); | ||
| 58 | break; | ||
| 59 | default: | ||
| 60 | DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", | ||
| 61 | crtc); | ||
| 62 | return EINVAL; | ||
| 63 | } | ||
| 64 | |||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | void radeon_disable_vblank(struct drm_device *dev, int crtc) | ||
| 69 | { | ||
| 70 | switch (crtc) { | ||
| 71 | case 0: | ||
| 72 | radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0); | ||
| 73 | break; | ||
| 74 | case 1: | ||
| 75 | radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0); | ||
| 76 | break; | ||
| 77 | default: | ||
| 78 | DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", | ||
| 79 | crtc); | ||
| 80 | break; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv) | ||
| 85 | { | ||
| 86 | u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & | ||
| 87 | (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT | | ||
| 88 | RADEON_CRTC2_VBLANK_STAT); | ||
| 89 | |||
| 90 | if (irqs) | 42 | if (irqs) |
| 91 | RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); | 43 | RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); |
| 92 | |||
| 93 | return irqs; | 44 | return irqs; |
| 94 | } | 45 | } |
| 95 | 46 | ||
| @@ -121,21 +72,39 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) | |||
| 121 | /* Only consider the bits we're interested in - others could be used | 72 | /* Only consider the bits we're interested in - others could be used |
| 122 | * outside the DRM | 73 | * outside the DRM |
| 123 | */ | 74 | */ |
| 124 | stat = radeon_acknowledge_irqs(dev_priv); | 75 | stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | |
| 76 | RADEON_CRTC_VBLANK_STAT | | ||
| 77 | RADEON_CRTC2_VBLANK_STAT)); | ||
| 125 | if (!stat) | 78 | if (!stat) |
| 126 | return IRQ_NONE; | 79 | return IRQ_NONE; |
| 127 | 80 | ||
| 128 | stat &= dev_priv->irq_enable_reg; | 81 | stat &= dev_priv->irq_enable_reg; |
| 129 | 82 | ||
| 130 | /* SW interrupt */ | 83 | /* SW interrupt */ |
| 131 | if (stat & RADEON_SW_INT_TEST) | 84 | if (stat & RADEON_SW_INT_TEST) { |
| 132 | DRM_WAKEUP(&dev_priv->swi_queue); | 85 | DRM_WAKEUP(&dev_priv->swi_queue); |
| 86 | } | ||
| 133 | 87 | ||
| 134 | /* VBLANK interrupt */ | 88 | /* VBLANK interrupt */ |
| 135 | if (stat & RADEON_CRTC_VBLANK_STAT) | 89 | if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) { |
| 136 | drm_handle_vblank(dev, 0); | 90 | int vblank_crtc = dev_priv->vblank_crtc; |
| 137 | if (stat & RADEON_CRTC2_VBLANK_STAT) | 91 | |
| 138 | drm_handle_vblank(dev, 1); | 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 | |||
| 105 | DRM_WAKEUP(&dev->vbl_queue); | ||
| 106 | drm_vbl_send_signals(dev); | ||
| 107 | } | ||
| 139 | 108 | ||
| 140 | return IRQ_HANDLED; | 109 | return IRQ_HANDLED; |
| 141 | } | 110 | } |
| @@ -175,27 +144,54 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr) | |||
| 175 | return ret; | 144 | return ret; |
| 176 | } | 145 | } |
| 177 | 146 | ||
| 178 | u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc) | 147 | static int radeon_driver_vblank_do_wait(struct drm_device * dev, |
| 148 | unsigned int *sequence, int crtc) | ||
| 179 | { | 149 | { |
| 180 | drm_radeon_private_t *dev_priv = dev->dev_private; | 150 | drm_radeon_private_t *dev_priv = |
| 181 | u32 crtc_cnt_reg, crtc_status_reg; | 151 | (drm_radeon_private_t *) dev->dev_private; |
| 182 | 152 | unsigned int cur_vblank; | |
| 153 | int ret = 0; | ||
| 154 | int ack = 0; | ||
| 155 | atomic_t *counter; | ||
| 183 | if (!dev_priv) { | 156 | if (!dev_priv) { |
| 184 | DRM_ERROR("called with no initialization\n"); | 157 | DRM_ERROR("called with no initialization\n"); |
| 185 | return -EINVAL; | 158 | return -EINVAL; |
| 186 | } | 159 | } |
| 187 | 160 | ||
| 188 | if (crtc == 0) { | 161 | if (crtc == DRM_RADEON_VBLANK_CRTC1) { |
| 189 | crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME; | 162 | counter = &dev->vbl_received; |
| 190 | crtc_status_reg = RADEON_CRTC_STATUS; | 163 | ack |= RADEON_CRTC_VBLANK_STAT; |
| 191 | } else if (crtc == 1) { | 164 | } else if (crtc == DRM_RADEON_VBLANK_CRTC2) { |
| 192 | crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME; | 165 | counter = &dev->vbl_received2; |
| 193 | crtc_status_reg = RADEON_CRTC2_STATUS; | 166 | ack |= RADEON_CRTC2_VBLANK_STAT; |
| 194 | } else { | 167 | } else |
| 195 | return -EINVAL; | 168 | return -EINVAL; |
| 196 | } | ||
| 197 | 169 | ||
| 198 | return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1); | 170 | radeon_acknowledge_irqs(dev_priv, ack); |
| 171 | |||
| 172 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | ||
| 173 | |||
| 174 | /* Assume that the user has missed the current sequence number | ||
| 175 | * by about a day rather than she wants to wait for years | ||
| 176 | * using vertical blanks... | ||
| 177 | */ | ||
| 178 | DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, | ||
| 179 | (((cur_vblank = atomic_read(counter)) | ||
| 180 | - *sequence) <= (1 << 23))); | ||
| 181 | |||
| 182 | *sequence = cur_vblank; | ||
| 183 | |||
| 184 | return ret; | ||
| 185 | } | ||
| 186 | |||
| 187 | int radeon_driver_vblank_wait(struct drm_device *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(struct drm_device *dev, unsigned int *sequence) | ||
| 193 | { | ||
| 194 | return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2); | ||
| 199 | } | 195 | } |
| 200 | 196 | ||
| 201 | /* Needs the lock as it touches the ring. | 197 | /* Needs the lock as it touches the ring. |
| @@ -238,6 +234,21 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr | |||
| 238 | return radeon_wait_irq(dev, irqwait->irq_seq); | 234 | return radeon_wait_irq(dev, irqwait->irq_seq); |
| 239 | } | 235 | } |
| 240 | 236 | ||
| 237 | static void radeon_enable_interrupt(struct drm_device *dev) | ||
| 238 | { | ||
| 239 | drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; | ||
| 240 | |||
| 241 | dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE; | ||
| 242 | if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1) | ||
| 243 | dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK; | ||
| 244 | |||
| 245 | if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2) | ||
| 246 | dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK; | ||
| 247 | |||
| 248 | RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); | ||
| 249 | dev_priv->irq_enabled = 1; | ||
| 250 | } | ||
| 251 | |||
| 241 | /* drm_dma.h hooks | 252 | /* drm_dma.h hooks |
| 242 | */ | 253 | */ |
| 243 | void radeon_driver_irq_preinstall(struct drm_device * dev) | 254 | void radeon_driver_irq_preinstall(struct drm_device * dev) |
| @@ -249,27 +260,20 @@ void radeon_driver_irq_preinstall(struct drm_device * dev) | |||
| 249 | RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); | 260 | RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); |
| 250 | 261 | ||
| 251 | /* Clear bits if they're already high */ | 262 | /* Clear bits if they're already high */ |
| 252 | radeon_acknowledge_irqs(dev_priv); | 263 | radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | |
| 264 | RADEON_CRTC_VBLANK_STAT | | ||
| 265 | RADEON_CRTC2_VBLANK_STAT)); | ||
| 253 | } | 266 | } |
| 254 | 267 | ||
| 255 | int radeon_driver_irq_postinstall(struct drm_device * dev) | 268 | void radeon_driver_irq_postinstall(struct drm_device * dev) |
| 256 | { | 269 | { |
| 257 | drm_radeon_private_t *dev_priv = | 270 | drm_radeon_private_t *dev_priv = |
| 258 | (drm_radeon_private_t *) dev->dev_private; | 271 | (drm_radeon_private_t *) dev->dev_private; |
| 259 | int ret; | ||
| 260 | 272 | ||
| 261 | atomic_set(&dev_priv->swi_emitted, 0); | 273 | atomic_set(&dev_priv->swi_emitted, 0); |
| 262 | DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); | 274 | DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); |
| 263 | 275 | ||
| 264 | ret = drm_vblank_init(dev, 2); | 276 | radeon_enable_interrupt(dev); |
| 265 | if (ret) | ||
| 266 | return ret; | ||
| 267 | |||
| 268 | dev->max_vblank_count = 0x001fffff; | ||
| 269 | |||
| 270 | radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); | ||
| 271 | |||
| 272 | return 0; | ||
| 273 | } | 277 | } |
| 274 | 278 | ||
| 275 | void radeon_driver_irq_uninstall(struct drm_device * dev) | 279 | void radeon_driver_irq_uninstall(struct drm_device * dev) |
| @@ -311,5 +315,6 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value) | |||
| 311 | return -EINVAL; | 315 | return -EINVAL; |
| 312 | } | 316 | } |
| 313 | dev_priv->vblank_crtc = (unsigned int)value; | 317 | dev_priv->vblank_crtc = (unsigned int)value; |
| 318 | radeon_enable_interrupt(dev); | ||
| 314 | return 0; | 319 | return 0; |
| 315 | } | 320 | } |
