aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2018-03-05 05:17:02 -0500
committerLinus Walleij <linus.walleij@linaro.org>2018-03-07 16:48:19 -0500
commit2e7a66a8b5ebf1b04a866e5d7c981640f7f62934 (patch)
treea100d4103f0aa011d1e9b8a4706306a2e5107023 /drivers
parent20a0dfeead0512af1d194ebaa8b0abe05323bbdb (diff)
drm/bridge: sii902x: Retry status read after DDI I2C
The following happens when connection a DVI output driven from the SiI9022 using a DVI-to-VGA adapter plug: i2c i2c-0: sendbytes: NAK bailout. i2c i2c-0: sendbytes: NAK bailout. Then no picture. Apparently the I2C engine inside the SiI9022 is not smart enough to try to fall back to DDC I2C. Or the vendor have not integrated the electronics properly. I don't know which one it is. After this, the I2C bus seems stalled and the first attempt to read the status register fails, and the code returns with negative return value, and the display fails to initialized. Instead, retry status readout five times and continue even if this fails. Tested on the ARM Versatile Express with a DVI-to-VGA connector, it now gives picture. Introduce a helper struct device *dev variable to make the code more readable. Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Liviu Dudau <Liviu.Dudau@arm.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20180305101702.13441-1-linus.walleij@linaro.org
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/bridge/sii902x.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index b1ab4ab09532..60373d7eb220 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -137,7 +137,9 @@ static int sii902x_get_modes(struct drm_connector *connector)
137 struct sii902x *sii902x = connector_to_sii902x(connector); 137 struct sii902x *sii902x = connector_to_sii902x(connector);
138 struct regmap *regmap = sii902x->regmap; 138 struct regmap *regmap = sii902x->regmap;
139 u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; 139 u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
140 struct device *dev = &sii902x->i2c->dev;
140 unsigned long timeout; 141 unsigned long timeout;
142 unsigned int retries;
141 unsigned int status; 143 unsigned int status;
142 struct edid *edid; 144 struct edid *edid;
143 int num = 0; 145 int num = 0;
@@ -159,7 +161,7 @@ static int sii902x_get_modes(struct drm_connector *connector)
159 time_before(jiffies, timeout)); 161 time_before(jiffies, timeout));
160 162
161 if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) { 163 if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
162 dev_err(&sii902x->i2c->dev, "failed to acquire the i2c bus\n"); 164 dev_err(dev, "failed to acquire the i2c bus\n");
163 return -ETIMEDOUT; 165 return -ETIMEDOUT;
164 } 166 }
165 167
@@ -179,9 +181,19 @@ static int sii902x_get_modes(struct drm_connector *connector)
179 if (ret) 181 if (ret)
180 return ret; 182 return ret;
181 183
182 ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA, &status); 184 /*
185 * Sometimes the I2C bus can stall after failure to use the
186 * EDID channel. Retry a few times to see if things clear
187 * up, else continue anyway.
188 */
189 retries = 5;
190 do {
191 ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA,
192 &status);
193 retries--;
194 } while (ret && retries);
183 if (ret) 195 if (ret)
184 return ret; 196 dev_err(dev, "failed to read status (%d)\n", ret);
185 197
186 ret = regmap_update_bits(regmap, SII902X_SYS_CTRL_DATA, 198 ret = regmap_update_bits(regmap, SII902X_SYS_CTRL_DATA,
187 SII902X_SYS_CTRL_DDC_BUS_REQ | 199 SII902X_SYS_CTRL_DDC_BUS_REQ |
@@ -201,7 +213,7 @@ static int sii902x_get_modes(struct drm_connector *connector)
201 213
202 if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ | 214 if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
203 SII902X_SYS_CTRL_DDC_BUS_GRTD)) { 215 SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
204 dev_err(&sii902x->i2c->dev, "failed to release the i2c bus\n"); 216 dev_err(dev, "failed to release the i2c bus\n");
205 return -ETIMEDOUT; 217 return -ETIMEDOUT;
206 } 218 }
207 219