Re: [PATCH v2] drm/bridge: analogix_dp: Fix PE/VS value shift mismatch during link training

From: Vicente Bergas

Date: Wed Jun 24 2026 - 13:41:26 EST


On Tue, Jun 23, 2026 at 4:35 AM Damon Ding <damon.ding@xxxxxxxxxxxxxx> wrote:
>
> 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@xxxxxxxxx>
> Closes: https://lore.kernel.org/all/CAAMcf8D-d+5n=H44KeKBSqWY42m+o32W+mO-r15VqWNyYhJL7Q@xxxxxxxxxxxxxx/
> Fixes: d84b087c7662 ("drm/bridge: analogix_dp: Apply DP helper APIs to get adjusted voltages and pre-emphasises")
> Signed-off-by: Damon Ding <damon.ding@xxxxxxxxxxxxxx>
>
> ---
>
> Changes in v2:
> - Fix the ambiguous descriptions in commit msg.
> ---
> drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 7a85774aaac1..1d39a354c3d9 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -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)
> --
> 2.34.1

Tested-by: Vicente Bergas

This patch was tested toghether with
[PATCH v1] drm/bridge: analogix_dp: Apply standard DP training delay helpers

Regards,
Vicente.