diff options
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_connectors.c | 45 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_i2c.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 6 |
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 | */ | ||
443 | static 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 | |||
433 | static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, | 463 | static 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 | */ |
35 | bool radeon_ddc_probe(struct radeon_connector *radeon_connector) | 35 | bool 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); |
515 | extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); | 518 | extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); |
516 | extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); | 519 | extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); |
517 | extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); | 520 | extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, |
521 | bool requires_extended_probe); | ||
518 | extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); | 522 | extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); |
519 | 523 | ||
520 | extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); | 524 | extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); |