drm/i915/dsc: Add Per connector debugfs node for DSC support/enable
authorManasi Navare <manasi.d.navare@intel.com>
Thu, 6 Dec 2018 00:54:07 +0000 (16:54 -0800)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Mon, 17 Dec 2018 07:19:32 +0000 (23:19 -0800)
DSC can be supported per DP connector. This patch adds a per connector
debugfs node to expose DSC support capability by the kernel.
The same node can be used from userspace to force DSC enable.

force_dsc_en written through this debugfs node is used to force
DSC even for lower resolutions.

Credits to Ville Syrjala for suggesting the proper locks to be used
and to Lyude Paul for explaining how to use them in this context

v8:
* Add else if (ret) for drm_modeset_lock (Lyude)
v7:
* Get crtc, crtc_state from connector atomic state
and add proper locks and backoff (Ville, Chris Wilson, Lyude)
(Suggested-by: Ville Syrjala <ville.syrjala@linux.intel.com>)
* Use %zu for printing size_t variable (Lyude)
v6:
* Read fec_capable only for non edp (Manasi)
v5:
* Name it dsc sink support and also add
fec support in the same node (Ville)
v4:
* Add missed connector_status check (Manasi)
* Create i915_dsc_support node only for Gen >=10 (manasi)
* Access intel_dp->dsc_dpcd only if its not NULL (Manasi)
v3:
* Combine Force_dsc_en with this patch (Ville)
v2:
* Use kstrtobool_from_user to avoid explicit error checking (Lyude)
* Rebase on drm-tip (Manasi)

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
Cc: Lyude Paul <lyude@redhat.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181206005407.4698-1-manasi.d.navare@intel.com
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h

index ed44e30f875efaf5cb8fdebac074f974b1dbebc6..77486a6146146186bfc999a87459d3e07d53bbb5 100644 (file)
@@ -5094,6 +5094,105 @@ static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data)
 }
 DEFINE_SHOW_ATTRIBUTE(i915_hdcp_sink_capability);
 
+static int i915_dsc_fec_support_show(struct seq_file *m, void *data)
+{
+       struct drm_connector *connector = m->private;
+       struct drm_device *dev = connector->dev;
+       struct drm_crtc *crtc;
+       struct intel_dp *intel_dp;
+       struct drm_modeset_acquire_ctx ctx;
+       struct intel_crtc_state *crtc_state = NULL;
+       int ret = 0;
+       bool try_again = false;
+
+       drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
+
+       do {
+               ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
+                                      &ctx);
+               if (ret) {
+                       ret = -EINTR;
+                       break;
+               }
+               crtc = connector->state->crtc;
+               if (connector->status != connector_status_connected || !crtc) {
+                       ret = -ENODEV;
+                       break;
+               }
+               ret = drm_modeset_lock(&crtc->mutex, &ctx);
+               if (ret == -EDEADLK) {
+                       ret = drm_modeset_backoff(&ctx);
+                       if (!ret) {
+                               try_again = true;
+                               continue;
+                       }
+                       break;
+               } else if (ret) {
+                       break;
+               }
+               intel_dp = enc_to_intel_dp(&intel_attached_encoder(connector)->base);
+               crtc_state = to_intel_crtc_state(crtc->state);
+               seq_printf(m, "DSC_Enabled: %s\n",
+                          yesno(crtc_state->dsc_params.compression_enable));
+               if (intel_dp->dsc_dpcd)
+                       seq_printf(m, "DSC_Sink_Support: %s\n",
+                                  yesno(drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)));
+               if (!intel_dp_is_edp(intel_dp))
+                       seq_printf(m, "FEC_Sink_Support: %s\n",
+                                  yesno(drm_dp_sink_supports_fec(intel_dp->fec_capable)));
+       } while (try_again);
+
+       drm_modeset_drop_locks(&ctx);
+       drm_modeset_acquire_fini(&ctx);
+
+       return ret;
+}
+
+static ssize_t i915_dsc_fec_support_write(struct file *file,
+                                         const char __user *ubuf,
+                                         size_t len, loff_t *offp)
+{
+       bool dsc_enable = false;
+       int ret;
+       struct drm_connector *connector =
+               ((struct seq_file *)file->private_data)->private;
+       struct intel_encoder *encoder = intel_attached_encoder(connector);
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+
+       if (len == 0)
+               return 0;
+
+       DRM_DEBUG_DRIVER("Copied %zu bytes from user to force DSC\n",
+                        len);
+
+       ret = kstrtobool_from_user(ubuf, len, &dsc_enable);
+       if (ret < 0)
+               return ret;
+
+       DRM_DEBUG_DRIVER("Got %s for DSC Enable\n",
+                        (dsc_enable) ? "true" : "false");
+       intel_dp->force_dsc_en = dsc_enable;
+
+       *offp += len;
+       return len;
+}
+
+static int i915_dsc_fec_support_open(struct inode *inode,
+                                    struct file *file)
+{
+       return single_open(file, i915_dsc_fec_support_show,
+                          inode->i_private);
+}
+
+static const struct file_operations i915_dsc_fec_support_fops = {
+       .owner = THIS_MODULE,
+       .open = i915_dsc_fec_support_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .write = i915_dsc_fec_support_write
+};
+
 /**
  * i915_debugfs_connector_add - add i915 specific connector debugfs files
  * @connector: pointer to a registered drm_connector
@@ -5106,6 +5205,7 @@ DEFINE_SHOW_ATTRIBUTE(i915_hdcp_sink_capability);
 int i915_debugfs_connector_add(struct drm_connector *connector)
 {
        struct dentry *root = connector->debugfs_entry;
+       struct drm_i915_private *dev_priv = to_i915(connector->dev);
 
        /* The connector must have been registered beforehands. */
        if (!root)
@@ -5130,5 +5230,11 @@ int i915_debugfs_connector_add(struct drm_connector *connector)
                                    connector, &i915_hdcp_sink_capability_fops);
        }
 
+       if (INTEL_GEN(dev_priv) >= 10 &&
+           (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+            connector->connector_type == DRM_MODE_CONNECTOR_eDP))
+               debugfs_create_file("i915_dsc_fec_support", S_IRUGO, root,
+                                   connector, &i915_dsc_fec_support_fops);
+
        return 0;
 }
index b3138abd332186864930340b31a15316a981d434..62484e1295633fb907816108bba8115121b2785c 100644 (file)
@@ -2051,7 +2051,8 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
                                                        &limits);
 
        /* enable compression if the mode doesn't fit available BW */
-       if (!ret) {
+       DRM_DEBUG_KMS("Force DSC en = %d\n", intel_dp->force_dsc_en);
+       if (!ret || intel_dp->force_dsc_en) {
                if (!intel_dp_dsc_compute_config(intel_dp, pipe_config,
                                                 conn_state, &limits))
                        return false;
index d08f08f607dd2a901002efe9a02a677124fc3029..cb3a055f18c868c5e3ad6a47f511dd9a68410db4 100644 (file)
@@ -1209,6 +1209,9 @@ struct intel_dp {
 
        /* Displayport compliance testing */
        struct intel_dp_compliance compliance;
+
+       /* Display stream compression testing */
+       bool force_dsc_en;
 };
 
 enum lspcon_vendor {