Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 262565
b: refs/heads/master
c: e384fab
h: refs/heads/master
i:
  262563: 9faf378
v: v3
  • Loading branch information
Thomas Reim authored and Dave Airlie committed Aug 4, 2011
1 parent 6ce01f2 commit 70bb9da
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 051963d4832ed61e5ae74f5330b0a94489e101b9
refs/heads/master: e384fab8c6f3ca88600bcb2ebdf0eb2f90864fab
45 changes: 42 additions & 3 deletions trunk/drivers/gpu/drm/radeon/radeon_connectors.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,36 @@ 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;
}

/* 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 @@ -661,7 +691,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
ret = connector_status_disconnected;

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

if (radeon_connector->ddc_bus)
dret = radeon_ddc_probe(radeon_connector);
dret = radeon_ddc_probe(radeon_connector,
radeon_connector->requires_extended_probe);
if (dret) {
if (radeon_connector->edid) {
kfree(radeon_connector->edid);
Expand Down Expand Up @@ -1251,7 +1283,8 @@ 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))
if (radeon_ddc_probe(radeon_connector,
radeon_connector->requires_extended_probe))
ret = connector_status_connected;
}
}
Expand Down Expand Up @@ -1406,6 +1439,9 @@ 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 @@ -1752,6 +1788,9 @@ 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
9 changes: 9 additions & 0 deletions trunk/drivers/gpu/drm/radeon/radeon_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -751,8 +751,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
if (!radeon_connector->ddc_bus)
return -1;
edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
/* Log EDID retrieval status here. In particular with regard to
* connectors with requires_extended_probe flag set, that will prevent
* function radeon_dvi_detect() to fetch EDID on this connector,
* as long as there is no valid EDID header found */
if (edid) {
DRM_INFO("Radeon display connector %s: Found valid EDID",
drm_get_connector_name(connector));
kfree(edid);
} else {
DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
drm_get_connector_name(connector));
}
return ret;
}
Expand Down
32 changes: 24 additions & 8 deletions trunk/drivers/gpu/drm/radeon/radeon_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@
* radeon_ddc_probe
*
*/
bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
{
u8 out_buf[] = { 0x0, 0x0};
u8 buf[2];
u8 out = 0x0;
u8 buf[8];
int ret;
struct i2c_msg msgs[] = {
{
.addr = 0x50,
.flags = 0,
.len = 1,
.buf = out_buf,
.buf = &out,
},
{
.addr = 0x50,
Expand All @@ -52,15 +52,31 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
}
};

/* 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);

ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
if (ret == 2)
return true;

return false;
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;
}
}
return true;
}

/* bit banging i2c */
Expand Down
6 changes: 5 additions & 1 deletion trunk/drivers/gpu/drm/radeon/radeon_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,9 @@ 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 @@ -514,7 +517,8 @@ 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);
extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
bool requires_extended_probe);
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 70bb9da

Please sign in to comment.