RE: [PATCH] drm/bridge: ti-sn65dsi86: Add retries for link training

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 

 

 

On some panels hooked up to the ti-sn65dsi86 bridge chip we found that

link training was failing.  Specifically, we'd see:

 

  ti_sn65dsi86 2-002d: [drm:ti_sn_bridge_enable] *ERROR* Link training failed, link is off (-5)

 

The panel was hooked up to a logic analyzer and it was found that, as

part of link training, the bridge chip was writing a 0x1 to DPCD

address 00600h and the panel responded NACK.  As can be seen in header

files, the write of 0x1 to DPCD address 0x600h means we were trying to

write the value DP_SET_POWER_D0 to the register DP_SET_POWER.  The

panel vendor says that a NACK in this case is not unexpected and means

"not ready, try again".

 

In testing, we found that this panel would respond with a NACK in

about 1/25 times.  Adding the retry logic worked fine and the most

number of tries needed was 3.  Just to be safe, we'll add 10 tries

here and we'll add a little blurb to the logs if we ever need more

than 5.

 

Signed-off-by: Douglas Anderson <dianders@xxxxxxxxxxxx>

---

 

drivers/gpu/drm/bridge/ti-sn65dsi86.c | 40 +++++++++++++++++++--------

1 file changed, 29 insertions(+), 11 deletions(-)

 

diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c

index ecdf9b01340f..6e12cda69b54 100644

--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c

+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c

@@ -106,6 +106,8 @@

#define SN_NUM_GPIOS                               4

#define SN_GPIO_PHYSICAL_OFFSET                     1

+#define SN_LINK_TRAINING_TRIES            10

+

/**

  * struct ti_sn_bridge - Platform data for ti-sn65dsi86 driver.

  * @dev:          Pointer to our device.

@@ -673,6 +675,7 @@ static int ti_sn_link_training(struct ti_sn_bridge *pdata, int dp_rate_idx,

{

          unsigned int val;

          int ret;

+         int i;

           /* set dp clk frequency value */

          regmap_update_bits(pdata->regmap, SN_DATARATE_CONFIG_REG,

@@ -689,19 +692,34 @@ static int ti_sn_link_training(struct ti_sn_bridge *pdata, int dp_rate_idx,

                     goto exit;

          }

-          /* Semi auto link training mode */

-          regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0x0A);

-          ret = regmap_read_poll_timeout(pdata->regmap, SN_ML_TX_MODE_REG, val,

-                                                 val == ML_TX_MAIN_LINK_OFF ||

-                                                 val == ML_TX_NORMAL_MODE, 1000,

-                                                 500 * 1000);

-          if (ret) {

-                    *last_err_str = "Training complete polling failed";

-          } else if (val == ML_TX_MAIN_LINK_OFF) {

-                    *last_err_str = "Link training failed, link is off";

-                    ret = -EIO;

+         /*

+         * We'll try to link train several times.  As part of link training

+         * the bridge chip will write DP_SET_POWER_D0 to DP_SET_POWER.  If

+         * the panel isn't ready quite it might respond NAK here which means

+         * we need to try again.

+         */

+         for (i = 0; i < SN_LINK_TRAINING_TRIES; i++) {

+                    /* Semi auto link training mode */

+                    regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0x0A);

+                    ret = regmap_read_poll_timeout(pdata->regmap, SN_ML_TX_MODE_REG, val,

+                                                     val == ML_TX_MAIN_LINK_OFF ||

+                                                     val == ML_TX_NORMAL_MODE, 1000,

+                                                     500 * 1000);

+                    if (ret) {

+                               *last_err_str = "Training complete polling failed";

+                    } else if (val == ML_TX_MAIN_LINK_OFF) {

+                               *last_err_str = "Link training failed, link is off";

+                               ret = -EIO;

+                               continue;

+                    }

+

+                    break;

          }

+         /* If we saw quite a few retries, add a note about it */

+         if (!ret && i > SN_LINK_TRAINING_TRIES / 2)

+                    DRM_DEV_INFO(pdata->dev, "Link training needed %d retries\n", i);

+

exit:

          /* Disable the PLL if we failed */

          if (ret)

--

2.28.0.806.g8561365e88-goog

 

 

Tested on the Lenovo C630, and haven’t seen the message, although I hadn’t seen the described issue before either.

Tested-By: Steev Klimaszewski <steev@xxxxxxxx>

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux