diff options
Diffstat (limited to 'drivers/gpu/drm/gma500/psb_irq.c')
-rw-r--r-- | drivers/gpu/drm/gma500/psb_irq.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index 1869586457b1..8652cdf3f03f 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c | |||
@@ -190,6 +190,9 @@ static void mid_pipe_event_handler(struct drm_device *dev, int pipe) | |||
190 | */ | 190 | */ |
191 | static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) | 191 | static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) |
192 | { | 192 | { |
193 | if (vdc_stat & _PSB_IRQ_ASLE) | ||
194 | psb_intel_opregion_asle_intr(dev); | ||
195 | |||
193 | if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG) | 196 | if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG) |
194 | mid_pipe_event_handler(dev, 0); | 197 | mid_pipe_event_handler(dev, 0); |
195 | 198 | ||
@@ -199,11 +202,9 @@ static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) | |||
199 | 202 | ||
200 | irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) | 203 | irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) |
201 | { | 204 | { |
202 | struct drm_device *dev = (struct drm_device *) arg; | 205 | struct drm_device *dev = arg; |
203 | struct drm_psb_private *dev_priv = | 206 | struct drm_psb_private *dev_priv = dev->dev_private; |
204 | (struct drm_psb_private *) dev->dev_private; | 207 | uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, hotplug_int = 0; |
205 | |||
206 | uint32_t vdc_stat, dsp_int = 0, sgx_int = 0; | ||
207 | int handled = 0; | 208 | int handled = 0; |
208 | 209 | ||
209 | spin_lock(&dev_priv->irqmask_lock); | 210 | spin_lock(&dev_priv->irqmask_lock); |
@@ -220,6 +221,8 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) | |||
220 | 221 | ||
221 | if (vdc_stat & _PSB_IRQ_SGX_FLAG) | 222 | if (vdc_stat & _PSB_IRQ_SGX_FLAG) |
222 | sgx_int = 1; | 223 | sgx_int = 1; |
224 | if (vdc_stat & _PSB_IRQ_DISP_HOTSYNC) | ||
225 | hotplug_int = 1; | ||
223 | 226 | ||
224 | vdc_stat &= dev_priv->vdc_irq_mask; | 227 | vdc_stat &= dev_priv->vdc_irq_mask; |
225 | spin_unlock(&dev_priv->irqmask_lock); | 228 | spin_unlock(&dev_priv->irqmask_lock); |
@@ -241,6 +244,13 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) | |||
241 | handled = 1; | 244 | handled = 1; |
242 | } | 245 | } |
243 | 246 | ||
247 | /* Note: this bit has other meanings on some devices, so we will | ||
248 | need to address that later if it ever matters */ | ||
249 | if (hotplug_int && dev_priv->ops->hotplug) { | ||
250 | handled = dev_priv->ops->hotplug(dev); | ||
251 | REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT)); | ||
252 | } | ||
253 | |||
244 | PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R); | 254 | PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R); |
245 | (void) PSB_RVDC32(PSB_INT_IDENTITY_R); | 255 | (void) PSB_RVDC32(PSB_INT_IDENTITY_R); |
246 | DRM_READMEMORYBARRIER(); | 256 | DRM_READMEMORYBARRIER(); |
@@ -273,6 +283,11 @@ void psb_irq_preinstall(struct drm_device *dev) | |||
273 | dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; | 283 | dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; |
274 | */ | 284 | */ |
275 | 285 | ||
286 | /* Revisit this area - want per device masks ? */ | ||
287 | if (dev_priv->ops->hotplug) | ||
288 | dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC; | ||
289 | dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE; | ||
290 | |||
276 | /* This register is safe even if display island is off */ | 291 | /* This register is safe even if display island is off */ |
277 | PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); | 292 | PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); |
278 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); | 293 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); |
@@ -305,18 +320,23 @@ int psb_irq_postinstall(struct drm_device *dev) | |||
305 | else | 320 | else |
306 | psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); | 321 | psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); |
307 | 322 | ||
323 | if (dev_priv->ops->hotplug_enable) | ||
324 | dev_priv->ops->hotplug_enable(dev, true); | ||
325 | |||
308 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); | 326 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); |
309 | return 0; | 327 | return 0; |
310 | } | 328 | } |
311 | 329 | ||
312 | void psb_irq_uninstall(struct drm_device *dev) | 330 | void psb_irq_uninstall(struct drm_device *dev) |
313 | { | 331 | { |
314 | struct drm_psb_private *dev_priv = | 332 | struct drm_psb_private *dev_priv = dev->dev_private; |
315 | (struct drm_psb_private *) dev->dev_private; | ||
316 | unsigned long irqflags; | 333 | unsigned long irqflags; |
317 | 334 | ||
318 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); | 335 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); |
319 | 336 | ||
337 | if (dev_priv->ops->hotplug_enable) | ||
338 | dev_priv->ops->hotplug_enable(dev, false); | ||
339 | |||
320 | PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); | 340 | PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); |
321 | 341 | ||
322 | if (dev->vblank_enabled[0]) | 342 | if (dev->vblank_enabled[0]) |
@@ -406,7 +426,7 @@ void psb_irq_turn_off_dpst(struct drm_device *dev) | |||
406 | psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); | 426 | psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); |
407 | 427 | ||
408 | pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); | 428 | pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); |
409 | PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE), | 429 | PSB_WVDC32(pwm_reg & ~PWM_PHASEIN_INT_ENABLE, |
410 | PWM_CONTROL_LOGIC); | 430 | PWM_CONTROL_LOGIC); |
411 | pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); | 431 | pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); |
412 | 432 | ||