On Sat, 3 Oct 2026 at 07:28, Finn Zeruhn <[email protected]> wrote:
>
> When aux->no_zero_sized is set, drm_dp_i2c_xfer() cannot use a bare
> address packet to close the transaction, so it clears MOT on the last
> data packet instead. The check only looks at the position within the
> current i2c_msg, so MOT is cleared at the end of every message and each
> one is terminated by an I2C stop.
>
> This breaks E-DDC reads of EDID blocks 2 and up. Those are read as three
> messages: a write of the segment pointer to 0x30, a write of the offset
> to 0x50, and the read. The stop after the first message resets the
> segment pointer, so the read returns segment 0 again.
>
> On a Pimax Dream Air (three EDID blocks, native timings in a DisplayID
> extension in block 2) connected to an RTX 5070 Ti with nouveau, block 2
> reads back as a copy of block 0. The checksum is valid, so nothing is
> reported, and the connector only offers fallback modes.
>
> Clear MOT only on the last packet of the last message, as the commit
> that added the option describes. With this, block 2 reads correctly and
> the native 7104x3840 modes are listed for the Dream Air.
>
> The same problem was pointed out by the Sashiko review of the patch that
> sets no_zero_sized for all DisplayPort connectors in nouveau.

nice catch,

Reviwed-by Dave Airlie <[email protected]>
>
> Fixes: f0ddbb1eed18 ("drm/dp: add option to disable zero sized address only 
> transactions.")
> Link: https://lore.kernel.org/all/[email protected]/
> Cc: [email protected]
> Assisted-by: Claude:claude-opus-5-5
> Signed-off-by: Finn Zeruhn <[email protected]>
> ---
>  drivers/gpu/drm/display/drm_dp_helper.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> b/drivers/gpu/drm/display/drm_dp_helper.c
> index 488fd123a01a..7676285c19f8 100644
> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> @@ -2192,7 +2192,8 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, 
> struct i2c_msg *msgs,
>                         msg.buffer = msgs[i].buf + j;
>                         msg.size = min(transfer_size, msgs[i].len - j);
>
> -                       if (j + msg.size == msgs[i].len && aux->no_zero_sized)
> +                       if (aux->no_zero_sized && i == num - 1 &&
> +                           j + msg.size == msgs[i].len)
>                                 msg.request &= ~DP_AUX_I2C_MOT;
>                         err = drm_dp_i2c_drain_msg(aux, &msg);
>
>
> base-commit: bca45af5998a05f34b13a2ef11e639bac9c62643
> --
> 2.56.0
>

Reply via email to