Skip to content

Commit f85634b

Browse files
linuswgregkh
authored andcommitted
drm/bridge: sii902x: Retry status read after DDI I2C
[ Upstream commit 2e7a66a ] 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ä <[email protected]> Reviewed-by: Liviu Dudau <[email protected]> Signed-off-by: Linus Walleij <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 3b64e1c commit f85634b

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

drivers/gpu/drm/bridge/sii902x.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ static int sii902x_get_modes(struct drm_connector *connector)
137137
struct sii902x *sii902x = connector_to_sii902x(connector);
138138
struct regmap *regmap = sii902x->regmap;
139139
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
140+
struct device *dev = &sii902x->i2c->dev;
140141
unsigned long timeout;
142+
unsigned int retries;
141143
unsigned int status;
142144
struct edid *edid;
143145
int num = 0;
@@ -159,7 +161,7 @@ static int sii902x_get_modes(struct drm_connector *connector)
159161
time_before(jiffies, timeout));
160162

161163
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");
163165
return -ETIMEDOUT;
164166
}
165167

@@ -179,9 +181,19 @@ static int sii902x_get_modes(struct drm_connector *connector)
179181
if (ret)
180182
return ret;
181183

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);
183195
if (ret)
184-
return ret;
196+
dev_err(dev, "failed to read status (%d)\n", ret);
185197

186198
ret = regmap_update_bits(regmap, SII902X_SYS_CTRL_DATA,
187199
SII902X_SYS_CTRL_DDC_BUS_REQ |
@@ -201,7 +213,7 @@ static int sii902x_get_modes(struct drm_connector *connector)
201213

202214
if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
203215
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");
205217
return -ETIMEDOUT;
206218
}
207219

0 commit comments

Comments
 (0)