@@ -1386,6 +1386,9 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
case FBC_CHIP_DEFAULT:
seq_puts(m, "disabled per chip default");
break;
+ case FBC_DEBUG_FS:
+ seq_puts(m, "disabled per debugfs");
+ break;
default:
seq_puts(m, "unknown reason");
}
@@ -1394,6 +1397,52 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
return 0;
}
+static int i915_fbc_disable_get(void *data, u64 *val)
+{
+ struct drm_device *dev = data;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ if (!HAS_FBC(dev))
+ return -ENODEV;
+
+ *val = dev_priv->fbc.disable;
+
+ return 0;
+}
+
+static int i915_fbc_disable_set(void *data, u64 val)
+{
+ struct drm_device *dev = data;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_crtc *crtc;
+
+ if (!HAS_FBC(dev))
+ return -ENODEV;
+
+ if (dev_priv->fbc.disable == (bool)val)
+ return 0;
+
+ drm_modeset_lock_all(dev);
+
+ DRM_DEBUG_DRIVER("Setting FBC disable %s\n",
+ val ? "true" : "false");
+
+ dev_priv->fbc.disable = (bool)val;
+
+ /* Reset enabled crtc to force FBC state update */
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+ if (crtc->enabled)
+ intel_crtc_restore_mode(crtc);
+
+ drm_modeset_unlock_all(dev);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(i915_fbc_disable_fops,
+ i915_fbc_disable_get, i915_fbc_disable_set,
+ "%llu\n");
+
static int i915_ips_status(struct seq_file *m, void *unused)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -3703,6 +3752,7 @@ static const struct i915_debugfs_files {
{"i915_rps_manual", &i915_rps_manual_fops},
{"i915_rc6_disable", &i915_rc6_disable_fops},
{"i915_ips_disable", &i915_ips_disable_fops},
+ {"i915_fbc_disable", &i915_fbc_disable_fops},
{"i915_cache_sharing", &i915_cache_sharing_fops},
{"i915_ring_stop", &i915_ring_stop_fops},
{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
@@ -763,7 +763,10 @@ struct i915_fbc {
FBC_MULTIPLE_PIPES, /* more than one pipe active */
FBC_MODULE_PARAM,
FBC_CHIP_DEFAULT, /* disabled by default on this chip */
+ FBC_DEBUG_FS, /* user requests disabling through debugfs */
} no_fbc_reason;
+
+ bool disable;
};
struct i915_psr {
@@ -519,6 +519,11 @@ void intel_update_fbc(struct drm_device *dev)
DRM_DEBUG_KMS("fbc disabled per module param\n");
goto out_disable;
}
+ if (dev_priv->fbc.disable) {
+ if (set_no_fbc_reason(dev_priv, FBC_DEBUG_FS))
+ DRM_DEBUG_KMS("fbc disabled per debugfs\n");
+ goto out_disable;
+ }
if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ||
(adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
if (set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE))