drm/i915: provide FBC status in debugfs
authorJesse Barnes <jbarnes@virtuousgeek.org>
Fri, 5 Feb 2010 20:42:41 +0000 (12:42 -0800)
committerEric Anholt <eric@anholt.net>
Mon, 22 Feb 2010 16:46:57 +0000 (11:46 -0500)
Tools like powertop want to check the current FBC status and report it
to the user.  So add a debugfs file indicating whether FBC is enabled,
and if not, why.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_display.c

index 55340de..96e8b9b 100644 (file)
@@ -477,6 +477,54 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
        return 0;
 }
 
+static int i915_fbc_status(struct seq_file *m, void *unused)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_crtc *crtc;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       bool fbc_enabled = false;
+
+       if (!dev_priv->display.fbc_enabled) {
+               seq_printf(m, "FBC unsupported on this chipset\n");
+               return 0;
+       }
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               if (!crtc->enabled)
+                       continue;
+               if (dev_priv->display.fbc_enabled(crtc))
+                       fbc_enabled = true;
+       }
+
+       if (fbc_enabled) {
+               seq_printf(m, "FBC enabled\n");
+       } else {
+               seq_printf(m, "FBC disabled: ");
+               switch (dev_priv->no_fbc_reason) {
+               case FBC_STOLEN_TOO_SMALL:
+                       seq_printf(m, "not enough stolen memory");
+                       break;
+               case FBC_UNSUPPORTED_MODE:
+                       seq_printf(m, "mode not supported");
+                       break;
+               case FBC_MODE_TOO_LARGE:
+                       seq_printf(m, "mode too large");
+                       break;
+               case FBC_BAD_PLANE:
+                       seq_printf(m, "FBC unsupported on plane");
+                       break;
+               case FBC_NOT_TILED:
+                       seq_printf(m, "scanout buffer not tiled");
+                       break;
+               default:
+                       seq_printf(m, "unknown reason");
+               }
+               seq_printf(m, "\n");
+       }
+       return 0;
+}
+
 static int
 i915_wedged_open(struct inode *inode,
                 struct file *filp)
@@ -599,6 +647,7 @@ static struct drm_info_list i915_debugfs_list[] = {
        {"i915_delayfreq_table", i915_delayfreq_table, 0},
        {"i915_inttoext_table", i915_inttoext_table, 0},
        {"i915_drpc_info", i915_drpc_info, 0},
+       {"i915_fbc_status", i915_fbc_status, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
index 3afe361..47805a4 100644 (file)
@@ -1249,6 +1249,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
        /* Leave 1M for line length buffer & misc. */
        compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0);
        if (!compressed_fb) {
+               dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
                i915_warn_stolen(dev);
                return;
        }
@@ -1256,6 +1257,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
        compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
        if (!compressed_fb) {
                i915_warn_stolen(dev);
+               dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
                return;
        }
 
index 7df89ae..953ad64 100644 (file)
@@ -192,6 +192,14 @@ struct intel_device_info {
        u8 cursor_needs_physical : 1;
 };
 
+enum no_fbc_reason {
+       FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */
+       FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */
+       FBC_MODE_TOO_LARGE, /* mode too large for compression */
+       FBC_BAD_PLANE, /* fbc not supported on plane */
+       FBC_NOT_TILED, /* buffer not tiled */
+};
+
 typedef struct drm_i915_private {
        struct drm_device *dev;
 
@@ -597,6 +605,8 @@ typedef struct drm_i915_private {
        u8 cur_delay;
        u8 min_delay;
        u8 max_delay;
+
+       enum no_fbc_reason no_fbc_reason;
 } drm_i915_private_t;
 
 /** driver private structure attached to each drm_gem_object */
index e879885..a483f41 100644 (file)
@@ -1188,25 +1188,30 @@ static void intel_update_fbc(struct drm_crtc *crtc,
        if (intel_fb->obj->size > dev_priv->cfb_size) {
                DRM_DEBUG_KMS("framebuffer too large, disabling "
                                "compression\n");
+               dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
                goto out_disable;
        }
        if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
            (mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
                DRM_DEBUG_KMS("mode incompatible with compression, "
                                "disabling\n");
+               dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE;
                goto out_disable;
        }
        if ((mode->hdisplay > 2048) ||
            (mode->vdisplay > 1536)) {
                DRM_DEBUG_KMS("mode too large for compression, disabling\n");
+               dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE;
                goto out_disable;
        }
        if ((IS_I915GM(dev) || IS_I945GM(dev)) && plane != 0) {
                DRM_DEBUG_KMS("plane not 0, disabling compression\n");
+               dev_priv->no_fbc_reason = FBC_BAD_PLANE;
                goto out_disable;
        }
        if (obj_priv->tiling_mode != I915_TILING_X) {
                DRM_DEBUG_KMS("framebuffer not tiled, disabling compression\n");
+               dev_priv->no_fbc_reason = FBC_NOT_TILED;
                goto out_disable;
        }