From nobody Sun Feb 8 15:01:25 2026 Received: from mail-qt1-f172.google.com (mail-qt1-f172.google.com [209.85.160.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A8596BB5B for ; Sun, 21 Dec 2025 20:04:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766347488; cv=none; b=OstnbhBdROa03CQ0HleAyxjt8YNb9zulrGhbaz6G6j0c9BCDLiiVc8c46FIK354yRorhd+vj7acSVLyIRJMi59wPWP4eX/pX4rfWjFloT0J+D8tEKYknB2tBJOIxCtLlgRhyTSXCmrLUjtND5tJmMOUT6GzitrP1kZGH52LccCE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766347488; c=relaxed/simple; bh=nVhrxnq/I4WWnukGhxJK/Zxs8D7WQrSZhM1wLGXvoIw=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=kuNiHLPTIzgUnwoBlCNeaSarylh0cKz+fe8m9WUqlP3dnhEvfdCfmA81Ij3LD8CUPk88550RvUmvOPcCMpd4hbe3di87BR7Aw4JMqqCPWJP70ZHpzi7m6xfmKlgLuVA+I+CuKwAhbbgWcRYhBtlsLRnE/JuKajKlM/C+sVnj4/I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=dionne-riel.com; spf=pass smtp.mailfrom=dionne-riel.com; dkim=pass (2048-bit key) header.d=dionne-riel-com.20230601.gappssmtp.com header.i=@dionne-riel-com.20230601.gappssmtp.com header.b=lSBSv8sm; arc=none smtp.client-ip=209.85.160.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=dionne-riel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=dionne-riel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=dionne-riel-com.20230601.gappssmtp.com header.i=@dionne-riel-com.20230601.gappssmtp.com header.b="lSBSv8sm" Received: by mail-qt1-f172.google.com with SMTP id d75a77b69052e-4ee05b2b1beso32964881cf.2 for ; Sun, 21 Dec 2025 12:04:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dionne-riel-com.20230601.gappssmtp.com; s=20230601; t=1766347485; x=1766952285; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=qcubWTT1Pz5+LyJxHMvMkV1HwdecC4T519WRIUvUPgQ=; b=lSBSv8smEQFRImhNWCR+qabAiewlQvniqTtFQTBV7XmX8A6kwOrYpkayU2rK2v7g0H 93Dbdmo1S9vRGIF45j7nJgXOjp6ZVL/JnmRpUPOYNM+DXD3MGHN3cbsnHkUYmLgyqNj9 G8el3l6kO5YpNqts/Z4fYg1UIpa6Gkk2M9j2FupxmJQa0DiF0ly7tB5PBKPS1LT3EZFn clb4k+njbYjRBSemzX48Qvjppvz6aiEPwKLCPnYgLYXNPfphoa0h4GJkNohpxs2I3rrH DEs0SkZE6YFB70rPpCx3DRHmnaooFlMkJPy5kOGXQO+azuIg0drPU0od0JpsYhLLL5xf OV6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766347485; x=1766952285; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=qcubWTT1Pz5+LyJxHMvMkV1HwdecC4T519WRIUvUPgQ=; b=pXOGVpTTJIELPBTkts7Nkjj5knBocYfRhEwSb+Y8LerEqh/166RJdDczzUhPrqBKN9 yu0kWAkVXAQczWDSFhAoGPtJfdWXXgMFh6ypUzAgIjeApLlzKaa0sjbeorRnFIbsaj3O JmcDh8IEDGhJ5LcSKpHEoIaZlaOSGxvY4S+agGFC+dRe9GvVt+3P2l2XEo3aNZCtvoIt O+iJoownZYQo735uzOmcHiu6AzMSnz2tcxEpZxLnAqPnwHM7eAKcrUEZVKh1doXNHUFB 1bjaPP8d6qqsJTlnqNudTYtPIjxcVP9roLFXnHsXcaqtWBqkkk/dcXpOosiQ/sHQ8WmX 3cIw== X-Forwarded-Encrypted: i=1; AJvYcCUUfIvuxiubP3agKklDIzMpBRLkGkGQdJSI8pqlrM76sUbObd8jxBcCzkOwg8Im3dUCtJxq/5vKbSzHF7I=@vger.kernel.org X-Gm-Message-State: AOJu0YwaM6vGTd6H8d9+U9awd/8tlDUjRkGCZJjHZpiaTJh7p7oqcLeF LpHTt8bxZQyk1uEMKmiTjpaEUFcAdnuqZAYHQGCS6pyjZp5o6tn4GrcUCR8Be40hCQ== X-Gm-Gg: AY/fxX5eYcdwV9UTJQg9VjbyYInRucQi2+Lbke+w+/C/cFhwCF34AbGMl4DwOACJ3GC wzSyzZAWX/Iy/DmVLFbwu8hQr19gzHi3NrP6HHqLMMz1JBA70qHJ7jBf3l+LUpNPaQwGMjwkgTU 4MACEplu5cND/WH7K6iriWKHKUds2Fl4RUCYbS7eLcLHCZbyHbq2uH9wqrS2b5AaFJBWX3lVo+b DKge0q3PNGLqYoK9sYaNY+jaD1c9AuMix7IyGBtsEE3QFjge1dMdhbr1oCQHz5kcYGSnb4hzQEC gRQ4eWVRl+Pe68wjxi5Y9lTVF4CWMGMG3qoFmuR7fDgxj9Zn/bUrTFaIg3QJFpUmBHZ3jMsJ58w as/NHSlVvF5UmuJbduAQaMHM1//0iAcXYEuBEkZ8p2OBnROVqkOumHoE5WN99X/549fQnvnV1pM 0xow0RMcCdkkHaiGHeALm2qxw3usBycZOEvi1QQrg/WwWmnMLKtI8K/a21c4rdRmfk0A== X-Google-Smtp-Source: AGHT+IHjMsneMdbMo6QX5DQyZgWSFlMlf1e85YnTnHkFeIucTQyjyuU9w8NrvIqxqGP47xXp9FUyAg== X-Received: by 2002:a05:622a:250c:b0:4ee:24b8:2275 with SMTP id d75a77b69052e-4f4abcf6df2mr142149051cf.1.1766347485320; Sun, 21 Dec 2025 12:04:45 -0800 (PST) Received: from frankgrimes.elk-nominal.ts.net (135-23-195-66.cpe.pppoe.ca. [135.23.195.66]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-4f4ac62d53dsm63802501cf.19.2025.12.21.12.04.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 21 Dec 2025 12:04:43 -0800 (PST) From: Samuel Dionne-Riel To: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter Cc: Samuel Dionne-Riel , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH] drm: panel-backlight-quirks: Add kernel parameters for quirks Date: Sun, 21 Dec 2025 15:04:34 -0500 Message-ID: <20251221200434.2735218-2-samuel@dionne-riel.com> X-Mailer: git-send-email 2.51.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The goal is to enable end-users to try the different values quickly, so that they can document, for example, the better minimum backlight values for their systems. All quirks should be implemented, since this is a change meant to empower end-users in providing quick and complete quirks data for later addition to the quirks data. This is attempting to keep the largely unspecified behaviour as close as possible to the previous behaviour. This is currently an amdgpu-specific driver, but it shouldn't stay specific to that driver. The current usage always copies the values to its own runtime data (caps, in amdgpu). Without knowing the contract between this module and other modules, it's impossible to know if the driver could instead keep the pointer to the returned quirk. This quirk also currently has no multi-panel uses, but theoretically could be used on a system with dual screens, and with multiple different EDID matched panels. As such, the change has been authored to harden against this situation, and ensure that when no parameter has been given, that this would continue returning the same values (i.e. pointing at the quirk data structure elements directly). It may be preferrable to instead document that the values returned by this function are only good until then next time the function is called. Or it may be that filling a caller-owned structure may be preferred, so that there never is any concurrency concerns. Signed-off-by: Samuel Dionne-Riel --- This is sent as an RFC as I have basically no idea if this is correct, or desirable in its form. This was authored on top of the backlight curve changes, so this exact implementation depends on "Add quirk to disable custom brightness curve", but decoupling it is trivial, if for some reason that change gets held back for longer than this one. As stated in the patch, the rationale is that end-users should be able to quickly try values without having to mess with either a full kernel rebuild (easiest) or somehow messing with their systems so an updated quirks module is loaded before amdgpu gets loaded. I believe that the current semantics are *sufficient*, and that supporting more than one display on the kernel cmdline might not be worth the pain, when this would be a rare situation, and mainly as a means to gather the correct values for sending the appropriate changes. The implementation, though, I don't know how good or bad it is, and how palatable specifically for its maintainers. So please provide suggestions on how this should be done. Thanks! Link: https://lore.kernel.org/all/20251221192422.2726883-1-samuel@dionne-ri= el.com/ Signed-off-by: Samuel Dionne-Riel --- drivers/gpu/drm/drm_panel_backlight_quirks.c | 79 +++++++++++++++++--- 1 file changed, 69 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_panel_backlight_quirks.c b/drivers/gpu/drm= /drm_panel_backlight_quirks.c index 537dc6dd05343..1682409613d22 100644 --- a/drivers/gpu/drm/drm_panel_backlight_quirks.c +++ b/drivers/gpu/drm/drm_panel_backlight_quirks.c @@ -8,6 +8,21 @@ #include #include =20 +// The parameters use the type-specific max value as a flag for being unse= t. +// The semantics of these quirk values are drivers and device-specific. + +u16 param_min_brightness =3D U16_MAX; +MODULE_PARM_DESC(min_brightness, "minimum brightness override for all pane= l backlights. Value usage is driver-specific."); +module_param_named(min_brightness, param_min_brightness, ushort, 0444); + +u32 param_brightness_mask =3D U32_MAX; +MODULE_PARM_DESC(brightness_mask, "integer mask to bitwise OR with set bri= ghtness values for panel-specific fixes. Value usage is driver-specific."); +module_param_named(brightness_mask, param_brightness_mask, uint, 0444); + +bool param_disable_custom_brightness_curve =3D false; +MODULE_PARM_DESC(disable_custom_brightness_curve, "when true, custom brigh= tness curve support is disabled in the driver. Value usage is driver-specif= ic."); +module_param_named(disable_custom_brightness_curve, param_disable_custom_b= rightness_curve, bool, 0444); + struct drm_panel_match { enum dmi_field field; const char * const value; @@ -98,6 +113,8 @@ static const struct drm_get_panel_backlight_quirk drm_pa= nel_min_backlight_quirks }, }; =20 +static struct drm_panel_backlight_quirk quirk_from_param =3D { }; + static bool drm_panel_min_backlight_quirk_matches( const struct drm_get_panel_backlight_quirk *quirk, const struct drm_edid *edid) @@ -132,23 +149,65 @@ static bool drm_panel_min_backlight_quirk_matches( const struct drm_panel_backlight_quirk * drm_get_panel_backlight_quirk(const struct drm_edid *edid) { - const struct drm_get_panel_backlight_quirk *quirk; + const struct drm_get_panel_backlight_quirk *quirk =3D NULL; size_t i; + bool parameters_given =3D false; =20 - if (!IS_ENABLED(CONFIG_DMI)) - return ERR_PTR(-ENODATA); + if (param_min_brightness < U16_MAX) + parameters_given =3D true; =20 - if (!edid) - return ERR_PTR(-EINVAL); + if (param_brightness_mask < U32_MAX) + parameters_given =3D true; =20 - for (i =3D 0; i < ARRAY_SIZE(drm_panel_min_backlight_quirks); i++) { - quirk =3D &drm_panel_min_backlight_quirks[i]; + if (param_disable_custom_brightness_curve) + parameters_given =3D true; =20 - if (drm_panel_min_backlight_quirk_matches(quirk, edid)) - return &quirk->quirk; + if (IS_ENABLED(CONFIG_DMI) && edid) { + for (i =3D 0; i < ARRAY_SIZE(drm_panel_min_backlight_quirks); i++) { + quirk =3D &drm_panel_min_backlight_quirks[i]; + + if (drm_panel_min_backlight_quirk_matches(quirk, edid)) + break; + } } =20 - return ERR_PTR(-ENODATA); + if (i =3D=3D ARRAY_SIZE(drm_panel_min_backlight_quirks)) { + // Found no quirk. + quirk =3D NULL; + } + + if (!parameters_given && !quirk) { + if (!edid) + return ERR_PTR(-EINVAL); + + return ERR_PTR(-ENODATA); + } + + // We are returning from quirk_from_param only when parameters are given. + // This assumes that the return value's data can be kept by the driver, + // and that the driver supports more than one match at a time. + // (Think multiple-display devices.) + // When using a module parameter, only one set of values is supported. + if (parameters_given) { + // First copy the matched data, when found. + if (quirk) + memcpy(&quirk_from_param, &quirk->quirk, sizeof(quirk_from_param)); + + // Apply module parameters to the found quirk. + if (param_min_brightness < U16_MAX) + quirk_from_param.min_brightness =3D param_min_brightness; + if (param_brightness_mask < U32_MAX) + quirk_from_param.brightness_mask =3D param_brightness_mask; + + // We force the disable_custom_brightness_curve value when any parameter= is given. + // This ensures users can override the quirk-defined value. + // This comes at the cost of requiring any other value to be specified t= o work. + quirk_from_param.disable_custom_brightness_curve =3D param_disable_custo= m_brightness_curve; + + return &quirk_from_param; + } + + return &quirk->quirk; } EXPORT_SYMBOL(drm_get_panel_backlight_quirk); =20 --=20 2.51.0