drm/i915/sdvo: If at first we don't succeed in reading the response, wait
We were not pausing after detecting the response was pending and so did not allow the hardware sufficient time to complete before aborting. This lead to transient failures whilst probing SDVO devices. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=30235 Reported-by: Knut Petersen <Knut_Petersen@t-online.de> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
8e934dbf26
commit
d121a5d2a0
|
@ -473,20 +473,6 @@ static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 3;
|
|
||||||
while (status == SDVO_CMD_STATUS_PENDING && i--) {
|
|
||||||
if (!intel_sdvo_read_byte(intel_sdvo,
|
|
||||||
SDVO_I2C_CMD_STATUS,
|
|
||||||
&status))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
||||||
DRM_DEBUG_KMS("command returns response %s [%d]\n",
|
|
||||||
status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP ? cmd_status_names[status] : "???",
|
|
||||||
status);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,6 +483,8 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
|
||||||
u8 status;
|
u8 status;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The documentation states that all commands will be
|
* The documentation states that all commands will be
|
||||||
* processed within 15µs, and that we need only poll
|
* processed within 15µs, and that we need only poll
|
||||||
|
@ -505,14 +493,19 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
|
||||||
*
|
*
|
||||||
* Check 5 times in case the hardware failed to read the docs.
|
* Check 5 times in case the hardware failed to read the docs.
|
||||||
*/
|
*/
|
||||||
do {
|
if (!intel_sdvo_read_byte(intel_sdvo,
|
||||||
|
SDVO_I2C_CMD_STATUS,
|
||||||
|
&status))
|
||||||
|
goto log_fail;
|
||||||
|
|
||||||
|
while (status == SDVO_CMD_STATUS_PENDING && retry--) {
|
||||||
|
udelay(15);
|
||||||
if (!intel_sdvo_read_byte(intel_sdvo,
|
if (!intel_sdvo_read_byte(intel_sdvo,
|
||||||
SDVO_I2C_CMD_STATUS,
|
SDVO_I2C_CMD_STATUS,
|
||||||
&status))
|
&status))
|
||||||
return false;
|
goto log_fail;
|
||||||
} while (status == SDVO_CMD_STATUS_PENDING && --retry);
|
}
|
||||||
|
|
||||||
DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo));
|
|
||||||
if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
|
if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
|
||||||
DRM_LOG_KMS("(%s)", cmd_status_names[status]);
|
DRM_LOG_KMS("(%s)", cmd_status_names[status]);
|
||||||
else
|
else
|
||||||
|
@ -533,7 +526,7 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
log_fail:
|
log_fail:
|
||||||
DRM_LOG_KMS("\n");
|
DRM_LOG_KMS("... failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,6 +543,7 @@ static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode)
|
||||||
static bool intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo,
|
static bool intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo,
|
||||||
u8 ddc_bus)
|
u8 ddc_bus)
|
||||||
{
|
{
|
||||||
|
/* This must be the immediately preceding write before the i2c xfer */
|
||||||
return intel_sdvo_write_cmd(intel_sdvo,
|
return intel_sdvo_write_cmd(intel_sdvo,
|
||||||
SDVO_CMD_SET_CONTROL_BUS_SWITCH,
|
SDVO_CMD_SET_CONTROL_BUS_SWITCH,
|
||||||
&ddc_bus, 1);
|
&ddc_bus, 1);
|
||||||
|
@ -557,7 +551,10 @@ static bool intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo,
|
||||||
|
|
||||||
static bool intel_sdvo_set_value(struct intel_sdvo *intel_sdvo, u8 cmd, const void *data, int len)
|
static bool intel_sdvo_set_value(struct intel_sdvo *intel_sdvo, u8 cmd, const void *data, int len)
|
||||||
{
|
{
|
||||||
return intel_sdvo_write_cmd(intel_sdvo, cmd, data, len);
|
if (!intel_sdvo_write_cmd(intel_sdvo, cmd, data, len))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return intel_sdvo_read_response(intel_sdvo, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -859,18 +856,21 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
|
||||||
|
|
||||||
intel_dip_infoframe_csum(&avi_if);
|
intel_dip_infoframe_csum(&avi_if);
|
||||||
|
|
||||||
if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_INDEX,
|
if (!intel_sdvo_set_value(intel_sdvo,
|
||||||
|
SDVO_CMD_SET_HBUF_INDEX,
|
||||||
set_buf_index, 2))
|
set_buf_index, 2))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(avi_if); i += 8) {
|
for (i = 0; i < sizeof(avi_if); i += 8) {
|
||||||
if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_DATA,
|
if (!intel_sdvo_set_value(intel_sdvo,
|
||||||
|
SDVO_CMD_SET_HBUF_DATA,
|
||||||
data, 8))
|
data, 8))
|
||||||
return false;
|
return false;
|
||||||
data++;
|
data++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_TXRATE,
|
return intel_sdvo_set_value(intel_sdvo,
|
||||||
|
SDVO_CMD_SET_HBUF_TXRATE,
|
||||||
&tx_rate, 1);
|
&tx_rate, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue