|
@@ -975,7 +975,10 @@ void
|
|
|
intel_wait_for_vblank(struct drm_device *dev)
|
|
|
{
|
|
|
/* Wait for 20ms, i.e. one cycle at 50hz. */
|
|
|
- msleep(20);
|
|
|
+ if (in_dbg_master())
|
|
|
+ mdelay(20); /* The kernel debugger cannot call msleep() */
|
|
|
+ else
|
|
|
+ msleep(20);
|
|
|
}
|
|
|
|
|
|
/* Parameters have changed, update FBC info */
|
|
@@ -1314,6 +1317,98 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/* Assume fb object is pinned & idle & fenced and just update base pointers */
|
|
|
+static int
|
|
|
+intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|
|
+ int x, int y)
|
|
|
+{
|
|
|
+ struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
+ struct intel_framebuffer *intel_fb;
|
|
|
+ struct drm_i915_gem_object *obj_priv;
|
|
|
+ struct drm_gem_object *obj;
|
|
|
+ int plane = intel_crtc->plane;
|
|
|
+ unsigned long Start, Offset;
|
|
|
+ int dspbase = (plane == 0 ? DSPAADDR : DSPBADDR);
|
|
|
+ int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF);
|
|
|
+ int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
|
|
|
+ int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
|
|
|
+ int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
|
|
|
+ u32 dspcntr;
|
|
|
+
|
|
|
+ switch (plane) {
|
|
|
+ case 0:
|
|
|
+ case 1:
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ DRM_ERROR("Can't update plane %d in SAREA\n", plane);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ intel_fb = to_intel_framebuffer(fb);
|
|
|
+ obj = intel_fb->obj;
|
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
+
|
|
|
+ dspcntr = I915_READ(dspcntr_reg);
|
|
|
+ /* Mask out pixel format bits in case we change it */
|
|
|
+ dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
|
|
|
+ switch (fb->bits_per_pixel) {
|
|
|
+ case 8:
|
|
|
+ dspcntr |= DISPPLANE_8BPP;
|
|
|
+ break;
|
|
|
+ case 16:
|
|
|
+ if (fb->depth == 15)
|
|
|
+ dspcntr |= DISPPLANE_15_16BPP;
|
|
|
+ else
|
|
|
+ dspcntr |= DISPPLANE_16BPP;
|
|
|
+ break;
|
|
|
+ case 24:
|
|
|
+ case 32:
|
|
|
+ dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ DRM_ERROR("Unknown color depth\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ if (IS_I965G(dev)) {
|
|
|
+ if (obj_priv->tiling_mode != I915_TILING_NONE)
|
|
|
+ dspcntr |= DISPPLANE_TILED;
|
|
|
+ else
|
|
|
+ dspcntr &= ~DISPPLANE_TILED;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (IS_IRONLAKE(dev))
|
|
|
+ /* must disable */
|
|
|
+ dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
|
|
|
+
|
|
|
+ I915_WRITE(dspcntr_reg, dspcntr);
|
|
|
+
|
|
|
+ Start = obj_priv->gtt_offset;
|
|
|
+ Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
|
|
|
+
|
|
|
+ DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
|
|
|
+ I915_WRITE(dspstride, fb->pitch);
|
|
|
+ if (IS_I965G(dev)) {
|
|
|
+ I915_WRITE(dspbase, Offset);
|
|
|
+ I915_READ(dspbase);
|
|
|
+ I915_WRITE(dspsurf, Start);
|
|
|
+ I915_READ(dspsurf);
|
|
|
+ I915_WRITE(dsptileoff, (y << 16) | x);
|
|
|
+ } else {
|
|
|
+ I915_WRITE(dspbase, Start + Offset);
|
|
|
+ I915_READ(dspbase);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((IS_I965G(dev) || plane == 0))
|
|
|
+ intel_update_fbc(crtc, &crtc->mode);
|
|
|
+
|
|
|
+ intel_wait_for_vblank(dev);
|
|
|
+ intel_increase_pllclock(crtc, true);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|
|
struct drm_framebuffer *old_fb)
|
|
@@ -4814,6 +4909,7 @@ static const struct drm_crtc_helper_funcs intel_helper_funcs = {
|
|
|
.mode_fixup = intel_crtc_mode_fixup,
|
|
|
.mode_set = intel_crtc_mode_set,
|
|
|
.mode_set_base = intel_pipe_set_base,
|
|
|
+ .mode_set_base_atomic = intel_pipe_set_base_atomic,
|
|
|
.prepare = intel_crtc_prepare,
|
|
|
.commit = intel_crtc_commit,
|
|
|
.load_lut = intel_crtc_load_lut,
|