diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/drm_edid.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index af60d9be9632..9c595e3b9c20 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -230,24 +230,32 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, | |||
230 | int block, int len) | 230 | int block, int len) |
231 | { | 231 | { |
232 | unsigned char start = block * EDID_LENGTH; | 232 | unsigned char start = block * EDID_LENGTH; |
233 | struct i2c_msg msgs[] = { | 233 | int ret, retries = 5; |
234 | { | ||
235 | .addr = DDC_ADDR, | ||
236 | .flags = 0, | ||
237 | .len = 1, | ||
238 | .buf = &start, | ||
239 | }, { | ||
240 | .addr = DDC_ADDR, | ||
241 | .flags = I2C_M_RD, | ||
242 | .len = len, | ||
243 | .buf = buf, | ||
244 | } | ||
245 | }; | ||
246 | 234 | ||
247 | if (i2c_transfer(adapter, msgs, 2) == 2) | 235 | /* The core i2c driver will automatically retry the transfer if the |
248 | return 0; | 236 | * adapter reports EAGAIN. However, we find that bit-banging transfers |
237 | * are susceptible to errors under a heavily loaded machine and | ||
238 | * generate spurious NAKs and timeouts. Retrying the transfer | ||
239 | * of the individual block a few times seems to overcome this. | ||
240 | */ | ||
241 | do { | ||
242 | struct i2c_msg msgs[] = { | ||
243 | { | ||
244 | .addr = DDC_ADDR, | ||
245 | .flags = 0, | ||
246 | .len = 1, | ||
247 | .buf = &start, | ||
248 | }, { | ||
249 | .addr = DDC_ADDR, | ||
250 | .flags = I2C_M_RD, | ||
251 | .len = len, | ||
252 | .buf = buf, | ||
253 | } | ||
254 | }; | ||
255 | ret = i2c_transfer(adapter, msgs, 2); | ||
256 | } while (ret != 2 && --retries); | ||
249 | 257 | ||
250 | return -1; | 258 | return ret == 2 ? 0 : -1; |
251 | } | 259 | } |
252 | 260 | ||
253 | static u8 * | 261 | static u8 * |