AMD-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: David Francis <David.Francis-5C7GfCeVMHo@public.gmane.org>
To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Cc: David Francis <David.Francis-5C7GfCeVMHo@public.gmane.org>
Subject: [PATCH 2/2] drm/amd: Add abm level drm property
Date: Tue, 13 Nov 2018 12:06:19 -0500	[thread overview]
Message-ID: <20181113170619.21156-2-David.Francis@amd.com> (raw)
In-Reply-To: <20181113170619.21156-1-David.Francis-5C7GfCeVMHo@public.gmane.org>

Adaptive Backlight Management (ABM) is a feature
that reduces backlight level to save power, while
increasing pixel contrast and pixel luminance
to maintain readability and image quality.

ABM will adjust in response to the
pixel luminance of the displayed content.

ABM is made available as a drm property on eDP
monitors called "abm level", which ranges from 0 to 4.
When this property is set to 0, ABM is off.  Levels 1
to 4 represent different ranges of backlight reduction.
At higher levels both the backlight reduction and pixel
adjustment will be greater.

ABM requires DMCU firmware, which is currently available for
Raven ASICs only.  If the feature does not work, please
ensure your firmware is up to date.drm/amd: Add abm drm property

Adaptive Backlight Management (ABM) is a feature that reduces backlight
and increases contrast to save power.  It is available only on Raven
series ASICs and only on eDP monitors.

This is a new property on amdgpu connectors, with a range of
0 (off) to 4 (severe backlight reduction).

Signed-off-by: David Francis <David.Francis@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   |  5 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h      |  2 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 37 ++++++++++++++++---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  1 +
 4 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 7d6a36bca9dd..ced8cefa223b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -637,6 +637,11 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev)
 						 "freesync_capable");
 		if (!adev->mode_info.freesync_capable_property)
 			return -ENOMEM;
+		adev->mode_info.abm_level_property =
+			drm_property_create_range(adev->ddev, 0,
+						"abm level", 0, 4);
+		if (!adev->mode_info.abm_level_property)
+			return -ENOMEM;
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 1627dd3413c7..2938635c0fc1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -342,6 +342,8 @@ struct amdgpu_mode_info {
 	struct drm_property *freesync_property;
 	/* it is used to know about display capability of freesync mode */
 	struct drm_property *freesync_capable_property;
+	/* Adaptive Backlight Modulation (power feature) */
+	struct drm_property *abm_level_property;
 	/* hardcoded DFP edid from BIOS */
 	struct edid *bios_hardcoded_edid;
 	int bios_hardcoded_edid_size;
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 f71febb4210d..96d60e735e71 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3038,6 +3038,9 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector,
 	} else if (property == adev->mode_info.freesync_capable_property) {
 		dm_new_state->freesync_capable = val;
 		ret = 0;
+	} else if (property == adev->mode_info.abm_level_property) {
+		dm_new_state->abm_level = val;
+		ret = 0;
 	}
 
 	return ret;
@@ -3086,7 +3089,11 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector,
 	} else if (property == adev->mode_info.freesync_capable_property) {
 		*val = dm_state->freesync_capable;
 		ret = 0;
+	} else if (property == adev->mode_info.abm_level_property) {
+		*val = dm_state->abm_level;
+		ret = 0;
 	}
+
 	return ret;
 }
 
@@ -3151,6 +3158,7 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector)
 
 	new_state->freesync_capable = state->freesync_capable;
 	new_state->freesync_enable = state->freesync_enable;
+	new_state->abm_level = state->abm_level;
 
 	return &new_state->base;
 }
@@ -3904,6 +3912,11 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
 		drm_object_attach_property(&aconnector->base.base,
 				adev->mode_info.freesync_capable_property, 0);
 	}
+
+	if (connector_type == DRM_MODE_CONNECTOR_eDP) {
+		drm_object_attach_property(&aconnector->base.base,
+				adev->mode_info.abm_level_property, 0);
+	}
 }
 
 static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
@@ -4399,7 +4412,8 @@ static bool commit_planes_to_stream(
 		uint8_t new_plane_count,
 		struct dm_crtc_state *dm_new_crtc_state,
 		struct dm_crtc_state *dm_old_crtc_state,
-		struct dc_state *state)
+		struct dc_state *state,
+		bool abm_level_changed)
 {
 	/* no need to dynamically allocate this. it's pretty small */
 	struct dc_surface_update updates[MAX_SURFACES];
@@ -4410,6 +4424,7 @@ static bool commit_planes_to_stream(
 	struct dc_stream_state *dc_stream = dm_new_crtc_state->stream;
 	struct dc_stream_update *stream_update =
 			kzalloc(sizeof(struct dc_stream_update), GFP_KERNEL);
+	unsigned int abm_level;
 
 	if (!stream_update) {
 		BREAK_TO_DEBUGGER();
@@ -4442,6 +4457,11 @@ static bool commit_planes_to_stream(
 		stream_update->adjust = &dc_stream->adjust;
 	}
 
+	if (abm_level_changed) {
+		abm_level = dm_new_crtc_state->stream->abm_level;
+		stream_update->abm_level = &abm_level;
+	}
+
 	for (i = 0; i < new_plane_count; i++) {
 		updates[i].surface = plane_states[i];
 		updates[i].gamma =
@@ -4585,7 +4605,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 							planes_count,
 							acrtc_state,
 							dm_old_crtc_state,
-							dm_state->context))
+							dm_state->context,
+							false))
 			dm_error("%s: Failed to attach plane!\n", __func__);
 	} else {
 		/*TODO BUG Here should go disable planes on CRTC. */
@@ -4759,12 +4780,13 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 		}
 	}
 
-	/* Handle scaling and underscan changes*/
+	/* Handle scaling, underscan, freesync, and abm changes*/
 	for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) {
 		struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state);
 		struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state);
 		struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc);
 		struct dc_stream_status *status = NULL;
+		bool abm_level_changed = dm_old_con_state->abm_level != dm_new_con_state->abm_level;
 
 		if (acrtc) {
 			new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base);
@@ -4776,7 +4798,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 			continue;
 
 		/* Skip anything that is not scaling or underscan changes */
-		if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state))
+		if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state)
+				&& !abm_level_changed)
 			continue;
 
 		dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
@@ -4794,6 +4817,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 		dm_new_crtc_state->stream->adjust = dm_new_crtc_state->adjust;
 		dm_new_crtc_state->stream->vrr_infopacket = dm_new_crtc_state->vrr_infopacket;
 
+		if (abm_level_changed)
+			dm_new_crtc_state->stream->abm_level = dm_new_con_state->abm_level;
+
 		/*TODO How it works with MPO ?*/
 		if (!commit_planes_to_stream(
 				dm->dc,
@@ -4801,7 +4827,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 				status->plane_count,
 				dm_new_crtc_state,
 				to_dm_crtc_state(old_crtc_state),
-				dm_state->context))
+				dm_state->context,
+				abm_level_changed))
 			dm_error("%s: Failed to update stream scaling!\n", __func__);
 	}
 
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 d6960644d714..6c593ee60c19 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -255,6 +255,7 @@ struct dm_connector_state {
 	bool underscan_enable;
 	bool freesync_enable;
 	bool freesync_capable;
+	uint8_t abm_level;
 };
 
 #define to_dm_connector_state(x)\
-- 
2.17.1

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

  parent reply	other threads:[~2018-11-13 17:06 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-13 17:06 [PATCH 1/2] drm/amd: Load DMCU IRAM David Francis
     [not found] ` <20181113170619.21156-1-David.Francis-5C7GfCeVMHo@public.gmane.org>
2018-11-13 17:06   ` David Francis [this message]
     [not found]     ` <20181113170619.21156-2-David.Francis-5C7GfCeVMHo@public.gmane.org>
2018-11-13 18:51       ` [PATCH 2/2] drm/amd: Add abm level drm property Alex Deucher

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181113170619.21156-2-David.Francis@amd.com \
    --to=david.francis-5c7gfcevmho@public.gmane.org \
    --cc=amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox