From: "Mario Limonciello (AMD)" <superm1@kernel.org>
To: Maxime Ripard <mripard@kernel.org>,
Alex Deucher <alexander.deucher@amd.com>,
Jani Nikula <jani.nikula@linux.intel.com>,
Javier Martinez Canillas <javierm@redhat.com>,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>,
Simona Vetter <simona@ffwll.ch>,
Harry Wentland <harry.wentland@amd.com>,
Leo Li <sunpeng.li@amd.com>,
Rodrigo Siqueira <siqueira@igalia.com>
Cc: Mario Limonciello <superm1@kernel.org>,
Xaver Hugl <xaver.hugl@gmail.com>,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
intel-xe@lists.freedesktop.org, nouveau@lists.freedesktop.org,
Mario Limonciello <mario.limonciello@amd.com>
Subject: [PATCH v11 05/12] drm/i915/display: add luminance property support
Date: Tue, 03 Nov 2026 16:42:06 -0600 [thread overview]
Message-ID: <20261103-superm1-backlight-property-v11-5-00cce7b2ba22@kernel.org> (raw)
In-Reply-To: <20261103-superm1-backlight-property-v11-0-00cce7b2ba22@kernel.org>
From: Mario Limonciello <mario.limonciello@amd.com>
Expose the DRM LUMINANCE connector property for eDP, LVDS, and DSI panels
when CONFIG_DRM_LUMINANCE is enabled. Keep registering the existing
backlight class device otherwise, preserving its userspace ABI.
Use the existing Intel brightness scaling and programming path from
connector helper callbacks. Apply atomic luminance after modeset enables
so updates made while a panel is inactive take effect when it is enabled
again. The shared display code provides the same behavior to i915 and Xe.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
v11:
* Call acpi_video_backlight_use_native() before attaching LUMINANCE and
leave the panel to acpi_video otherwise (Sashiko)
* Enable the backlight at the committed LUMINANCE level (Sashiko)
* Fix build with CONFIG_BACKLIGHT_CLASS_DEVICE=n (Sashiko)
* Keep selecting BACKLIGHT_CLASS_DEVICE if ACPI (Sashiko)
* Fall back to the backlight class device if attaching LUMINANCE fails
---
drivers/gpu/drm/i915/display/icl_dsi.c | 1 +
drivers/gpu/drm/i915/display/intel_backlight.c | 74 ++++++++++++++++++++++----
drivers/gpu/drm/i915/display/intel_backlight.h | 1 +
drivers/gpu/drm/i915/display/intel_display.c | 2 +
drivers/gpu/drm/i915/display/intel_dp.c | 1 +
drivers/gpu/drm/i915/display/intel_lvds.c | 1 +
drivers/gpu/drm/i915/display/intel_panel.c | 8 +--
drivers/gpu/drm/i915/display/vlv_dsi.c | 1 +
8 files changed, 76 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index ea0cdb7822f39..37ff84c03ce05 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -1801,6 +1801,7 @@ static const struct drm_connector_helper_funcs gen11_dsi_connector_helper_funcs
.get_modes = intel_dsi_get_modes,
.mode_valid = gen11_dsi_mode_valid,
.atomic_check = intel_digital_connector_atomic_check,
+ .set_luminance = intel_backlight_set_luminance,
};
static int gen11_dsi_host_attach(struct mipi_dsi_host *host,
diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c
index b128896cb1c2d..f9e84d17d3fb0 100644
--- a/drivers/gpu/drm/i915/display/intel_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_backlight.c
@@ -9,6 +9,7 @@
#include <linux/string_helpers.h>
#include <acpi/video.h>
+#include <drm/drm_connector.h>
#include <drm/drm_file.h>
#include <drm/drm_print.h>
#include <drm/intel/pci_config.h>
@@ -76,6 +77,16 @@ static u32 clamp_user_to_hw(struct intel_connector *connector,
return hw_level;
}
+/* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
+static u32 scale_user_to_hw(struct intel_connector *connector,
+ u32 user_level, u32 user_max)
+{
+ struct intel_panel *panel = &connector->panel;
+
+ return scale(user_level, 0, user_max,
+ panel->backlight.min, panel->backlight.max);
+}
+
/* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */
static u32 scale_hw_to_user(struct intel_connector *connector,
u32 hw_level, u32 user_max)
@@ -778,6 +789,16 @@ static void __intel_backlight_enable(const struct intel_crtc_state *crtc_state,
WARN_ON(panel->backlight.max == 0);
+ /*
+ * Enable at the luminance committed in this atomic state, rather than
+ * at a stale level which would only be corrected afterwards by
+ * drm_atomic_helper_commit_luminance_enables().
+ */
+ if (connector->base.luminance_property)
+ panel->backlight.level =
+ scale_user_to_hw(connector, conn_state->luminance,
+ panel->backlight.max);
+
if (panel->backlight.level < panel->backlight.min) {
panel->backlight.level = panel->backlight.min;
if (panel->backlight.device)
@@ -831,16 +852,6 @@ static u32 intel_panel_get_backlight(struct intel_connector *connector)
return val;
}
-/* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
-static u32 scale_user_to_hw(struct intel_connector *connector,
- u32 user_level, u32 user_max)
-{
- struct intel_panel *panel = &connector->panel;
-
- return scale(user_level, 0, user_max,
- panel->backlight.min, panel->backlight.max);
-}
-
/* set backlight brightness to level in range [0..max], scaling wrt hw min */
static void intel_panel_set_backlight(const struct drm_connector_state *conn_state,
u32 user_level, u32 user_max)
@@ -1670,6 +1681,9 @@ int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe)
{
struct intel_display *display = to_intel_display(connector);
struct intel_panel *panel = &connector->panel;
+ struct drm_connector *base = &connector->base;
+ u32 brightness;
+ u32 max;
int ret;
if (!connector->panel.vbt.backlight.present) {
@@ -1703,6 +1717,19 @@ int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe)
panel->backlight.present = true;
+ /*
+ * acpi_video_backlight_use_native() also tells the ACPI video code that
+ * a native backlight is available. If native control should not be
+ * used, leave the backlight to acpi_video, which is registered later
+ * from intel_acpi_video_register().
+ */
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE) && acpi_video_backlight_use_native()) {
+ max = panel->backlight.max;
+ brightness = scale_hw_to_user(connector, panel->backlight.level, max);
+ ret = drm_connector_attach_luminance_property(base, 0, max, brightness);
+ drm_WARN_ON(display->drm, ret);
+ }
+
drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] backlight initialized, %s, brightness %u/%u\n",
connector->base.base.id, connector->base.name,
@@ -1712,6 +1739,33 @@ int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe)
return 0;
}
+void intel_backlight_set_luminance(const struct drm_connector_state *conn_state)
+{
+ struct intel_connector *connector =
+ to_intel_connector(conn_state->connector);
+ struct intel_display *display = to_intel_display(connector);
+ struct intel_panel *panel = &connector->panel;
+ u32 hw_level;
+
+ if (!panel->backlight.present)
+ return;
+
+ guard(mutex)(&display->backlight.lock);
+
+ /*
+ * Nothing to do if __intel_backlight_enable() already programmed this
+ * level as part of a modeset enable.
+ */
+ hw_level = scale_user_to_hw(connector, conn_state->luminance,
+ panel->backlight.max);
+ if (hw_level == panel->backlight.level)
+ return;
+
+ panel->backlight.level = hw_level;
+ if (panel->backlight.enabled)
+ intel_panel_actually_set_backlight(conn_state, hw_level);
+}
+
void intel_backlight_destroy(struct intel_panel *panel)
{
/* dispose of the pwm */
diff --git a/drivers/gpu/drm/i915/display/intel_backlight.h b/drivers/gpu/drm/i915/display/intel_backlight.h
index 339643f638978..1634ce414695a 100644
--- a/drivers/gpu/drm/i915/display/intel_backlight.h
+++ b/drivers/gpu/drm/i915/display/intel_backlight.h
@@ -32,6 +32,7 @@ void intel_backlight_set_acpi(const struct drm_connector_state *conn_state,
u32 level, u32 max);
void intel_backlight_set_pwm_level(const struct drm_connector_state *conn_state,
u32 level);
+void intel_backlight_set_luminance(const struct drm_connector_state *conn_state);
u32 intel_backlight_invert_pwm_level(struct intel_connector *connector, u32 level);
u32 intel_backlight_level_to_pwm(struct intel_connector *connector, u32 level);
u32 intel_backlight_level_from_pwm(struct intel_connector *connector, u32 val);
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index c1c2b99cfb53b..f87c78e316a5d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7845,6 +7845,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
display->modeset.funcs->commit_modeset_enables(state);
+ drm_atomic_helper_commit_luminance_enables(&state->base);
+
intel_display_power_dc3co_compute(state);
/* FIXME probably need to sequence this properly */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index ef164a7976187..905c8743a2a2b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -7060,6 +7060,7 @@ static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs =
.get_modes = intel_dp_get_modes,
.mode_valid = intel_dp_mode_valid,
.atomic_check = intel_dp_connector_atomic_check,
+ .set_luminance = intel_backlight_set_luminance,
};
enum irqreturn
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index 872753478cf21..fa668b1debb21 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -502,6 +502,7 @@ static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs
.get_modes = intel_lvds_get_modes,
.mode_valid = intel_lvds_mode_valid,
.atomic_check = intel_digital_connector_atomic_check,
+ .set_luminance = intel_backlight_set_luminance,
};
static const struct drm_connector_funcs intel_lvds_connector_funcs = {
diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
index 81e638d0c7b33..9e2a53f300d39 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -610,9 +610,11 @@ int intel_panel_register(struct intel_connector *connector)
struct intel_panel *panel = &connector->panel;
int ret;
- ret = intel_backlight_device_register(connector);
- if (ret)
- return ret;
+ if (!connector->base.luminance_property) {
+ ret = intel_backlight_device_register(connector);
+ if (ret)
+ return ret;
+ }
if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI ||
connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) {
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 8829f365592ef..7e60407e0af4a 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -1555,6 +1555,7 @@ static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs
.get_modes = intel_dsi_get_modes,
.mode_valid = vlv_dsi_mode_valid,
.atomic_check = intel_digital_connector_atomic_check,
+ .set_luminance = intel_backlight_set_luminance,
};
static const struct drm_connector_funcs intel_dsi_connector_funcs = {
--
2.53.0
next prev parent reply other threads:[~2026-11-03 22:42 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 22:42 [PATCH v11 00/12] Add support for a DRM backlight capability Mario Limonciello (AMD)
2026-11-03 22:42 ` [PATCH v11 01/12] drm: add connector LUMINANCE property Mario Limonciello (AMD)
2026-11-03 22:42 ` [PATCH v11 02/12] drm/amd/display: Pass up errors reading actual brightness Mario Limonciello (AMD)
2026-11-03 22:42 ` [PATCH v11 03/12] drm/amdgpu: Check bios_scratch_reg_offset in backlight level helper Mario Limonciello (AMD)
2026-11-03 22:42 ` [PATCH v11 04/12] drm/amd: add luminance property support Mario Limonciello (AMD)
2026-11-03 22:42 ` Mario Limonciello (AMD) [this message]
2026-11-03 22:42 ` [PATCH v11 06/12] drm/bridge: add connector luminance operations Mario Limonciello (AMD)
2026-11-03 22:42 ` [PATCH v11 07/12] drm/panel: add connector luminance forwarding Mario Limonciello (AMD)
2026-11-03 22:42 ` [PATCH v11 08/12] drm/bridge_connector: add luminance support Mario Limonciello (AMD)
2026-11-03 22:42 ` [PATCH v11 09/12] drm/nouveau: add connector " Mario Limonciello (AMD)
2026-11-03 22:42 ` [PATCH v11 10/12] drm/gud: " Mario Limonciello (AMD)
2026-11-03 22:42 ` [PATCH v11 11/12] drm/bridge: add PS8622 " Mario Limonciello (AMD)
2026-11-03 22:42 ` [PATCH v11 12/12] drm/solomon: add SSD130x " Mario Limonciello (AMD)
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=20261103-superm1-backlight-property-v11-5-00cce7b2ba22@kernel.org \
--to=superm1@kernel.org \
--cc=airlied@gmail.com \
--cc=alexander.deucher@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=harry.wentland@amd.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=jani.nikula@linux.intel.com \
--cc=javierm@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mario.limonciello@amd.com \
--cc=mripard@kernel.org \
--cc=nouveau@lists.freedesktop.org \
--cc=simona@ffwll.ch \
--cc=siqueira@igalia.com \
--cc=sunpeng.li@amd.com \
--cc=tzimmermann@suse.de \
--cc=xaver.hugl@gmail.com \
/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
all inboxes | Powered by JetHome®