[Intel-gfx] [PATCH 4/5] drm/i915: Add sys drrs toggle interface
Alexandra Yates
alexandra.yates at linux.intel.com
Tue Apr 12 19:18:47 UTC 2016
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.yates at 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
More information about the Intel-gfx
mailing list