aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorThomas Reim <reimth@gmail.com>2011-07-29 10:28:58 -0400
committerDave Airlie <airlied@redhat.com>2011-08-04 09:39:50 -0400
commite384fab8c6f3ca88600bcb2ebdf0eb2f90864fab (patch)
tree10477faf78310c3fb3fd4bbb9a81df9215b487d9 /drivers/gpu
parent051963d4832ed61e5ae74f5330b0a94489e101b9 (diff)
drm/radeon: Extended DDC Probing for Connectors with Improperly Wired DDC Lines (here: Asus M2A-VM HDMI)
Some integrated ATI Radeon chipset implementations with add-on HDMI card (e. g. Asus M2A-VM HDMI) indicate the availability of a DDC even when the add-on card is not plugged in or HDMI is disabled in BIOS setup. In this case, drm_get_edid() and drm_edid_block_valid() periodically dump data and kernel errors into system log files and onto terminals. For these connectors DDC probing is extended by a check for a correct EDID header. Only in case a valid EDID header is also found, the (HDMI or DVI) connector will be used by the Radeon driver. This prevents the kernel driver from useless flooding of logs and terminal sessions with EDID dumps and error messages. This patch adds a flag 'requires_extended_probe' to the radeon_connector structure. In function radeon_connector_needs_extended_probe() this flag can be set on a chipset family/vendor/connector type specific basis. In addition, function radeon_ddc_probe() has been adapted to perform extended DDC probing if required by the connector's flag. Requires function drm_edid_header_is_valid() in DRM module provided by [PATCH] drm: Separate EDID Header Check from EDID Block Check. Tested for kernel 2.6.35, 2.6.38 and 3.0 on Asus M2A-VM HDMI board BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=668196 BugLink: http://bugs.launchpad.net/bugs/7228066 Cc: <stable@kernel.org> Signed-off-by: Thomas Reim <reimth@gmail.com> Reviewed-by: Alex Deucher <alexdeucher@gmail.com> Acked-by: Stephen Michaels <Stephen.Micheals@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c45
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_i2c.c32
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h6
4 files changed, 80 insertions, 12 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 9792d4ffdc86..6a0f1befbc15 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -430,6 +430,36 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
430 return 0; 430 return 0;
431} 431}
432 432
433/*
434 * Some integrated ATI Radeon chipset implementations (e. g.
435 * Asus M2A-VM HDMI) may indicate the availability of a DDC,
436 * even when there's no monitor connected. For these connectors
437 * following DDC probe extension will be applied: check also for the
438 * availability of EDID with at least a correct EDID header. Only then,
439 * DDC is assumed to be available. This prevents drm_get_edid() and
440 * drm_edid_block_valid() from periodically dumping data and kernel
441 * errors into the logs and onto the terminal.
442 */
443static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
444 uint32_t supported_device,
445 int connector_type)
446{
447 /* Asus M2A-VM HDMI board sends data to i2c bus even,
448 * if HDMI add-on card is not plugged in or HDMI is disabled in
449 * BIOS. Valid DDC can only be assumed, if also a valid EDID header
450 * can be retrieved via i2c bus during DDC probe */
451 if ((dev->pdev->device == 0x791e) &&
452 (dev->pdev->subsystem_vendor == 0x1043) &&
453 (dev->pdev->subsystem_device == 0x826d)) {
454 if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
455 (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
456 return true;
457 }
458
459 /* Default: no EDID header probe required for DDC probing */
460 return false;
461}
462
433static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, 463static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
434 struct drm_connector *connector) 464 struct drm_connector *connector)
435{ 465{
@@ -661,7 +691,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
661 ret = connector_status_disconnected; 691 ret = connector_status_disconnected;
662 692
663 if (radeon_connector->ddc_bus) 693 if (radeon_connector->ddc_bus)
664 dret = radeon_ddc_probe(radeon_connector); 694 dret = radeon_ddc_probe(radeon_connector,
695 radeon_connector->requires_extended_probe);
665 if (dret) { 696 if (dret) {
666 if (radeon_connector->edid) { 697 if (radeon_connector->edid) {
667 kfree(radeon_connector->edid); 698 kfree(radeon_connector->edid);
@@ -833,7 +864,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
833 bool dret = false; 864 bool dret = false;
834 865
835 if (radeon_connector->ddc_bus) 866 if (radeon_connector->ddc_bus)
836 dret = radeon_ddc_probe(radeon_connector); 867 dret = radeon_ddc_probe(radeon_connector,
868 radeon_connector->requires_extended_probe);
837 if (dret) { 869 if (dret) {
838 if (radeon_connector->edid) { 870 if (radeon_connector->edid) {
839 kfree(radeon_connector->edid); 871 kfree(radeon_connector->edid);
@@ -1251,7 +1283,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
1251 if (radeon_dp_getdpcd(radeon_connector)) 1283 if (radeon_dp_getdpcd(radeon_connector))
1252 ret = connector_status_connected; 1284 ret = connector_status_connected;
1253 } else { 1285 } else {
1254 if (radeon_ddc_probe(radeon_connector)) 1286 if (radeon_ddc_probe(radeon_connector,
1287 radeon_connector->requires_extended_probe))
1255 ret = connector_status_connected; 1288 ret = connector_status_connected;
1256 } 1289 }
1257 } 1290 }
@@ -1406,6 +1439,9 @@ radeon_add_atom_connector(struct drm_device *dev,
1406 radeon_connector->shared_ddc = shared_ddc; 1439 radeon_connector->shared_ddc = shared_ddc;
1407 radeon_connector->connector_object_id = connector_object_id; 1440 radeon_connector->connector_object_id = connector_object_id;
1408 radeon_connector->hpd = *hpd; 1441 radeon_connector->hpd = *hpd;
1442 radeon_connector->requires_extended_probe =
1443 radeon_connector_needs_extended_probe(rdev, supported_device,
1444 connector_type);
1409 radeon_connector->router = *router; 1445 radeon_connector->router = *router;
1410 if (router->ddc_valid || router->cd_valid) { 1446 if (router->ddc_valid || router->cd_valid) {
1411 radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info); 1447 radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
@@ -1752,6 +1788,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
1752 radeon_connector->devices = supported_device; 1788 radeon_connector->devices = supported_device;
1753 radeon_connector->connector_object_id = connector_object_id; 1789 radeon_connector->connector_object_id = connector_object_id;
1754 radeon_connector->hpd = *hpd; 1790 radeon_connector->hpd = *hpd;
1791 radeon_connector->requires_extended_probe =
1792 radeon_connector_needs_extended_probe(rdev, supported_device,
1793 connector_type);
1755 switch (connector_type) { 1794 switch (connector_type) {
1756 case DRM_MODE_CONNECTOR_VGA: 1795 case DRM_MODE_CONNECTOR_VGA:
1757 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); 1796 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 28f4655905bc..1a858944e4f3 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -751,8 +751,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
751 if (!radeon_connector->ddc_bus) 751 if (!radeon_connector->ddc_bus)
752 return -1; 752 return -1;
753 edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); 753 edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
754 /* Log EDID retrieval status here. In particular with regard to
755 * connectors with requires_extended_probe flag set, that will prevent
756 * function radeon_dvi_detect() to fetch EDID on this connector,
757 * as long as there is no valid EDID header found */
754 if (edid) { 758 if (edid) {
759 DRM_INFO("Radeon display connector %s: Found valid EDID",
760 drm_get_connector_name(connector));
755 kfree(edid); 761 kfree(edid);
762 } else {
763 DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
764 drm_get_connector_name(connector));
756 } 765 }
757 return ret; 766 return ret;
758} 767}
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 781196db792f..6c111c1fa3f9 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -32,17 +32,17 @@
32 * radeon_ddc_probe 32 * radeon_ddc_probe
33 * 33 *
34 */ 34 */
35bool radeon_ddc_probe(struct radeon_connector *radeon_connector) 35bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
36{ 36{
37 u8 out_buf[] = { 0x0, 0x0}; 37 u8 out = 0x0;
38 u8 buf[2]; 38 u8 buf[8];
39 int ret; 39 int ret;
40 struct i2c_msg msgs[] = { 40 struct i2c_msg msgs[] = {
41 { 41 {
42 .addr = 0x50, 42 .addr = 0x50,
43 .flags = 0, 43 .flags = 0,
44 .len = 1, 44 .len = 1,
45 .buf = out_buf, 45 .buf = &out,
46 }, 46 },
47 { 47 {
48 .addr = 0x50, 48 .addr = 0x50,
@@ -52,15 +52,31 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
52 } 52 }
53 }; 53 };
54 54
55 /* Read 8 bytes from i2c for extended probe of EDID header */
56 if (requires_extended_probe)
57 msgs[1].len = 8;
58
55 /* on hw with routers, select right port */ 59 /* on hw with routers, select right port */
56 if (radeon_connector->router.ddc_valid) 60 if (radeon_connector->router.ddc_valid)
57 radeon_router_select_ddc_port(radeon_connector); 61 radeon_router_select_ddc_port(radeon_connector);
58 62
59 ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); 63 ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
60 if (ret == 2) 64 if (ret != 2)
61 return true; 65 /* Couldn't find an accessible DDC on this connector */
62 66 return false;
63 return false; 67 if (requires_extended_probe) {
68 /* Probe also for valid EDID header
69 * EDID header starts with:
70 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
71 * Only the first 6 bytes must be valid as
72 * drm_edid_block_valid() can fix the last 2 bytes */
73 if (drm_edid_header_is_valid(buf) < 6) {
74 /* Couldn't find an accessible EDID on this
75 * connector */
76 return false;
77 }
78 }
79 return true;
64} 80}
65 81
66/* bit banging i2c */ 82/* bit banging i2c */
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 6df4e3cec0c2..d09031c03e26 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -438,6 +438,9 @@ struct radeon_connector {
438 struct radeon_i2c_chan *ddc_bus; 438 struct radeon_i2c_chan *ddc_bus;
439 /* some systems have an hdmi and vga port with a shared ddc line */ 439 /* some systems have an hdmi and vga port with a shared ddc line */
440 bool shared_ddc; 440 bool shared_ddc;
441 /* for some Radeon chip families we apply an additional EDID header
442 check as part of the DDC probe */
443 bool requires_extended_probe;
441 bool use_digital; 444 bool use_digital;
442 /* we need to mind the EDID between detect 445 /* we need to mind the EDID between detect
443 and get modes due to analog/digital/tvencoder */ 446 and get modes due to analog/digital/tvencoder */
@@ -514,7 +517,8 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
514 u8 val); 517 u8 val);
515extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); 518extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
516extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); 519extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
517extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); 520extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
521 bool requires_extended_probe);
518extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); 522extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
519 523
520extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); 524extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);