diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e5eb11d..e98298f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2087,8 +2087,44 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); I915_WRITE(DSPLINOFF(plane), linear_offset); - } else - I915_WRITE(DSPADDR(plane), i915_gem_obj_ggtt_offset(obj) + linear_offset); + } else if (INTEL_INFO(dev)->gen == 2 && IS_I830(dev) && !intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { + unsigned long planeadr = i915_gem_obj_ggtt_offset(obj) + linear_offset; + DRM_DEBUG_KMS("Plane address is 0x%lx",planeadr); + // I830 panning flicker work around. Only for non-LVDS output, only for i830. + if (obj->tiling_mode != I915_TILING_NONE) { + if ((planeadr & 0x40)) { + DRM_DEBUG_KMS("Detected potential flicker in tiling mode"); + DRM_DEBUG_KMS("No workaround available"); + DRM_DEBUG_KMS("Use a linear frame buffer"); + } + } else { + switch (fb->pixel_format) { + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ABGR8888: + { + unsigned long int oldadr = I915_READ(DSPADDR(plane)); + if (((oldadr ^ planeadr) & 0x40) && (planeadr & 0xc0) == 0xc0) { + DRM_DEBUG_KMS("Detected potential flicker in linear mode"); + I915_WRITE(DSPADDR(plane), planeadr & (~(0x80))); + POSTING_READ(reg); + intel_wait_for_vblank(dev,intel_crtc->pipe); + } + } + break; + default: + DRM_DEBUG_KMS("No flicker workaround available\n"); + break; + } + } + I915_WRITE(DSPADDR(plane), planeadr); + } else { + I915_WRITE(DSPADDR(plane), i915_gem_obj_ggtt_offset(obj) + linear_offset); + } POSTING_READ(reg); return 0;