[PATCH 9/9] drm/bridge: ti-sn65dsi86: Skip non-standard DP rates
From: Douglas Anderson
Date: Fri Dec 13 2019 - 18:46:17 EST
The bridge chip supports these DP rates according to TI's spec:
* 1.62 Gbps (RBR)
* 2.16 Gbps
* 2.43 Gbps
* 2.7 Gbps (HBR)
* 3.24 Gbps
* 4.32 Gbps
* 5.4 Gbps (HBR2)
As far as I can tell, only RBR, HBR, and HBR2 are part of the DP spec.
If other rates work then I believe it's because the sink has allowed
bending the spec a little bit.
I hoped that we could tell which rates would work and which rates
didn't work based on whether link training passed or not.
Unfortunately this wasn't so good on at least one panel hooked up to
the bridge (AUO B116XAK01). On that panel with 24 bpp configured:
* 1.62: too small for 69500 kHz at 24 bpp
* 2.16: link training failed
* 2.43: link training passed, but garbage on screen
* 2.7: joy and happiness
Let's bypass all non-standard rates, which makes this panel happy
working. I'll still keep the code organized in such a way where it
_could_ try the other rates, though, on the assumption that eventually
someone will find a way to make use of them.
Signed-off-by: Douglas Anderson <dianders@xxxxxxxxxxxx>
---
drivers/gpu/drm/bridge/ti-sn65dsi86.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index cc8bef172f69..cb774ee536cd 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -454,6 +454,15 @@ static const unsigned int ti_sn_bridge_dp_rate_lut[] = {
0, 1620, 2160, 2430, 2700, 3240, 4320, 5400
};
+/**
+ * A table indicating which of the rates in ti_sn_bridge_dp_rate_lut
+ * is as per the DP spec (AKA a standard) as opposed to an intermediate
+ * rate.
+ */
+static const bool ti_sn_bridge_dp_rate_standard[] = {
+ false, true, false, false, true, false, false, true
+};
+
static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn_bridge *pdata)
{
unsigned int bit_rate_khz, dp_rate_mhz;
@@ -660,6 +669,18 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge)
for (dp_rate_idx = ti_sn_bridge_calc_min_dp_rate_idx(pdata);
dp_rate_idx <= max_dp_rate_idx;
dp_rate_idx++) {
+ /*
+ * To be on the safe side, we'll skip all non-standard
+ * rates and move up to the next standard one. This is
+ * because some panels will pass link training with a non-
+ * standard rate but just show garbage. If the non-standard
+ * rates are useful we should figure out how to enable them
+ * through querying the panel, having a per-panel whitelist,
+ * or adding a DT property.
+ */
+ if (!ti_sn_bridge_dp_rate_standard[dp_rate_idx])
+ continue;
+
ret = ti_sn_link_training(pdata, dp_rate_idx, &last_err_str);
if (!ret)
break;
--
2.24.1.735.g03f4e72817-goog