diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a05ac2c91ba2..287b42c9d1a8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -3604,6 +3604,30 @@ static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) | |||
3604 | */ | 3604 | */ |
3605 | } | 3605 | } |
3606 | 3606 | ||
3607 | /** | ||
3608 | * i9xx_fixup_plane - ugly workaround for G45 to fire up the hardware | ||
3609 | * cursor plane briefly if not already running after enabling the display | ||
3610 | * plane. | ||
3611 | * This workaround avoids occasional blank screens when self refresh is | ||
3612 | * enabled. | ||
3613 | */ | ||
3614 | static void | ||
3615 | g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe) | ||
3616 | { | ||
3617 | u32 cntl = I915_READ(CURCNTR(pipe)); | ||
3618 | |||
3619 | if ((cntl & CURSOR_MODE) == 0) { | ||
3620 | u32 fw_bcl_self = I915_READ(FW_BLC_SELF); | ||
3621 | |||
3622 | I915_WRITE(FW_BLC_SELF, fw_bcl_self & ~FW_BLC_SELF_EN); | ||
3623 | I915_WRITE(CURCNTR(pipe), CURSOR_MODE_64_ARGB_AX); | ||
3624 | intel_wait_for_vblank(dev_priv->dev, pipe); | ||
3625 | I915_WRITE(CURCNTR(pipe), cntl); | ||
3626 | I915_WRITE(CURBASE(pipe), I915_READ(CURBASE(pipe))); | ||
3627 | I915_WRITE(FW_BLC_SELF, fw_bcl_self); | ||
3628 | } | ||
3629 | } | ||
3630 | |||
3607 | static void i9xx_crtc_enable(struct drm_crtc *crtc) | 3631 | static void i9xx_crtc_enable(struct drm_crtc *crtc) |
3608 | { | 3632 | { |
3609 | struct drm_device *dev = crtc->dev; | 3633 | struct drm_device *dev = crtc->dev; |
@@ -3629,6 +3653,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) | |||
3629 | 3653 | ||
3630 | intel_enable_pipe(dev_priv, pipe, false); | 3654 | intel_enable_pipe(dev_priv, pipe, false); |
3631 | intel_enable_plane(dev_priv, plane, pipe); | 3655 | intel_enable_plane(dev_priv, plane, pipe); |
3656 | if (IS_G4X(dev)) | ||
3657 | g4x_fixup_plane(dev_priv, pipe); | ||
3632 | 3658 | ||
3633 | intel_crtc_load_lut(crtc); | 3659 | intel_crtc_load_lut(crtc); |
3634 | intel_update_fbc(dev); | 3660 | intel_update_fbc(dev); |
@@ -7256,8 +7282,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
7256 | { | 7282 | { |
7257 | struct drm_device *dev = crtc->dev; | 7283 | struct drm_device *dev = crtc->dev; |
7258 | struct drm_i915_private *dev_priv = dev->dev_private; | 7284 | struct drm_i915_private *dev_priv = dev->dev_private; |
7259 | struct intel_framebuffer *intel_fb; | 7285 | struct drm_framebuffer *old_fb = crtc->fb; |
7260 | struct drm_i915_gem_object *obj; | 7286 | struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj; |
7261 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 7287 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
7262 | struct intel_unpin_work *work; | 7288 | struct intel_unpin_work *work; |
7263 | unsigned long flags; | 7289 | unsigned long flags; |
@@ -7282,8 +7308,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
7282 | 7308 | ||
7283 | work->event = event; | 7309 | work->event = event; |
7284 | work->crtc = crtc; | 7310 | work->crtc = crtc; |
7285 | intel_fb = to_intel_framebuffer(crtc->fb); | 7311 | work->old_fb_obj = to_intel_framebuffer(old_fb)->obj; |
7286 | work->old_fb_obj = intel_fb->obj; | ||
7287 | INIT_WORK(&work->work, intel_unpin_work_fn); | 7312 | INIT_WORK(&work->work, intel_unpin_work_fn); |
7288 | 7313 | ||
7289 | ret = drm_vblank_get(dev, intel_crtc->pipe); | 7314 | ret = drm_vblank_get(dev, intel_crtc->pipe); |
@@ -7303,9 +7328,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
7303 | intel_crtc->unpin_work = work; | 7328 | intel_crtc->unpin_work = work; |
7304 | spin_unlock_irqrestore(&dev->event_lock, flags); | 7329 | spin_unlock_irqrestore(&dev->event_lock, flags); |
7305 | 7330 | ||
7306 | intel_fb = to_intel_framebuffer(fb); | ||
7307 | obj = intel_fb->obj; | ||
7308 | |||
7309 | if (atomic_read(&intel_crtc->unpin_work_count) >= 2) | 7331 | if (atomic_read(&intel_crtc->unpin_work_count) >= 2) |
7310 | flush_workqueue(dev_priv->wq); | 7332 | flush_workqueue(dev_priv->wq); |
7311 | 7333 | ||
@@ -7340,6 +7362,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
7340 | 7362 | ||
7341 | cleanup_pending: | 7363 | cleanup_pending: |
7342 | atomic_dec(&intel_crtc->unpin_work_count); | 7364 | atomic_dec(&intel_crtc->unpin_work_count); |
7365 | crtc->fb = old_fb; | ||
7343 | drm_gem_object_unreference(&work->old_fb_obj->base); | 7366 | drm_gem_object_unreference(&work->old_fb_obj->base); |
7344 | drm_gem_object_unreference(&obj->base); | 7367 | drm_gem_object_unreference(&obj->base); |
7345 | mutex_unlock(&dev->struct_mutex); | 7368 | mutex_unlock(&dev->struct_mutex); |