This interface allows enabling/disabling of DRRS feature.  It allows
to see immediately the power management savings and will allow
to expose this through sysfs interface for powertop to leverage its
functionality.

Signed-off-by: Alexandra Yates <alexandra.ya...@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h   |  1 +
 drivers/gpu/drm/i915/i915_sysfs.c | 86 +++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_ddi.c  |  9 +++-
 drivers/gpu/drm/i915/intel_dp.c   | 26 +++++++++---
 drivers/gpu/drm/i915/intel_drv.h  |  4 +-
 5 files changed, 116 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index bbe189f..4c5eea6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -964,6 +964,7 @@ struct i915_drrs {
        unsigned busy_frontbuffer_bits;
        enum drrs_refresh_rate_type refresh_rate_type;
        enum drrs_support_type type;
+       bool sysfs_set;
 };
 
 struct i915_psr {
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c 
b/drivers/gpu/drm/i915/i915_sysfs.c
index 81aa534..f489ab6 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -264,6 +264,72 @@ toggle_psr(struct device *kdev, struct device_attribute 
*attr,
        return count;
 }
 
+static ssize_t
+show_drrs(struct device *kdev, struct device_attribute *attr, char *buf)
+{
+       struct drm_minor *dminor = dev_to_drm_minor(kdev);
+       struct drm_device *dev = dminor->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       ssize_t ret;
+
+       mutex_lock(&dev_priv->drrs.mutex);
+       ret = snprintf(buf, PAGE_SIZE, "%s\n", dev_priv->drrs.dp ?
+                       "enabled":"disabled");
+       mutex_unlock(&dev_priv->drrs.mutex);
+       return ret;
+}
+
+static ssize_t
+toggle_drrs(struct device *kdev, struct device_attribute *attr,
+       const char *buf, size_t count)
+{
+       struct drm_minor *dminor = dev_to_drm_minor(kdev);
+       struct drm_device *dev = dminor->dev;
+       struct intel_connector *connector;
+       struct intel_encoder *encoder;
+       struct intel_crtc *crtc = NULL;
+       struct intel_dp *intel_dp = NULL;
+       u32 val;
+       ssize_t ret;
+       bool sysfs_set = true;
+
+       ret = kstrtou32(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       for_each_intel_connector(dev, connector) {
+               if (!connector->base.encoder)
+                       continue;
+
+               encoder = to_intel_encoder(connector->base.encoder);
+               crtc = to_intel_crtc(encoder->base.crtc);
+               intel_dp = enc_to_intel_dp(&encoder->base);
+       }
+       if (!crtc)
+               return -ENODEV;
+
+       switch (val) {
+       case 0:
+               ret = intel_edp_drrs_disable(intel_dp, sysfs_set);
+               if (ret)
+                       return ret;
+               break;
+       case 1:
+               if (encoder->type == INTEL_OUTPUT_EDP) {
+                       ret = intel_edp_drrs_enable(intel_dp, sysfs_set);
+                       if (ret)
+                               return ret;
+               }
+               break;
+       default:
+               return -EINVAL;
+
+       }
+
+       return count;
+}
+
+static DEVICE_ATTR(drrs_enable, S_IRUGO | S_IWUSR, show_drrs, toggle_drrs);
 static DEVICE_ATTR(fbc_enable, S_IRUGO | S_IWUSR, show_fbc, toggle_fbc);
 static DEVICE_ATTR(psr_enable, S_IRUGO | S_IWUSR, show_psr, toggle_psr);
 static DEVICE_ATTR(rc6_enable, S_IRUGO | S_IWUSR, show_rc6_mask, toggle_rc6);
@@ -323,6 +389,17 @@ static struct attribute_group media_rc6_attr_group = {
        .name = power_group_name,
        .attrs =  media_rc6_attrs
 };
+
+static struct attribute *drrs_attrs[] = {
+       &dev_attr_drrs_enable.attr,
+       NULL
+};
+
+static struct attribute_group drrs_attr_group = {
+       .name = power_group_name,
+       .attrs = drrs_attrs
+};
+
 #endif
 
 static int l3_access_valid(struct drm_device *dev, loff_t offset)
@@ -788,6 +865,14 @@ void i915_setup_sysfs(struct drm_device *dev)
                if (ret)
                        DRM_ERROR("PSR sysfs setup failed\n");
        }
+
+       if (HAS_PSR(dev)) {
+               ret = sysfs_merge_group(&dev->primary->kdev->kobj,
+                                       &drrs_attr_group);
+               if (ret)
+                       DRM_ERROR("DRRS sysfs setup failed\n");
+       }
+
        if (HAS_RC6(dev)) {
                ret = sysfs_merge_group(&dev->primary->kdev->kobj,
                                        &rc6_attr_group);
@@ -844,6 +929,7 @@ void i915_teardown_sysfs(struct drm_device *dev)
        device_remove_bin_file(dev->primary->kdev,  &dpf_attrs_1);
        device_remove_bin_file(dev->primary->kdev,  &dpf_attrs);
 #ifdef CONFIG_PM
+       sysfs_unmerge_group(&dev->primary->kdev->kobj, &drrs_attr_group);
        sysfs_unmerge_group(&dev->primary->kdev->kobj, &fbc_attr_group);
        sysfs_unmerge_group(&dev->primary->kdev->kobj, &psr_attr_group);
        sysfs_unmerge_group(&dev->primary->kdev->kobj, &rc6_attr_group);
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 8e384e5..eb6f0f9 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1691,7 +1691,9 @@ static void intel_enable_ddi(struct intel_encoder 
*intel_encoder)
                intel_edp_backlight_on(intel_dp);
                if (dev_priv->psr.sysfs_set != true)
                        intel_psr_enable(intel_dp, dev_priv->psr.sysfs_set);
-               intel_edp_drrs_enable(intel_dp);
+               if (dev_priv->drrs.sysfs_set != true)
+                       intel_edp_drrs_enable(intel_dp,
+                                               dev_priv->drrs.sysfs_set);
        }
 
        if (intel_crtc->config->has_audio) {
@@ -1717,7 +1719,10 @@ static void intel_disable_ddi(struct intel_encoder 
*intel_encoder)
        if (type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
-               intel_edp_drrs_disable(intel_dp);
+               if (dev_priv->drrs.sysfs_set != true)
+                       intel_edp_drrs_disable(intel_dp,
+                                               dev_priv->drrs.sysfs_set);
+
                if (dev_priv->psr.sysfs_set != true)
                        intel_psr_disable(intel_dp, dev_priv->psr.sysfs_set);
                intel_edp_backlight_off(intel_dp);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 183a60a..ec4bd12 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -5413,42 +5413,53 @@ static void intel_dp_set_drrs_state(struct drm_device 
*dev, int refresh_rate)
 /**
  * intel_edp_drrs_enable - init drrs struct if supported
  * @intel_dp: DP struct
+ * @sysfs_set: Identifies if this featudre is set from sysfs.
  *
  * Initializes frontbuffer_bits and drrs.dp
+ *
+ * Returns:
+ * 0 on success and -errno otherwise.
  */
-void intel_edp_drrs_enable(struct intel_dp *intel_dp)
+int intel_edp_drrs_enable(struct intel_dp *intel_dp, bool sysfs_set)
 {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
        struct drm_crtc *crtc = dig_port->base.base.crtc;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int ret = 0;
 
        if (!intel_crtc->config->has_drrs) {
                DRM_DEBUG_KMS("Panel doesn't support DRRS\n");
-               return;
+               return -EINVAL;
        }
 
        mutex_lock(&dev_priv->drrs.mutex);
        if (WARN_ON(dev_priv->drrs.dp)) {
                DRM_ERROR("DRRS already enabled\n");
+               ret = -EALREADY;
                goto unlock;
        }
 
        dev_priv->drrs.busy_frontbuffer_bits = 0;
 
        dev_priv->drrs.dp = intel_dp;
-
+       if (sysfs_set)
+               dev_priv->drrs.sysfs_set = sysfs_set;
 unlock:
        mutex_unlock(&dev_priv->drrs.mutex);
+       return ret;
 }
 
 /**
  * intel_edp_drrs_disable - Disable DRRS
  * @intel_dp: DP struct
+ * @sysfs_set: Identifies if this featudre is set from sysfs.
  *
+ * Returns:
+ * 0 on success and -errno otherwise.
  */
-void intel_edp_drrs_disable(struct intel_dp *intel_dp)
+int intel_edp_drrs_disable(struct intel_dp *intel_dp, bool sysfs_set)
 {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5457,12 +5468,12 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
        if (!intel_crtc->config->has_drrs)
-               return;
+               return -EINVAL;
 
        mutex_lock(&dev_priv->drrs.mutex);
        if (!dev_priv->drrs.dp) {
                mutex_unlock(&dev_priv->drrs.mutex);
-               return;
+               return -EALREADY;
        }
 
        if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
@@ -5471,9 +5482,12 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp)
                        fixed_mode->vrefresh);
 
        dev_priv->drrs.dp = NULL;
+       if (sysfs_set)
+               dev_priv->drrs.sysfs_set = sysfs_set;
        mutex_unlock(&dev_priv->drrs.mutex);
 
        cancel_delayed_work_sync(&dev_priv->drrs.work);
+       return 0;
 }
 
 static void intel_edp_drrs_downclock_work(struct work_struct *work)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d280847..eda84ae 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1299,8 +1299,8 @@ void intel_dp_hot_plug(struct intel_encoder 
*intel_encoder);
 void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv);
 uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes);
 void intel_plane_destroy(struct drm_plane *plane);
-void intel_edp_drrs_enable(struct intel_dp *intel_dp);
-void intel_edp_drrs_disable(struct intel_dp *intel_dp);
+int intel_edp_drrs_enable(struct intel_dp *intel_dp, bool sysfs_set);
+int intel_edp_drrs_disable(struct intel_dp *intel_dp, bool sysfs_set);
 void intel_edp_drrs_invalidate(struct drm_device *dev,
                unsigned frontbuffer_bits);
 void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to