From: sashiko-bot@kernel.org
To: "Mario Limonciello (AMD)" <superm1@kernel.org>
Cc: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
intel-xe@lists.freedesktop.org
Subject: Re: [PATCH v10 12/15] drm/radeon: add connector luminance support
Date: Mon, 02 Nov 2026 19:13:35 +0000 [thread overview]
Message-ID: <sashiko-outbox-193983@kernel.org> (raw)
In-Reply-To: <20261102-superm1-backlight-property-v10-12-b2a6f24131f5@kernel.org>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] drm/radeon: unreachable atomic LUMINANCE property on non-atomic KMS driver
- [High] drm/radeon: legacy LVDS backlight ignored and panel turned off in radeon_legacy_lvds_update()
- [High] drm/radeon: missing luminance callbacks in radeon_dp_connector_helper_funcs
- [Medium] drm/radeon: Kconfig unmet dependency and link error with DRM_LUMINANCE
- [Medium] drm/radeon: ACPI ATIF brightness events ignored when dig->bl_dev is NULL
- [Medium] drm/radeon: memory leak of backlight_priv when LCD encoder links to multiple connectors
--
commit d872f715df68798d7e323e8f154d8558d421e434
Author: Mario Limonciello <mario.limonciello@amd.com>
drm/radeon: add connector luminance support
This commit adds support for exposing Radeon panel brightness through the
connector LUMINANCE property when CONFIG_DRM_LUMINANCE is enabled, reusing
the AtomBIOS and legacy hardware programming paths while keeping the
backlight class interface otherwise.
> diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig
> index 3cd70aef770e1..2ccad1f2f8cee 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
[Severity: Medium]
Can making BACKLIGHT_CLASS_DEVICE conditional on !DRM_LUMINANCE cause an
unmet Kconfig dependency and linker failures when CONFIG_DRM_LUMINANCE=y,
CONFIG_ACPI=y, and CONFIG_BACKLIGHT_CLASS_DEVICE is disabled (or modular
with built-in DRM_RADEON)?
Just below in drivers/gpu/drm/radeon/Kconfig, DRM_RADEON still
unconditionally selects ACPI_VIDEO:
# radeon depends on ACPI_VIDEO when ACPI is enabled, for select to work
# ACPI_VIDEO's dependencies must also be selected.
select INPUT if ACPI
select ACPI_VIDEO if ACPI
In drivers/acpi/Kconfig, ACPI_VIDEO depends on BACKLIGHT_CLASS_DEVICE:
config ACPI_VIDEO
tristate "Video"
depends on BACKLIGHT_CLASS_DEVICE
In addition, radeon_atif_handler() in drivers/gpu/drm/radeon/radeon_acpi.c
unconditionally calls backlight_force_update(), which has no inline stub in
include/linux/backlight.h when CONFIG_BACKLIGHT_CLASS_DEVICE is disabled:
if (rdev->is_atom_bios) {
struct radeon_encoder_atom_dig *dig = enc->enc_priv;
backlight_force_update(dig->bl_dev,
BACKLIGHT_UPDATE_HOTKEY);
} else {
struct radeon_encoder_lvds *dig = enc->enc_priv;
backlight_force_update(dig->bl_dev,
BACKLIGHT_UPDATE_HOTKEY);
}
> 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;
[Severity: Medium]
Can this leak the struct radeon_backlight_privdata allocation in pdata
when an encoder with ATOM_DEVICE_LCD_SUPPORT is shared across multiple
connectors?
In radeon_add_atom_encoder() and radeon_add_legacy_encoder(), encoders
sharing the same encoder_enum combine their device bitmasks via
radeon_encoder->devices |= supported_device. When
radeon_link_encoder_connector() in drivers/gpu/drm/radeon/radeon_encoders.c
links encoders and connectors, it checks radeon_encoder->devices rather
than radeon_connector->devices:
if (radeon_encoder->devices & radeon_connector->devices) {
drm_connector_attach_encoder(connector, encoder);
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
radeon_encoder_add_backlight(radeon_encoder, connector);
}
When radeon_encoder_add_backlight() is invoked a second time for the same
radeon_encoder (both here in radeon_atom_backlight_init() and in
radeon_legacy_backlight_init()), radeon_encoder->backlight_priv is
overwritten with the newly allocated pdata. With CONFIG_DRM_LUMINANCE
enabled, drm_connector_attach_luminance_property() succeeds on the second
connector and leaks the first pdata allocation (or if registration fails
and jumps to error:, radeon_encoder->backlight_priv is cleared to NULL
without freeing or preserving the first allocation).
> +
> + 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;
> + }
[Severity: High]
How can userspace access or update the LUMINANCE property on radeon when
radeon is a non-atomic KMS driver?
In drivers/gpu/drm/radeon/radeon_drv.c, kms_driver does not advertise
DRIVER_ATOMIC:
.driver_features =
DRIVER_GEM | DRIVER_RENDER | DRIVER_MODESET,
However, drm_connector_attach_luminance_property() creates the LUMINANCE
property with DRM_MODE_PROP_ATOMIC:
property = drm_property_create_range(connector->dev, DRM_MODE_PROP_ATOMIC,
"LUMINANCE", min, max);
Because DRIVER_ATOMIC is not set:
1. drm_setclientcap() rejects DRM_CLIENT_CAP_ATOMIC, so
drm_mode_object_get_properties() hides DRM_MODE_PROP_ATOMIC properties
from userspace.
2. Legacy property updates go through drm_mode_obj_set_property_ioctl() ->
set_property_legacy() -> radeon_lvds_set_property(), which ignores
everything except scaling_mode_property.
3. radeon_set_luminance() and radeon_disable_luminance() are only invoked
by drm_atomic_helper_commit_luminance_enables() and
drm_atomic_helper_commit_luminance_disables(), which radeon never calls.
Since radeon_atom_backlight_init() and radeon_legacy_backlight_init()
return early before backlight_device_register() when CONFIG_DRM_LUMINANCE
is enabled (and set rdev->mode_info.bl_encoder, which also prevents the
acpi_video_register_backlight() fallback in radeon_encoder_add_backlight()),
won't this leave panels with no working brightness control interface?
[Severity: Medium]
Also, when dig->bl_dev is set to NULL here (and in
radeon_legacy_backlight_init()), won't ACPI ATIF panel brightness events
stop working?
In drivers/gpu/drm/radeon/radeon_acpi.c, radeon_acpi_init() locates
atif->encoder_for_bl by checking dig->bl_dev:
if (rdev->is_atom_bios) {
struct radeon_encoder_atom_dig *dig = enc->enc_priv;
if (dig->bl_dev) {
target = enc;
break;
}
} else {
struct radeon_encoder_lvds *dig = enc->enc_priv;
if (dig->bl_dev) {
target = enc;
break;
}
}
When dig->bl_dev is NULL, atif->encoder_for_bl remains NULL and
radeon_atif_handler() ignores ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST events.
[ ... ]
> 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
[ ... ]
> @@ -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,
> };
[Severity: High]
Are .set_luminance and .disable_luminance also needed in
radeon_dp_connector_helper_funcs?
In radeon_add_atom_connector(), native DRM_MODE_CONNECTOR_eDP connectors
and DP-bridge (TRAVIS/NUTMEG) DRM_MODE_CONNECTOR_LVDS/eDP connectors use
radeon_dp_connector_helper_funcs:
drm_connector_init_with_ddc(dev, &radeon_connector->base,
&radeon_edp_connector_funcs,
connector_type,
ddc);
drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
Their encoders have ATOM_DEVICE_LCD_SUPPORT set, so
radeon_link_encoder_connector() -> radeon_encoder_add_backlight() ->
radeon_atom_backlight_init() attaches the LUMINANCE property to those
connectors, but radeon_dp_connector_helper_funcs does not wire up
.set_luminance or .disable_luminance (and on DP-bridge connectors,
radeon_dvi_encoder() rather than radeon_best_single_encoder() selects the
encoder with enc_priv).
> 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
[ ... ]
> @@ -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;
> + }
[Severity: High]
When lvds->bl_dev is set to NULL here without initializing
lvds->backlight_level, won't radeon_legacy_lvds_update() ignore brightness
updates and radeon_legacy_set_backlight_level() power off the panel?
In radeon_legacy_lvds_update(), lvds->backlight_level is only used if
lvds->bl_dev is non-NULL:
if (radeon_encoder->enc_priv) {
if (rdev->is_atom_bios) {
struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
panel_pwr_delay = lvds->panel_pwr_delay;
if (lvds->bl_dev)
backlight_level = lvds->backlight_level;
} else {
struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
panel_pwr_delay = lvds->panel_pwr_delay;
if (lvds->bl_dev)
backlight_level = lvds->backlight_level;
}
}
Furthermore, radeon_legacy_set_backlight_level() checks the previous value
of lvds->backlight_level before updating it:
if (radeon_encoder->enc_priv) {
if (rdev->is_atom_bios) {
struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
if (lvds->backlight_level > 0)
dpms_mode = lvds->dpms_mode;
else
dpms_mode = DRM_MODE_DPMS_OFF;
lvds->backlight_level = level;
} else {
struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
if (lvds->backlight_level > 0)
dpms_mode = lvds->dpms_mode;
else
dpms_mode = DRM_MODE_DPMS_OFF;
lvds->backlight_level = level;
}
}
radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
Because lvds->backlight_level starts at 0 (or becomes 0 when maximum
brightness is set on a pdata->negative panel where
level = RADEON_MAX_BL_LEVEL - level), radeon_legacy_set_backlight_level()
will pass DRM_MODE_DPMS_OFF to radeon_legacy_lvds_update().
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261102-superm1-backlight-property-v10-0-b2a6f24131f5@kernel.org?part=12
next prev parent reply other threads:[~2026-11-02 19:13 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20261102-superm1-backlight-property-v10-0-b2a6f24131f5@kernel.org>
[not found] ` <20261102-superm1-backlight-property-v10-1-b2a6f24131f5@kernel.org>
2026-11-02 17:07 ` [PATCH v10 01/15] drm: add connector LUMINANCE property sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-5-b2a6f24131f5@kernel.org>
2026-11-02 18:00 ` [PATCH v10 05/15] drm/amd/display: update KUnit luminance fixtures sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-6-b2a6f24131f5@kernel.org>
2026-11-02 18:17 ` [PATCH v10 06/15] drm/i915/display: add luminance property support sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-7-b2a6f24131f5@kernel.org>
2026-11-02 18:24 ` [PATCH v10 07/15] drm/bridge: add connector luminance operations sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-8-b2a6f24131f5@kernel.org>
2026-11-02 18:34 ` [PATCH v10 08/15] drm/panel: add connector luminance forwarding sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-10-b2a6f24131f5@kernel.org>
2026-11-02 18:49 ` [PATCH v10 10/15] drm/nouveau: add connector luminance support sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-11-b2a6f24131f5@kernel.org>
2026-11-02 19:02 ` [PATCH v10 11/15] drm/gud: " sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-12-b2a6f24131f5@kernel.org>
2026-11-02 19:13 ` sashiko-bot [this message]
[not found] ` <20261102-superm1-backlight-property-v10-13-b2a6f24131f5@kernel.org>
2026-11-02 19:22 ` [PATCH v10 13/15] drm/gma500: " sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-14-b2a6f24131f5@kernel.org>
2026-11-02 19:31 ` [PATCH v10 14/15] drm/bridge: add PS8622 " sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-15-b2a6f24131f5@kernel.org>
2026-11-02 19:49 ` [PATCH v10 15/15] drm/solomon: add SSD130x " sashiko-bot
[not found] ` <20261102-superm1-backlight-property-v10-3-b2a6f24131f5@kernel.org>
2026-11-02 17:32 ` [PATCH v10 03/15] drm/amd: add luminance property support sashiko-bot
2026-11-03 15:58 ` Leo Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-193983@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=superm1@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox