From 4799fc81d42e0651a444ced59036a06418609785 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 4 Mar 2025 01:56:03 +1000 Subject: drm/dp: add option to disable zero sized address only transactions. [ Upstream commit f0ddbb1eed1898286d2bd99fd6ab64ca9700d267 ] Some older NVIDIA and some newer NVIDIA hardware/firmware seems to have issues with address only transactions (firmware rejects them). Add an option to the core drm dp to avoid address only transactions, This just puts the MOT flag removal on the last message of the transfer and avoids the start of transfer transaction. This with the flag set in nouveau, allows eDP probing on GB203 device. Signed-off-by: Dave Airlie Reviewed-by: Ben Skeggs Reviewed-by: Timur Tabi Tested-by: Timur Tabi Signed-off-by: Dave Airlie Signed-off-by: Sasha Levin --- drivers/gpu/drm/display/drm_dp_helper.c | 39 +++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/display') diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index dbce1c3f4969..753d7c3942a1 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -2081,14 +2081,17 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, for (i = 0; i < num; i++) { msg.address = msgs[i].addr; - drm_dp_i2c_msg_set_request(&msg, &msgs[i]); - /* Send a bare address packet to start the transaction. - * Zero sized messages specify an address only (bare - * address) transaction. - */ - msg.buffer = NULL; - msg.size = 0; - err = drm_dp_i2c_do_msg(aux, &msg); + + if (!aux->no_zero_sized) { + drm_dp_i2c_msg_set_request(&msg, &msgs[i]); + /* Send a bare address packet to start the transaction. + * Zero sized messages specify an address only (bare + * address) transaction. + */ + msg.buffer = NULL; + msg.size = 0; + err = drm_dp_i2c_do_msg(aux, &msg); + } /* * Reset msg.request in case in case it got @@ -2107,6 +2110,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) + msg.request &= ~DP_AUX_I2C_MOT; err = drm_dp_i2c_drain_msg(aux, &msg); /* @@ -2124,15 +2129,17 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, } if (err >= 0) err = num; - /* Send a bare address packet to close out the transaction. - * Zero sized messages specify an address only (bare - * address) transaction. - */ - msg.request &= ~DP_AUX_I2C_MOT; - msg.buffer = NULL; - msg.size = 0; - (void)drm_dp_i2c_do_msg(aux, &msg); + if (!aux->no_zero_sized) { + /* Send a bare address packet to close out the transaction. + * Zero sized messages specify an address only (bare + * address) transaction. + */ + msg.request &= ~DP_AUX_I2C_MOT; + msg.buffer = NULL; + msg.size = 0; + (void)drm_dp_i2c_do_msg(aux, &msg); + } return err; } -- cgit v1.2.3