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@xxxxxxxxxxxxxxx> --- 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@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx