According to the eDP specification (e.g., VESA eDP 1.4b, section 3.3.10.2), if DP_EDP_PWMGEN_BIT_COUNT is less than DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, the sink is required to use the MIN value as the effective bit count.
Some eDP panels report DP_EDP_PWMGEN_BIT_COUNT as 0 while still providing valid non-zero MIN and MAX capability values. This patch updates the logic to use the CAP_MIN value in such cases, ensuring correct scaling of AUX-set backlight brightness values. This improves compatibility with panels like the Samsung ATNA40YK20 used on the Lenovo T14s Gen6 (Snapdragon variant with OLED) which report a bit count of 0 but declares an 11-bit PWM capability range. Co-developed-by: Rui Miguel Silva <rui.si...@linaro.org> Signed-off-by: Rui Miguel Silva <rui.si...@linaro.org> Signed-off-by: Christopher Obbard <christopher.obb...@linaro.org> --- Changes in v2: - Split backlight brightness patch from T14s OLED enablement series. - Use PWMGEN_CAP_MIN rather than MAX (Dmitry). - Rework commit message to reference eDP spec. - Rebase on drm-misc-next. - Link to v1: https://lore.kernel.org/all/20250325-wip-obbardc-qcom-t14s-oled-panel-v2-4-e9bc7c9d3...@linaro.org/ --- drivers/gpu/drm/display/drm_dp_helper.c | 50 ++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index dbce1c3f49691fc687fee2404b723c73d533f23d..0b843d5b634f89f144b62b30311834d118b79ba9 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -4083,7 +4083,7 @@ drm_edp_backlight_probe_max(struct drm_dp_aux *aux, struct drm_edp_backlight_inf { int fxp, fxp_min, fxp_max, fxp_actual, f = 1; int ret; - u8 pn, pn_min, pn_max; + u8 pn, pn_min, pn_max, bl_caps; if (!bl->aux_set) return 0; @@ -4094,8 +4094,39 @@ drm_edp_backlight_probe_max(struct drm_dp_aux *aux, struct drm_edp_backlight_inf aux->name, ret); return -ENODEV; } - pn &= DP_EDP_PWMGEN_BIT_COUNT_MASK; + + ret = drm_dp_dpcd_readb(aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min); + if (ret != 1) { + drm_dbg_kms(aux->drm_dev, "%s: Failed to read pwmgen bit count cap min: %d\n", + aux->name, ret); + return 0; + } + pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK; + + ret = drm_dp_dpcd_readb(aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max); + if (ret != 1) { + drm_dbg_kms(aux->drm_dev, "%s: Failed to read pwmgen bit count cap max: %d\n", + aux->name, ret); + return 0; + } + pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK; + + ret = drm_dp_dpcd_readb(aux, DP_EDP_BACKLIGHT_ADJUSTMENT_CAP, &bl_caps); + if (ret != 1) { + bl_caps = 0; + drm_dbg_kms(aux->drm_dev, "%s: Failed to read backlight adjustment cap: %d\n", + aux->name, ret); + } + + /* + * Some eDP panels report brightness byte count support, but the byte count + * reading is 0 (e.g. Samsung ATNA40YK20) so use pn_min instead. + */ + if (!pn && (bl_caps & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT) + && pn_min) + pn = pn_min; + bl->max = (1 << pn) - 1; if (!driver_pwm_freq_hz) return 0; @@ -4122,21 +4153,6 @@ drm_edp_backlight_probe_max(struct drm_dp_aux *aux, struct drm_edp_backlight_inf * - FxP is within 25% of desired value. * Note: 25% is arbitrary value and may need some tweak. */ - ret = drm_dp_dpcd_readb(aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min); - if (ret != 1) { - drm_dbg_kms(aux->drm_dev, "%s: Failed to read pwmgen bit count cap min: %d\n", - aux->name, ret); - return 0; - } - ret = drm_dp_dpcd_readb(aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max); - if (ret != 1) { - drm_dbg_kms(aux->drm_dev, "%s: Failed to read pwmgen bit count cap max: %d\n", - aux->name, ret); - return 0; - } - pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK; - pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK; - /* Ensure frequency is within 25% of desired value */ fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4); fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4); --- base-commit: ee20c69c789b6cb2179a535cf440d72b98f4a134 change-id: 20250327-wip-obbardc-qcom-t14s-oled-panel-brightness-4020865b6580 Best regards, -- Christopher Obbard <christopher.obb...@linaro.org>