AMD-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Add support for 'power saving policy' property
@ 2024-05-22 22:05 Mario Limonciello
  2024-05-22 22:05 ` [PATCH v2 1/2] drm: Introduce 'power saving policy' drm property Mario Limonciello
  2024-05-22 22:05 ` [PATCH v2 2/2] drm/amd: Add power_saving_policy drm property to eDP connectors Mario Limonciello
  0 siblings, 2 replies; 5+ messages in thread
From: Mario Limonciello @ 2024-05-22 22:05 UTC (permalink / raw)
  To: amd-gfx, Simon Ser
  Cc: Harry Wentland, Xaver Hugl, dri-devel, Leo Li, Sean Paul,
	Mario Limonciello

During the Display Next hackfest 2024 one of the topics discussed
was the need for compositor to be able to relay intention to drivers
that color fidelity is preferred over power savings.

To accomplish this a new optional DRM property is being introduced called
"power saving policy".  This property is a bit mask that can be configured
with requests of "Require color accuracy" or "Require low latency"
that can be configured by the compositor.

When a driver advertises support for this property and the compositor
sets it to "Require color accuracy" then the driver will disable any power
saving features that can compromise color fidelity.

In practice the main feature this currently applies to is the
"Adaptive Backlight Modulation" feature within AMD DCN on eDP panels.

When the compositor has marked the property  "Require color accuracy" then
this feature will be disabled and any userspace that tries to turn it on
will get an -EBUSY return code.

Compositors can also request that low latency is critical which in practice
should cause PSR and PSR2 to be disabled.

When the compositor has restored the value back to no requirements then the
previous value that would have been programmed will be restored.

---
v1->v2:
 * New property as a bitmask
 * Handle both ABM and PSR/PSR2
 * Add documentation

Mario Limonciello (2):
  drm: Introduce 'power saving policy' drm property
  drm/amd: Add power_saving_policy drm property to eDP connectors

 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   |  4 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 51 +++++++++++++++++--
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 +
 drivers/gpu/drm/drm_connector.c               | 46 +++++++++++++++++
 include/drm/drm_connector.h                   |  2 +
 include/drm/drm_mode_config.h                 |  5 ++
 include/uapi/drm/drm_mode.h                   |  7 +++
 7 files changed, 112 insertions(+), 5 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/2] drm: Introduce 'power saving policy' drm property
  2024-05-22 22:05 [PATCH v2 0/2] Add support for 'power saving policy' property Mario Limonciello
@ 2024-05-22 22:05 ` Mario Limonciello
  2024-06-04 21:52   ` Leo Li
  2024-05-22 22:05 ` [PATCH v2 2/2] drm/amd: Add power_saving_policy drm property to eDP connectors Mario Limonciello
  1 sibling, 1 reply; 5+ messages in thread
From: Mario Limonciello @ 2024-05-22 22:05 UTC (permalink / raw)
  To: amd-gfx, Simon Ser
  Cc: Harry Wentland, Xaver Hugl, dri-devel, Leo Li, Sean Paul,
	Mario Limonciello

The `power saving policy` DRM property is an optional property that
can be added to a connector by a driver.

This property is for compositors to indicate intent of policy of
whether a driver can use power saving features that may compromise
the experience intended by the compositor.

Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
 drivers/gpu/drm/drm_connector.c | 46 +++++++++++++++++++++++++++++++++
 include/drm/drm_connector.h     |  2 ++
 include/drm/drm_mode_config.h   |  5 ++++
 include/uapi/drm/drm_mode.h     |  7 +++++
 4 files changed, 60 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 4d2df7f64dc5..088a5874c7a4 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -961,6 +961,11 @@ static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = {
 	{ DRM_MODE_SCALE_ASPECT, "Full aspect" },
 };
 
+static const struct drm_prop_enum_list drm_power_saving_policy_enum_list[] = {
+	{ __builtin_ffs(DRM_MODE_REQUIRE_COLOR_ACCURACY) - 1, "Require color accuracy" },
+	{ __builtin_ffs(DRM_MODE_REQUIRE_LOW_LATENCY) - 1, "Require low latency" },
+};
+
 static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = {
 	{ DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" },
 	{ DRM_MODE_PICTURE_ASPECT_4_3, "4:3" },
@@ -1499,6 +1504,16 @@ static const u32 dp_colorspaces =
  *
  *	Drivers can set up these properties by calling
  *	drm_mode_create_tv_margin_properties().
+ * power saving policy:
+ *	This property is used to set the power saving policy for the connector.
+ *	This property is populated with a bitmask of optional requirements set
+ *	by the drm master for the drm driver to respect:
+ *	- "Require color accuracy": Disable power saving features that will
+ *	  affect color fidelity.
+ *	  For example: Hardware assisted backlight modulation.
+ *	- "Require low latency": Disable power saving features that will
+ *	  affect latency.
+ *	  For example: Panel self refresh (PSR)
  */
 
 int drm_connector_create_standard_properties(struct drm_device *dev)
@@ -1963,6 +1978,37 @@ int drm_mode_create_scaling_mode_property(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
 
+/**
+ * drm_mode_create_power_saving_policy_property - create power saving policy property
+ * @dev: DRM device
+ * @supported_policies: bitmask of supported power saving policies
+ *
+ * Called by a driver the first time it's needed, must be attached to desired
+ * connectors.
+ *
+ * Returns: %0
+ */
+int drm_mode_create_power_saving_policy_property(struct drm_device *dev,
+						 uint64_t supported_policies)
+{
+	struct drm_property *power_saving;
+
+	if (dev->mode_config.power_saving_policy)
+		return 0;
+	WARN_ON((supported_policies & DRM_MODE_POWER_SAVING_POLICY_ALL) == 0);
+
+	power_saving =
+		drm_property_create_bitmask(dev, 0, "power saving policy",
+					    drm_power_saving_policy_enum_list,
+					    ARRAY_SIZE(drm_power_saving_policy_enum_list),
+					    supported_policies);
+
+	dev->mode_config.power_saving_policy = power_saving;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_mode_create_power_saving_policy_property);
+
 /**
  * DOC: Variable refresh properties
  *
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index fe88d7fc6b8f..b0ec2ec48de7 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -2025,6 +2025,8 @@ int drm_mode_create_dp_colorspace_property(struct drm_connector *connector,
 					   u32 supported_colorspaces);
 int drm_mode_create_content_type_property(struct drm_device *dev);
 int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
+int drm_mode_create_power_saving_policy_property(struct drm_device *dev,
+						 uint64_t supported_policies);
 
 int drm_connector_set_path_property(struct drm_connector *connector,
 				    const char *path);
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 973119a9176b..32077e701e2f 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -954,6 +954,11 @@ struct drm_mode_config {
 	 */
 	struct drm_atomic_state *suspend_state;
 
+	/**
+	 * @power_saving_policy: bitmask for power saving policy requests.
+	 */
+	struct drm_property *power_saving_policy;
+
 	const struct drm_mode_config_helper_funcs *helper_private;
 };
 
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 7040e7ea80c7..c2c86623552c 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -152,6 +152,13 @@ extern "C" {
 #define DRM_MODE_SCALE_CENTER		2 /* Centered, no scaling */
 #define DRM_MODE_SCALE_ASPECT		3 /* Full screen, preserve aspect */
 
+/* power saving policy options */
+#define DRM_MODE_REQUIRE_COLOR_ACCURACY	BIT(0)	/* Compositor requires color accuracy */
+#define DRM_MODE_REQUIRE_LOW_LATENCY	BIT(1)	/* Compositor requires low latency */
+
+#define DRM_MODE_POWER_SAVING_POLICY_ALL	(DRM_MODE_REQUIRE_COLOR_ACCURACY |\
+						 DRM_MODE_REQUIRE_LOW_LATENCY)
+
 /* Dithering mode options */
 #define DRM_MODE_DITHERING_OFF	0
 #define DRM_MODE_DITHERING_ON	1
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/2] drm/amd: Add power_saving_policy drm property to eDP connectors
  2024-05-22 22:05 [PATCH v2 0/2] Add support for 'power saving policy' property Mario Limonciello
  2024-05-22 22:05 ` [PATCH v2 1/2] drm: Introduce 'power saving policy' drm property Mario Limonciello
@ 2024-05-22 22:05 ` Mario Limonciello
  2024-06-04 21:52   ` Leo Li
  1 sibling, 1 reply; 5+ messages in thread
From: Mario Limonciello @ 2024-05-22 22:05 UTC (permalink / raw)
  To: amd-gfx, Simon Ser
  Cc: Harry Wentland, Xaver Hugl, dri-devel, Leo Li, Sean Paul,
	Mario Limonciello

When the `power_saving_policy` property is set to bit mask
"Require color accuracy" ABM should be disabled immediately and
any requests by sysfs to update will return an -EBUSY error.

When the `power_saving_policy` property is set to bit mask
"Require low latency" PSR should be disabled.

When the property is restored to an empty bit mask the previous
value of ABM and pSR will be restored.

Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   |  4 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 51 +++++++++++++++++--
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 +
 3 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 3ecc7ef95172..cfb5220cf182 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -1350,6 +1350,10 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev)
 					 "dither",
 					 amdgpu_dither_enum_list, sz);
 
+	if (adev->dc_enabled)
+		drm_mode_create_power_saving_policy_property(adev_to_drm(adev),
+							     DRM_MODE_POWER_SAVING_POLICY_ALL);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 01b0a331e4a6..a480e86892de 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6421,6 +6421,13 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector,
 	} else if (property == adev->mode_info.underscan_property) {
 		dm_new_state->underscan_enable = val;
 		ret = 0;
+	} else if (property == dev->mode_config.power_saving_policy) {
+		dm_new_state->abm_forbidden = val & DRM_MODE_REQUIRE_COLOR_ACCURACY;
+		dm_new_state->abm_level = (dm_new_state->abm_forbidden || !amdgpu_dm_abm_level) ?
+						ABM_LEVEL_IMMEDIATE_DISABLE :
+						amdgpu_dm_abm_level;
+		dm_new_state->psr_forbidden = val & DRM_MODE_REQUIRE_LOW_LATENCY;
+		ret = 0;
 	}
 
 	return ret;
@@ -6463,6 +6470,13 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector,
 	} else if (property == adev->mode_info.underscan_property) {
 		*val = dm_state->underscan_enable;
 		ret = 0;
+	} else if (property == dev->mode_config.power_saving_policy) {
+		*val = 0;
+		if (dm_state->psr_forbidden)
+			*val |= DRM_MODE_REQUIRE_LOW_LATENCY;
+		if (dm_state->abm_forbidden)
+			*val |= DRM_MODE_REQUIRE_COLOR_ACCURACY;
+		ret = 0;
 	}
 
 	return ret;
@@ -6489,9 +6503,12 @@ static ssize_t panel_power_savings_show(struct device *device,
 	u8 val;
 
 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-	val = to_dm_connector_state(connector->state)->abm_level ==
-		ABM_LEVEL_IMMEDIATE_DISABLE ? 0 :
-		to_dm_connector_state(connector->state)->abm_level;
+	if (to_dm_connector_state(connector->state)->abm_forbidden)
+		val = 0;
+	else
+		val = to_dm_connector_state(connector->state)->abm_level ==
+			ABM_LEVEL_IMMEDIATE_DISABLE ? 0 :
+			to_dm_connector_state(connector->state)->abm_level;
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
 
 	return sysfs_emit(buf, "%u\n", val);
@@ -6515,10 +6532,16 @@ static ssize_t panel_power_savings_store(struct device *device,
 		return -EINVAL;
 
 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-	to_dm_connector_state(connector->state)->abm_level = val ?:
-		ABM_LEVEL_IMMEDIATE_DISABLE;
+	if (to_dm_connector_state(connector->state)->abm_forbidden)
+		ret = -EBUSY;
+	else
+		to_dm_connector_state(connector->state)->abm_level = val ?:
+			ABM_LEVEL_IMMEDIATE_DISABLE;
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
 
+	if (ret)
+		return ret;
+
 	drm_kms_helper_hotplug_event(dev);
 
 	return count;
@@ -7689,6 +7712,13 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
 	aconnector->base.state->max_bpc = 16;
 	aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc;
 
+	if (connector_type == DRM_MODE_CONNECTOR_eDP &&
+	    (dc_is_dmcu_initialized(adev->dm.dc) ||
+	     adev->dm.dc->ctx->dmub_srv)) {
+		drm_object_attach_property(&aconnector->base.base,
+				dm->ddev->mode_config.power_saving_policy, 0);
+	}
+
 	if (connector_type == DRM_MODE_CONNECTOR_HDMIA) {
 		/* Content Type is currently only implemented for HDMI. */
 		drm_connector_attach_content_type_property(&aconnector->base);
@@ -9344,6 +9374,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 			stream_update.hdr_static_metadata = &hdr_packet;
 		}
 
+		if (dm_old_con_state->psr_forbidden && !dm_new_con_state->psr_forbidden)
+			amdgpu_dm_psr_disable(dm_new_crtc_state->stream);
+		else if (!dm_old_con_state->psr_forbidden && dm_new_con_state->psr_forbidden)
+			amdgpu_dm_psr_enable(dm_new_crtc_state->stream);
+
 		status = dc_stream_get_status(dm_new_crtc_state->stream);
 
 		if (WARN_ON(!status))
@@ -10019,6 +10054,12 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
 		update_stream_scaling_settings(
 			&new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream);
 
+
+	if (dm_old_conn_state->psr_forbidden && !dm_new_conn_state->psr_forbidden)
+		amdgpu_dm_psr_disable(dm_new_crtc_state->stream);
+	else if (!dm_old_conn_state->psr_forbidden && dm_new_conn_state->psr_forbidden)
+		amdgpu_dm_psr_enable(dm_new_crtc_state->stream);
+
 	/* ABM settings */
 	dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 09519b7abf67..b246e82f5b0d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -873,6 +873,8 @@ struct dm_connector_state {
 	bool underscan_enable;
 	bool freesync_capable;
 	bool update_hdcp;
+	bool abm_forbidden;
+	bool psr_forbidden;
 	uint8_t abm_level;
 	int vcpi_slots;
 	uint64_t pbn;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] drm/amd: Add power_saving_policy drm property to eDP connectors
  2024-05-22 22:05 ` [PATCH v2 2/2] drm/amd: Add power_saving_policy drm property to eDP connectors Mario Limonciello
@ 2024-06-04 21:52   ` Leo Li
  0 siblings, 0 replies; 5+ messages in thread
From: Leo Li @ 2024-06-04 21:52 UTC (permalink / raw)
  To: Mario Limonciello, amd-gfx, Simon Ser
  Cc: Harry Wentland, Xaver Hugl, dri-devel, Sean Paul


On 2024-05-22 18:05, Mario Limonciello wrote:
> When the `power_saving_policy` property is set to bit mask
> "Require color accuracy" ABM should be disabled immediately and
> any requests by sysfs to update will return an -EBUSY error.
> 
> When the `power_saving_policy` property is set to bit mask
> "Require low latency" PSR should be disabled.
> 
> When the property is restored to an empty bit mask the previous
> value of ABM and pSR will be restored.
> 
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   |  4 ++
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 51 +++++++++++++++++--
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 +
>   3 files changed, 52 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
> index 3ecc7ef95172..cfb5220cf182 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
> @@ -1350,6 +1350,10 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev)
>   					 "dither",
>   					 amdgpu_dither_enum_list, sz);
>   
> +	if (adev->dc_enabled)
> +		drm_mode_create_power_saving_policy_property(adev_to_drm(adev),
> +							     DRM_MODE_POWER_SAVING_POLICY_ALL);
> +
>   	return 0;
>   }
>   
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 01b0a331e4a6..a480e86892de 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -6421,6 +6421,13 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector,
>   	} else if (property == adev->mode_info.underscan_property) {
>   		dm_new_state->underscan_enable = val;
>   		ret = 0;
> +	} else if (property == dev->mode_config.power_saving_policy) {
> +		dm_new_state->abm_forbidden = val & DRM_MODE_REQUIRE_COLOR_ACCURACY;
> +		dm_new_state->abm_level = (dm_new_state->abm_forbidden || !amdgpu_dm_abm_level) ?
> +						ABM_LEVEL_IMMEDIATE_DISABLE :
> +						amdgpu_dm_abm_level;
> +		dm_new_state->psr_forbidden = val & DRM_MODE_REQUIRE_LOW_LATENCY;
> +		ret = 0;
>   	}
>   
>   	return ret;
> @@ -6463,6 +6470,13 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector,
>   	} else if (property == adev->mode_info.underscan_property) {
>   		*val = dm_state->underscan_enable;
>   		ret = 0;
> +	} else if (property == dev->mode_config.power_saving_policy) {
> +		*val = 0;
> +		if (dm_state->psr_forbidden)
> +			*val |= DRM_MODE_REQUIRE_LOW_LATENCY;
> +		if (dm_state->abm_forbidden)
> +			*val |= DRM_MODE_REQUIRE_COLOR_ACCURACY;
> +		ret = 0;
>   	}
>   
>   	return ret;
> @@ -6489,9 +6503,12 @@ static ssize_t panel_power_savings_show(struct device *device,
>   	u8 val;
>   
>   	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> -	val = to_dm_connector_state(connector->state)->abm_level ==
> -		ABM_LEVEL_IMMEDIATE_DISABLE ? 0 :
> -		to_dm_connector_state(connector->state)->abm_level;
> +	if (to_dm_connector_state(connector->state)->abm_forbidden)
> +		val = 0;
> +	else
> +		val = to_dm_connector_state(connector->state)->abm_level ==
> +			ABM_LEVEL_IMMEDIATE_DISABLE ? 0 :
> +			to_dm_connector_state(connector->state)->abm_level;
>   	drm_modeset_unlock(&dev->mode_config.connection_mutex);
>   
>   	return sysfs_emit(buf, "%u\n", val);
> @@ -6515,10 +6532,16 @@ static ssize_t panel_power_savings_store(struct device *device,
>   		return -EINVAL;
>   
>   	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> -	to_dm_connector_state(connector->state)->abm_level = val ?:
> -		ABM_LEVEL_IMMEDIATE_DISABLE;
> +	if (to_dm_connector_state(connector->state)->abm_forbidden)
> +		ret = -EBUSY;
> +	else
> +		to_dm_connector_state(connector->state)->abm_level = val ?:
> +			ABM_LEVEL_IMMEDIATE_DISABLE;
>   	drm_modeset_unlock(&dev->mode_config.connection_mutex);
>   
> +	if (ret)
> +		return ret;
> +
>   	drm_kms_helper_hotplug_event(dev);
>   
>   	return count;
> @@ -7689,6 +7712,13 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
>   	aconnector->base.state->max_bpc = 16;
>   	aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc;
>   
> +	if (connector_type == DRM_MODE_CONNECTOR_eDP &&
> +	    (dc_is_dmcu_initialized(adev->dm.dc) ||
> +	     adev->dm.dc->ctx->dmub_srv)) {
> +		drm_object_attach_property(&aconnector->base.base,
> +				dm->ddev->mode_config.power_saving_policy, 0);
> +	}
> +
>   	if (connector_type == DRM_MODE_CONNECTOR_HDMIA) {
>   		/* Content Type is currently only implemented for HDMI. */
>   		drm_connector_attach_content_type_property(&aconnector->base);
> @@ -9344,6 +9374,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
>   			stream_update.hdr_static_metadata = &hdr_packet;
>   		}
>   
> +		if (dm_old_con_state->psr_forbidden && !dm_new_con_state->psr_forbidden)
> +			amdgpu_dm_psr_disable(dm_new_crtc_state->stream);
> +		else if (!dm_old_con_state->psr_forbidden && dm_new_con_state->psr_forbidden)
> +			amdgpu_dm_psr_enable(dm_new_crtc_state->stream);
> +

Thanks for the patch!

Unfortunately, enabling/disabling PSR today isn't as straightforward as a call
to amdgpu_dm_psr_enable/disable. The conditions for enabling PSR is quite
convoluted and need some untangling...

For now, I think the easiest way to pipe this property through is to hijack the
`amdgpu_dm_connector->disallow_edp_enter_psr` flag. IIRC, it is currently hooked
up to a debugfs that force disables PSR for testing purposes. Eventually, we can
probably deprecate the debugfs and use this property instead.

We could change the above 'if/else if' to something like the following:

```
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
<snip>

aconnector->disallow_edp_enter_psr = dm_new_con_state->psr_forbidden

/* immediately disable PSR if disallowed */
if (aconnector->disallow_edp_enter_psr) {
	mutex_lock(&dm->dc_lock);
	amdgpu_dm_psr_disable(dm_new_crtc_state->stream);
	mutex_unlock(&dm->dc_lock);
}
```

The moment disallow_edp_enter_psr flips to 0, the next fast update should
re-enable PSR. There isn't any guarantee of an immediate re-enable, but I think
that should be fine.


>   		status = dc_stream_get_status(dm_new_crtc_state->stream);
>   
>   		if (WARN_ON(!status))
> @@ -10019,6 +10054,12 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
>   		update_stream_scaling_settings(
>   			&new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream);
>   
> +
> +	if (dm_old_conn_state->psr_forbidden && !dm_new_conn_state->psr_forbidden)
> +		amdgpu_dm_psr_disable(dm_new_crtc_state->stream);
> +	else if (!dm_old_conn_state->psr_forbidden && dm_new_conn_state->psr_forbidden)
> +		amdgpu_dm_psr_enable(dm_new_crtc_state->stream);
> +

dm_update_crtc_state() can be called as part of atomic check, so we should not 
do any hw programming here.

There aren't any reasons I can think of to reject allow/disallowing PSR either, 
so this part shouldn't be necessary and can be dropped.

Thanks,
Leo

>   	/* ABM settings */
>   	dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
>   
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> index 09519b7abf67..b246e82f5b0d 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -873,6 +873,8 @@ struct dm_connector_state {
>   	bool underscan_enable;
>   	bool freesync_capable;
>   	bool update_hdcp;
> +	bool abm_forbidden;
> +	bool psr_forbidden;
>   	uint8_t abm_level;
>   	int vcpi_slots;
>   	uint64_t pbn;

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] drm: Introduce 'power saving policy' drm property
  2024-05-22 22:05 ` [PATCH v2 1/2] drm: Introduce 'power saving policy' drm property Mario Limonciello
@ 2024-06-04 21:52   ` Leo Li
  0 siblings, 0 replies; 5+ messages in thread
From: Leo Li @ 2024-06-04 21:52 UTC (permalink / raw)
  To: Mario Limonciello, amd-gfx, Simon Ser
  Cc: Harry Wentland, Xaver Hugl, dri-devel, Sean Paul



On 2024-05-22 18:05, Mario Limonciello wrote:
> The `power saving policy` DRM property is an optional property that
> can be added to a connector by a driver.
> 
> This property is for compositors to indicate intent of policy of
> whether a driver can use power saving features that may compromise
> the experience intended by the compositor.
> 
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>

Acked-by: Leo Li <sunpeng.li@amd.com>

Thanks!
> ---
>   drivers/gpu/drm/drm_connector.c | 46 +++++++++++++++++++++++++++++++++
>   include/drm/drm_connector.h     |  2 ++
>   include/drm/drm_mode_config.h   |  5 ++++
>   include/uapi/drm/drm_mode.h     |  7 +++++
>   4 files changed, 60 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 4d2df7f64dc5..088a5874c7a4 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -961,6 +961,11 @@ static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = {
>   	{ DRM_MODE_SCALE_ASPECT, "Full aspect" },
>   };
>   
> +static const struct drm_prop_enum_list drm_power_saving_policy_enum_list[] = {
> +	{ __builtin_ffs(DRM_MODE_REQUIRE_COLOR_ACCURACY) - 1, "Require color accuracy" },
> +	{ __builtin_ffs(DRM_MODE_REQUIRE_LOW_LATENCY) - 1, "Require low latency" },
> +};
> +
>   static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = {
>   	{ DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" },
>   	{ DRM_MODE_PICTURE_ASPECT_4_3, "4:3" },
> @@ -1499,6 +1504,16 @@ static const u32 dp_colorspaces =
>    *
>    *	Drivers can set up these properties by calling
>    *	drm_mode_create_tv_margin_properties().
> + * power saving policy:
> + *	This property is used to set the power saving policy for the connector.
> + *	This property is populated with a bitmask of optional requirements set
> + *	by the drm master for the drm driver to respect:
> + *	- "Require color accuracy": Disable power saving features that will
> + *	  affect color fidelity.
> + *	  For example: Hardware assisted backlight modulation.
> + *	- "Require low latency": Disable power saving features that will
> + *	  affect latency.
> + *	  For example: Panel self refresh (PSR)
>    */
>   
>   int drm_connector_create_standard_properties(struct drm_device *dev)
> @@ -1963,6 +1978,37 @@ int drm_mode_create_scaling_mode_property(struct drm_device *dev)
>   }
>   EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
>   
> +/**
> + * drm_mode_create_power_saving_policy_property - create power saving policy property
> + * @dev: DRM device
> + * @supported_policies: bitmask of supported power saving policies
> + *
> + * Called by a driver the first time it's needed, must be attached to desired
> + * connectors.
> + *
> + * Returns: %0
> + */
> +int drm_mode_create_power_saving_policy_property(struct drm_device *dev,
> +						 uint64_t supported_policies)
> +{
> +	struct drm_property *power_saving;
> +
> +	if (dev->mode_config.power_saving_policy)
> +		return 0;
> +	WARN_ON((supported_policies & DRM_MODE_POWER_SAVING_POLICY_ALL) == 0);
> +
> +	power_saving =
> +		drm_property_create_bitmask(dev, 0, "power saving policy",
> +					    drm_power_saving_policy_enum_list,
> +					    ARRAY_SIZE(drm_power_saving_policy_enum_list),
> +					    supported_policies);
> +
> +	dev->mode_config.power_saving_policy = power_saving;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_mode_create_power_saving_policy_property);
> +
>   /**
>    * DOC: Variable refresh properties
>    *
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index fe88d7fc6b8f..b0ec2ec48de7 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -2025,6 +2025,8 @@ int drm_mode_create_dp_colorspace_property(struct drm_connector *connector,
>   					   u32 supported_colorspaces);
>   int drm_mode_create_content_type_property(struct drm_device *dev);
>   int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
> +int drm_mode_create_power_saving_policy_property(struct drm_device *dev,
> +						 uint64_t supported_policies);
>   
>   int drm_connector_set_path_property(struct drm_connector *connector,
>   				    const char *path);
> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
> index 973119a9176b..32077e701e2f 100644
> --- a/include/drm/drm_mode_config.h
> +++ b/include/drm/drm_mode_config.h
> @@ -954,6 +954,11 @@ struct drm_mode_config {
>   	 */
>   	struct drm_atomic_state *suspend_state;
>   
> +	/**
> +	 * @power_saving_policy: bitmask for power saving policy requests.
> +	 */
> +	struct drm_property *power_saving_policy;
> +
>   	const struct drm_mode_config_helper_funcs *helper_private;
>   };
>   
> diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
> index 7040e7ea80c7..c2c86623552c 100644
> --- a/include/uapi/drm/drm_mode.h
> +++ b/include/uapi/drm/drm_mode.h
> @@ -152,6 +152,13 @@ extern "C" {
>   #define DRM_MODE_SCALE_CENTER		2 /* Centered, no scaling */
>   #define DRM_MODE_SCALE_ASPECT		3 /* Full screen, preserve aspect */
>   
> +/* power saving policy options */
> +#define DRM_MODE_REQUIRE_COLOR_ACCURACY	BIT(0)	/* Compositor requires color accuracy */
> +#define DRM_MODE_REQUIRE_LOW_LATENCY	BIT(1)	/* Compositor requires low latency */
> +
> +#define DRM_MODE_POWER_SAVING_POLICY_ALL	(DRM_MODE_REQUIRE_COLOR_ACCURACY |\
> +						 DRM_MODE_REQUIRE_LOW_LATENCY)
> +
>   /* Dithering mode options */
>   #define DRM_MODE_DITHERING_OFF	0
>   #define DRM_MODE_DITHERING_ON	1

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-06-04 21:53 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-22 22:05 [PATCH v2 0/2] Add support for 'power saving policy' property Mario Limonciello
2024-05-22 22:05 ` [PATCH v2 1/2] drm: Introduce 'power saving policy' drm property Mario Limonciello
2024-06-04 21:52   ` Leo Li
2024-05-22 22:05 ` [PATCH v2 2/2] drm/amd: Add power_saving_policy drm property to eDP connectors Mario Limonciello
2024-06-04 21:52   ` Leo Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox