* [PATCH v9 00/21] Add support for a DRM backlight capability
@ 2026-10-02 19:00 Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 01/21] drm: add connector LUMINANCE property Mario Limonciello
` (21 more replies)
0 siblings, 22 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
At Display Next Hackfest 2026 we reviewed progress moving brightness
control into the DRM connector properties.
There is a range LUMINANCE property that will default to 0->0.
Once a driver attaches a backlight it will be updated to 1->max.
If the panel supports the minimum backlight turning off the display
the range can later be updated to 0->max instead of 1->max.
Version 8 had a lot of review feedback, and the biggest change is that
this no longer has the legacy sysfs interface for brightness control.
There is a Kconfig knob introduced that turns on the new API, and when
the new API is available all drivers will conflict with the old backlight
control API.
This will allow us to land the new brightness control API and the transition
to the new API separately. *This series only tracks the new API itself.*
Here's the main review items that I tried to cover in v8->v9.
- [x] Javier Martinez Canillas: separate generic DRM luminance infrastructure
from the backlight-subsystem adapter; let drivers own the hardware path;
avoid a leaky `drm_backlight_link()` mid-layer.
- [x] Thomas Zimmermann: invoke a connector helper callback from atomic helper
sequencing; keep backlight-specific state in driver-owned structures and
helper code rather than embedding it in DRM core objects.
- [x] Thomas Zimmermann, Leo Li, Harry Wentland: make luminance and display
power/DPMS independent. Preserve requested luminance while a display is
disabled and apply it when the display is enabled.
- [x] Jani Nikula: remove `IS_REACHABLE()` linkage workarounds and express any
remaining dependencies through Kconfig.
- [x] Thomas Zimmermann: remove the driver capability flag if userspace can
discover support by the connector property itself.
- [x] Thomas Zimmermann: remove redundant brightness-change notification and
DRM readback loops when the committed property already contains the
authoritative requested value.
- [x] Maxime Ripard: split the new DRM UAPI from legacy sysfs compatibility so
the property can be reviewed and merged independently.
- [x] Javier Martinez Canillas / Maxime Ripard / Thomas Zimmermann / Xaver Hugl:
preserve legacy sysfs behavior for legacy userspace; avoid silently
breaking the de-facto backlight UAPI while DRM-master ownership is
introduced.
- [x] Harry Wentland / Jani Nikula / Xaver Hugl: terminology reviewed. Retain
`LUMINANCE` as an explicit author decision, while documenting that the
property contains relative, driver-defined levels rather than physical
cd/m^2 values.
As the series changed significantly from all this feedback I did not see value
in a per-patch changelog. Instead here is the changelog from the whole series:
- Reworked the interface around driver-owned connector helper callbacks.
Removed the generic DRM backlight adapter, backend-linking layer, and
backlight state embedded in DRM core objects.
- Made LUMINANCE an atomic connector property whose requested value is
independent of display power. Disable panel emission before shutting down
the pipeline, preserve the requested value while inactive, and apply it
after the pipeline is enabled.
- Removed DRM_CLIENT_CAP_LUMINANCE and the associated per-client takeover,
legacy sysfs inhibition, property visibility, notification, and hardware
readback machinery.
- Removed the kernel-internal backlight API and the backlight notifier
restoration from the series.
- Added the default-off CONFIG_DRM_LUMINANCE option. When disabled, drivers
retain their existing backlight class devices and userspace ABI. When
enabled, all DRM-owned brightness implementations migrate to the connector
property together.
- Migrated AMDGPU, legacy AMD display, i915/Xe, Nouveau, Radeon, GMA500, GUD,
PS8622, SSD130x, panel and bridge connectors, and the DRM MIPI DBI drivers.
- Added common panel, bridge, and MIPI DBI luminance forwarding helpers.
- Retained the LUMINANCE name, while documenting that values are relative,
driver-defined levels rather than physical luminance in cd/m^2.
- Added connector property lifecycle coverage and updated the AMD display
KUnit fixtures for both CONFIG_DRM_LUMINANCE configurations.
- Fixed error propagation when AMD Display Core reads the current brightness
and guarded legacy AMDGPU backlight scratch-register access.
- Restructured the series from 14 to 21 patches splitting the core
infrastructure, shared helpers, and individual driver migrations.
The following compositors have implemented matching support:
* Kwin: https://invent.kde.org/plasma/kwin/-/merge_requests/9298
* Mutter: https://gitlab.gnome.org/swick/mutter/-/commits/wip/kms-luminance-prop
* Wlroots: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5384
I've tested this series using Kwin on amdgpu. I've compile tested other
drivers.
The series is also available on this branch for easy testing.
https://git.kernel.org/pub/scm/linux/kernel/git/superm1/linux.git/log/?h=superm1/backlight-property-v9
And lastly; I've used an LLM to assist with implementing this version, particularly
on all the drivers I wasn't familiar with.
Assisted-by: LLM
Mario Limonciello (19):
drm: add connector LUMINANCE property
drm/amd/display: Pass up errors reading actual brightness
drm/amd: add luminance property support
drm/i915/display: add luminance property support
drm: add panel and bridge connector luminance forwarding
drm/mipi-dbi: add connector luminance helpers
drm/tiny: migrate panel-mipi-dbi to connector luminance
drm/tiny: migrate HX8357D to connector luminance
drm/tiny: migrate ILI9163 to connector luminance
drm/tiny: migrate ILI9341 to connector luminance
drm/tiny: migrate ILI9486 to connector luminance
drm/tiny: migrate MI0283QT to connector luminance
drm/sitronix: migrate ST7735R to connector luminance
drm/nouveau: add connector luminance support
drm/gud: add connector luminance support
drm/radeon: add connector luminance support
drm/gma500: add connector luminance support
drm/bridge: add PS8622 connector luminance support
drm/solomon: add SSD130x connector luminance support
Mario Limonciello (AMD) (2):
drm/amdgpu: Check bios_scratch_reg_offset in backlight level helper
drm/amd/display: update KUnit luminance fixtures
drivers/gpu/drm/Kconfig | 14 +++
drivers/gpu/drm/amd/amdgpu/Kconfig | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 7 +-
.../gpu/drm/amd/amdgpu/amdgpu_connectors.c | 20 ++++
.../gpu/drm/amd/amdgpu/atombios_encoders.c | 17 ++-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 22 ++--
.../display/amdgpu_dm/amdgpu_dm_backlight.c | 55 +++++++--
.../display/amdgpu_dm/amdgpu_dm_backlight.h | 4 +-
.../display/amdgpu_dm/amdgpu_dm_connector.c | 7 +-
.../tests/amdgpu_dm_backlight_test.c | 47 ++++++--
.../amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c | 7 +-
drivers/gpu/drm/bridge/Kconfig | 2 +-
drivers/gpu/drm/bridge/panel.c | 39 +++++++
drivers/gpu/drm/bridge/parade-ps8622.c | 45 +++++--
.../gpu/drm/display/drm_bridge_connector.c | 65 +++++++++++
drivers/gpu/drm/drm_atomic_helper.c | 73 +++++++++++-
drivers/gpu/drm/drm_atomic_state_helper.c | 7 ++
drivers/gpu/drm/drm_atomic_uapi.c | 5 +
drivers/gpu/drm/drm_connector.c | 57 +++++++++
drivers/gpu/drm/drm_mipi_dbi.c | 36 ++++++
drivers/gpu/drm/drm_panel.c | 55 +++++++++
drivers/gpu/drm/gma500/Kconfig | 2 +-
drivers/gpu/drm/gma500/backlight.c | 45 ++++---
drivers/gpu/drm/gma500/cdv_intel_lvds.c | 2 +
drivers/gpu/drm/gma500/psb_drv.c | 2 +-
drivers/gpu/drm/gma500/psb_drv.h | 4 +-
drivers/gpu/drm/gma500/psb_intel_lvds.c | 3 +-
drivers/gpu/drm/gud/Kconfig | 2 +-
drivers/gpu/drm/gud/gud_connector.c | 48 +++++++-
drivers/gpu/drm/i915/Kconfig | 2 +-
drivers/gpu/drm/i915/display/icl_dsi.c | 1 +
.../gpu/drm/i915/display/intel_backlight.c | 20 ++++
.../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 +
drivers/gpu/drm/nouveau/Kconfig | 4 +-
drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +-
drivers/gpu/drm/nouveau/nouveau_backlight.c | 110 ++++++++++++++----
drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +
drivers/gpu/drm/nouveau/nouveau_connector.h | 14 +++
drivers/gpu/drm/radeon/Kconfig | 2 +-
drivers/gpu/drm/radeon/atombios_encoders.c | 32 ++++-
drivers/gpu/drm/radeon/radeon_connectors.c | 34 ++++++
.../gpu/drm/radeon/radeon_legacy_encoders.c | 49 ++++++--
drivers/gpu/drm/radeon/radeon_mode.h | 2 +
drivers/gpu/drm/sitronix/Kconfig | 2 +-
drivers/gpu/drm/sitronix/st7735r.c | 3 +
drivers/gpu/drm/solomon/Kconfig | 2 +-
drivers/gpu/drm/solomon/ssd130x.c | 79 ++++++++++---
drivers/gpu/drm/tests/drm_connector_test.c | 28 +++++
drivers/gpu/drm/tiny/Kconfig | 12 +-
drivers/gpu/drm/tiny/hx8357d.c | 3 +
drivers/gpu/drm/tiny/ili9163.c | 3 +
drivers/gpu/drm/tiny/ili9341.c | 3 +
drivers/gpu/drm/tiny/ili9486.c | 3 +
drivers/gpu/drm/tiny/mi0283qt.c | 3 +
drivers/gpu/drm/tiny/panel-mipi-dbi.c | 3 +
drivers/gpu/drm/xe/Kconfig | 2 +-
include/drm/drm_atomic_helper.h | 3 +
include/drm/drm_bridge.h | 26 +++++
include/drm/drm_connector.h | 16 +++
include/drm/drm_mipi_dbi.h | 7 +-
include/drm/drm_modeset_helper_vtables.h | 25 ++++
include/drm/drm_panel.h | 5 +
67 files changed, 1070 insertions(+), 140 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v9 01/21] drm: add connector LUMINANCE property
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-03 11:37 ` Javier Martinez Canillas
2026-10-02 19:00 ` [PATCH v9 02/21] drm/amd/display: Pass up errors reading actual brightness Mario Limonciello
` (20 subsequent siblings)
21 siblings, 1 reply; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Panel brightness is a property of a display, and thus of a DRM
connector. Add an atomic per-connector LUMINANCE range property so
compositors can manage relative panel luminance together with the rest
of the display state.
Keep the core backend-agnostic. Drivers create the property with their
hardware range and implement connector helper callbacks to set luminance
or disable panel emission. The atomic helpers sequence those callbacks
around pipeline enable and disable, including luminance-only commits.
The stored property value is independent of display power. A commit made
while the connector is inactive is retained and applied on the next
enable; disabling the pipeline does not overwrite it.
LUMINANCE values are relative, driver-defined levels rather than
absolute luminance in cd/m^2. The interface supports emissive panels as
well as panels with a separate backlight.
Keep the interface behind a default-off DRM_LUMINANCE option. Migrated
drivers retain their legacy backlight class ABI unless the new interface
is explicitly selected, allowing the DRM UAPI and legacy compatibility
policy to remain separate.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/Kconfig | 14 +++++
drivers/gpu/drm/drm_atomic_helper.c | 73 +++++++++++++++++++++-
drivers/gpu/drm/drm_atomic_state_helper.c | 7 +++
drivers/gpu/drm/drm_atomic_uapi.c | 5 ++
drivers/gpu/drm/drm_connector.c | 57 +++++++++++++++++
drivers/gpu/drm/tests/drm_connector_test.c | 28 +++++++++
include/drm/drm_atomic_helper.h | 3 +
include/drm/drm_connector.h | 16 +++++
include/drm/drm_modeset_helper_vtables.h | 25 ++++++++
9 files changed, 227 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 65d46dfa72661..9c183c8e2b71b 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -33,6 +33,20 @@ endmenu
if DRM
+config DRM_LUMINANCE
+ bool "DRM connector luminance support"
+ help
+ Expose relative luminance as an atomic DRM connector property. Values
+ are driver-defined levels rather than absolute luminance in cd/m^2.
+ Drivers provide connector helper callbacks to program their hardware;
+ the DRM core does not depend on a particular backend.
+
+ Drivers migrated to this interface will use it instead of registering
+ a legacy backlight class device. Leave this disabled to preserve the
+ de-facto userspace ABI in /sys/class/backlight.
+
+ If in doubt, say N.
+
config DRM_MIPI_DBI
tristate
depends on DRM
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 9d006f98413a5..1e9b7b8acccfe 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1375,6 +1375,8 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_encoder_bridge_post_disable);
static void
disable_outputs(struct drm_device *dev, struct drm_atomic_commit *state)
{
+ drm_atomic_helper_commit_luminance_disables(state);
+
drm_atomic_helper_commit_encoder_bridge_disable(dev, state);
drm_atomic_helper_commit_encoder_bridge_post_disable(dev, state);
@@ -1382,6 +1384,45 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_commit *state)
drm_atomic_helper_commit_crtc_disable(dev, state);
}
+/**
+ * drm_atomic_helper_commit_luminance_disables - disable panel emission
+ * @state: atomic state object being committed
+ *
+ * Invokes each connector driver's luminance disable callback before a
+ * display pipeline is disabled. The connector property's stored value is left
+ * untouched so it can be restored when the pipeline is enabled again.
+ */
+void drm_atomic_helper_commit_luminance_disables(struct drm_atomic_commit *state)
+{
+ struct drm_connector_state *old_conn_state, *new_conn_state;
+ struct drm_connector *connector;
+ int i;
+
+ for_each_oldnew_connector_in_state(state, connector, old_conn_state,
+ new_conn_state, i) {
+ const struct drm_connector_helper_funcs *funcs;
+ struct drm_crtc_state *old_crtc_state, *new_crtc_state = NULL;
+
+ if (!connector->luminance_property || !old_conn_state->crtc)
+ continue;
+
+ old_crtc_state =
+ drm_atomic_get_old_crtc_state(state, old_conn_state->crtc);
+ if (new_conn_state->crtc)
+ new_crtc_state =
+ drm_atomic_get_new_crtc_state(state, new_conn_state->crtc);
+
+ if (!crtc_needs_disable(old_crtc_state, new_crtc_state) ||
+ !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state))
+ continue;
+
+ funcs = connector->helper_private;
+ if (funcs && funcs->disable_luminance)
+ funcs->disable_luminance(old_conn_state);
+ }
+}
+EXPORT_SYMBOL(drm_atomic_helper_commit_luminance_disables);
+
/**
* drm_atomic_helper_update_legacy_modeset_state - update legacy modeset state
* @dev: DRM device
@@ -1771,10 +1812,41 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
drm_atomic_helper_commit_encoder_bridge_enable(dev, state);
+ drm_atomic_helper_commit_luminance_enables(state);
+
drm_atomic_helper_commit_writebacks(dev, state);
}
EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
+/**
+ * drm_atomic_helper_commit_luminance_enables - apply luminance
+ * @state: atomic state object being committed
+ *
+ * Invokes each connector driver's luminance callback after the display
+ * pipeline has been enabled. The callback is also invoked for brightness-only
+ * commits while the connector remains active. Changes committed while the
+ * connector is inactive remain stored in atomic state until a later enable.
+ */
+void drm_atomic_helper_commit_luminance_enables(struct drm_atomic_commit *state)
+{
+ struct drm_connector_state *new_conn_state;
+ struct drm_connector *connector;
+ int i;
+
+ for_each_new_connector_in_state(state, connector, new_conn_state, i) {
+ const struct drm_connector_helper_funcs *funcs;
+
+ if (!connector->luminance_property || !new_conn_state->crtc ||
+ !new_conn_state->crtc->state->active)
+ continue;
+
+ funcs = connector->helper_private;
+ if (funcs && funcs->set_luminance)
+ funcs->set_luminance(new_conn_state);
+ }
+}
+EXPORT_SYMBOL(drm_atomic_helper_commit_luminance_enables);
+
/*
* For atomic updates which touch just a single CRTC, calculate the time of the
* next vblank, and inform all the fences of the deadline.
@@ -4187,4 +4259,3 @@ drm_atomic_helper_bridge_get_hdmi_output_bus_fmts(struct drm_bridge *bridge,
return out_fmts;
}
EXPORT_SYMBOL(drm_atomic_helper_bridge_get_hdmi_output_bus_fmts);
-
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index 406157a3660fd..5c31bf2bdbe76 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -408,7 +408,14 @@ void
__drm_atomic_helper_connector_state_init(struct drm_connector_state *conn_state,
struct drm_connector *connector)
{
+ u64 value;
+
conn_state->connector = connector;
+ if (connector->luminance_property &&
+ !drm_object_property_get_default_value(&connector->base,
+ connector->luminance_property,
+ &value))
+ conn_state->luminance = value;
}
EXPORT_SYMBOL(__drm_atomic_helper_connector_state_init);
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 1eebcf6f5e05b..dffc51cd8d13c 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -30,6 +30,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_connector.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_print.h>
#include <drm/drm_drv.h>
@@ -969,6 +970,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
state->hdmi.broadcast_rgb = val;
} else if (property == connector->color_format_property) {
state->color_format = val;
+ } else if (property == connector->luminance_property) {
+ state->luminance = val;
} else if (connector->funcs->atomic_set_property) {
return connector->funcs->atomic_set_property(connector,
state, property, val);
@@ -1056,6 +1059,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
*val = state->hdmi.broadcast_rgb;
} else if (property == connector->color_format_property) {
*val = state->color_format;
+ } else if (property == connector->luminance_property) {
+ *val = state->luminance;
} else if (connector->funcs->atomic_get_property) {
return connector->funcs->atomic_get_property(connector,
state, property, val);
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index d94c86bfed866..2e433f76f467a 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -810,6 +810,47 @@ void drm_connector_attach_edid_property(struct drm_connector *connector)
}
EXPORT_SYMBOL(drm_connector_attach_edid_property);
+/**
+ * drm_connector_attach_luminance_property - attach luminance property
+ * @connector: connector to attach the property to
+ * @min: minimum supported relative brightness
+ * @max: maximum supported relative brightness
+ * @value: initial relative brightness
+ *
+ * Creates the atomic ``LUMINANCE`` range property for @connector.
+ * Drivers should call this during connector initialization. The property's
+ * units are driver-defined; they do not represent absolute luminance.
+ *
+ * Returns:
+ * Zero on success, a negative errno otherwise.
+ */
+int drm_connector_attach_luminance_property(struct drm_connector *connector,
+ unsigned int min,
+ unsigned int max,
+ unsigned int value)
+{
+ struct drm_property *property;
+
+ if (drm_WARN_ON(connector->dev, min > max || value < min || value > max))
+ return -EINVAL;
+
+ if (connector->luminance_property)
+ return 0;
+
+ property = drm_property_create_range(connector->dev, DRM_MODE_PROP_ATOMIC,
+ "LUMINANCE", min, max);
+ if (!property)
+ return -ENOMEM;
+
+ connector->luminance_property = property;
+ drm_object_attach_property(&connector->base, property, value);
+ if (connector->state)
+ connector->state->luminance = value;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_luminance_property);
+
/**
* drm_connector_attach_encoder - attach a connector to an encoder
* @connector: connector to attach
@@ -1681,6 +1722,22 @@ EXPORT_SYMBOL(drm_hdmi_connector_get_output_format_name);
* Summarizing: Only set "DPMS" when the connector is known to be enabled,
* assume that a successful SETCONFIG call also sets "DPMS" to on, and
* never read back the value of "DPMS" because it can be incorrect.
+ * LUMINANCE:
+ * Atomic range property for controlling a panel's relative luminance.
+ * The unit and range are driver-defined and do not represent an absolute
+ * luminance in cd/m^2. This name therefore also applies to emissive panels
+ * that do not contain a separate backlight.
+ *
+ * The property is independent of the connector's display-power state.
+ * Changing it while the connector is inactive stores the new value without
+ * turning the display on. The atomic helpers apply the stored value after
+ * the display pipeline is enabled and invoke a separate driver callback
+ * before disabling the pipeline; neither action changes the property value.
+ *
+ * Drivers create the property with
+ * drm_connector_attach_luminance_property() and implement the
+ * corresponding &drm_connector_helper_funcs callbacks. Connectors that do
+ * not support luminance control do not expose the property.
* panel_type:
* Immutable enum property to indicate the type of connected panel.
* Possible values are "unknown" (default), "OLED", and "LCD".
diff --git a/drivers/gpu/drm/tests/drm_connector_test.c b/drivers/gpu/drm/tests/drm_connector_test.c
index 3368aedd4e669..e43692d38ebb8 100644
--- a/drivers/gpu/drm/tests/drm_connector_test.c
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -137,6 +137,33 @@ static void drm_test_drmm_connector_init_null_ddc(struct kunit *test)
KUNIT_EXPECT_EQ(test, ret, 0);
}
+static void drm_test_connector_attach_luminance_property(struct kunit *test)
+{
+ struct drm_connector_init_priv *priv = test->priv;
+ struct drm_connector *connector = &priv->connector;
+ struct drm_property *property;
+ u64 value;
+ int ret;
+
+ ret = drmm_connector_init(&priv->drm, connector, &dummy_funcs,
+ DRM_MODE_CONNECTOR_eDP, NULL);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+ KUNIT_ASSERT_NULL(test, connector->state);
+
+ ret = drm_connector_attach_luminance_property(connector, 10, 100, 50);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+ property = connector->luminance_property;
+ KUNIT_ASSERT_NOT_NULL(test, property);
+
+ ret = drm_object_property_get_default_value(&connector->base, property, &value);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+ KUNIT_EXPECT_EQ(test, value, (u64)50);
+
+ drm_atomic_helper_connector_reset(connector);
+ KUNIT_ASSERT_NOT_NULL(test, connector->state);
+ KUNIT_EXPECT_EQ(test, connector->state->luminance, 50u);
+}
+
/*
* Test that the registration of a connector succeeds for all possible
* connector types.
@@ -190,6 +217,7 @@ KUNIT_ARRAY_PARAM(drm_connector_init_type_valid,
static struct kunit_case drmm_connector_init_tests[] = {
KUNIT_CASE(drm_test_drmm_connector_init),
KUNIT_CASE(drm_test_drmm_connector_init_null_ddc),
+ KUNIT_CASE(drm_test_connector_attach_luminance_property),
KUNIT_CASE_PARAM(drm_test_drmm_connector_init_type_valid,
drm_connector_init_type_valid_gen_params),
{ }
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 4cfeec70d648a..3084dd5cd6a1f 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -116,6 +116,9 @@ void drm_atomic_helper_commit_encoder_bridge_enable(struct drm_device *dev,
void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
struct drm_atomic_commit *old_state);
+void drm_atomic_helper_commit_luminance_disables(struct drm_atomic_commit *state);
+void drm_atomic_helper_commit_luminance_enables(struct drm_atomic_commit *state);
+
int drm_atomic_helper_prepare_planes(struct drm_device *dev,
struct drm_atomic_commit *state);
void drm_atomic_helper_unprepare_planes(struct drm_device *dev,
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 2ee7c59329aae..7f7d115b65f9f 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1369,6 +1369,11 @@ struct drm_connector_state {
* @drm_atomic_helper_connector_hdmi_check().
*/
struct drm_connector_hdmi_state hdmi;
+
+ /**
+ * @luminance: Relative panel luminance requested by userspace.
+ */
+ unsigned int luminance;
};
struct drm_connector_hdmi_audio_funcs {
@@ -2714,6 +2719,13 @@ struct drm_connector {
* @cec: CEC-related data.
*/
struct drm_connector_cec cec;
+
+ /**
+ * @luminance_property: Optional atomic range property for relative panel
+ * luminance. Drivers create it with
+ * drm_connector_attach_luminance_property().
+ */
+ struct drm_property *luminance_property;
};
#define obj_to_connector(x) container_of(x, struct drm_connector, base)
@@ -2980,6 +2992,10 @@ const char *drm_get_colorspace_name(enum drm_colorspace colorspace);
int drm_connector_attach_color_format_property(struct drm_connector *connector,
unsigned long supported_color_formats);
+int drm_connector_attach_luminance_property(struct drm_connector *connector,
+ unsigned int min,
+ unsigned int max,
+ unsigned int value);
/**
* drm_for_each_connector_iter - connector_list iterator macro
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index 60b30cc269404..cecacc1755a36 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -1147,6 +1147,31 @@ struct drm_connector_helper_funcs {
void (*atomic_commit)(struct drm_connector *connector,
struct drm_atomic_commit *state);
+ /**
+ * @set_luminance:
+ *
+ * Apply &drm_connector_state.luminance to an active panel. The
+ * atomic helpers call this after enabling the display pipeline and for
+ * brightness-only commits while the connector remains active.
+ *
+ * This callback is optional and is only used by connectors exposing the
+ * ``LUMINANCE`` property.
+ */
+ void (*set_luminance)(const struct drm_connector_state *new_state);
+
+ /**
+ * @disable_luminance:
+ *
+ * Turn panel light emission off before disabling the display pipeline.
+ * This callback does not change the ``LUMINANCE`` property; the
+ * stored value is restored through @set_luminance when the panel
+ * is enabled again.
+ *
+ * This callback is optional and is only used by connectors exposing the
+ * ``LUMINANCE`` property.
+ */
+ void (*disable_luminance)(const struct drm_connector_state *old_state);
+
/**
* @prepare_writeback_job:
*
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 02/21] drm/amd/display: Pass up errors reading actual brightness
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 01/21] drm: add connector LUMINANCE property Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 03/21] drm/amd: add luminance property support Mario Limonciello
` (19 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
[Why]
If the DC API fails to return actual brightness when backlight control
API requests it, then the wrong value may be returned.
[How]
Change return type of amdgpu_dm_backlight_get_level() to an integer
and pass an error code up to the caller.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
.../drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c | 13 +++++++++----
.../drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.h | 2 +-
.../amdgpu_dm/tests/amdgpu_dm_backlight_test.c | 4 ++--
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
index 45e1732a5b041..64a963c218c8b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
@@ -372,7 +372,7 @@ int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
EXPORT_IF_KUNIT(amdgpu_dm_backlight_update_status);
STATIC_IFN_KUNIT
-u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm, int bl_idx)
+int amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm, int bl_idx)
{
int ret;
struct amdgpu_dm_backlight_caps caps;
@@ -385,14 +385,14 @@ u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm, int bl_idx)
u32 avg, peak;
if (!dc_link_get_backlight_level_nits(link, &avg, &peak))
- return dm->brightness[bl_idx];
+ return -EINVAL;
return convert_brightness_to_user(&caps, avg);
}
ret = dc_link_get_backlight_level(link);
if (ret == DC_ERROR_UNEXPECTED)
- return dm->brightness[bl_idx];
+ return -EINVAL;
return convert_brightness_to_user(&caps, ret);
}
@@ -403,8 +403,13 @@ int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
{
struct amdgpu_display_manager *dm = bl_get_data(bd);
int i = amdgpu_dm_backlight_get_device_index(dm, bd);
+ int ret;
+
+ ret = amdgpu_dm_backlight_get_level(dm, i);
+ if (ret < 0)
+ return dm->brightness[i];
- return amdgpu_dm_backlight_get_level(dm, i);
+ return ret;
}
EXPORT_IF_KUNIT(amdgpu_dm_backlight_get_brightness);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.h
index 9ad888d3ae7b2..891749322191c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.h
@@ -57,7 +57,7 @@ void amdgpu_dm_validate_backlight_caps(struct amdgpu_display_manager *dm, int bl
struct dc_stream_state *dm_find_stream_with_link(struct amdgpu_display_manager *dm,
struct dc_link *link);
int amdgpu_dm_backlight_update_status(struct backlight_device *bd);
-u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm, int bl_idx);
+int amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm, int bl_idx);
int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd);
ssize_t panel_power_savings_show(struct device *device,
struct device_attribute *attr,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
index 5221050dec2f1..b21850788f36f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
@@ -382,7 +382,7 @@ static void dm_test_backlight_get_level_pwm_error(struct kunit *test)
dm->brightness[0] = 4321;
dm->backlight_link[0] = link;
- KUNIT_EXPECT_EQ(test, amdgpu_dm_backlight_get_level(dm, 0), 4321U);
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_backlight_get_level(dm, 0), -EINVAL);
}
/**
@@ -424,7 +424,7 @@ static void dm_test_backlight_get_level_aux_error(struct kunit *test)
caps->caps_valid = true;
caps->aux_support = true;
- KUNIT_EXPECT_EQ(test, amdgpu_dm_backlight_get_level(dm, 0), 6789U);
+ KUNIT_EXPECT_EQ(test, amdgpu_dm_backlight_get_level(dm, 0), -EINVAL);
}
/**
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 03/21] drm/amd: add luminance property support
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 01/21] drm: add connector LUMINANCE property Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 02/21] drm/amd/display: Pass up errors reading actual brightness Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 04/21] drm/amdgpu: Check bios_scratch_reg_offset in backlight level helper Mario Limonciello
` (18 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Expose the DRM LUMINANCE connector property for internal panels when
CONFIG_DRM_LUMINANCE is enabled. Keep registering the existing backlight
class device otherwise, preserving its userspace ABI.
Use the existing brightness scaling and programming paths from connector
helper callbacks in both Display Core and legacy display. Apply atomic
luminance after the display pipeline is enabled so changes made while a
connector is inactive take effect on the next enable.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/amd/amdgpu/Kconfig | 2 +-
.../gpu/drm/amd/amdgpu/amdgpu_connectors.c | 20 +++++++++
.../gpu/drm/amd/amdgpu/atombios_encoders.c | 17 +++++++-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 22 ++++++----
.../display/amdgpu_dm/amdgpu_dm_backlight.c | 42 +++++++++++++++++--
.../display/amdgpu_dm/amdgpu_dm_backlight.h | 2 +
.../display/amdgpu_dm/amdgpu_dm_connector.c | 7 +++-
7 files changed, 96 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig
index 12e4a41bf1f04..f273fb79c0e02 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -20,7 +20,7 @@ config DRM_AMDGPU
select I2C
select I2C_ALGOBIT
select CRC16
- select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
select INTERVAL_TREE
select DRM_BUDDY
select DRM_SUBALLOC_HELPER
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index 92c98e999efe9..209a7a6c246db 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -798,11 +798,31 @@ static int amdgpu_connector_set_lcd_property(struct drm_connector *connector,
return 0;
}
+static void amdgpu_connector_set_luminance(const struct drm_connector_state *conn_state)
+{
+ struct drm_encoder *encoder =
+ amdgpu_connector_best_single_encoder(conn_state->connector);
+
+ if (encoder)
+ amdgpu_atombios_encoder_set_backlight_level(to_amdgpu_encoder(encoder),
+ conn_state->luminance);
+}
+
+static void amdgpu_connector_disable_luminance(const struct drm_connector_state *conn_state)
+{
+ struct drm_encoder *encoder =
+ amdgpu_connector_best_single_encoder(conn_state->connector);
+
+ if (encoder)
+ amdgpu_atombios_encoder_set_backlight_level(to_amdgpu_encoder(encoder), 0);
+}
static const struct drm_connector_helper_funcs amdgpu_connector_lvds_helper_funcs = {
.get_modes = amdgpu_connector_lvds_get_modes,
.mode_valid = amdgpu_connector_lvds_mode_valid,
.best_encoder = amdgpu_connector_best_single_encoder,
+ .set_luminance = amdgpu_connector_set_luminance,
+ .disable_luminance = amdgpu_connector_disable_luminance,
};
static const struct drm_connector_funcs amdgpu_connector_lvds_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
index a1d05df0ac99b..dbff532ac1bcd 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
@@ -191,6 +191,21 @@ void amdgpu_atombios_encoder_init_backlight(struct amdgpu_encoder *amdgpu_encode
goto register_acpi_backlight;
}
+ dig = amdgpu_encoder->enc_priv;
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ unsigned int brightness;
+
+ brightness = amdgpu_atombios_encoder_get_backlight_level(amdgpu_encoder);
+ if (drm_connector_attach_luminance_property(drm_connector, 0,
+ AMDGPU_MAX_BL_LEVEL,
+ brightness))
+ return;
+
+ dig->backlight_level = brightness;
+ dig->bl_dev = NULL;
+ return;
+ }
+
pdata = kmalloc_obj(struct amdgpu_backlight_privdata);
if (!pdata) {
DRM_ERROR("Memory allocation failed\n");
@@ -211,7 +226,6 @@ void amdgpu_atombios_encoder_init_backlight(struct amdgpu_encoder *amdgpu_encode
pdata->encoder = amdgpu_encoder;
- dig = amdgpu_encoder->enc_priv;
dig->bl_dev = bd;
bd->props.brightness = amdgpu_atombios_encoder_get_backlight_brightness(bd);
@@ -2123,4 +2137,3 @@ amdgpu_atombios_encoder_get_dig_info(struct amdgpu_encoder *amdgpu_encoder)
return dig;
}
-
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 2b0686bcc7fd2..e79920ca17ac5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5175,9 +5175,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_commit *state)
}
/* Skip any modesets/resets */
- if (!acrtc || drm_atomic_crtc_needs_modeset(new_crtc_state))
+ if (!acrtc || !new_crtc_state ||
+ drm_atomic_crtc_needs_modeset(new_crtc_state))
continue;
+ drm_connector_update_privacy_screen(new_con_state);
+
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
@@ -5257,8 +5260,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_commit *state)
&stream_update);
mutex_unlock(&dm->dc_lock);
kfree(dummy_updates);
-
- drm_connector_update_privacy_screen(new_con_state);
}
/**
@@ -5376,11 +5377,16 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_commit *state)
/* Update audio instances for each connector. */
amdgpu_dm_commit_audio(dev, state);
- /* restore the backlight level */
- for (i = 0; i < dm->num_of_edps; i++) {
- if (dm->backlight_dev[i] &&
- (dm->actual_brightness[i] != dm->brightness[i]))
- amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ /* Apply brightness after the display pipeline is enabled. */
+ drm_atomic_helper_commit_luminance_enables(state);
+ } else {
+ /* Restore the legacy backlight level. */
+ for (i = 0; i < dm->num_of_edps; i++) {
+ if (dm->backlight_dev[i] &&
+ dm->actual_brightness[i] != dm->brightness[i])
+ amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
+ }
}
/*
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
index 64a963c218c8b..7b9ab94244176 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
@@ -40,6 +40,7 @@
#include <linux/backlight.h>
#include <linux/power_supply.h>
+#include <drm/drm_connector.h>
#include <drm/drm_edid.h>
#include <drm/drm_utils.h>
@@ -233,13 +234,17 @@ struct dc_stream_state *dm_find_stream_with_link(
struct amdgpu_display_manager *dm,
struct dc_link *link)
{
- struct dc_state *cur_dc_state = dm->dc->current_state;
+ struct dc_state *cur_dc_state;
struct dc_stream_state *stream = NULL;
int i;
+ if (!dm || !dm->dc || !dm->dc->current_state || !link)
+ return NULL;
+
+ cur_dc_state = dm->dc->current_state;
for (i = 0; i < cur_dc_state->stream_count; i++) {
stream = cur_dc_state->streams[i];
- if (stream->link == link)
+ if (stream && stream->link == link)
return stream;
}
@@ -293,7 +298,7 @@ void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
dm->brightness[bl_idx] = user_brightness;
/* update scratch register */
- if (bl_idx == 0)
+ if (bl_idx == 0 && dm->adev && dm->adev->rmmio && dm->adev->bios_scratch_reg_offset)
amdgpu_atombios_scratch_regs_set_backlight_level(dm->adev, dm->brightness[bl_idx]);
brightness = convert_brightness_from_user(caps, dm->brightness[bl_idx]);
link = (struct dc_link *)dm->backlight_link[bl_idx];
@@ -591,6 +596,10 @@ void amdgpu_dm_setup_backlight_device(struct amdgpu_display_manager *dm,
{
struct dc_link *link = aconnector->dc_link;
int bl_idx = dm->num_of_edps;
+ struct backlight_properties props = { 0 };
+ struct amdgpu_dm_backlight_caps *caps;
+ struct drm_connector *connector = &aconnector->base;
+ int ret;
if (!(link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) ||
link->type == dc_connection_none)
@@ -609,6 +618,19 @@ void amdgpu_dm_setup_backlight_device(struct amdgpu_display_manager *dm,
amdgpu_dm_update_connector_ext_caps(aconnector);
+ caps = &dm->backlight_caps[bl_idx];
+ amdgpu_dm_backlight_fill_props(caps, power_supply_is_system_supplied() > 0,
+ !(amdgpu_dc_debug_mask &
+ DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE),
+ &props);
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ unsigned int max = props.max_brightness;
+ unsigned int value = props.brightness;
+
+ ret = drm_connector_attach_luminance_property(connector, 0, max, value);
+ drm_WARN_ON(adev_to_drm(dm->adev), ret);
+ }
+
/* Offer ABM property when user didn't turn off by module parameter.
* OLED panels are included to support CACP (Content Adaptive
* Contrast and Power) feature via set_abm_level.
@@ -620,6 +642,20 @@ void amdgpu_dm_setup_backlight_device(struct amdgpu_display_manager *dm,
}
EXPORT_IF_KUNIT(amdgpu_dm_setup_backlight_device);
+void amdgpu_dm_set_luminance(const struct drm_connector_state *state)
+{
+ struct amdgpu_dm_connector *aconnector =
+ to_amdgpu_dm_connector(state->connector);
+ struct amdgpu_display_manager *dm =
+ &drm_to_adev(state->connector->dev)->dm;
+
+ if (aconnector->bl_idx < 0)
+ return;
+
+ amdgpu_dm_backlight_set_level(dm, aconnector->bl_idx,
+ state->luminance);
+}
+
/**
* DOC: panel power savings
*
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.h
index 891749322191c..859224cb37988 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.h
@@ -33,6 +33,7 @@ struct dc_stream_state;
struct device;
struct device_attribute;
struct drm_connector;
+struct drm_connector_state;
struct attribute_group;
#define AMDGPU_DM_DEFAULT_MIN_BACKLIGHT 12
@@ -47,6 +48,7 @@ void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
void amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector);
void amdgpu_dm_setup_backlight_device(struct amdgpu_display_manager *dm,
struct amdgpu_dm_connector *aconnector);
+void amdgpu_dm_set_luminance(const struct drm_connector_state *state);
void amdgpu_dm_update_connector_ext_caps(struct amdgpu_dm_connector *aconnector);
bool amdgpu_dm_should_create_sysfs(struct amdgpu_dm_connector *aconnector);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
index 2a63a1c9b79d8..41610bed02c6d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
@@ -1922,7 +1922,8 @@ STATIC_IFN_KUNIT void amdgpu_dm_connector_destroy(struct drm_connector *connecto
}
if (aconnector->bl_idx != -1) {
- backlight_device_unregister(dm->backlight_dev[aconnector->bl_idx]);
+ if (dm->backlight_dev[aconnector->bl_idx])
+ backlight_device_unregister(dm->backlight_dev[aconnector->bl_idx]);
dm->backlight_dev[aconnector->bl_idx] = NULL;
}
@@ -2016,7 +2017,8 @@ amdgpu_dm_connector_late_register(struct drm_connector *connector)
return r;
}
- amdgpu_dm_register_backlight_device(amdgpu_dm_connector);
+ if (!IS_ENABLED(CONFIG_DRM_LUMINANCE))
+ amdgpu_dm_register_backlight_device(amdgpu_dm_connector);
if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
(connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
@@ -2679,6 +2681,7 @@ amdgpu_dm_connector_helper_funcs = {
.get_modes = get_modes,
.mode_valid = amdgpu_dm_connector_mode_valid,
.atomic_check = amdgpu_dm_connector_atomic_check,
+ .set_luminance = amdgpu_dm_set_luminance,
};
int amdgpu_dm_convert_dc_color_depth_into_bpc(enum dc_color_depth display_color_depth)
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 04/21] drm/amdgpu: Check bios_scratch_reg_offset in backlight level helper
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (2 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 03/21] drm/amd: add luminance property support Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 05/21] drm/amd/display: update KUnit luminance fixtures Mario Limonciello
` (17 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Ensure adev->bios_scratch_reg_offset is non-zero before accessing
scratch registers in amdgpu_atombios_scratch_regs_set_backlight_level()
to avoid dereferencing unmapped MMIO offsets.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index 27c0dc8f6137a..2d8c2ba04e670 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -1622,7 +1622,12 @@ void amdgpu_atombios_scratch_regs_engine_hung(struct amdgpu_device *adev,
void amdgpu_atombios_scratch_regs_set_backlight_level(struct amdgpu_device *adev,
u32 backlight_level)
{
- u32 tmp = RREG32(adev->bios_scratch_reg_offset + 2);
+ u32 tmp;
+
+ if (!adev->bios_scratch_reg_offset)
+ return;
+
+ tmp = RREG32(adev->bios_scratch_reg_offset + 2);
tmp &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
tmp |= (backlight_level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT) &
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 05/21] drm/amd/display: update KUnit luminance fixtures
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (3 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 04/21] drm/amdgpu: Check bios_scratch_reg_offset in backlight level helper Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 06/21] drm/i915/display: add luminance property support Mario Limonciello
` (16 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Initialize complete DRM connector state in backlight test fixtures so
the atomic LUMINANCE property can be attached. Check the optional
property and keep the ABM property expectations correct with either
interface selected.
Also initialize the display-manager lock and mode configuration needed
by the existing backlight registration test.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
.../tests/amdgpu_dm_backlight_test.c | 43 +++++++++++++++----
.../amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c | 7 ++-
2 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
index b21850788f36f..8883010e8af9c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
@@ -41,12 +41,21 @@ static void setup_test_connector(struct kunit *test,
struct dm_backlight_connector_fixture *fixture,
int bl_idx, enum signal_type signal)
{
- fixture->adev = kunit_kzalloc(test, sizeof(*fixture->adev), GFP_KERNEL);
- fixture->aconnector = kunit_kzalloc(test, sizeof(*fixture->aconnector), GFP_KERNEL);
+ int ret;
+
+ fixture->adev = dm_kunit_alloc_adev(test);
+ ret = drmm_mode_config_init(&fixture->adev->ddev);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ fixture->aconnector = dm_kunit_alloc_connector(test, fixture->adev, NULL);
fixture->link = kunit_kzalloc(test, sizeof(*fixture->link), GFP_KERNEL);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fixture->adev);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fixture->aconnector);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fixture->link);
+ ret = drmm_connector_init(&fixture->adev->ddev,
+ &fixture->aconnector->base,
+ &dm_backlight_test_connector_funcs,
+ DRM_MODE_CONNECTOR_eDP, NULL);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+ drm_atomic_helper_connector_reset(&fixture->aconnector->base);
fixture->aconnector->bl_idx = bl_idx;
fixture->aconnector->dc_link = fixture->link;
@@ -483,12 +492,17 @@ static void dm_test_register_backlight_device_success(struct kunit *test)
struct dc_link *link = dm_kunit_alloc_link(test);
struct drm_minor *primary;
unsigned int max;
+ int ret;
+
+ ret = drmm_mode_config_init(&adev->ddev);
+ KUNIT_ASSERT_EQ(test, ret, 0);
setup_test_link_service(test, link);
link->dc->link_srv->edp_get_backlight_level = dm_test_get_backlight_level_error;
primary = kunit_kzalloc(test, sizeof(*primary), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, primary);
adev->ddev.primary = primary;
+ adev->dm.ddev = &adev->ddev;
adev->dm.backlight_link[0] = link;
aconnector = dm_kunit_alloc_connector(test, adev, link);
@@ -1872,6 +1886,7 @@ static void dm_test_setup_backlight_device_attaches_abm_property(struct kunit *t
struct dc_link *link;
int saved_abm_level = amdgpu_dm_get_abm_level_param();
int saved_backlight = amdgpu_dm_get_backlight_param();
+ int abm_index;
int old_count;
int ret;
@@ -1890,6 +1905,7 @@ static void dm_test_setup_backlight_device_attaches_abm_property(struct kunit *t
&dm_backlight_test_connector_funcs,
DRM_MODE_CONNECTOR_eDP, NULL);
KUNIT_ASSERT_EQ(test, ret, 0);
+ drm_atomic_helper_connector_reset(&aconnector->base);
link = dm_kunit_alloc_link(test);
link->connector_signal = SIGNAL_TYPE_EDP;
@@ -1900,15 +1916,26 @@ static void dm_test_setup_backlight_device_attaches_abm_property(struct kunit *t
dm->adev = adev;
dm->ddev = &adev->ddev;
old_count = aconnector->base.base.properties->count;
+ abm_index = old_count + IS_ENABLED(CONFIG_DRM_LUMINANCE);
amdgpu_dm_setup_backlight_device(dm, aconnector);
KUNIT_EXPECT_EQ(test, dm->num_of_edps, 1);
KUNIT_EXPECT_EQ(test, aconnector->bl_idx, 0);
- KUNIT_EXPECT_EQ(test, aconnector->base.base.properties->count, old_count + 1);
- KUNIT_EXPECT_PTR_EQ(test, aconnector->base.base.properties->properties[old_count], prop);
- KUNIT_EXPECT_EQ(test, aconnector->base.base.properties->values[old_count],
- (uint64_t)ABM_SYSFS_CONTROL);
+ KUNIT_EXPECT_EQ(test, aconnector->base.base.properties->count,
+ old_count + 1 + IS_ENABLED(CONFIG_DRM_LUMINANCE));
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ KUNIT_EXPECT_NOT_NULL(test,
+ aconnector->base.luminance_property);
+ KUNIT_EXPECT_LE(test,
+ aconnector->base.state->luminance,
+ (uint64_t)MAX_BACKLIGHT_LEVEL);
+ }
+ KUNIT_EXPECT_PTR_EQ(test,
+ aconnector->base.base.properties->properties[abm_index],
+ prop);
+ KUNIT_EXPECT_EQ(test, aconnector->base.base.properties->values[abm_index],
+ (uint64_t)ABM_SYSFS_CONTROL);
amdgpu_dm_set_backlight_param(saved_backlight);
amdgpu_dm_set_abm_level_param(saved_abm_level);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c
index aad122c7229f5..66c9b2cb70fcd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c
@@ -20,6 +20,7 @@
struct amdgpu_device *dm_kunit_alloc_adev(struct kunit *test)
{
+ struct amdgpu_device *adev;
struct drm_device *drm;
struct device *dev;
@@ -32,7 +33,11 @@ struct amdgpu_device *dm_kunit_alloc_adev(struct kunit *test)
DRIVER_MODESET | DRIVER_ATOMIC);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
- return drm_to_adev(drm);
+ adev = drm_to_adev(drm);
+
+ mutex_init(&adev->dm.dc_lock);
+
+ return adev;
}
EXPORT_SYMBOL(dm_kunit_alloc_adev);
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 06/21] drm/i915/display: add luminance property support
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (4 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 05/21] drm/amd/display: update KUnit luminance fixtures Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 07/21] drm: add panel and bridge connector luminance forwarding Mario Limonciello
` (15 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
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>
---
drivers/gpu/drm/i915/Kconfig | 2 +-
drivers/gpu/drm/i915/display/icl_dsi.c | 1 +
.../gpu/drm/i915/display/intel_backlight.c | 20 +++++++++++++++++++
.../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 +
drivers/gpu/drm/xe/Kconfig | 2 +-
10 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 5e939004b6463..f2113642a7aa3 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -26,7 +26,7 @@ config DRM_I915
select IRQ_WORK
# i915 depends on ACPI_VIDEO when ACPI is enabled
# but for select to work, need to select ACPI_VIDEO's dependencies, ick
- select BACKLIGHT_CLASS_DEVICE if ACPI
+ select BACKLIGHT_CLASS_DEVICE if ACPI && !DRM_LUMINANCE
select INPUT if ACPI
select X86_PLATFORM_DEVICES if ACPI
select ACPI_WMI if ACPI
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..6d658c7b5d99f 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>
@@ -1670,6 +1671,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 +1707,13 @@ int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe)
panel->backlight.present = true;
+ max = panel->backlight.max;
+ brightness = scale_hw_to_user(connector, panel->backlight.level, max);
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ 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 +1723,15 @@ 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);
+
+ intel_panel_set_backlight(conn_state, conn_state->luminance,
+ connector->panel.backlight.max);
+}
+
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 fc30a455bed36..497d387bb6c0d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7656,6 +7656,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 0cd5e6b5034cf..c800cffc6444d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6802,6 +6802,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..501573a75b89c 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 (!IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ 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 = {
diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig
index 4d7dcaff2b915..becb9a06d66bd 100644
--- a/drivers/gpu/drm/xe/Kconfig
+++ b/drivers/gpu/drm/xe/Kconfig
@@ -27,7 +27,7 @@ config DRM_XE
select IRQ_WORK
# xe depends on ACPI_VIDEO when ACPI is enabled
# but for select to work, need to select ACPI_VIDEO's dependencies, ick
- select BACKLIGHT_CLASS_DEVICE if ACPI
+ select BACKLIGHT_CLASS_DEVICE if ACPI && !DRM_LUMINANCE
select INPUT if ACPI
select ACPI_VIDEO if X86 && ACPI
select ACPI_WMI if X86 && ACPI
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 07/21] drm: add panel and bridge connector luminance forwarding
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (5 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 06/21] drm/i915/display: add luminance property support Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-12 8:41 ` Maxime Ripard
2026-10-02 19:00 ` [PATCH v9 08/21] drm/mipi-dbi: add connector luminance helpers Mario Limonciello
` (14 subsequent siblings)
21 siblings, 1 reply; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Forward connector luminance operations through panel and bridge connectors.
Allow bridges that own brightness control to expose luminance operations,
and route panel bridges to the panel backlight backend.
Attach the property only when a usable brightness backend is present and
CONFIG_DRM_LUMINANCE is enabled.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/bridge/panel.c | 39 +++++++++++
.../gpu/drm/display/drm_bridge_connector.c | 65 +++++++++++++++++++
drivers/gpu/drm/drm_panel.c | 55 ++++++++++++++++
include/drm/drm_bridge.h | 26 ++++++++
include/drm/drm_panel.h | 5 ++
5 files changed, 190 insertions(+)
diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 02388a3de626e..e447b959cf407 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -45,9 +45,29 @@ static int panel_bridge_connector_get_modes(struct drm_connector *connector)
return drm_panel_get_modes(panel_bridge->panel, connector);
}
+static void
+panel_bridge_connector_set_luminance(const struct drm_connector_state *conn_state)
+{
+ struct panel_bridge *panel_bridge =
+ drm_connector_to_panel_bridge(conn_state->connector);
+
+ drm_panel_set_luminance(panel_bridge->panel, conn_state->luminance);
+}
+
+static void
+panel_bridge_connector_disable_luminance(const struct drm_connector_state *conn_state)
+{
+ struct panel_bridge *panel_bridge =
+ drm_connector_to_panel_bridge(conn_state->connector);
+
+ drm_panel_disable_luminance(panel_bridge->panel);
+}
+
static const struct drm_connector_helper_funcs
panel_bridge_connector_helper_funcs = {
.get_modes = panel_bridge_connector_get_modes,
+ .set_luminance = panel_bridge_connector_set_luminance,
+ .disable_luminance = panel_bridge_connector_disable_luminance,
};
static const struct drm_connector_funcs panel_bridge_connector_funcs = {
@@ -82,6 +102,10 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
drm_panel_bridge_set_orientation(connector, bridge);
+ ret = drm_panel_attach_luminance_property(panel_bridge->panel, connector);
+ if (ret)
+ return ret;
+
drm_connector_attach_encoder(&panel_bridge->connector,
encoder);
@@ -233,6 +257,21 @@ bool drm_bridge_is_panel(const struct drm_bridge *bridge)
}
EXPORT_SYMBOL(drm_bridge_is_panel);
+/**
+ * drm_panel_bridge_to_panel - return the panel wrapped by a panel bridge
+ * @bridge: panel bridge
+ *
+ * Return: the wrapped panel, or %NULL if @bridge isn't a panel bridge
+ */
+struct drm_panel *drm_panel_bridge_to_panel(struct drm_bridge *bridge)
+{
+ if (!drm_bridge_is_panel(bridge))
+ return NULL;
+
+ return drm_bridge_to_panel_bridge(bridge)->panel;
+}
+EXPORT_SYMBOL(drm_panel_bridge_to_panel);
+
/**
* drm_panel_bridge_add - Creates a &drm_bridge and &drm_connector that
* just calls the appropriate functions from &drm_panel.
diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c
index 707d7143e475f..99c83b1acbe5a 100644
--- a/drivers/gpu/drm/display/drm_bridge_connector.c
+++ b/drivers/gpu/drm/display/drm_bridge_connector.c
@@ -18,6 +18,7 @@
#include <drm/drm_edid.h>
#include <drm/drm_managed.h>
#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_panel.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include <drm/display/drm_hdcp_helper.h>
@@ -123,6 +124,18 @@ struct drm_bridge_connector {
* DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER).
*/
struct drm_bridge *bridge_hdmi_cec;
+ /**
+ * @bridge_luminance:
+ *
+ * The last bridge in the chain that controls panel luminance.
+ */
+ struct drm_bridge *bridge_luminance;
+ /**
+ * @panel:
+ *
+ * The panel at the end of the bridge chain, if any.
+ */
+ struct drm_panel *panel;
/**
* @hdmi_funcs:
@@ -420,6 +433,30 @@ static int drm_bridge_connector_atomic_check(struct drm_connector *connector,
return 0;
}
+static void
+drm_bridge_connector_set_luminance(const struct drm_connector_state *conn_state)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(conn_state->connector);
+
+ drm_panel_set_luminance(bridge_connector->panel, conn_state->luminance);
+ if (bridge_connector->bridge_luminance)
+ bridge_connector->bridge_luminance->funcs->set_luminance
+ (bridge_connector->bridge_luminance, conn_state->luminance);
+}
+
+static void
+drm_bridge_connector_disable_luminance(const struct drm_connector_state *conn_state)
+{
+ struct drm_bridge_connector *bridge_connector =
+ to_drm_bridge_connector(conn_state->connector);
+
+ drm_panel_disable_luminance(bridge_connector->panel);
+ if (bridge_connector->bridge_luminance)
+ bridge_connector->bridge_luminance->funcs->set_luminance
+ (bridge_connector->bridge_luminance, 0);
+}
+
static const struct drm_connector_helper_funcs drm_bridge_connector_helper_funcs = {
.get_modes = drm_bridge_connector_get_modes,
.detect_ctx = drm_bridge_connector_detect_ctx,
@@ -428,6 +465,8 @@ static const struct drm_connector_helper_funcs drm_bridge_connector_helper_funcs
.enable_hpd = drm_bridge_connector_enable_hpd,
.disable_hpd = drm_bridge_connector_disable_hpd,
.atomic_check = drm_bridge_connector_atomic_check,
+ .set_luminance = drm_bridge_connector_set_luminance,
+ .disable_luminance = drm_bridge_connector_disable_luminance,
};
static enum drm_mode_status
@@ -834,6 +873,7 @@ static void drm_bridge_connector_put_bridges(struct drm_device *dev, void *data)
drm_bridge_put(bridge_connector->bridge_hdmi_audio);
drm_bridge_put(bridge_connector->bridge_dp_audio);
drm_bridge_put(bridge_connector->bridge_hdmi_cec);
+ drm_bridge_put(bridge_connector->bridge_luminance);
}
/**
@@ -917,6 +957,13 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
drm_bridge_put(bridge_connector->bridge_detect);
bridge_connector->bridge_detect = drm_bridge_get(bridge);
}
+ if (bridge->ops & DRM_BRIDGE_OP_LUMINANCE) {
+ if (!bridge->funcs->set_luminance)
+ return ERR_PTR(-EINVAL);
+
+ drm_bridge_put(bridge_connector->bridge_luminance);
+ bridge_connector->bridge_luminance = drm_bridge_get(bridge);
+ }
if (bridge->ops & DRM_BRIDGE_OP_HDMI) {
if (bridge_connector->bridge_hdmi)
return ERR_PTR(-EBUSY);
@@ -1143,6 +1190,24 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
if (panel_bridge)
drm_panel_bridge_set_orientation(connector, panel_bridge);
+ if (panel_bridge) {
+ bridge_connector->panel = drm_panel_bridge_to_panel(panel_bridge);
+ ret = drm_panel_attach_luminance_property(bridge_connector->panel,
+ connector);
+ if (ret)
+ return ERR_PTR(ret);
+ }
+
+ if (bridge_connector->bridge_luminance && !connector->luminance_property) {
+ struct drm_bridge *bridge = bridge_connector->bridge_luminance;
+
+ ret = drm_connector_attach_luminance_property(connector, 0,
+ bridge->luminance_max,
+ bridge->luminance);
+ if (ret)
+ return ERR_PTR(ret);
+ }
+
if (support_hdcp && IS_REACHABLE(CONFIG_DRM_DISPLAY_HELPER) &&
IS_ENABLED(CONFIG_DRM_DISPLAY_HDCP_HELPER))
drm_connector_attach_content_protection_property(connector, true);
diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
index f8f6082e637fd..25355748009a4 100644
--- a/drivers/gpu/drm/drm_panel.c
+++ b/drivers/gpu/drm/drm_panel.c
@@ -341,6 +341,61 @@ void drm_panel_disable(struct drm_panel *panel)
}
EXPORT_SYMBOL(drm_panel_disable);
+/**
+ * drm_panel_attach_luminance_property - expose a panel backlight through DRM
+ * @panel: panel whose backlight is controlled
+ * @connector: connector on which to expose the property
+ *
+ * The backlight class device remains the internal hardware backend. When the
+ * luminance UAPI is enabled, userspace controls that backend through the DRM
+ * connector property instead.
+ *
+ * Return: 0 on success or a negative error code
+ */
+int drm_panel_attach_luminance_property(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct backlight_device *backlight;
+
+ if (!IS_ENABLED(CONFIG_DRM_LUMINANCE) || !panel)
+ return 0;
+
+ backlight = panel->backlight;
+ if (!backlight)
+ return 0;
+
+ return drm_connector_attach_luminance_property(connector, 0,
+ backlight->props.max_brightness,
+ backlight->props.brightness);
+}
+EXPORT_SYMBOL(drm_panel_attach_luminance_property);
+
+/**
+ * drm_panel_set_luminance - set a panel backlight's relative luminance
+ * @panel: panel whose backlight is controlled
+ * @luminance: relative luminance level
+ */
+void drm_panel_set_luminance(struct drm_panel *panel, unsigned int luminance)
+{
+ if (!panel || !panel->backlight)
+ return;
+
+ panel->backlight->props.brightness = luminance;
+ backlight_update_status(panel->backlight);
+}
+EXPORT_SYMBOL(drm_panel_set_luminance);
+
+/**
+ * drm_panel_disable_luminance - turn off a panel backlight
+ * @panel: panel whose backlight is controlled
+ */
+void drm_panel_disable_luminance(struct drm_panel *panel)
+{
+ if (panel)
+ backlight_disable(panel->backlight);
+}
+EXPORT_SYMBOL(drm_panel_disable_luminance);
+
/**
* drm_panel_get_modes - probe the available display modes of a panel
* @panel: DRM panel
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 77b3ffe692304..56511d4ded55a 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -62,6 +62,15 @@ enum drm_bridge_attach_flags {
* struct drm_bridge_funcs - drm_bridge control functions
*/
struct drm_bridge_funcs {
+ /**
+ * @set_luminance:
+ *
+ * Apply a relative luminance level to a bridge that controls panel
+ * emission. Bridges implementing this callback shall set
+ * @DRM_BRIDGE_OP_LUMINANCE.
+ */
+ void (*set_luminance)(struct drm_bridge *bridge, unsigned int luminance);
+
/**
* @attach:
*
@@ -1021,6 +1030,11 @@ enum drm_bridge_ops {
* &drm_bridge_funcs->hdmi_clear_spd_infoframe callbacks.
*/
DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME = BIT(10),
+
+ /**
+ * @DRM_BRIDGE_OP_LUMINANCE: The bridge controls panel luminance.
+ */
+ DRM_BRIDGE_OP_LUMINANCE = BIT(11),
};
/**
@@ -1071,6 +1085,12 @@ struct drm_bridge {
void *driver_private;
/** @ops: bitmask of operations supported by the bridge */
enum drm_bridge_ops ops;
+
+ /** @luminance_max: Maximum relative luminance level. */
+ unsigned int luminance_max;
+
+ /** @luminance: Current relative luminance level. */
+ unsigned int luminance;
/**
* @type: Type of the connection at the bridge output
* (DRM_MODE_CONNECTOR_*). For bridges at the end of this chain this
@@ -1530,6 +1550,7 @@ struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel,
void drm_panel_bridge_remove(struct drm_bridge *bridge);
int drm_panel_bridge_set_orientation(struct drm_connector *connector,
struct drm_bridge *bridge);
+struct drm_panel *drm_panel_bridge_to_panel(struct drm_bridge *bridge);
struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
struct drm_panel *panel);
struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
@@ -1549,6 +1570,11 @@ static inline int drm_panel_bridge_set_orientation(struct drm_connector *connect
{
return -EINVAL;
}
+
+static inline struct drm_panel *drm_panel_bridge_to_panel(struct drm_bridge *bridge)
+{
+ return NULL;
+}
#endif
#if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL_BRIDGE)
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index b87323443f49c..dfd225ba05c8d 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -333,6 +333,11 @@ void drm_panel_unprepare(struct drm_panel *panel);
void drm_panel_enable(struct drm_panel *panel);
void drm_panel_disable(struct drm_panel *panel);
+int drm_panel_attach_luminance_property(struct drm_panel *panel,
+ struct drm_connector *connector);
+void drm_panel_set_luminance(struct drm_panel *panel, unsigned int luminance);
+void drm_panel_disable_luminance(struct drm_panel *panel);
+
int drm_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector);
#if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL)
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 08/21] drm/mipi-dbi: add connector luminance helpers
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (6 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 07/21] drm: add panel and bridge connector luminance forwarding Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-03 11:03 ` Javier Martinez Canillas
2026-10-02 19:00 ` [PATCH v9 09/21] drm/tiny: migrate panel-mipi-dbi to connector luminance Mario Limonciello
` (13 subsequent siblings)
21 siblings, 1 reply; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Add common helpers for MIPI DBI drivers to attach the connector LUMINANCE
property and forward updates to their backlight backend when
CONFIG_DRM_LUMINANCE is enabled.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/drm_mipi_dbi.c | 36 ++++++++++++++++++++++++++++++++++
include/drm/drm_mipi_dbi.h | 7 ++++++-
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index 25cf04d029f77..85e3b98a7ccb0 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -496,6 +496,42 @@ int drm_mipi_dbi_connector_helper_get_modes(struct drm_connector *connector)
}
EXPORT_SYMBOL(drm_mipi_dbi_connector_helper_get_modes);
+int drm_mipi_dbi_connector_attach_luminance_property(struct drm_connector *connector)
+{
+ struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(connector->dev);
+ struct backlight_device *backlight = dbidev->backlight;
+
+ if (!IS_ENABLED(CONFIG_DRM_LUMINANCE) || !backlight)
+ return 0;
+
+ return drm_connector_attach_luminance_property(connector, 0,
+ backlight->props.max_brightness,
+ backlight->props.brightness);
+}
+EXPORT_SYMBOL(drm_mipi_dbi_connector_attach_luminance_property);
+
+void drm_mipi_dbi_connector_set_luminance(const struct drm_connector_state *conn_state)
+{
+ struct mipi_dbi_dev *dbidev =
+ drm_to_mipi_dbi_dev(conn_state->connector->dev);
+
+ if (!dbidev->backlight)
+ return;
+
+ dbidev->backlight->props.brightness = conn_state->luminance;
+ backlight_update_status(dbidev->backlight);
+}
+EXPORT_SYMBOL(drm_mipi_dbi_connector_set_luminance);
+
+void drm_mipi_dbi_connector_disable_luminance(const struct drm_connector_state *conn_state)
+{
+ struct mipi_dbi_dev *dbidev =
+ drm_to_mipi_dbi_dev(conn_state->connector->dev);
+
+ backlight_disable(dbidev->backlight);
+}
+EXPORT_SYMBOL(drm_mipi_dbi_connector_disable_luminance);
+
static int mipi_dbi_rotate_mode(struct drm_display_mode *mode,
unsigned int rotation)
{
diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h
index d93e25fdc2e1e..8462c6bd6ca9e 100644
--- a/include/drm/drm_mipi_dbi.h
+++ b/include/drm/drm_mipi_dbi.h
@@ -263,9 +263,14 @@ void drm_mipi_dbi_crtc_helper_atomic_disable(struct drm_crtc *crtc,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state
int drm_mipi_dbi_connector_helper_get_modes(struct drm_connector *connector);
+int drm_mipi_dbi_connector_attach_luminance_property(struct drm_connector *connector);
+void drm_mipi_dbi_connector_set_luminance(const struct drm_connector_state *conn_state);
+void drm_mipi_dbi_connector_disable_luminance(const struct drm_connector_state *conn_state);
#define DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS \
- .get_modes = drm_mipi_dbi_connector_helper_get_modes
+ .get_modes = drm_mipi_dbi_connector_helper_get_modes, \
+ .set_luminance = drm_mipi_dbi_connector_set_luminance, \
+ .disable_luminance = drm_mipi_dbi_connector_disable_luminance
/*
* Mode config
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 09/21] drm/tiny: migrate panel-mipi-dbi to connector luminance
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (7 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 08/21] drm/mipi-dbi: add connector luminance helpers Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-03 11:22 ` Javier Martinez Canillas
2026-10-02 19:00 ` [PATCH v9 10/21] drm/tiny: migrate HX8357D " Mario Limonciello
` (12 subsequent siblings)
21 siblings, 1 reply; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Attach the connector LUMINANCE property for MIPI DBI compatible panels
and retain the legacy backlight class interface only when DRM_LUMINANCE is
disabled.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/tiny/Kconfig | 2 +-
drivers/gpu/drm/tiny/panel-mipi-dbi.c | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
index f0e72d4b6a470..e61a429538bc0 100644
--- a/drivers/gpu/drm/tiny/Kconfig
+++ b/drivers/gpu/drm/tiny/Kconfig
@@ -73,7 +73,7 @@ config DRM_PANEL_MIPI_DBI
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_MIPI_DBI
- select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
select VIDEOMODE_HELPERS
help
Say Y here if you want to enable support for MIPI DBI compatible
diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
index 60cd65cae41d8..730f1b219fdec 100644
--- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c
+++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
@@ -485,6 +485,9 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
if (ret)
return ret;
drm_connector_helper_add(connector, &panel_mipi_dbi_connector_helper_funcs);
+ ret = drm_mipi_dbi_connector_attach_luminance_property(connector);
+ if (ret)
+ return ret;
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 10/21] drm/tiny: migrate HX8357D to connector luminance
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (8 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 09/21] drm/tiny: migrate panel-mipi-dbi to connector luminance Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 11/21] drm/tiny: migrate ILI9163 " Mario Limonciello
` (11 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Attach the connector LUMINANCE property for HX8357D displays and retain
the legacy backlight class interface only when DRM_LUMINANCE is disabled.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/tiny/Kconfig | 2 +-
drivers/gpu/drm/tiny/hx8357d.c | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
index e61a429538bc0..9914c096ba7fe 100644
--- a/drivers/gpu/drm/tiny/Kconfig
+++ b/drivers/gpu/drm/tiny/Kconfig
@@ -105,7 +105,7 @@ config TINYDRM_HX8357D
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_MIPI_DBI
- select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
help
DRM driver for the following HX8357D panels:
* YX350HV15-T 3.5" 340x350 TFT (Adafruit 3.5")
diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c
index f942a8d09ff22..c5cfee13b3e99 100644
--- a/drivers/gpu/drm/tiny/hx8357d.c
+++ b/drivers/gpu/drm/tiny/hx8357d.c
@@ -355,6 +355,9 @@ static int hx8357d_probe(struct spi_device *spi)
if (ret)
return ret;
drm_connector_helper_add(connector, &hx8357d_connector_helper_funcs);
+ ret = drm_mipi_dbi_connector_attach_luminance_property(connector);
+ if (ret)
+ return ret;
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 11/21] drm/tiny: migrate ILI9163 to connector luminance
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (9 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 10/21] drm/tiny: migrate HX8357D " Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 12/21] drm/tiny: migrate ILI9341 " Mario Limonciello
` (10 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Attach the connector LUMINANCE property for ILI9163 displays and retain
the legacy backlight class interface only when DRM_LUMINANCE is disabled.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/tiny/Kconfig | 2 +-
drivers/gpu/drm/tiny/ili9163.c | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
index 9914c096ba7fe..e553b0aaa7571 100644
--- a/drivers/gpu/drm/tiny/Kconfig
+++ b/drivers/gpu/drm/tiny/Kconfig
@@ -115,7 +115,7 @@ config TINYDRM_HX8357D
config TINYDRM_ILI9163
tristate "DRM support for ILI9163 display panels"
depends on DRM && SPI
- select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
select DRM_CLIENT_SELECTION
select DRM_GEM_DMA_HELPER
select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c
index 8842424504e3f..46c1582d7b444 100644
--- a/drivers/gpu/drm/tiny/ili9163.c
+++ b/drivers/gpu/drm/tiny/ili9163.c
@@ -286,6 +286,9 @@ static int ili9163_probe(struct spi_device *spi)
if (ret)
return ret;
drm_connector_helper_add(connector, &ili9163_connector_helper_funcs);
+ ret = drm_mipi_dbi_connector_attach_luminance_property(connector);
+ if (ret)
+ return ret;
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 12/21] drm/tiny: migrate ILI9341 to connector luminance
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (10 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 11/21] drm/tiny: migrate ILI9163 " Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 13/21] drm/tiny: migrate ILI9486 " Mario Limonciello
` (9 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Attach the connector LUMINANCE property for ILI9341 displays and retain
the legacy backlight class interface only when DRM_LUMINANCE is disabled.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/tiny/Kconfig | 2 +-
drivers/gpu/drm/tiny/ili9341.c | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
index e553b0aaa7571..85b166b659388 100644
--- a/drivers/gpu/drm/tiny/Kconfig
+++ b/drivers/gpu/drm/tiny/Kconfig
@@ -146,7 +146,7 @@ config TINYDRM_ILI9341
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_MIPI_DBI
- select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
help
DRM driver for the following Ilitek ILI9341 panels:
* YX240QV29-T 2.4" 240x320 TFT (Adafruit 2.4")
diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c
index 003381aa22ea4..3a5c8b39ec7dc 100644
--- a/drivers/gpu/drm/tiny/ili9341.c
+++ b/drivers/gpu/drm/tiny/ili9341.c
@@ -317,6 +317,9 @@ static int ili9341_probe(struct spi_device *spi)
if (ret)
return ret;
drm_connector_helper_add(connector, &ili9341_connector_helper_funcs);
+ ret = drm_mipi_dbi_connector_attach_luminance_property(connector);
+ if (ret)
+ return ret;
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 13/21] drm/tiny: migrate ILI9486 to connector luminance
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (11 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 12/21] drm/tiny: migrate ILI9341 " Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 14/21] drm/tiny: migrate MI0283QT " Mario Limonciello
` (8 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Attach the connector LUMINANCE property for ILI9486 displays and retain
the legacy backlight class interface only when DRM_LUMINANCE is disabled.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/tiny/Kconfig | 2 +-
drivers/gpu/drm/tiny/ili9486.c | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
index 85b166b659388..778e450f381e0 100644
--- a/drivers/gpu/drm/tiny/Kconfig
+++ b/drivers/gpu/drm/tiny/Kconfig
@@ -160,7 +160,7 @@ config TINYDRM_ILI9486
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_MIPI_DBI
- select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
help
DRM driver for the following Ilitek ILI9486 panels:
* PISCREEN 3.5" 320x480 TFT (Ozzmaker 3.5")
diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c
index c945a91443158..480f14bb3bfb0 100644
--- a/drivers/gpu/drm/tiny/ili9486.c
+++ b/drivers/gpu/drm/tiny/ili9486.c
@@ -345,6 +345,9 @@ static int ili9486_probe(struct spi_device *spi)
if (ret)
return ret;
drm_connector_helper_add(connector, &ili9486_connector_helper_funcs);
+ ret = drm_mipi_dbi_connector_attach_luminance_property(connector);
+ if (ret)
+ return ret;
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 14/21] drm/tiny: migrate MI0283QT to connector luminance
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (12 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 13/21] drm/tiny: migrate ILI9486 " Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 15/21] drm/sitronix: migrate ST7735R " Mario Limonciello
` (7 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Attach the connector LUMINANCE property for MI0283QT displays and retain
the legacy backlight class interface only when DRM_LUMINANCE is disabled.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/tiny/Kconfig | 2 +-
drivers/gpu/drm/tiny/mi0283qt.c | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
index 778e450f381e0..fea8beb8b8ca3 100644
--- a/drivers/gpu/drm/tiny/Kconfig
+++ b/drivers/gpu/drm/tiny/Kconfig
@@ -175,7 +175,7 @@ config TINYDRM_MI0283QT
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_MIPI_DBI
- select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
help
DRM driver for the Multi-Inno MI0283QT display panel
If M is selected the module will be called mi0283qt.
diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c
index b0121e89e2dc0..1414ae47dd079 100644
--- a/drivers/gpu/drm/tiny/mi0283qt.c
+++ b/drivers/gpu/drm/tiny/mi0283qt.c
@@ -325,6 +325,9 @@ static int mi0283qt_probe(struct spi_device *spi)
if (ret)
return ret;
drm_connector_helper_add(connector, &mi0283qt_connector_helper_funcs);
+ ret = drm_mipi_dbi_connector_attach_luminance_property(connector);
+ if (ret)
+ return ret;
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 15/21] drm/sitronix: migrate ST7735R to connector luminance
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (13 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 14/21] drm/tiny: migrate MI0283QT " Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 16/21] drm/nouveau: add connector luminance support Mario Limonciello
` (6 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Attach the connector LUMINANCE property for ST7735R displays and retain
the legacy backlight class interface only when DRM_LUMINANCE is disabled.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/sitronix/Kconfig | 2 +-
drivers/gpu/drm/sitronix/st7735r.c | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/sitronix/Kconfig b/drivers/gpu/drm/sitronix/Kconfig
index 41a428ef8295e..027fbddf4593b 100644
--- a/drivers/gpu/drm/sitronix/Kconfig
+++ b/drivers/gpu/drm/sitronix/Kconfig
@@ -59,7 +59,7 @@ config DRM_ST7735R
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select DRM_MIPI_DBI
- select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
help
DRM driver for Sitronix ST7715R/ST7735R with one of the following
LCDs:
diff --git a/drivers/gpu/drm/sitronix/st7735r.c b/drivers/gpu/drm/sitronix/st7735r.c
index bd763871dca0c..105d994c07ab6 100644
--- a/drivers/gpu/drm/sitronix/st7735r.c
+++ b/drivers/gpu/drm/sitronix/st7735r.c
@@ -330,6 +330,9 @@ static int st7735r_probe(struct spi_device *spi)
if (ret)
return ret;
drm_connector_helper_add(connector, &st7735r_connector_helper_funcs);
+ ret = drm_mipi_dbi_connector_attach_luminance_property(connector);
+ if (ret)
+ return ret;
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 16/21] drm/nouveau: add connector luminance support
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (14 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 15/21] drm/sitronix: migrate ST7735R " Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 17/21] drm/gud: " Mario Limonciello
` (5 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Expose Nouveau panel brightness through the connector LUMINANCE property
when DRM_LUMINANCE is enabled. Reuse the existing NV40, NV50, and DPCD
hardware paths while preserving the backlight class interface otherwise.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/nouveau/Kconfig | 4 +-
drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +-
drivers/gpu/drm/nouveau/nouveau_backlight.c | 110 ++++++++++++++++----
drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +
drivers/gpu/drm/nouveau/nouveau_connector.h | 14 +++
5 files changed, 108 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig
index 3b5757aed9c84..2dcb7c5344f48 100644
--- a/drivers/gpu/drm/nouveau/Kconfig
+++ b/drivers/gpu/drm/nouveau/Kconfig
@@ -17,13 +17,13 @@ config DRM_NOUVEAU
select DRM_SCHED
select I2C
select I2C_ALGOBIT
- select BACKLIGHT_CLASS_DEVICE if DRM_NOUVEAU_BACKLIGHT
+ select BACKLIGHT_CLASS_DEVICE if DRM_NOUVEAU_BACKLIGHT && !DRM_LUMINANCE
select X86_PLATFORM_DEVICES if ACPI && X86
select ACPI_WMI if ACPI && X86
select MXM_WMI if ACPI && X86
select POWER_SUPPLY
# Similar to i915, we need to select ACPI_VIDEO and it's dependencies
- select BACKLIGHT_CLASS_DEVICE if ACPI && X86
+ select BACKLIGHT_CLASS_DEVICE if ACPI && X86 && !DRM_LUMINANCE
select INPUT if ACPI && X86
select THERMAL if ACPI && X86
select ACPI_VIDEO if ACPI && X86
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index add19d479ebe4..3810083daefdc 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1839,7 +1839,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_commit *st
backlight = nv_connector->backlight;
if (backlight && backlight->uses_dpcd)
drm_edp_backlight_enable(&nv_connector->aux, &backlight->edp_info,
- backlight->dev->props.brightness);
+ backlight->brightness);
#endif
break;
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index da1ee24a2531d..fefcfa8c2a3a9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -73,12 +73,10 @@ nv40_get_intensity(struct backlight_device *bd)
}
static int
-nv40_set_intensity(struct backlight_device *bd)
+nv40_set_intensity_value(struct nouveau_encoder *nv_encoder, int val)
{
- struct nouveau_encoder *nv_encoder = bl_get_data(bd);
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
struct nvif_object *device = &drm->client.device.object;
- int val = bd->props.brightness;
int reg = nvif_rd32(device, NV40_PMC_BACKLIGHT);
nvif_wr32(device, NV40_PMC_BACKLIGHT,
@@ -87,6 +85,12 @@ nv40_set_intensity(struct backlight_device *bd)
return 0;
}
+static int
+nv40_set_intensity(struct backlight_device *bd)
+{
+ return nv40_set_intensity_value(bl_get_data(bd), bd->props.brightness);
+}
+
static const struct backlight_ops nv40_bl_ops = {
.options = BL_CORE_SUSPENDRESUME,
.get_brightness = nv40_get_intensity,
@@ -105,6 +109,8 @@ nv40_backlight_init(struct nouveau_encoder *encoder,
return -ENODEV;
props->max_brightness = 31;
+ props->brightness = (nvif_rd32(device, NV40_PMC_BACKLIGHT) &
+ NV40_PMC_BACKLIGHT_MASK) >> 16;
*ops = &nv40_bl_ops;
return 0;
}
@@ -234,12 +240,15 @@ nv50_backlight_init(struct nouveau_backlight *bl,
const struct backlight_ops **ops)
{
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
+ int brightness;
+
+ brightness = nvif_outp_bl_get(&nv_encoder->outp);
/*
* Note when this runs the connectors have not been probed yet,
* so nv_conn->base.status is not set yet.
*/
- if (nvif_outp_bl_get(&nv_encoder->outp) < 0 ||
+ if (brightness < 0 ||
drm_helper_probe_detect(&nv_conn->base, NULL, false) != connector_status_connected)
return -ENODEV;
@@ -284,6 +293,7 @@ nv50_backlight_init(struct nouveau_backlight *bl,
*ops = &nv50_bl_ops;
props->max_brightness = 100;
+ props->brightness = brightness;
return 0;
}
@@ -317,10 +327,13 @@ nouveau_backlight_init(struct drm_connector *connector)
bl = kzalloc_obj(*bl);
if (!bl)
return -ENOMEM;
+ bl->id = -1;
+ bl->encoder = nv_encoder;
switch (device->info.family) {
case NV_DEVICE_INFO_V0_CURIE:
ret = nv40_backlight_init(nv_encoder, &props, &ops);
+ bl->uses_nv40 = true;
break;
case NV_DEVICE_INFO_V0_TESLA:
case NV_DEVICE_INFO_V0_FERMI:
@@ -349,26 +362,39 @@ nouveau_backlight_init(struct drm_connector *connector)
goto fail_alloc;
}
- if (!nouveau_get_backlight_name(backlight_name, bl)) {
- NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
- goto fail_alloc;
- }
-
props.type = BACKLIGHT_RAW;
- bl->dev = backlight_device_register(backlight_name, connector->kdev,
- nv_encoder, ops, &props);
- if (IS_ERR(bl->dev)) {
- if (bl->id >= 0)
- ida_free(&bl_ida, bl->id);
- ret = PTR_ERR(bl->dev);
- goto fail_alloc;
+ bl->brightness = props.brightness;
+ bl->max_brightness = props.max_brightness;
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ ret = drm_connector_attach_luminance_property(connector, 0, props.max_brightness,
+ props.brightness);
+ if (ret)
+ goto fail_alloc;
+ } else {
+ if (!nouveau_get_backlight_name(backlight_name, bl)) {
+ NV_ERROR(drm,
+ "Failed to retrieve a unique name for the backlight interface\n");
+ goto fail_alloc;
+ }
+
+ bl->dev = backlight_device_register(backlight_name, connector->kdev,
+ nv_encoder, ops, &props);
+ if (IS_ERR(bl->dev)) {
+ if (bl->id >= 0)
+ ida_free(&bl_ida, bl->id);
+ ret = PTR_ERR(bl->dev);
+ goto fail_alloc;
+ }
}
nouveau_connector(connector)->backlight = bl;
- if (!bl->dev->props.brightness)
- bl->dev->props.brightness =
- bl->dev->ops->get_brightness(bl->dev);
- backlight_update_status(bl->dev);
+ if (bl->dev) {
+ if (!bl->dev->props.brightness)
+ bl->dev->props.brightness =
+ bl->dev->ops->get_brightness(bl->dev);
+ bl->brightness = bl->dev->props.brightness;
+ backlight_update_status(bl->dev);
+ }
return 0;
@@ -396,7 +422,9 @@ nouveau_backlight_fini(struct drm_connector *connector)
if (bl->id >= 0)
ida_free(&bl_ida, bl->id);
- backlight_device_unregister(bl->dev);
+ if (!IS_ENABLED(CONFIG_DRM_LUMINANCE))
+ backlight_device_unregister(bl->dev);
+
nv_conn->backlight = NULL;
kfree(bl);
}
@@ -412,3 +440,43 @@ nouveau_backlight_dtor(void)
{
ida_destroy(&bl_ida);
}
+
+void
+nouveau_backlight_set_luminance(const struct drm_connector_state *conn_state)
+{
+ struct nouveau_connector *nv_connector = nouveau_connector(conn_state->connector);
+ struct nouveau_backlight *bl = nv_connector->backlight;
+ unsigned int luminance = conn_state->luminance;
+
+ if (!bl || !bl->max_brightness)
+ return;
+
+ bl->brightness = luminance;
+ if (bl->uses_dpcd) {
+ drm_edp_backlight_set_level(&nv_connector->aux, &bl->edp_info,
+ luminance);
+ return;
+ }
+
+ if (bl->uses_nv40)
+ nv40_set_intensity_value(bl->encoder, luminance);
+ else
+ nvif_outp_bl_set(&bl->encoder->outp, luminance);
+}
+
+void
+nouveau_backlight_disable_luminance(const struct drm_connector_state *conn_state)
+{
+ struct nouveau_connector *nv_connector = nouveau_connector(conn_state->connector);
+ struct nouveau_backlight *bl = nv_connector->backlight;
+
+ if (!bl)
+ return;
+
+ if (bl->uses_dpcd)
+ drm_edp_backlight_disable(&nv_connector->aux, &bl->edp_info);
+ else if (bl->uses_nv40)
+ nv40_set_intensity_value(bl->encoder, 0);
+ else
+ nvif_outp_bl_set(&bl->encoder->outp, 0);
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index cc3caf8de64b0..56ee579ea7909 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1225,6 +1225,8 @@ nouveau_connector_helper_funcs = {
.mode_valid = nouveau_connector_mode_valid,
.best_encoder = nouveau_connector_best_encoder,
.atomic_check = nouveau_connector_atomic_check,
+ .set_luminance = nouveau_backlight_set_luminance,
+ .disable_luminance = nouveau_backlight_disable_luminance,
};
static const struct drm_connector_funcs
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index eb292d2ba4bcd..0cee3e4c1d11c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -50,9 +50,13 @@ struct nouveau_backlight {
struct backlight_device *dev;
struct drm_edp_backlight_info edp_info;
+ struct nouveau_encoder *encoder;
bool uses_dpcd : 1;
+ bool uses_nv40 : 1;
int id;
+ int brightness;
+ int max_brightness;
};
#endif
@@ -239,6 +243,8 @@ extern int nouveau_backlight_init(struct drm_connector *);
extern void nouveau_backlight_fini(struct drm_connector *);
extern void nouveau_backlight_ctor(void);
extern void nouveau_backlight_dtor(void);
+void nouveau_backlight_set_luminance(const struct drm_connector_state *conn_state);
+void nouveau_backlight_disable_luminance(const struct drm_connector_state *conn_state);
#else
static inline int
nouveau_backlight_init(struct drm_connector *connector)
@@ -257,6 +263,14 @@ nouveau_backlight_ctor(void) {
static inline void
nouveau_backlight_dtor(void) {
}
+
+static inline void
+nouveau_backlight_set_luminance(const struct drm_connector_state *conn_state) {
+}
+
+static inline void
+nouveau_backlight_disable_luminance(const struct drm_connector_state *conn_state) {
+}
#endif
#endif /* __NOUVEAU_CONNECTOR_H__ */
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 17/21] drm/gud: add connector luminance support
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (15 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 16/21] drm/nouveau: add connector luminance support Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 18/21] drm/radeon: " Mario Limonciello
` (4 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Expose GUD display brightness through the connector LUMINANCE property
when DRM_LUMINANCE is enabled. Keep brightness state in the connector and
retain the asynchronous USB update path.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/gud/Kconfig | 2 +-
drivers/gpu/drm/gud/gud_connector.c | 48 +++++++++++++++++++++++++++--
2 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/gud/Kconfig b/drivers/gpu/drm/gud/Kconfig
index b4d2136942f0e..6c250d3d5e203 100644
--- a/drivers/gpu/drm/gud/Kconfig
+++ b/drivers/gpu/drm/gud/Kconfig
@@ -7,7 +7,7 @@ config DRM_GUD
select DRM_CLIENT_SELECTION
select DRM_KMS_HELPER
select DRM_GEM_SHMEM_HELPER
- select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
help
This is a DRM display driver for GUD USB Displays or display
adapters.
diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c
index 8141c3a1e30ad..bd7688676e9e1 100644
--- a/drivers/gpu/drm/gud/gud_connector.c
+++ b/drivers/gpu/drm/gud/gud_connector.c
@@ -16,6 +16,7 @@
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
+
#include <drm/gud.h>
#include "gud_internal.h"
@@ -25,6 +26,7 @@ struct gud_connector {
struct drm_encoder encoder;
struct backlight_device *backlight;
struct work_struct backlight_work;
+ unsigned int brightness;
/* Supported properties */
u16 *properties;
@@ -84,7 +86,7 @@ static void gud_connector_backlight_update_status_work(struct work_struct *work)
}
/* Reuse tv.brightness to avoid having to subclass */
- connector_state->tv.brightness = gconn->backlight->props.brightness;
+ connector_state->tv.brightness = READ_ONCE(gconn->brightness);
ret = drm_atomic_commit(state);
out:
@@ -110,6 +112,8 @@ static int gud_connector_backlight_update_status(struct backlight_device *bd)
struct drm_connector *connector = bl_get_data(bd);
struct gud_connector *gconn = to_gud_connector(connector);
+ WRITE_ONCE(gconn->brightness, bd->props.brightness);
+
/* The USB timeout is 5 seconds so use system_long_wq for worst case scenario */
queue_work(system_long_wq, &gconn->backlight_work);
@@ -132,6 +136,19 @@ static int gud_connector_backlight_register(struct gud_connector *gconn)
.brightness = gconn->initial_brightness,
};
+ gconn->brightness = props.brightness;
+
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ int ret;
+
+ ret = drm_connector_attach_luminance_property(connector, 0, props.max_brightness,
+ props.brightness);
+ if (ret)
+ return ret;
+
+ return 0;
+ }
+
name = kasprintf(GFP_KERNEL, "card%d-%s-backlight",
connector->dev->primary->index, connector->name);
if (!name)
@@ -314,12 +331,37 @@ static int gud_connector_atomic_check(struct drm_connector *connector,
return 0;
}
+static void gud_connector_set_luminance(const struct drm_connector_state *conn_state);
+static void gud_connector_disable_luminance(const struct drm_connector_state *conn_state);
+
static const struct drm_connector_helper_funcs gud_connector_helper_funcs = {
.detect_ctx = gud_connector_detect,
.get_modes = gud_connector_get_modes,
.atomic_check = gud_connector_atomic_check,
+ .set_luminance = gud_connector_set_luminance,
+ .disable_luminance = gud_connector_disable_luminance,
};
+static void gud_connector_set_luminance(const struct drm_connector_state *conn_state)
+{
+ struct drm_connector *connector = conn_state->connector;
+ struct gud_connector *gconn = to_gud_connector(connector);
+ unsigned int luminance = conn_state->luminance;
+
+ WRITE_ONCE(gconn->brightness, luminance);
+
+ /* The workqueue will apply it to the hardware */
+ queue_work(system_long_wq, &gconn->backlight_work);
+}
+
+static void gud_connector_disable_luminance(const struct drm_connector_state *conn_state)
+{
+ struct gud_connector *gconn = to_gud_connector(conn_state->connector);
+
+ WRITE_ONCE(gconn->brightness, 0);
+ queue_work(system_long_wq, &gconn->backlight_work);
+}
+
static int gud_connector_late_register(struct drm_connector *connector)
{
struct gud_connector *gconn = to_gud_connector(connector);
@@ -334,7 +376,9 @@ static void gud_connector_early_unregister(struct drm_connector *connector)
{
struct gud_connector *gconn = to_gud_connector(connector);
- backlight_device_unregister(gconn->backlight);
+ if (gconn->backlight)
+ backlight_device_unregister(gconn->backlight);
+
cancel_work_sync(&gconn->backlight_work);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 18/21] drm/radeon: add connector luminance support
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (16 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 17/21] drm/gud: " Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 19/21] drm/gma500: " Mario Limonciello
` (3 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Expose Radeon panel brightness through the connector LUMINANCE property
when DRM_LUMINANCE is enabled. Reuse the AtomBIOS and legacy hardware
programming paths and preserve the backlight class interface otherwise.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/radeon/Kconfig | 2 +-
drivers/gpu/drm/radeon/atombios_encoders.c | 32 ++++++++++--
drivers/gpu/drm/radeon/radeon_connectors.c | 34 +++++++++++++
.../gpu/drm/radeon/radeon_legacy_encoders.c | 49 +++++++++++++++----
drivers/gpu/drm/radeon/radeon_mode.h | 2 +
5 files changed, 106 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig
index c479f0c0dd5c4..cfb0679066a12 100644
--- a/drivers/gpu/drm/radeon/Kconfig
+++ b/drivers/gpu/drm/radeon/Kconfig
@@ -17,7 +17,7 @@ config DRM_RADEON
select SND_HDA_COMPONENT if SND_HDA_CORE
select POWER_SUPPLY
select HWMON
- select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
select INTERVAL_TREE
select I2C
select I2C_ALGOBIT
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 5b9c72bf40994..e6f762625bf1a 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -227,6 +227,27 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
memset(&props, 0, sizeof(props));
props.max_brightness = RADEON_MAX_BL_LEVEL;
props.type = BACKLIGHT_RAW;
+ pdata->encoder = radeon_encoder;
+ pdata->atom = true;
+ radeon_encoder->backlight_priv = pdata;
+
+ dig = radeon_encoder->enc_priv;
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ props.brightness = atombios_get_backlight_level(radeon_encoder);
+ if (!props.brightness)
+ props.brightness = RADEON_MAX_BL_LEVEL;
+
+ if (drm_connector_attach_luminance_property(drm_connector, 0,
+ props.max_brightness,
+ props.brightness))
+ goto error;
+
+ atombios_set_backlight_level(radeon_encoder, props.brightness);
+ dig->bl_dev = NULL;
+ rdev->mode_info.bl_encoder = radeon_encoder;
+ return;
+ }
+
snprintf(bl_name, sizeof(bl_name),
"radeon_bl%d", dev->primary->index);
bd = backlight_device_register(bl_name, drm_connector->kdev,
@@ -236,9 +257,6 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
goto error;
}
- pdata->encoder = radeon_encoder;
-
- dig = radeon_encoder->enc_priv;
dig->bl_dev = bd;
bd->props.brightness = radeon_atom_backlight_get_brightness(bd);
@@ -258,6 +276,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
return;
error:
+ radeon_encoder->backlight_priv = NULL;
kfree(pdata);
return;
}
@@ -282,12 +301,19 @@ static void radeon_atom_backlight_exit(struct radeon_encoder *radeon_encoder)
bd = dig->bl_dev;
dig->bl_dev = NULL;
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ kfree(radeon_encoder->backlight_priv);
+ radeon_encoder->backlight_priv = NULL;
+ return;
+ }
+
if (bd) {
struct radeon_legacy_backlight_privdata *pdata;
pdata = bl_get_data(bd);
backlight_device_unregister(bd);
kfree(pdata);
+ radeon_encoder->backlight_priv = NULL;
DRM_INFO("radeon atom LVDS backlight unloaded\n");
}
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 16b048f58c9be..655361407b819 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -31,6 +31,7 @@
#include <drm/drm_probe_helper.h>
#include <drm/radeon_drm.h>
#include "radeon.h"
+#include "radeon_asic.h"
#include "radeon_audio.h"
#include "atom.h"
@@ -931,11 +932,44 @@ static int radeon_lvds_set_property(struct drm_connector *connector,
return 0;
}
+static void radeon_set_luminance(const struct drm_connector_state *conn_state)
+{
+ struct drm_encoder *encoder = radeon_best_single_encoder(conn_state->connector);
+ struct radeon_encoder *radeon_encoder;
+ struct radeon_backlight_privdata *pdata;
+ u8 level = conn_state->luminance;
+
+ if (!encoder)
+ return;
+
+ radeon_encoder = to_radeon_encoder(encoder);
+ pdata = radeon_encoder->backlight_priv;
+ if (!pdata)
+ return;
+
+ if (pdata->atom) {
+ atombios_set_backlight_level(radeon_encoder, level);
+ } else {
+ if (pdata->negative)
+ level = RADEON_MAX_BL_LEVEL - level;
+ radeon_legacy_set_backlight_level(radeon_encoder, level);
+ }
+}
+
+static void radeon_disable_luminance(const struct drm_connector_state *conn_state)
+{
+ struct drm_connector_state state = *conn_state;
+
+ state.luminance = 0;
+ radeon_set_luminance(&state);
+}
static const struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = {
.get_modes = radeon_lvds_get_modes,
.mode_valid = radeon_lvds_mode_valid,
.best_encoder = radeon_best_single_encoder,
+ .set_luminance = radeon_set_luminance,
+ .disable_luminance = radeon_disable_luminance,
};
static const struct drm_connector_funcs radeon_lvds_connector_funcs = {
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 1f82e2b57f5d5..96b0dfd8e3521 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -403,16 +403,9 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
memset(&props, 0, sizeof(props));
props.max_brightness = RADEON_MAX_BL_LEVEL;
props.type = BACKLIGHT_RAW;
- snprintf(bl_name, sizeof(bl_name),
- "radeon_bl%d", dev->primary->index);
- bd = backlight_device_register(bl_name, drm_connector->kdev,
- pdata, &radeon_backlight_ops, &props);
- if (IS_ERR(bd)) {
- DRM_ERROR("Backlight registration failed\n");
- goto error;
- }
-
pdata->encoder = radeon_encoder;
+ pdata->atom = false;
+ radeon_encoder->backlight_priv = pdata;
backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
@@ -441,6 +434,36 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
#endif
}
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ props.brightness = pdata->negative ?
+ RADEON_MAX_BL_LEVEL - backlight_level : backlight_level;
+ if (drm_connector_attach_luminance_property(drm_connector, 0,
+ props.max_brightness,
+ props.brightness))
+ goto error;
+
+ if (rdev->is_atom_bios) {
+ struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+
+ lvds->bl_dev = NULL;
+ } else {
+ struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+
+ lvds->bl_dev = NULL;
+ }
+ rdev->mode_info.bl_encoder = radeon_encoder;
+ return;
+ }
+
+ snprintf(bl_name, sizeof(bl_name),
+ "radeon_bl%d", dev->primary->index);
+ bd = backlight_device_register(bl_name, drm_connector->kdev,
+ pdata, &radeon_backlight_ops, &props);
+ if (IS_ERR(bd)) {
+ DRM_ERROR("Backlight registration failed\n");
+ goto error;
+ }
+
if (rdev->is_atom_bios) {
struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
lvds->bl_dev = bd;
@@ -459,6 +482,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
return;
error:
+ radeon_encoder->backlight_priv = NULL;
kfree(pdata);
return;
}
@@ -482,12 +506,19 @@ static void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder)
lvds->bl_dev = NULL;
}
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ kfree(radeon_encoder->backlight_priv);
+ radeon_encoder->backlight_priv = NULL;
+ return;
+ }
+
if (bd) {
struct radeon_backlight_privdata *pdata;
pdata = bl_get_data(bd);
backlight_device_unregister(bd);
kfree(pdata);
+ radeon_encoder->backlight_priv = NULL;
DRM_INFO("radeon legacy LVDS backlight unloaded\n");
}
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 031a3bf6fe0a4..c4e09e0dacba0 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -283,6 +283,7 @@ struct radeon_mode_info {
struct radeon_backlight_privdata {
struct radeon_encoder *encoder;
uint8_t negative;
+ bool atom;
};
#define MAX_H_CODE_TIMING_LEN 32
@@ -455,6 +456,7 @@ struct radeon_encoder {
uint32_t underscan_vborder;
struct drm_display_mode native_mode;
void *enc_priv;
+ struct radeon_backlight_privdata *backlight_priv;
int audio_polling_active;
bool is_ext_encoder;
u16 caps;
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 19/21] drm/gma500: add connector luminance support
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (17 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 18/21] drm/radeon: " Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 20/21] drm/bridge: add PS8622 " Mario Limonciello
` (2 subsequent siblings)
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Expose GMA500 panel brightness through the connector LUMINANCE property
when DRM_LUMINANCE is enabled. Route updates through the existing platform
backlight operations and preserve legacy registration otherwise.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/gma500/Kconfig | 2 +-
drivers/gpu/drm/gma500/backlight.c | 45 ++++++++++++++++---------
drivers/gpu/drm/gma500/cdv_intel_lvds.c | 2 ++
drivers/gpu/drm/gma500/psb_drv.c | 2 +-
drivers/gpu/drm/gma500/psb_drv.h | 4 ++-
drivers/gpu/drm/gma500/psb_intel_lvds.c | 3 +-
6 files changed, 38 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig
index a2acaa699dd58..72b14a7d07d5c 100644
--- a/drivers/gpu/drm/gma500/Kconfig
+++ b/drivers/gpu/drm/gma500/Kconfig
@@ -9,7 +9,7 @@ config DRM_GMA500
select I2C_ALGOBIT
# GMA500 depends on ACPI_VIDEO when ACPI is enabled, just like i915
select ACPI_VIDEO if ACPI
- select BACKLIGHT_CLASS_DEVICE if ACPI
+ select BACKLIGHT_CLASS_DEVICE if ACPI && !DRM_LUMINANCE
select INPUT if ACPI
select X86_PLATFORM_DEVICES if ACPI
select ACPI_WMI if ACPI
diff --git a/drivers/gpu/drm/gma500/backlight.c b/drivers/gpu/drm/gma500/backlight.c
index c8f1716a12d52..4bb39fba04539 100644
--- a/drivers/gpu/drm/gma500/backlight.c
+++ b/drivers/gpu/drm/gma500/backlight.c
@@ -8,7 +8,6 @@
*/
#include <linux/backlight.h>
-
#include <acpi/video.h>
#include <drm/drm_print.h>
@@ -73,10 +72,9 @@ static const struct backlight_ops gma_backlight_ops __maybe_unused = {
.update_status = gma_backlight_update_status,
};
-int gma_backlight_init(struct drm_device *dev)
+int gma_backlight_init(struct drm_device *dev, struct drm_connector *connector)
{
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
- struct backlight_properties props __maybe_unused = {};
int ret;
dev_priv->backlight_enabled = true;
@@ -92,28 +90,43 @@ int gma_backlight_init(struct drm_device *dev)
return 0;
}
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- props.brightness = dev_priv->backlight_level;
- props.max_brightness = PSB_MAX_BRIGHTNESS;
- props.type = BACKLIGHT_RAW;
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE))
+ return drm_connector_attach_luminance_property(connector, 0,
+ PSB_MAX_BRIGHTNESS,
+ dev_priv->backlight_level);
+
+ {
+ struct backlight_properties props = {};
- dev_priv->backlight_device =
- backlight_device_register(dev_priv->ops->backlight_name,
- dev->dev, dev,
- &gma_backlight_ops, &props);
- if (IS_ERR(dev_priv->backlight_device))
- return PTR_ERR(dev_priv->backlight_device);
-#endif
+ props.brightness = dev_priv->backlight_level;
+ props.max_brightness = PSB_MAX_BRIGHTNESS;
+ props.type = BACKLIGHT_RAW;
+
+ dev_priv->backlight_device =
+ backlight_device_register(dev_priv->ops->backlight_name,
+ dev->dev, dev,
+ &gma_backlight_ops, &props);
+ if (IS_ERR(dev_priv->backlight_device))
+ return PTR_ERR(dev_priv->backlight_device);
+ }
return 0;
}
+void gma_connector_set_luminance(const struct drm_connector_state *conn_state)
+{
+ gma_backlight_set(conn_state->connector->dev, conn_state->luminance);
+}
+
+void gma_connector_disable_luminance(const struct drm_connector_state *conn_state)
+{
+ gma_backlight_disable(conn_state->connector->dev);
+}
+
void gma_backlight_exit(struct drm_device *dev)
{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
if (dev_priv->backlight_device)
backlight_device_unregister(dev_priv->backlight_device);
-#endif
}
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index 336ab411d6995..cef97f1532358 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -412,6 +412,8 @@ static const struct drm_connector_helper_funcs
.get_modes = cdv_intel_lvds_get_modes,
.mode_valid = cdv_intel_lvds_mode_valid,
.best_encoder = gma_best_encoder,
+ .set_luminance = gma_connector_set_luminance,
+ .disable_luminance = gma_connector_disable_luminance,
};
static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index d17cb5b4a4bf2..5de7af651ac39 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -396,7 +396,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags)
if (gma_encoder->type == INTEL_OUTPUT_LVDS ||
gma_encoder->type == INTEL_OUTPUT_MIPI) {
- ret = gma_backlight_init(dev);
+ ret = gma_backlight_init(dev, connector);
if (ret == 0)
acpi_video_register_backlight();
break;
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index db197b865b90a..4fc22c66e6c8f 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -604,11 +604,13 @@ int psb_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
#endif
/* backlight.c */
-int gma_backlight_init(struct drm_device *dev);
+int gma_backlight_init(struct drm_device *dev, struct drm_connector *connector);
void gma_backlight_exit(struct drm_device *dev);
void gma_backlight_disable(struct drm_device *dev);
void gma_backlight_enable(struct drm_device *dev);
void gma_backlight_set(struct drm_device *dev, int v);
+void gma_connector_set_luminance(const struct drm_connector_state *conn_state);
+void gma_connector_disable_luminance(const struct drm_connector_state *conn_state);
/* oaktrail_crtc.c */
extern const struct drm_crtc_helper_funcs oaktrail_helper_funcs;
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index cd882786d9461..fa0bc8492ff7f 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -610,6 +610,8 @@ const struct drm_connector_helper_funcs
.get_modes = psb_intel_lvds_get_modes,
.mode_valid = psb_intel_lvds_mode_valid,
.best_encoder = gma_best_encoder,
+ .set_luminance = gma_connector_set_luminance,
+ .disable_luminance = gma_connector_disable_luminance,
};
const struct drm_connector_funcs psb_intel_lvds_connector_funcs = {
@@ -808,4 +810,3 @@ void psb_intel_lvds_init(struct drm_device *dev,
err_free_encoder:
kfree(gma_encoder);
}
-
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 20/21] drm/bridge: add PS8622 connector luminance support
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (18 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 19/21] drm/gma500: " Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 21/21] drm/solomon: add SSD130x " Mario Limonciello
2026-10-02 19:55 ` ✗ Fi.CI.BUILD: failure for Add support for a DRM backlight capability (rev4) Patchwork
21 siblings, 0 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Expose PS8622 brightness through bridge luminance operations when
DRM_LUMINANCE is enabled. Keep registering the backlight class device
otherwise.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/bridge/Kconfig | 2 +-
drivers/gpu/drm/bridge/parade-ps8622.c | 45 +++++++++++++++++++-------
2 files changed, 34 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 837db36cdf48e..d78eb9f117d1e 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -278,7 +278,7 @@ config DRM_PARADE_PS8622
depends on OF
select DRM_PANEL
select DRM_KMS_HELPER
- select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
help
Parade eDP-LVDS bridge chip driver.
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index 3a2ec482037df..229d9d7218c4e 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -45,6 +45,7 @@ struct ps8622_bridge {
struct drm_bridge *panel_bridge;
struct regulator *v12;
struct backlight_device *bl;
+ u8 brightness;
struct gpio_desc *gpio_slp;
struct gpio_desc *gpio_rst;
@@ -276,7 +277,7 @@ static int ps8622_send_config(struct ps8622_bridge *ps8622)
/* FFh for 100% brightness, 0h for 0% brightness */
err = ps8622_set(cl, 0x01, 0xa7,
- ps8622->bl->props.brightness);
+ ps8622->brightness);
if (err)
goto error;
} else {
@@ -324,6 +325,8 @@ static int ps8622_backlight_update(struct backlight_device *bl)
struct ps8622_bridge *ps8622 = dev_get_drvdata(&bl->dev);
int ret, brightness = backlight_get_brightness(bl);
+ ps8622->brightness = brightness;
+
if (!ps8622->enabled)
return -EINVAL;
@@ -332,6 +335,15 @@ static int ps8622_backlight_update(struct backlight_device *bl)
return ret;
}
+static void ps8622_set_luminance(struct drm_bridge *bridge,
+ unsigned int luminance)
+{
+ struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge);
+
+ ps8622->brightness = luminance;
+ ps8622_set(ps8622->client, 0x01, 0xa7, luminance);
+}
+
static const struct backlight_ops ps8622_backlight_ops = {
.update_status = ps8622_backlight_update,
};
@@ -438,6 +450,7 @@ static const struct drm_bridge_funcs ps8622_bridge_funcs = {
.atomic_disable = ps8622_disable,
.atomic_post_disable = ps8622_post_disable,
.attach = ps8622_attach,
+ .set_luminance = ps8622_set_luminance,
};
static const struct of_device_id ps8622_devices[] = {
@@ -502,18 +515,25 @@ static int ps8622_probe(struct i2c_client *client)
ps8622->lane_count = ps8622->max_lane_count;
}
+ ps8622->brightness = PS8622_MAX_BRIGHTNESS;
if (!of_property_read_bool(dev->of_node, "use-external-pwm")) {
- ps8622->bl = backlight_device_register("ps8622-backlight",
- dev, ps8622, &ps8622_backlight_ops,
- NULL);
- if (IS_ERR(ps8622->bl)) {
- DRM_ERROR("failed to register backlight\n");
- ret = PTR_ERR(ps8622->bl);
- ps8622->bl = NULL;
- return ret;
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ ps8622->bridge.ops |= DRM_BRIDGE_OP_LUMINANCE;
+ ps8622->bridge.luminance_max = PS8622_MAX_BRIGHTNESS;
+ ps8622->bridge.luminance = ps8622->brightness;
+ } else {
+ ps8622->bl = backlight_device_register("ps8622-backlight",
+ dev, ps8622,
+ &ps8622_backlight_ops, NULL);
+ if (IS_ERR(ps8622->bl)) {
+ DRM_ERROR("failed to register backlight\n");
+ ret = PTR_ERR(ps8622->bl);
+ ps8622->bl = NULL;
+ return ret;
+ }
+ ps8622->bl->props.max_brightness = PS8622_MAX_BRIGHTNESS;
+ ps8622->bl->props.brightness = ps8622->brightness;
}
- ps8622->bl->props.max_brightness = PS8622_MAX_BRIGHTNESS;
- ps8622->bl->props.brightness = PS8622_MAX_BRIGHTNESS;
}
ps8622->bridge.type = DRM_MODE_CONNECTOR_LVDS;
@@ -529,7 +549,8 @@ static void ps8622_remove(struct i2c_client *client)
{
struct ps8622_bridge *ps8622 = i2c_get_clientdata(client);
- backlight_device_unregister(ps8622->bl);
+ if (ps8622->bl)
+ backlight_device_unregister(ps8622->bl);
drm_bridge_remove(&ps8622->bridge);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v9 21/21] drm/solomon: add SSD130x connector luminance support
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (19 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 20/21] drm/bridge: add PS8622 " Mario Limonciello
@ 2026-10-02 19:00 ` Mario Limonciello
2026-10-03 10:30 ` Javier Martinez Canillas
2026-10-03 10:39 ` Javier Martinez Canillas
2026-10-02 19:55 ` ✗ Fi.CI.BUILD: failure for Add support for a DRM backlight capability (rev4) Patchwork
21 siblings, 2 replies; 29+ messages in thread
From: Mario Limonciello @ 2026-10-02 19:00 UTC (permalink / raw)
To: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Expose SSD130x contrast through the connector LUMINANCE property when
DRM_LUMINANCE is enabled. Program contrast directly and retain the
backlight class interface otherwise.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/gpu/drm/solomon/Kconfig | 2 +-
drivers/gpu/drm/solomon/ssd130x.c | 79 +++++++++++++++++++++++--------
2 files changed, 61 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/solomon/Kconfig b/drivers/gpu/drm/solomon/Kconfig
index 400a6cab3a671..f0d52bc71cdfc 100644
--- a/drivers/gpu/drm/solomon/Kconfig
+++ b/drivers/gpu/drm/solomon/Kconfig
@@ -1,7 +1,7 @@
config DRM_SSD130X
tristate "DRM support for Solomon SSD13xx OLED displays"
depends on DRM && MMU
- select BACKLIGHT_CLASS_DEVICE
+ select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
select DRM_CLIENT_SELECTION
select DRM_GEM_SHMEM_HELPER
select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
index 324467ae9309f..8aec74ecdcb6d 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -1831,7 +1831,8 @@ static void ssd130x_encoder_atomic_enable(struct drm_encoder *encoder,
ssd130x_write_cmd(ssd130x, 1, SSD13XX_DISPLAY_ON);
- backlight_enable(ssd130x->bl_dev);
+ if (ssd130x->bl_dev)
+ backlight_enable(ssd130x->bl_dev);
return;
@@ -1857,7 +1858,8 @@ static void ssd132x_encoder_atomic_enable(struct drm_encoder *encoder,
ssd130x_write_cmd(ssd130x, 1, SSD13XX_DISPLAY_ON);
- backlight_enable(ssd130x->bl_dev);
+ if (ssd130x->bl_dev)
+ backlight_enable(ssd130x->bl_dev);
return;
@@ -1882,7 +1884,8 @@ static void ssd133x_encoder_atomic_enable(struct drm_encoder *encoder,
ssd130x_write_cmd(ssd130x, 1, SSD13XX_DISPLAY_ON);
- backlight_enable(ssd130x->bl_dev);
+ if (ssd130x->bl_dev)
+ backlight_enable(ssd130x->bl_dev);
return;
@@ -1907,7 +1910,8 @@ static void ssd135x_encoder_atomic_enable(struct drm_encoder *encoder,
ssd130x_write_cmd(ssd130x, 1, SSD13XX_DISPLAY_ON);
- backlight_enable(ssd130x->bl_dev);
+ if (ssd130x->bl_dev)
+ backlight_enable(ssd130x->bl_dev);
return;
@@ -1921,7 +1925,8 @@ static void ssd130x_encoder_atomic_disable(struct drm_encoder *encoder,
struct drm_device *drm = encoder->dev;
struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
- backlight_disable(ssd130x->bl_dev);
+ if (ssd130x->bl_dev)
+ backlight_disable(ssd130x->bl_dev);
ssd130x_write_cmd(ssd130x, 1, SSD13XX_DISPLAY_OFF);
@@ -1958,8 +1963,44 @@ static int ssd130x_connector_get_modes(struct drm_connector *connector)
return drm_connector_helper_get_modes_fixed(connector, &ssd130x->mode);
}
+static int ssd130x_set_luminance_value(struct ssd130x_device *ssd130x,
+ unsigned int luminance)
+{
+ int ret;
+
+ ssd130x->contrast = luminance;
+
+ switch (ssd130x->device_info->family_id) {
+ case SSD133X_FAMILY:
+ return ssd133x_set_contrast(ssd130x, luminance);
+ case SSD135X_FAMILY:
+ return ssd135x_set_contrast(ssd130x, luminance);
+ default:
+ ret = ssd130x_write_cmd(ssd130x, 1, SSD13XX_CONTRAST);
+ if (ret < 0)
+ return ret;
+ return ssd130x_write_cmd(ssd130x, 1, luminance);
+ }
+}
+
+static void ssd130x_connector_set_luminance(const struct drm_connector_state *conn_state)
+{
+ struct ssd130x_device *ssd130x = drm_to_ssd130x(conn_state->connector->dev);
+
+ ssd130x_set_luminance_value(ssd130x, conn_state->luminance);
+}
+
+static void ssd130x_connector_disable_luminance(const struct drm_connector_state *conn_state)
+{
+ struct ssd130x_device *ssd130x = drm_to_ssd130x(conn_state->connector->dev);
+
+ ssd130x_set_luminance_value(ssd130x, 0);
+}
+
static const struct drm_connector_helper_funcs ssd130x_connector_helper_funcs = {
.get_modes = ssd130x_connector_get_modes,
+ .set_luminance = ssd130x_connector_set_luminance,
+ .disable_luminance = ssd130x_connector_disable_luminance,
};
static const struct drm_connector_funcs ssd130x_connector_funcs = {
@@ -1996,20 +2037,9 @@ static const struct drm_driver ssd130x_drm_driver = {
static int ssd130x_update_bl(struct backlight_device *bdev)
{
struct ssd130x_device *ssd130x = bl_get_data(bdev);
- int brightness = backlight_get_brightness(bdev);
- int ret;
-
- ssd130x->contrast = brightness;
-
- ret = ssd130x_write_cmd(ssd130x, 1, SSD13XX_CONTRAST);
- if (ret < 0)
- return ret;
- ret = ssd130x_write_cmd(ssd130x, 1, ssd130x->contrast);
- if (ret < 0)
- return ret;
-
- return 0;
+ return ssd130x_set_luminance_value(ssd130x,
+ backlight_get_brightness(bdev));
}
static int ssd133x_update_bl(struct backlight_device *bdev)
@@ -2030,7 +2060,7 @@ static int ssd135x_update_bl(struct backlight_device *bdev)
return ssd135x_set_contrast(ssd130x, ssd130x->contrast);
}
-static const struct backlight_ops ssd130xfb_bl_ops[] = {
+static const struct backlight_ops ssd130xfb_bl_ops[] __maybe_unused = {
[SSD130X_FAMILY] = {
.update_status = ssd130x_update_bl,
},
@@ -2191,6 +2221,13 @@ static int ssd130x_init_modeset(struct ssd130x_device *ssd130x)
}
drm_connector_helper_add(connector, &ssd130x_connector_helper_funcs);
+ if (IS_ENABLED(CONFIG_DRM_LUMINANCE)) {
+ ret = drm_connector_attach_luminance_property(connector, 0,
+ MAX_CONTRAST,
+ ssd130x->contrast);
+ if (ret)
+ return ret;
+ }
ret = drm_connector_attach_encoder(connector, encoder);
if (ret) {
@@ -2223,7 +2260,9 @@ static int ssd130x_get_resources(struct ssd130x_device *ssd130x)
struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
{
struct ssd130x_device *ssd130x;
+#ifndef CONFIG_DRM_LUMINANCE
struct backlight_device *bl;
+#endif
struct drm_device *drm;
int ret;
@@ -2248,6 +2287,7 @@ struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
if (ret)
return ERR_PTR(ret);
+#ifndef CONFIG_DRM_LUMINANCE
bl = devm_backlight_device_register(dev, dev_name(dev), dev, ssd130x,
&ssd130xfb_bl_ops[ssd130x->device_info->family_id],
NULL);
@@ -2258,6 +2298,7 @@ struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
bl->props.brightness = ssd130x->contrast;
bl->props.max_brightness = MAX_CONTRAST;
ssd130x->bl_dev = bl;
+#endif
ret = ssd130x_init_modeset(ssd130x);
if (ret)
--
2.43.0
^ permalink raw reply related [flat|nested] 29+ messages in thread
* ✗ Fi.CI.BUILD: failure for Add support for a DRM backlight capability (rev4)
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
` (20 preceding siblings ...)
2026-10-02 19:00 ` [PATCH v9 21/21] drm/solomon: add SSD130x " Mario Limonciello
@ 2026-10-02 19:55 ` Patchwork
21 siblings, 0 replies; 29+ messages in thread
From: Patchwork @ 2026-10-02 19:55 UTC (permalink / raw)
To: Mario Limonciello; +Cc: intel-gfx
== Series Details ==
Series: Add support for a DRM backlight capability (rev4)
URL : https://patchwork.freedesktop.org/series/169109/
State : failure
== Summary ==
Error: patch https://patchwork.freedesktop.org/api/1.0/series/169109/revisions/4/mbox/ not applied
Applying: drm: add connector LUMINANCE property
Applying: drm/amd/display: Pass up errors reading actual brightness
Applying: drm/amd: add luminance property support
Using index info to reconstruct a base tree...
M drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
M drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
M drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
Falling back to patching base and 3-way merge...
Auto-merging drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
Auto-merging drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
Auto-merging drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
Applying: drm/amdgpu: Check bios_scratch_reg_offset in backlight level helper
Applying: drm/amd/display: update KUnit luminance fixtures
Applying: drm/i915/display: add luminance property support
Applying: drm: add panel and bridge connector luminance forwarding
Using index info to reconstruct a base tree...
A drivers/gpu/drm/bridge/panel.c
M drivers/gpu/drm/display/drm_bridge_connector.c
M drivers/gpu/drm/drm_panel.c
M include/drm/drm_bridge.h
M include/drm/drm_panel.h
Falling back to patching base and 3-way merge...
Auto-merging include/drm/drm_panel.h
Auto-merging include/drm/drm_bridge.h
CONFLICT (content): Merge conflict in include/drm/drm_bridge.h
Auto-merging drivers/gpu/drm/drm_panel.c
Auto-merging drivers/gpu/drm/display/drm_bridge_connector.c
CONFLICT (modify/delete): drivers/gpu/drm/bridge/panel.c deleted in HEAD and modified in drm: add panel and bridge connector luminance forwarding. Version drm: add panel and bridge connector luminance forwarding of drivers/gpu/drm/bridge/panel.c left in tree.
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0007 drm: add panel and bridge connector luminance forwarding
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Build failed, no error log produced
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 21/21] drm/solomon: add SSD130x connector luminance support
2026-10-02 19:00 ` [PATCH v9 21/21] drm/solomon: add SSD130x " Mario Limonciello
@ 2026-10-03 10:30 ` Javier Martinez Canillas
2026-10-03 10:39 ` Javier Martinez Canillas
1 sibling, 0 replies; 29+ messages in thread
From: Javier Martinez Canillas @ 2026-10-03 10:30 UTC (permalink / raw)
To: Mario Limonciello, dri-devel, harry.wentland, Simona Vetter,
Alex Deucher, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Mario Limonciello <mario.limonciello@amd.com> writes:
Hello Mario,
> Expose SSD130x contrast through the connector LUMINANCE property when
> DRM_LUMINANCE is enabled. Program contrast directly and retain the
> backlight class interface otherwise.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
[...]
> struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
> {
> struct ssd130x_device *ssd130x;
> +#ifndef CONFIG_DRM_LUMINANCE
> struct backlight_device *bl;
> +#endif
[...]
> +#ifndef CONFIG_DRM_LUMINANCE
> bl = devm_backlight_device_register(dev, dev_name(dev), dev, ssd130x,
> &ssd130xfb_bl_ops[ssd130x->device_info->family_id],
> NULL);
> @@ -2258,6 +2298,7 @@ struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
> bl->props.brightness = ssd130x->contrast;
> bl->props.max_brightness = MAX_CONTRAST;
> ssd130x->bl_dev = bl;
> +#endif
I think that IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) makes more sense?
Other than that, the patch looks good to me.
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
--
Best regards,
Javier Martinez Canillas
Core Platforms
Red Hat
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 21/21] drm/solomon: add SSD130x connector luminance support
2026-10-02 19:00 ` [PATCH v9 21/21] drm/solomon: add SSD130x " Mario Limonciello
2026-10-03 10:30 ` Javier Martinez Canillas
@ 2026-10-03 10:39 ` Javier Martinez Canillas
1 sibling, 0 replies; 29+ messages in thread
From: Javier Martinez Canillas @ 2026-10-03 10:39 UTC (permalink / raw)
To: Mario Limonciello, dri-devel, harry.wentland, Simona Vetter,
Alex Deucher, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Mario Limonciello <mario.limonciello@amd.com> writes:
> Expose SSD130x contrast through the connector LUMINANCE property when
> DRM_LUMINANCE is enabled. Program contrast directly and retain the
> backlight class interface otherwise.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
Actually, one more comment:
>
> -static const struct backlight_ops ssd130xfb_bl_ops[] = {
> +static const struct backlight_ops ssd130xfb_bl_ops[] __maybe_unused = {
> [SSD130X_FAMILY] = {
> .update_status = ssd130x_update_bl,
> },
I think that instead of __maybe_unused, this definition could also
be guarded by IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE).
--
Best regards,
Javier Martinez Canillas
Core Platforms
Red Hat
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 08/21] drm/mipi-dbi: add connector luminance helpers
2026-10-02 19:00 ` [PATCH v9 08/21] drm/mipi-dbi: add connector luminance helpers Mario Limonciello
@ 2026-10-03 11:03 ` Javier Martinez Canillas
0 siblings, 0 replies; 29+ messages in thread
From: Javier Martinez Canillas @ 2026-10-03 11:03 UTC (permalink / raw)
To: Mario Limonciello, dri-devel, harry.wentland, Simona Vetter,
Alex Deucher, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Mario Limonciello <mario.limonciello@amd.com> writes:
> Add common helpers for MIPI DBI drivers to attach the connector LUMINANCE
> property and forward updates to their backlight backend when
> CONFIG_DRM_LUMINANCE is enabled.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
[...]
> +int drm_mipi_dbi_connector_attach_luminance_property(struct drm_connector *connector)
> +{
> + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(connector->dev);
> + struct backlight_device *backlight = dbidev->backlight;
> +
> + if (!IS_ENABLED(CONFIG_DRM_LUMINANCE) || !backlight)
> + return 0;
> +
> + return drm_connector_attach_luminance_property(connector, 0,
> + backlight->props.max_brightness,
> + backlight->props.brightness);
> +}
> +EXPORT_SYMBOL(drm_mipi_dbi_connector_attach_luminance_property);
> +
Drivers that call drm_connector_attach_luminance_property(), make it
conditional with if IS_ENABLED(CONFIG_DRM_LUMINANCE). I wonder if
should be the same for drivers calling this helper.
That is, instead of bailing out due !IS_ENABLED(CONFIG_DRM_LUMINANCE),
to make drivers do:
if (!IS_ENABLED(CONFIG_DRM_LUMINANCE) {
ret = drm_mipi_dbi_connector_attach_luminance_property(connector);
...
}
--
Best regards,
Javier Martinez Canillas
Core Platforms
Red Hat
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 09/21] drm/tiny: migrate panel-mipi-dbi to connector luminance
2026-10-02 19:00 ` [PATCH v9 09/21] drm/tiny: migrate panel-mipi-dbi to connector luminance Mario Limonciello
@ 2026-10-03 11:22 ` Javier Martinez Canillas
0 siblings, 0 replies; 29+ messages in thread
From: Javier Martinez Canillas @ 2026-10-03 11:22 UTC (permalink / raw)
To: Mario Limonciello, dri-devel, harry.wentland, Simona Vetter,
Alex Deucher, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Mario Limonciello <mario.limonciello@amd.com> writes:
> Attach the connector LUMINANCE property for MIPI DBI compatible panels
> and retain the legacy backlight class interface only when DRM_LUMINANCE is
> disabled.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
> drivers/gpu/drm/tiny/Kconfig | 2 +-
> drivers/gpu/drm/tiny/panel-mipi-dbi.c | 3 +++
> 2 files changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
> index f0e72d4b6a470..e61a429538bc0 100644
> --- a/drivers/gpu/drm/tiny/Kconfig
> +++ b/drivers/gpu/drm/tiny/Kconfig
> @@ -73,7 +73,7 @@ config DRM_PANEL_MIPI_DBI
> select DRM_KMS_HELPER
> select DRM_GEM_DMA_HELPER
> select DRM_MIPI_DBI
> - select BACKLIGHT_CLASS_DEVICE
> + select BACKLIGHT_CLASS_DEVICE if !DRM_LUMINANCE
> select VIDEOMODE_HELPERS
> help
> Say Y here if you want to enable support for MIPI DBI compatible
> diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
> index 60cd65cae41d8..730f1b219fdec 100644
> --- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c
> +++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
> @@ -485,6 +485,9 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
> if (ret)
> return ret;
> drm_connector_helper_add(connector, &panel_mipi_dbi_connector_helper_funcs);
> + ret = drm_mipi_dbi_connector_attach_luminance_property(connector);
> + if (ret)
> + return ret;
>
I don't see how this could work...
The drm_mipi_dbi_connector_attach_luminance_property() helper only attaches a
LUMINANCE property to the connector if DRM_LUMINANCE is enabled and backlight
is not NULL.
But if DRM_LUMINANCE is enabled, then backlight will always be NULL given that
the drivers/gpu/drm/tiny/panel-mipi-dbi.c driver does:
dbidev->backlight = devm_of_find_backlight(dev);
and devm_of_find_backlight() is just a stub that unconditionally return NULL if
BACKLIGHT_CLASS_DEVICE is disabled:
https://elixir.bootlin.com/linux/v7.3-rc5/source/include/linux/backlight.h#L441
I don't think we will be able to add support for the LUMINANCE property to MIPI
DBI drivers unless the drivers DT binding are changed. Or maybe what this shows
is that a backlight backend is really needed.
I would leave these drivers out for now and then later figure out how to make
them work without breaking the backlight sysfs interface.
Maybe what can be done is to add a new CONFIG_BACKLIGHT_SYSFS Kconfig symbol,
that defaults to y but allows the sysfs interface to be disabled. That way,
you could still have CONFIG_BACKLIGHT_CLASS_DEVICE enabled but prevent the
uAPI breakage.
Then in this MIPI DBI drivers you could do:
select DRM_LUMINANCE if !CONFIG_BACKLIGHT_SYSFS, or something like that.
--
Best regards,
Javier Martinez Canillas
Core Platforms
Red Hat
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 01/21] drm: add connector LUMINANCE property
2026-10-02 19:00 ` [PATCH v9 01/21] drm: add connector LUMINANCE property Mario Limonciello
@ 2026-10-03 11:37 ` Javier Martinez Canillas
0 siblings, 0 replies; 29+ messages in thread
From: Javier Martinez Canillas @ 2026-10-03 11:37 UTC (permalink / raw)
To: Mario Limonciello, dri-devel, harry.wentland, Simona Vetter,
Alex Deucher, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie
Cc: Xaver Hugl, amd-gfx,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
Mario Limonciello
Mario Limonciello <mario.limonciello@amd.com> writes:
Hello Mario,
> Panel brightness is a property of a display, and thus of a DRM
> connector. Add an atomic per-connector LUMINANCE range property so
> compositors can manage relative panel luminance together with the rest
> of the display state.
>
> Keep the core backend-agnostic. Drivers create the property with their
> hardware range and implement connector helper callbacks to set luminance
> or disable panel emission. The atomic helpers sequence those callbacks
> around pipeline enable and disable, including luminance-only commits.
>
> The stored property value is independent of display power. A commit made
> while the connector is inactive is retained and applied on the next
> enable; disabling the pipeline does not overwrite it.
>
> LUMINANCE values are relative, driver-defined levels rather than
> absolute luminance in cd/m^2. The interface supports emissive panels as
> well as panels with a separate backlight.
>
> Keep the interface behind a default-off DRM_LUMINANCE option. Migrated
> drivers retain their legacy backlight class ABI unless the new interface
> is explicitly selected, allowing the DRM UAPI and legacy compatibility
> policy to remain separate.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
Thanks a lot for the rework. I went through this patch and have no more
objections on the core bits.
Acked-by: Javier Martinez Canillas <javierm@redhat.com>
--
Best regards,
Javier Martinez Canillas
Core Platforms
Red Hat
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v9 07/21] drm: add panel and bridge connector luminance forwarding
2026-10-02 19:00 ` [PATCH v9 07/21] drm: add panel and bridge connector luminance forwarding Mario Limonciello
@ 2026-10-12 8:41 ` Maxime Ripard
0 siblings, 0 replies; 29+ messages in thread
From: Maxime Ripard @ 2026-10-12 8:41 UTC (permalink / raw)
To: Mario Limonciello
Cc: dri-devel, harry.wentland, Simona Vetter, Alex Deucher,
Maarten Lankhorst, Thomas Zimmermann, David Airlie, Xaver Hugl,
amd-gfx, open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS,
open list:INTEL DRM DISPLAY FOR XE AND I915 DRIVERS
[-- Attachment #1: Type: text/plain, Size: 760 bytes --]
On Fri, Oct 02, 2026 at 02:00:16PM -0500, Mario Limonciello wrote:
> Forward connector luminance operations through panel and bridge connectors.
> Allow bridges that own brightness control to expose luminance operations,
> and route panel bridges to the panel backlight backend.
>
> Attach the property only when a usable brightness backend is present and
> CONFIG_DRM_LUMINANCE is enabled.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
This should be split into multiple patches: one to enable luminance
support for bridges, one to do so for panels, and then hook everything
into drm_bridge_connector.
Also, we still have some direct panel consumers, so I don't think we
can handle it at the bridge level yet.
Maxime
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]
^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2026-10-12 8:41 UTC | newest]
Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-02 19:00 [PATCH v9 00/21] Add support for a DRM backlight capability Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 01/21] drm: add connector LUMINANCE property Mario Limonciello
2026-10-03 11:37 ` Javier Martinez Canillas
2026-10-02 19:00 ` [PATCH v9 02/21] drm/amd/display: Pass up errors reading actual brightness Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 03/21] drm/amd: add luminance property support Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 04/21] drm/amdgpu: Check bios_scratch_reg_offset in backlight level helper Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 05/21] drm/amd/display: update KUnit luminance fixtures Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 06/21] drm/i915/display: add luminance property support Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 07/21] drm: add panel and bridge connector luminance forwarding Mario Limonciello
2026-10-12 8:41 ` Maxime Ripard
2026-10-02 19:00 ` [PATCH v9 08/21] drm/mipi-dbi: add connector luminance helpers Mario Limonciello
2026-10-03 11:03 ` Javier Martinez Canillas
2026-10-02 19:00 ` [PATCH v9 09/21] drm/tiny: migrate panel-mipi-dbi to connector luminance Mario Limonciello
2026-10-03 11:22 ` Javier Martinez Canillas
2026-10-02 19:00 ` [PATCH v9 10/21] drm/tiny: migrate HX8357D " Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 11/21] drm/tiny: migrate ILI9163 " Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 12/21] drm/tiny: migrate ILI9341 " Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 13/21] drm/tiny: migrate ILI9486 " Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 14/21] drm/tiny: migrate MI0283QT " Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 15/21] drm/sitronix: migrate ST7735R " Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 16/21] drm/nouveau: add connector luminance support Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 17/21] drm/gud: " Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 18/21] drm/radeon: " Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 19/21] drm/gma500: " Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 20/21] drm/bridge: add PS8622 " Mario Limonciello
2026-10-02 19:00 ` [PATCH v9 21/21] drm/solomon: add SSD130x " Mario Limonciello
2026-10-03 10:30 ` Javier Martinez Canillas
2026-10-03 10:39 ` Javier Martinez Canillas
2026-10-02 19:55 ` ✗ Fi.CI.BUILD: failure for Add support for a DRM backlight capability (rev4) Patchwork
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.