The legacy backlight control interface can only be disabled when both the client and the driver agree that luminance can be set during a modeset. Add a DRIVER_CONNECTOR_LUMINANCE driver feature for the driver to advertise support, and a DRM_CLIENT_CAP_LUMINANCE client capability for a luminance-aware client to opt in.
When a client sets DRM_CLIENT_CAP_LUMINANCE, every DRM-connected backlight on the device is marked as taken over; writes to the legacy /sys/class/backlight/<dev>/brightness attribute then return -EBUSY until the last luminance-aware client clears the capability or closes its DRM file. The takeover follows the active backlight_device when drm_backlight_link() retargets the link. Signed-off-by: Mario Limonciello (AMD) <[email protected]> --- drivers/gpu/drm/drm_file.c | 5 +++++ drivers/gpu/drm/drm_ioctl.c | 24 ++++++++++++++++++++++++ include/drm/drm_drv.h | 7 +++++++ include/drm/drm_file.h | 8 ++++++++ include/uapi/drm/drm.h | 22 ++++++++++++++++++++++ 5 files changed, 66 insertions(+) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index ec820686b3021..4d2520de7614c 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -41,6 +41,7 @@ #include <linux/slab.h> #include <linux/vga_switcheroo.h> +#include <drm/drm_backlight.h> #include <drm/drm_client_event.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> @@ -252,6 +253,10 @@ void drm_file_free(struct drm_file *file) if (drm_core_check_feature(dev, DRIVER_MODESET)) { drm_fb_release(file); drm_property_destroy_user_blobs(dev, file); + if (file->supports_luminance_control) { + drm_backlight_uninhibit_legacy_all(dev); + file->supports_luminance_control = false; + } } if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 9039a39c43243..de2c9d9ab5285 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -28,12 +28,14 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include "drm/drm.h" #include <linux/export.h> #include <linux/nospec.h> #include <linux/pci.h> #include <linux/uaccess.h> #include <drm/drm_auth.h> +#include <drm/drm_backlight.h> #include <drm/drm_crtc.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> @@ -392,6 +394,28 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) file_priv->plane_color_pipeline = req->value; break; } + case DRM_CLIENT_CAP_LUMINANCE: + if (!drm_core_check_feature(dev, DRIVER_CONNECTOR_LUMINANCE)) + return -EOPNOTSUPP; + if (!file_priv->atomic) + return -EINVAL; + if (req->value > 1) + return -EINVAL; + + /* + * Serialize the compare-and-act so concurrent ioctls on a shared + * fd cannot unbalance the device-wide inhibit count. + */ + mutex_lock(&dev->mode_config.mutex); + if (req->value != file_priv->supports_luminance_control) { + if (req->value) + drm_backlight_inhibit_legacy_all(dev); + else + drm_backlight_uninhibit_legacy_all(dev); + file_priv->supports_luminance_control = req->value; + } + mutex_unlock(&dev->mode_config.mutex); + break; default: return -EINVAL; } diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index b23830494ed41..449160b9863f6 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -118,6 +118,13 @@ enum drm_driver_feature { */ DRIVER_CURSOR_HOTSPOT = BIT(9), + /** + * @DRIVER_CONNECTOR_LUMINANCE: + * + * Driver supports luminance control on a per connector basis. + */ + DRIVER_CONNECTOR_LUMINANCE = BIT(10), + /* IMPORTANT: Below are all the legacy flags, add new ones above. */ /** diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 6ee70ad65e1fd..0bb1e53f36bec 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -248,6 +248,14 @@ struct drm_file { */ bool supports_virtualized_cursor_plane; + /** + * @supports_luminance_control: + * + * This client is capable of setting the luminance for connectors. + * + */ + bool supports_luminance_control; + /** * @master: * diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index bc7ef7684099b..a3141d46d7d66 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -903,6 +903,28 @@ struct drm_get_cap { */ #define DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE 7 +/** + * DRM_CLIENT_CAP_LUMINANCE + * + * If set to 1, the client declares support for the LUMINANCE connector property + * and will control backlight brightness through the DRM atomic interface. This + * enables the kernel to expose the LUMINANCE property on connectors that have + * an associated backlight device. + * + * When this capability is enabled: + * - The LUMINANCE property becomes visible on supported connectors + * - Legacy sysfs writes to /sys/class/backlight/{*}/brightness will return + * -EBUSY to prevent conflicts with DRM-based brightness control + * - The client should include luminance values as part of atomic commits + * - Brightness changes are synchronized with display power state (DPMS) + * + * The LUMINANCE property accepts values from 0 to max_brightness, where 0 turns + * off the backlight, and 1 to max_brightness control the brightness level. + * + * This capability is supported starting in kernel 7.2. + */ +#define DRM_CLIENT_CAP_LUMINANCE 8 + /* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap { __u64 capability; -- 2.43.0
