drm/i915: use new fb debug hooks
authorJesse Barnes <jbarnes@virtuousgeek.org>
Mon, 2 Aug 2010 19:07:50 +0000 (12:07 -0700)
committerJason Wessel <jason.wessel@windriver.com>
Thu, 5 Aug 2010 14:22:31 +0000 (09:22 -0500)
Implement atomic kernel mode settings using the fb layer's debug hook
system for supporting debugger interaction.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_fb.c

index 5e21b31198249349dc5e69265dbe20c8b0a23d02..eff28e5de4dce813ef4b071cc0320fe3f3ce5b46 100644 (file)
@@ -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,
index 3e18c9e7729b6a475ce270d3329acf3d54288f1c..54acd8b534df4bd092c71f4e8ce0998b7cd9dc09 100644 (file)
@@ -61,6 +61,8 @@ static struct fb_ops intelfb_ops = {
        .fb_pan_display = drm_fb_helper_pan_display,
        .fb_blank = drm_fb_helper_blank,
        .fb_setcmap = drm_fb_helper_setcmap,
+       .fb_debug_enter = drm_fb_helper_debug_enter,
+       .fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
 static int intelfb_create(struct intel_fbdev *ifbdev,