Skip to content

Commit

Permalink
drm/radeon/kms: always do extended edid probe
Browse files Browse the repository at this point in the history
Rather than having a quirk list just always check the EDID header
when probing.  This is the recommended behavior according to the
display team.  This avoids problems with improperly terminated
i2c lines on some boards.  This is also what the proprietary
driver does.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Alex Deucher authored and Dave Airlie committed Nov 1, 2011
1 parent fab249e commit bc1c4dc
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 85 deletions.
69 changes: 6 additions & 63 deletions drivers/gpu/drm/radeon/radeon_connectors.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,55 +430,6 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
return 0;
}

/*
* Some integrated ATI Radeon chipset implementations (e. g.
* Asus M2A-VM HDMI) may indicate the availability of a DDC,
* even when there's no monitor connected. For these connectors
* following DDC probe extension will be applied: check also for the
* availability of EDID with at least a correct EDID header. Only then,
* DDC is assumed to be available. This prevents drm_get_edid() and
* drm_edid_block_valid() from periodically dumping data and kernel
* errors into the logs and onto the terminal.
*/
static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
uint32_t supported_device,
int connector_type)
{
/* Asus M2A-VM HDMI board sends data to i2c bus even,
* if HDMI add-on card is not plugged in or HDMI is disabled in
* BIOS. Valid DDC can only be assumed, if also a valid EDID header
* can be retrieved via i2c bus during DDC probe */
if ((dev->pdev->device == 0x791e) &&
(dev->pdev->subsystem_vendor == 0x1043) &&
(dev->pdev->subsystem_device == 0x826d)) {
if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
(supported_device == ATOM_DEVICE_DFP2_SUPPORT))
return true;
}
/* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
* for a DVI connector that is not implemented */
if ((dev->pdev->device == 0x796e) &&
(dev->pdev->subsystem_vendor == 0x1019) &&
(dev->pdev->subsystem_device == 0x2615)) {
if ((connector_type == DRM_MODE_CONNECTOR_DVID) &&
(supported_device == ATOM_DEVICE_DFP2_SUPPORT))
return true;
}
/* TOSHIBA Satellite L300D with ATI Mobility Radeon x1100
* (RS690M) sends data to i2c bus for a HDMI connector that
* is not implemented */
if ((dev->pdev->device == 0x791f) &&
(dev->pdev->subsystem_vendor == 0x1179) &&
(dev->pdev->subsystem_device == 0xff68)) {
if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
(supported_device == ATOM_DEVICE_DFP2_SUPPORT))
return true;
}

/* Default: no EDID header probe required for DDC probing */
return false;
}

static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
struct drm_connector *connector)
{
Expand Down Expand Up @@ -719,8 +670,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
ret = connector_status_disconnected;

if (radeon_connector->ddc_bus)
dret = radeon_ddc_probe(radeon_connector,
radeon_connector->requires_extended_probe);
dret = radeon_ddc_probe(radeon_connector);
if (dret) {
radeon_connector->detected_by_load = false;
if (radeon_connector->edid) {
Expand Down Expand Up @@ -902,8 +852,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
bool dret = false;

if (radeon_connector->ddc_bus)
dret = radeon_ddc_probe(radeon_connector,
radeon_connector->requires_extended_probe);
dret = radeon_ddc_probe(radeon_connector);
if (dret) {
radeon_connector->detected_by_load = false;
if (radeon_connector->edid) {
Expand Down Expand Up @@ -1327,8 +1276,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
if (encoder) {
/* setup ddc on the bridge */
radeon_atom_ext_encoder_setup_ddc(encoder);
if (radeon_ddc_probe(radeon_connector,
radeon_connector->requires_extended_probe)) /* try DDC */
if (radeon_ddc_probe(radeon_connector)) /* try DDC */
ret = connector_status_connected;
else if (radeon_connector->dac_load_detect) { /* try load detection */
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
Expand All @@ -1346,8 +1294,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
if (radeon_dp_getdpcd(radeon_connector))
ret = connector_status_connected;
} else {
if (radeon_ddc_probe(radeon_connector,
radeon_connector->requires_extended_probe))
if (radeon_ddc_probe(radeon_connector))
ret = connector_status_connected;
}
}
Expand Down Expand Up @@ -1492,9 +1439,7 @@ radeon_add_atom_connector(struct drm_device *dev,
radeon_connector->shared_ddc = shared_ddc;
radeon_connector->connector_object_id = connector_object_id;
radeon_connector->hpd = *hpd;
radeon_connector->requires_extended_probe =
radeon_connector_needs_extended_probe(rdev, supported_device,
connector_type);

radeon_connector->router = *router;
if (router->ddc_valid || router->cd_valid) {
radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
Expand Down Expand Up @@ -1842,9 +1787,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
radeon_connector->devices = supported_device;
radeon_connector->connector_object_id = connector_object_id;
radeon_connector->hpd = *hpd;
radeon_connector->requires_extended_probe =
radeon_connector_needs_extended_probe(rdev, supported_device,
connector_type);

switch (connector_type) {
case DRM_MODE_CONNECTOR_VGA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
Expand Down
28 changes: 11 additions & 17 deletions drivers/gpu/drm/radeon/radeon_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
* radeon_ddc_probe
*
*/
bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
{
u8 out = 0x0;
u8 buf[8];
Expand All @@ -47,15 +47,11 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_e
{
.addr = 0x50,
.flags = I2C_M_RD,
.len = 1,
.len = 8,
.buf = buf,
}
};

/* Read 8 bytes from i2c for extended probe of EDID header */
if (requires_extended_probe)
msgs[1].len = 8;

/* on hw with routers, select right port */
if (radeon_connector->router.ddc_valid)
radeon_router_select_ddc_port(radeon_connector);
Expand All @@ -64,17 +60,15 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_e
if (ret != 2)
/* Couldn't find an accessible DDC on this connector */
return false;
if (requires_extended_probe) {
/* Probe also for valid EDID header
* EDID header starts with:
* 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
* Only the first 6 bytes must be valid as
* drm_edid_block_valid() can fix the last 2 bytes */
if (drm_edid_header_is_valid(buf) < 6) {
/* Couldn't find an accessible EDID on this
* connector */
return false;
}
/* Probe also for valid EDID header
* EDID header starts with:
* 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
* Only the first 6 bytes must be valid as
* drm_edid_block_valid() can fix the last 2 bytes */
if (drm_edid_header_is_valid(buf) < 6) {
/* Couldn't find an accessible EDID on this
* connector */
return false;
}
return true;
}
Expand Down
6 changes: 1 addition & 5 deletions drivers/gpu/drm/radeon/radeon_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,6 @@ struct radeon_connector {
struct radeon_i2c_chan *ddc_bus;
/* some systems have an hdmi and vga port with a shared ddc line */
bool shared_ddc;
/* for some Radeon chip families we apply an additional EDID header
check as part of the DDC probe */
bool requires_extended_probe;
bool use_digital;
/* we need to mind the EDID between detect
and get modes due to analog/digital/tvencoder */
Expand Down Expand Up @@ -521,8 +518,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
u8 val);
extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
bool requires_extended_probe);
extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);

extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
Expand Down

0 comments on commit bc1c4dc

Please sign in to comment.