<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style></head><body lang=EN-US link=blue vlink="#954F72"><div class=WordSection1><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><o:p> </o:p></p><div style='mso-element:para-border-div;border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><p class=MsoNormal style='border:none;padding:0in'><b>From: </b><a href="mailto:dianders@chromium.org">Douglas Anderson</a><br><b>Sent: </b>Friday, October 2, 2020 4:04 PM<br><b>To: </b><a href="mailto:a.hajda@samsung.com">Andrzej Hajda</a>; <a href="mailto:narmstrong@baylibre.com">Neil Armstrong</a>; <a href="mailto:sam@ravnborg.org">Sam Ravnborg</a><br><b>Cc: </b><a href="mailto:robdclark@chromium.org">Rob Clark</a>; <a href="mailto:bjorn.andersson@linaro.org">Bjorn Andersson</a>; <a href="mailto:steev@kali.org">Steev Klimaszewski</a>; <a href="mailto:dianders@chromium.org">Douglas Anderson</a>; <a href="mailto:daniel@ffwll.ch">Daniel Vetter</a>; <a href="mailto:airlied@linux.ie">David Airlie</a>; <a href="mailto:jernej.skrabec@siol.net">Jernej Skrabec</a>; <a href="mailto:jonas@kwiboo.se">Jonas Karlman</a>; <a href="mailto:Laurent.pinchart@ideasonboard.com">Laurent Pinchart</a>; <a href="mailto:dri-devel@lists.freedesktop.org">dri-devel@lists.freedesktop.org</a>; <a href="mailto:linux-kernel@vger.kernel.org">linux-kernel@vger.kernel.org</a><br><b>Subject: </b>[PATCH] drm/bridge: ti-sn65dsi86: Add retries for link training</p></div><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>On some panels hooked up to the ti-sn65dsi86 bridge chip we found that</p><p class=MsoNormal>link training was failing.  Specifically, we'd see:</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>  ti_sn65dsi86 2-002d: [drm:ti_sn_bridge_enable] *ERROR* Link training failed, link is off (-5)</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>The panel was hooked up to a logic analyzer and it was found that, as</p><p class=MsoNormal>part of link training, the bridge chip was writing a 0x1 to DPCD</p><p class=MsoNormal>address 00600h and the panel responded NACK.  As can be seen in header</p><p class=MsoNormal>files, the write of 0x1 to DPCD address 0x600h means we were trying to</p><p class=MsoNormal>write the value DP_SET_POWER_D0 to the register DP_SET_POWER.  The</p><p class=MsoNormal>panel vendor says that a NACK in this case is not unexpected and means</p><p class=MsoNormal>"not ready, try again".</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>In testing, we found that this panel would respond with a NACK in</p><p class=MsoNormal>about 1/25 times.  Adding the retry logic worked fine and the most</p><p class=MsoNormal>number of tries needed was 3.  Just to be safe, we'll add 10 tries</p><p class=MsoNormal>here and we'll add a little blurb to the logs if we ever need more</p><p class=MsoNormal>than 5.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Signed-off-by: Douglas Anderson <dianders@chromium.org></p><p class=MsoNormal>---</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal> drivers/gpu/drm/bridge/ti-sn65dsi86.c | 40 +++++++++++++++++++--------</p><p class=MsoNormal> 1 file changed, 29 insertions(+), 11 deletions(-)</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c</p><p class=MsoNormal>index ecdf9b01340f..6e12cda69b54 100644</p><p class=MsoNormal>--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c</p><p class=MsoNormal>+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c</p><p class=MsoNormal>@@ -106,6 +106,8 @@</p><p class=MsoNormal> #define SN_NUM_GPIOS                               4</p><p class=MsoNormal> #define SN_GPIO_PHYSICAL_OFFSET                     1</p><p class=MsoNormal> </p><p class=MsoNormal>+#define SN_LINK_TRAINING_TRIES            10</p><p class=MsoNormal>+</p><p class=MsoNormal> /**</p><p class=MsoNormal>  * struct ti_sn_bridge - Platform data for ti-sn65dsi86 driver.</p><p class=MsoNormal>  * @dev:          Pointer to our device.</p><p class=MsoNormal>@@ -673,6 +675,7 @@ static int ti_sn_link_training(struct ti_sn_bridge *pdata, int dp_rate_idx,</p><p class=MsoNormal> {</p><p class=MsoNormal>           unsigned int val;</p><p class=MsoNormal>           int ret;</p><p class=MsoNormal>+         int i;</p><p class=MsoNormal> </p><p class=MsoNormal>           /* set dp clk frequency value */</p><p class=MsoNormal>           regmap_update_bits(pdata->regmap, SN_DATARATE_CONFIG_REG,</p><p class=MsoNormal>@@ -689,19 +692,34 @@ static int ti_sn_link_training(struct ti_sn_bridge *pdata, int dp_rate_idx,</p><p class=MsoNormal>                      goto exit;</p><p class=MsoNormal>           }</p><p class=MsoNormal> </p><p class=MsoNormal>-          /* Semi auto link training mode */</p><p class=MsoNormal>-          regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0x0A);</p><p class=MsoNormal>-          ret = regmap_read_poll_timeout(pdata->regmap, SN_ML_TX_MODE_REG, val,</p><p class=MsoNormal>-                                                 val == ML_TX_MAIN_LINK_OFF ||</p><p class=MsoNormal>-                                                 val == ML_TX_NORMAL_MODE, 1000,</p><p class=MsoNormal>-                                                 500 * 1000);</p><p class=MsoNormal>-          if (ret) {</p><p class=MsoNormal>-                    *last_err_str = "Training complete polling failed";</p><p class=MsoNormal>-          } else if (val == ML_TX_MAIN_LINK_OFF) {</p><p class=MsoNormal>-                    *last_err_str = "Link training failed, link is off";</p><p class=MsoNormal>-                    ret = -EIO;</p><p class=MsoNormal>+         /*</p><p class=MsoNormal>+          * We'll try to link train several times.  As part of link training</p><p class=MsoNormal>+          * the bridge chip will write DP_SET_POWER_D0 to DP_SET_POWER.  If</p><p class=MsoNormal>+          * the panel isn't ready quite it might respond NAK here which means</p><p class=MsoNormal>+          * we need to try again.</p><p class=MsoNormal>+          */</p><p class=MsoNormal>+         for (i = 0; i < SN_LINK_TRAINING_TRIES; i++) {</p><p class=MsoNormal>+                    /* Semi auto link training mode */</p><p class=MsoNormal>+                    regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0x0A);</p><p class=MsoNormal>+                    ret = regmap_read_poll_timeout(pdata->regmap, SN_ML_TX_MODE_REG, val,</p><p class=MsoNormal>+                                                     val == ML_TX_MAIN_LINK_OFF ||</p><p class=MsoNormal>+                                                     val == ML_TX_NORMAL_MODE, 1000,</p><p class=MsoNormal>+                                                     500 * 1000);</p><p class=MsoNormal>+                    if (ret) {</p><p class=MsoNormal>+                               *last_err_str = "Training complete polling failed";</p><p class=MsoNormal>+                    } else if (val == ML_TX_MAIN_LINK_OFF) {</p><p class=MsoNormal>+                               *last_err_str = "Link training failed, link is off";</p><p class=MsoNormal>+                               ret = -EIO;</p><p class=MsoNormal>+                               continue;</p><p class=MsoNormal>+                    }</p><p class=MsoNormal>+</p><p class=MsoNormal>+                    break;</p><p class=MsoNormal>           }</p><p class=MsoNormal> </p><p class=MsoNormal>+         /* If we saw quite a few retries, add a note about it */</p><p class=MsoNormal>+         if (!ret && i > SN_LINK_TRAINING_TRIES / 2)</p><p class=MsoNormal>+                    DRM_DEV_INFO(pdata->dev, "Link training needed %d retries\n", i);</p><p class=MsoNormal>+</p><p class=MsoNormal> exit:</p><p class=MsoNormal>           /* Disable the PLL if we failed */</p><p class=MsoNormal>           if (ret)</p><p class=MsoNormal>-- </p><p class=MsoNormal>2.28.0.806.g8561365e88-goog</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Tested on the Lenovo C630, and haven’t seen the message, although I hadn’t seen the described issue before either.</p><p class=MsoNormal>Tested-By: Steev Klimaszewski <steev@kali.org></p></div></body></html>