diff options
| author | Alex Deucher <alexdeucher@gmail.com> | 2010-11-08 11:08:29 -0500 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2010-11-08 22:43:32 -0500 |
| commit | fb939dfcf2a3a70357000617799925b6a11f9348 (patch) | |
| tree | 7b307b6edbd6e6c6f7b8a93a9fc95e1d87abcc8f | |
| parent | dccb2a952b1f0b51978fcb3f9899c7f46ffd4b28 (diff) | |
drm/radeon/kms: add support for clock/data path routers
This is a follow on to:
26b5bc986423cf3887e09188cb662ed651c5374d
(drm/radeon/kms: add support for router objects)
That patch added support for systems that use a mux to control
the ddc line routing between the connectors. This patch adds
support for systems that use a mux to control the encoder
clock and data path routing to the connectors.
Should fix:
https://bugs.freedesktop.org/show_bug.cgi?id=31339
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 26 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_connectors.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_encoders.c | 8 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_i2c.c | 41 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 17 |
6 files changed, 85 insertions, 29 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 04cac7ec9039..a1de975eec30 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
| @@ -526,7 +526,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
| 526 | if (crev < 2) | 526 | if (crev < 2) |
| 527 | return false; | 527 | return false; |
| 528 | 528 | ||
| 529 | router.valid = false; | 529 | router.ddc_valid = false; |
| 530 | router.cd_valid = false; | ||
| 530 | 531 | ||
| 531 | obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset); | 532 | obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset); |
| 532 | path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) | 533 | path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) |
| @@ -647,7 +648,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
| 647 | usDeviceTag)); | 648 | usDeviceTag)); |
| 648 | 649 | ||
| 649 | } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) { | 650 | } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) { |
| 650 | router.valid = false; | 651 | router.ddc_valid = false; |
| 652 | router.cd_valid = false; | ||
| 651 | for (k = 0; k < router_obj->ucNumberOfObjects; k++) { | 653 | for (k = 0; k < router_obj->ucNumberOfObjects; k++) { |
| 652 | u16 router_obj_id = le16_to_cpu(router_obj->asObjects[j].usObjectID); | 654 | u16 router_obj_id = le16_to_cpu(router_obj->asObjects[j].usObjectID); |
| 653 | if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) { | 655 | if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) { |
| @@ -657,6 +659,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
| 657 | ATOM_I2C_RECORD *i2c_record; | 659 | ATOM_I2C_RECORD *i2c_record; |
| 658 | ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; | 660 | ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; |
| 659 | ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path; | 661 | ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path; |
| 662 | ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *cd_path; | ||
| 660 | ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table = | 663 | ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table = |
| 661 | (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *) | 664 | (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *) |
| 662 | (ctx->bios + data_offset + | 665 | (ctx->bios + data_offset + |
| @@ -690,10 +693,18 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
| 690 | case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE: | 693 | case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE: |
| 691 | ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *) | 694 | ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *) |
| 692 | record; | 695 | record; |
| 693 | router.valid = true; | 696 | router.ddc_valid = true; |
| 694 | router.mux_type = ddc_path->ucMuxType; | 697 | router.ddc_mux_type = ddc_path->ucMuxType; |
| 695 | router.mux_control_pin = ddc_path->ucMuxControlPin; | 698 | router.ddc_mux_control_pin = ddc_path->ucMuxControlPin; |
| 696 | router.mux_state = ddc_path->ucMuxState[enum_id]; | 699 | router.ddc_mux_state = ddc_path->ucMuxState[enum_id]; |
| 700 | break; | ||
| 701 | case ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE: | ||
| 702 | cd_path = (ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *) | ||
| 703 | record; | ||
| 704 | router.cd_valid = true; | ||
| 705 | router.cd_mux_type = cd_path->ucMuxType; | ||
| 706 | router.cd_mux_control_pin = cd_path->ucMuxControlPin; | ||
| 707 | router.cd_mux_state = cd_path->ucMuxState[enum_id]; | ||
| 697 | break; | 708 | break; |
| 698 | } | 709 | } |
| 699 | record = (ATOM_COMMON_RECORD_HEADER *) | 710 | record = (ATOM_COMMON_RECORD_HEADER *) |
| @@ -860,7 +871,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct | |||
| 860 | size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE; | 871 | size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE; |
| 861 | struct radeon_router router; | 872 | struct radeon_router router; |
| 862 | 873 | ||
| 863 | router.valid = false; | 874 | router.ddc_valid = false; |
| 875 | router.cd_valid = false; | ||
| 864 | 876 | ||
| 865 | bios_connectors = kzalloc(bc_size, GFP_KERNEL); | 877 | bios_connectors = kzalloc(bc_size, GFP_KERNEL); |
| 866 | if (!bios_connectors) | 878 | if (!bios_connectors) |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index a9d541534796..fe6c74780f18 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -1116,7 +1116,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1116 | radeon_connector->shared_ddc = true; | 1116 | radeon_connector->shared_ddc = true; |
| 1117 | shared_ddc = true; | 1117 | shared_ddc = true; |
| 1118 | } | 1118 | } |
| 1119 | if (radeon_connector->router_bus && router->valid && | 1119 | if (radeon_connector->router_bus && router->ddc_valid && |
| 1120 | (radeon_connector->router.router_id == router->router_id)) { | 1120 | (radeon_connector->router.router_id == router->router_id)) { |
| 1121 | radeon_connector->shared_ddc = false; | 1121 | radeon_connector->shared_ddc = false; |
| 1122 | shared_ddc = false; | 1122 | shared_ddc = false; |
| @@ -1136,7 +1136,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1136 | radeon_connector->connector_object_id = connector_object_id; | 1136 | radeon_connector->connector_object_id = connector_object_id; |
| 1137 | radeon_connector->hpd = *hpd; | 1137 | radeon_connector->hpd = *hpd; |
| 1138 | radeon_connector->router = *router; | 1138 | radeon_connector->router = *router; |
| 1139 | if (router->valid) { | 1139 | if (router->ddc_valid || router->cd_valid) { |
| 1140 | radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info); | 1140 | radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info); |
| 1141 | if (!radeon_connector->router_bus) | 1141 | if (!radeon_connector->router_bus) |
| 1142 | goto failed; | 1142 | goto failed; |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 0383631da69c..1df4dc6c063c 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -315,10 +315,14 @@ static void radeon_print_display_setup(struct drm_device *dev) | |||
| 315 | radeon_connector->ddc_bus->rec.en_data_reg, | 315 | radeon_connector->ddc_bus->rec.en_data_reg, |
| 316 | radeon_connector->ddc_bus->rec.y_clk_reg, | 316 | radeon_connector->ddc_bus->rec.y_clk_reg, |
| 317 | radeon_connector->ddc_bus->rec.y_data_reg); | 317 | radeon_connector->ddc_bus->rec.y_data_reg); |
| 318 | if (radeon_connector->router_bus) | 318 | if (radeon_connector->router.ddc_valid) |
| 319 | DRM_INFO(" DDC Router 0x%x/0x%x\n", | 319 | DRM_INFO(" DDC Router 0x%x/0x%x\n", |
| 320 | radeon_connector->router.mux_control_pin, | 320 | radeon_connector->router.ddc_mux_control_pin, |
| 321 | radeon_connector->router.mux_state); | 321 | radeon_connector->router.ddc_mux_state); |
| 322 | if (radeon_connector->router.cd_valid) | ||
| 323 | DRM_INFO(" Clock/Data Router 0x%x/0x%x\n", | ||
| 324 | radeon_connector->router.cd_mux_control_pin, | ||
| 325 | radeon_connector->router.cd_mux_state); | ||
| 322 | } else { | 326 | } else { |
| 323 | if (connector->connector_type == DRM_MODE_CONNECTOR_VGA || | 327 | if (connector->connector_type == DRM_MODE_CONNECTOR_VGA || |
| 324 | connector->connector_type == DRM_MODE_CONNECTOR_DVII || | 328 | connector->connector_type == DRM_MODE_CONNECTOR_DVII || |
| @@ -398,8 +402,8 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) | |||
| 398 | int ret = 0; | 402 | int ret = 0; |
| 399 | 403 | ||
| 400 | /* on hw with routers, select right port */ | 404 | /* on hw with routers, select right port */ |
| 401 | if (radeon_connector->router.valid) | 405 | if (radeon_connector->router.ddc_valid) |
| 402 | radeon_router_select_port(radeon_connector); | 406 | radeon_router_select_ddc_port(radeon_connector); |
| 403 | 407 | ||
| 404 | if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || | 408 | if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || |
| 405 | (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { | 409 | (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { |
| @@ -432,8 +436,8 @@ static int radeon_ddc_dump(struct drm_connector *connector) | |||
| 432 | int ret = 0; | 436 | int ret = 0; |
| 433 | 437 | ||
| 434 | /* on hw with routers, select right port */ | 438 | /* on hw with routers, select right port */ |
| 435 | if (radeon_connector->router.valid) | 439 | if (radeon_connector->router.ddc_valid) |
| 436 | radeon_router_select_port(radeon_connector); | 440 | radeon_router_select_ddc_port(radeon_connector); |
| 437 | 441 | ||
| 438 | if (!radeon_connector->ddc_bus) | 442 | if (!radeon_connector->ddc_bus) |
| 439 | return -1; | 443 | return -1; |
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index b862be61c398..f678257c42e6 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c | |||
| @@ -1520,6 +1520,7 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec | |||
| 1520 | static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) | 1520 | static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) |
| 1521 | { | 1521 | { |
| 1522 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 1522 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 1523 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | ||
| 1523 | 1524 | ||
| 1524 | if (radeon_encoder->active_device & | 1525 | if (radeon_encoder->active_device & |
| 1525 | (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { | 1526 | (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { |
| @@ -1531,6 +1532,13 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) | |||
| 1531 | radeon_atom_output_lock(encoder, true); | 1532 | radeon_atom_output_lock(encoder, true); |
| 1532 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | 1533 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); |
| 1533 | 1534 | ||
| 1535 | /* select the clock/data port if it uses a router */ | ||
| 1536 | if (connector) { | ||
| 1537 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 1538 | if (radeon_connector->router.cd_valid) | ||
| 1539 | radeon_router_select_cd_port(radeon_connector); | ||
| 1540 | } | ||
| 1541 | |||
| 1534 | /* this is needed for the pll/ss setup to work correctly in some cases */ | 1542 | /* this is needed for the pll/ss setup to work correctly in some cases */ |
| 1535 | atombios_set_encoder_crtc_source(encoder); | 1543 | atombios_set_encoder_crtc_source(encoder); |
| 1536 | } | 1544 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 6a13ee38a5b9..24b8a8be2cd4 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c | |||
| @@ -53,8 +53,8 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector) | |||
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | /* on hw with routers, select right port */ | 55 | /* on hw with routers, select right port */ |
| 56 | if (radeon_connector->router.valid) | 56 | if (radeon_connector->router.ddc_valid) |
| 57 | radeon_router_select_port(radeon_connector); | 57 | radeon_router_select_ddc_port(radeon_connector); |
| 58 | 58 | ||
| 59 | ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); | 59 | ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); |
| 60 | if (ret == 2) | 60 | if (ret == 2) |
| @@ -1084,26 +1084,51 @@ void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c_bus, | |||
| 1084 | addr, val); | 1084 | addr, val); |
| 1085 | } | 1085 | } |
| 1086 | 1086 | ||
| 1087 | /* router switching */ | 1087 | /* ddc router switching */ |
| 1088 | void radeon_router_select_port(struct radeon_connector *radeon_connector) | 1088 | void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector) |
| 1089 | { | 1089 | { |
| 1090 | u8 val; | 1090 | u8 val; |
| 1091 | 1091 | ||
| 1092 | if (!radeon_connector->router.valid) | 1092 | if (!radeon_connector->router.ddc_valid) |
| 1093 | return; | 1093 | return; |
| 1094 | 1094 | ||
| 1095 | radeon_i2c_get_byte(radeon_connector->router_bus, | 1095 | radeon_i2c_get_byte(radeon_connector->router_bus, |
| 1096 | radeon_connector->router.i2c_addr, | 1096 | radeon_connector->router.i2c_addr, |
| 1097 | 0x3, &val); | 1097 | 0x3, &val); |
| 1098 | val &= radeon_connector->router.mux_control_pin; | 1098 | val &= radeon_connector->router.ddc_mux_control_pin; |
| 1099 | radeon_i2c_put_byte(radeon_connector->router_bus, | 1099 | radeon_i2c_put_byte(radeon_connector->router_bus, |
| 1100 | radeon_connector->router.i2c_addr, | 1100 | radeon_connector->router.i2c_addr, |
| 1101 | 0x3, val); | 1101 | 0x3, val); |
| 1102 | radeon_i2c_get_byte(radeon_connector->router_bus, | 1102 | radeon_i2c_get_byte(radeon_connector->router_bus, |
| 1103 | radeon_connector->router.i2c_addr, | 1103 | radeon_connector->router.i2c_addr, |
| 1104 | 0x1, &val); | 1104 | 0x1, &val); |
| 1105 | val &= radeon_connector->router.mux_control_pin; | 1105 | val &= radeon_connector->router.ddc_mux_control_pin; |
| 1106 | val |= radeon_connector->router.mux_state; | 1106 | val |= radeon_connector->router.ddc_mux_state; |
| 1107 | radeon_i2c_put_byte(radeon_connector->router_bus, | ||
| 1108 | radeon_connector->router.i2c_addr, | ||
| 1109 | 0x1, val); | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | /* clock/data router switching */ | ||
| 1113 | void radeon_router_select_cd_port(struct radeon_connector *radeon_connector) | ||
| 1114 | { | ||
| 1115 | u8 val; | ||
| 1116 | |||
| 1117 | if (!radeon_connector->router.cd_valid) | ||
| 1118 | return; | ||
| 1119 | |||
| 1120 | radeon_i2c_get_byte(radeon_connector->router_bus, | ||
| 1121 | radeon_connector->router.i2c_addr, | ||
| 1122 | 0x3, &val); | ||
| 1123 | val &= radeon_connector->router.cd_mux_control_pin; | ||
| 1124 | radeon_i2c_put_byte(radeon_connector->router_bus, | ||
| 1125 | radeon_connector->router.i2c_addr, | ||
| 1126 | 0x3, val); | ||
| 1127 | radeon_i2c_get_byte(radeon_connector->router_bus, | ||
| 1128 | radeon_connector->router.i2c_addr, | ||
| 1129 | 0x1, &val); | ||
| 1130 | val &= radeon_connector->router.cd_mux_control_pin; | ||
| 1131 | val |= radeon_connector->router.cd_mux_state; | ||
| 1107 | radeon_i2c_put_byte(radeon_connector->router_bus, | 1132 | radeon_i2c_put_byte(radeon_connector->router_bus, |
| 1108 | radeon_connector->router.i2c_addr, | 1133 | radeon_connector->router.i2c_addr, |
| 1109 | 0x1, val); | 1134 | 0x1, val); |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 92457163d070..680f57644e86 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
| @@ -401,13 +401,19 @@ struct radeon_hpd { | |||
| 401 | }; | 401 | }; |
| 402 | 402 | ||
| 403 | struct radeon_router { | 403 | struct radeon_router { |
| 404 | bool valid; | ||
| 405 | u32 router_id; | 404 | u32 router_id; |
| 406 | struct radeon_i2c_bus_rec i2c_info; | 405 | struct radeon_i2c_bus_rec i2c_info; |
| 407 | u8 i2c_addr; | 406 | u8 i2c_addr; |
| 408 | u8 mux_type; | 407 | /* i2c mux */ |
| 409 | u8 mux_control_pin; | 408 | bool ddc_valid; |
| 410 | u8 mux_state; | 409 | u8 ddc_mux_type; |
| 410 | u8 ddc_mux_control_pin; | ||
| 411 | u8 ddc_mux_state; | ||
| 412 | /* clock/data mux */ | ||
| 413 | bool cd_valid; | ||
| 414 | u8 cd_mux_type; | ||
| 415 | u8 cd_mux_control_pin; | ||
| 416 | u8 cd_mux_state; | ||
| 411 | }; | 417 | }; |
| 412 | 418 | ||
| 413 | struct radeon_connector { | 419 | struct radeon_connector { |
| @@ -488,7 +494,8 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c, | |||
| 488 | u8 slave_addr, | 494 | u8 slave_addr, |
| 489 | u8 addr, | 495 | u8 addr, |
| 490 | u8 val); | 496 | u8 val); |
| 491 | extern void radeon_router_select_port(struct radeon_connector *radeon_connector); | 497 | extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); |
| 498 | extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); | ||
| 492 | extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); | 499 | extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); |
| 493 | extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); | 500 | extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); |
| 494 | 501 | ||
