On 25/03/2025 21:21, Christopher Obbard wrote:
Some eDP devices report DP_EDP_PWMGEN_BIT_COUNT as 0, but still provide
valid non-zero MIN and MAX values. This patch reworks the logic to
fallback to the max value in such cases, ensuring correct backlight PWM
configuration even when the bit count value is not explicitly set.

I don't think this matches the eDP standard. It tells to use MIN if BIT_COUNT is less than MIN, if I understand it correctly.


This improves compatibility with eDP panels (e.g. Samsung ATNA40YK20
used on the Lenovo T14s Gen6 Snapdragon with OLED panel) which reports
DP_EDP_PWMGEN_BIT_COUNT as 0 but still provides valid non-zero MIN/MAX
values.

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>
---
  drivers/gpu/drm/display/drm_dp_helper.c | 51 ++++++++++++++++++++++-----------
  1 file changed, 34 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index 
da3c8521a7fa7d3c9761377363cdd4b44ab1106e..734b7b8e46394de21837cda6ca1b189413b25cd8
 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -3964,7 +3964,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;
@@ -3975,8 +3975,40 @@ 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 in these cases use pn_max
+        * for pn.
+        */
+       if (!pn && (bl_caps & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
+           && pn_max)
+               pn = pn_max;
+
        bl->max = (1 << pn) - 1;
        if (!driver_pwm_freq_hz)
                return 0;
@@ -4003,21 +4035,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);



--
With best wishes
Dmitry

Reply via email to