]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/dp: add option to disable zero sized address only transactions.
authorDave Airlie <airlied@redhat.com>
Mon, 3 Mar 2025 15:56:03 +0000 (01:56 +1000)
committerDave Airlie <airlied@redhat.com>
Sun, 18 May 2025 21:14:45 +0000 (07:14 +1000)
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 <airlied@redhat.com>
Reviewed-by: Ben Skeggs <bskeggs@nvidia.com>
Reviewed-by: Timur Tabi <ttabi@nvidia.com>
Tested-by: Timur Tabi <ttabi@nvidia.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/display/drm_dp_helper.c
include/drm/display/drm_dp_helper.h

index 56c7e3318f01079c3bde492a21c76ed37e9724ca..f2a6559a271008110504d5f8c114b5713946423b 100644 (file)
@@ -2137,14 +2137,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
@@ -2163,6 +2166,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);
 
                        /*
@@ -2180,15 +2185,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;
 }
 
index 7b19192c70313d66dce1b7ba40dd59c14f80a182..e4ca35143ff965ad4fc8e88fcb094fa0dfe714b3 100644 (file)
@@ -518,6 +518,11 @@ struct drm_dp_aux {
         * @powered_down: If true then the remote endpoint is powered down.
         */
        bool powered_down;
+
+       /**
+        * @no_zero_sized: If the hw can't use zero sized transfers (NVIDIA)
+        */
+       bool no_zero_sized;
 };
 
 int drm_dp_dpcd_probe(struct drm_dp_aux *aux, unsigned int offset);