]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/bridge: analogix_dp: Fix PE/VS value shift mismatch during link training
authorDamon Ding <damon.ding@rock-chips.com>
Tue, 23 Jun 2026 02:35:06 +0000 (10:35 +0800)
committerHeiko Stuebner <heiko@sntech.de>
Fri, 3 Jul 2026 16:48:02 +0000 (18:48 +0200)
VS/PE values returned by drm_dp_get_adjust_request_voltage() and
drm_dp_get_adjust_request_pre_emphasis() are already encoded to their
native DPCD register bit positions. However, DPCD_VOLTAGE_SWING_SET /
DPCD_PRE_EMPHASIS_SET macros perform an extra internal shift. Feeding
the raw offset-bearing values directly leads to overlapping bitfields
and invalid lane training configuration, causing link training failures
and black screen.

Add right shift using DP_TRAIN_*_SHIFT constants to strip the DPCD bit
offsets before passing values to the SET macros and subsequent checks.
Apply this fix for both clock recovery and adjust training code paths.

Reported-by: Vicente Bergas <vicencb@gmail.com>
Closes: https://lore.kernel.org/all/CAAMcf8D-d+5n=H44KeKBSqWY42m+o32W+mO-r15VqWNyYhJL7Q@mail.gmail.com/
Fixes: d84b087c7662 ("drm/bridge: analogix_dp: Apply DP helper APIs to get adjusted voltages and pre-emphasises")
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
Link: https://lore.kernel.org/all/CAAMcf8D-d+5n=H44KeKBSqWY42m+o32W+mO-r15VqWNyYhJL7Q@mail.gmail.com/
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patch.msgid.link/20260623023506.309858-1-damon.ding@rock-chips.com
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c

index 8cf6b73bceac075bf10a18d4f3e050ee0b755a77..5006ac181b2d7fc536dd2a189808a89314b9217e 100644 (file)
@@ -309,7 +309,9 @@ static void analogix_dp_get_adjust_training_lane(struct analogix_dp_device *dp,
        lane_count = dp->link_train.lane_count;
        for (lane = 0; lane < lane_count; lane++) {
                voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);
+               voltage_swing >>= DP_TRAIN_VOLTAGE_SWING_SHIFT;
                pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
+               pre_emphasis >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
                training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
                                DPCD_PRE_EMPHASIS_SET(pre_emphasis);
 
@@ -355,7 +357,9 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
        for (lane = 0; lane < lane_count; lane++) {
                training_lane = analogix_dp_get_lane_link_training(dp, lane);
                voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);
+               voltage_swing >>= DP_TRAIN_VOLTAGE_SWING_SHIFT;
                pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
+               pre_emphasis >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
 
                if (DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing &&
                    DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis)