diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/atombios_dp.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/atombios_dp.c | 149 |
1 files changed, 19 insertions, 130 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index d5699fe4f1e8..064023bed480 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c | |||
| @@ -34,8 +34,7 @@ | |||
| 34 | 34 | ||
| 35 | /* move these to drm_dp_helper.c/h */ | 35 | /* move these to drm_dp_helper.c/h */ |
| 36 | #define DP_LINK_CONFIGURATION_SIZE 9 | 36 | #define DP_LINK_CONFIGURATION_SIZE 9 |
| 37 | #define DP_LINK_STATUS_SIZE 6 | 37 | #define DP_DPCD_SIZE DP_RECEIVER_CAP_SIZE |
| 38 | #define DP_DPCD_SIZE 8 | ||
| 39 | 38 | ||
| 40 | static char *voltage_names[] = { | 39 | static char *voltage_names[] = { |
| 41 | "0.4V", "0.6V", "0.8V", "1.2V" | 40 | "0.4V", "0.6V", "0.8V", "1.2V" |
| @@ -290,78 +289,6 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, | |||
| 290 | 289 | ||
| 291 | /***** general DP utility functions *****/ | 290 | /***** general DP utility functions *****/ |
| 292 | 291 | ||
| 293 | static u8 dp_link_status(u8 link_status[DP_LINK_STATUS_SIZE], int r) | ||
| 294 | { | ||
| 295 | return link_status[r - DP_LANE0_1_STATUS]; | ||
| 296 | } | ||
| 297 | |||
| 298 | static u8 dp_get_lane_status(u8 link_status[DP_LINK_STATUS_SIZE], | ||
| 299 | int lane) | ||
| 300 | { | ||
| 301 | int i = DP_LANE0_1_STATUS + (lane >> 1); | ||
| 302 | int s = (lane & 1) * 4; | ||
| 303 | u8 l = dp_link_status(link_status, i); | ||
| 304 | return (l >> s) & 0xf; | ||
| 305 | } | ||
| 306 | |||
| 307 | static bool dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE], | ||
| 308 | int lane_count) | ||
| 309 | { | ||
| 310 | int lane; | ||
| 311 | u8 lane_status; | ||
| 312 | |||
| 313 | for (lane = 0; lane < lane_count; lane++) { | ||
| 314 | lane_status = dp_get_lane_status(link_status, lane); | ||
| 315 | if ((lane_status & DP_LANE_CR_DONE) == 0) | ||
| 316 | return false; | ||
| 317 | } | ||
| 318 | return true; | ||
| 319 | } | ||
| 320 | |||
| 321 | static bool dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE], | ||
| 322 | int lane_count) | ||
| 323 | { | ||
| 324 | u8 lane_align; | ||
| 325 | u8 lane_status; | ||
| 326 | int lane; | ||
| 327 | |||
| 328 | lane_align = dp_link_status(link_status, | ||
| 329 | DP_LANE_ALIGN_STATUS_UPDATED); | ||
| 330 | if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) | ||
| 331 | return false; | ||
| 332 | for (lane = 0; lane < lane_count; lane++) { | ||
| 333 | lane_status = dp_get_lane_status(link_status, lane); | ||
| 334 | if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS) | ||
| 335 | return false; | ||
| 336 | } | ||
| 337 | return true; | ||
| 338 | } | ||
| 339 | |||
| 340 | static u8 dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE], | ||
| 341 | int lane) | ||
| 342 | |||
| 343 | { | ||
| 344 | int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); | ||
| 345 | int s = ((lane & 1) ? | ||
| 346 | DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : | ||
| 347 | DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); | ||
| 348 | u8 l = dp_link_status(link_status, i); | ||
| 349 | |||
| 350 | return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; | ||
| 351 | } | ||
| 352 | |||
| 353 | static u8 dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE], | ||
| 354 | int lane) | ||
| 355 | { | ||
| 356 | int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); | ||
| 357 | int s = ((lane & 1) ? | ||
| 358 | DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : | ||
| 359 | DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); | ||
| 360 | u8 l = dp_link_status(link_status, i); | ||
| 361 | |||
| 362 | return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; | ||
| 363 | } | ||
| 364 | |||
| 365 | #define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 | 292 | #define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 |
| 366 | #define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5 | 293 | #define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5 |
| 367 | 294 | ||
| @@ -374,8 +301,8 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], | |||
| 374 | int lane; | 301 | int lane; |
| 375 | 302 | ||
| 376 | for (lane = 0; lane < lane_count; lane++) { | 303 | for (lane = 0; lane < lane_count; lane++) { |
| 377 | u8 this_v = dp_get_adjust_request_voltage(link_status, lane); | 304 | u8 this_v = drm_dp_get_adjust_request_voltage(link_status, lane); |
| 378 | u8 this_p = dp_get_adjust_request_pre_emphasis(link_status, lane); | 305 | u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); |
| 379 | 306 | ||
| 380 | DRM_DEBUG_KMS("requested signal parameters: lane %d voltage %s pre_emph %s\n", | 307 | DRM_DEBUG_KMS("requested signal parameters: lane %d voltage %s pre_emph %s\n", |
| 381 | lane, | 308 | lane, |
| @@ -420,37 +347,6 @@ static int dp_get_max_dp_pix_clock(int link_rate, | |||
| 420 | return (link_rate * lane_num * 8) / bpp; | 347 | return (link_rate * lane_num * 8) / bpp; |
| 421 | } | 348 | } |
| 422 | 349 | ||
| 423 | static int dp_get_max_link_rate(u8 dpcd[DP_DPCD_SIZE]) | ||
| 424 | { | ||
| 425 | switch (dpcd[DP_MAX_LINK_RATE]) { | ||
| 426 | case DP_LINK_BW_1_62: | ||
| 427 | default: | ||
| 428 | return 162000; | ||
| 429 | case DP_LINK_BW_2_7: | ||
| 430 | return 270000; | ||
| 431 | case DP_LINK_BW_5_4: | ||
| 432 | return 540000; | ||
| 433 | } | ||
| 434 | } | ||
| 435 | |||
| 436 | static u8 dp_get_max_lane_number(u8 dpcd[DP_DPCD_SIZE]) | ||
| 437 | { | ||
| 438 | return dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; | ||
| 439 | } | ||
| 440 | |||
| 441 | static u8 dp_get_dp_link_rate_coded(int link_rate) | ||
| 442 | { | ||
| 443 | switch (link_rate) { | ||
| 444 | case 162000: | ||
| 445 | default: | ||
| 446 | return DP_LINK_BW_1_62; | ||
| 447 | case 270000: | ||
| 448 | return DP_LINK_BW_2_7; | ||
| 449 | case 540000: | ||
| 450 | return DP_LINK_BW_5_4; | ||
| 451 | } | ||
| 452 | } | ||
| 453 | |||
| 454 | /***** radeon specific DP functions *****/ | 350 | /***** radeon specific DP functions *****/ |
| 455 | 351 | ||
| 456 | /* First get the min lane# when low rate is used according to pixel clock | 352 | /* First get the min lane# when low rate is used according to pixel clock |
| @@ -462,8 +358,8 @@ static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, | |||
| 462 | int pix_clock) | 358 | int pix_clock) |
| 463 | { | 359 | { |
| 464 | int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); | 360 | int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); |
| 465 | int max_link_rate = dp_get_max_link_rate(dpcd); | 361 | int max_link_rate = drm_dp_max_link_rate(dpcd); |
| 466 | int max_lane_num = dp_get_max_lane_number(dpcd); | 362 | int max_lane_num = drm_dp_max_lane_count(dpcd); |
| 467 | int lane_num; | 363 | int lane_num; |
| 468 | int max_dp_pix_clock; | 364 | int max_dp_pix_clock; |
| 469 | 365 | ||
| @@ -500,7 +396,7 @@ static int radeon_dp_get_dp_link_clock(struct drm_connector *connector, | |||
| 500 | return 540000; | 396 | return 540000; |
| 501 | } | 397 | } |
| 502 | 398 | ||
| 503 | return dp_get_max_link_rate(dpcd); | 399 | return drm_dp_max_link_rate(dpcd); |
| 504 | } | 400 | } |
| 505 | 401 | ||
| 506 | static u8 radeon_dp_encoder_service(struct radeon_device *rdev, | 402 | static u8 radeon_dp_encoder_service(struct radeon_device *rdev, |
| @@ -551,14 +447,15 @@ static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) | |||
| 551 | bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) | 447 | bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) |
| 552 | { | 448 | { |
| 553 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; | 449 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
| 554 | u8 msg[25]; | 450 | u8 msg[DP_DPCD_SIZE]; |
| 555 | int ret, i; | 451 | int ret, i; |
| 556 | 452 | ||
| 557 | ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg, 8, 0); | 453 | ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg, |
| 454 | DP_DPCD_SIZE, 0); | ||
| 558 | if (ret > 0) { | 455 | if (ret > 0) { |
| 559 | memcpy(dig_connector->dpcd, msg, 8); | 456 | memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); |
| 560 | DRM_DEBUG_KMS("DPCD: "); | 457 | DRM_DEBUG_KMS("DPCD: "); |
| 561 | for (i = 0; i < 8; i++) | 458 | for (i = 0; i < DP_DPCD_SIZE; i++) |
| 562 | DRM_DEBUG_KMS("%02x ", msg[i]); | 459 | DRM_DEBUG_KMS("%02x ", msg[i]); |
| 563 | DRM_DEBUG_KMS("\n"); | 460 | DRM_DEBUG_KMS("\n"); |
| 564 | 461 | ||
| @@ -664,7 +561,7 @@ bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) | |||
| 664 | 561 | ||
| 665 | if (!radeon_dp_get_link_status(radeon_connector, link_status)) | 562 | if (!radeon_dp_get_link_status(radeon_connector, link_status)) |
| 666 | return false; | 563 | return false; |
| 667 | if (dp_channel_eq_ok(link_status, dig->dp_lane_count)) | 564 | if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count)) |
| 668 | return false; | 565 | return false; |
| 669 | return true; | 566 | return true; |
| 670 | } | 567 | } |
| @@ -677,9 +574,8 @@ struct radeon_dp_link_train_info { | |||
| 677 | int enc_id; | 574 | int enc_id; |
| 678 | int dp_clock; | 575 | int dp_clock; |
| 679 | int dp_lane_count; | 576 | int dp_lane_count; |
| 680 | int rd_interval; | ||
| 681 | bool tp3_supported; | 577 | bool tp3_supported; |
| 682 | u8 dpcd[8]; | 578 | u8 dpcd[DP_RECEIVER_CAP_SIZE]; |
| 683 | u8 train_set[4]; | 579 | u8 train_set[4]; |
| 684 | u8 link_status[DP_LINK_STATUS_SIZE]; | 580 | u8 link_status[DP_LINK_STATUS_SIZE]; |
| 685 | u8 tries; | 581 | u8 tries; |
| @@ -765,7 +661,7 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) | |||
| 765 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp); | 661 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp); |
| 766 | 662 | ||
| 767 | /* set the link rate on the sink */ | 663 | /* set the link rate on the sink */ |
| 768 | tmp = dp_get_dp_link_rate_coded(dp_info->dp_clock); | 664 | tmp = drm_dp_link_rate_to_bw_code(dp_info->dp_clock); |
| 769 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp); | 665 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp); |
| 770 | 666 | ||
| 771 | /* start training on the source */ | 667 | /* start training on the source */ |
| @@ -821,17 +717,14 @@ static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) | |||
| 821 | dp_info->tries = 0; | 717 | dp_info->tries = 0; |
| 822 | voltage = 0xff; | 718 | voltage = 0xff; |
| 823 | while (1) { | 719 | while (1) { |
| 824 | if (dp_info->rd_interval == 0) | 720 | drm_dp_link_train_clock_recovery_delay(dp_info->dpcd); |
| 825 | udelay(100); | ||
| 826 | else | ||
| 827 | mdelay(dp_info->rd_interval * 4); | ||
| 828 | 721 | ||
| 829 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { | 722 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { |
| 830 | DRM_ERROR("displayport link status failed\n"); | 723 | DRM_ERROR("displayport link status failed\n"); |
| 831 | break; | 724 | break; |
| 832 | } | 725 | } |
| 833 | 726 | ||
| 834 | if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { | 727 | if (drm_dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
| 835 | clock_recovery = true; | 728 | clock_recovery = true; |
| 836 | break; | 729 | break; |
| 837 | } | 730 | } |
| @@ -886,17 +779,14 @@ static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) | |||
| 886 | dp_info->tries = 0; | 779 | dp_info->tries = 0; |
| 887 | channel_eq = false; | 780 | channel_eq = false; |
| 888 | while (1) { | 781 | while (1) { |
| 889 | if (dp_info->rd_interval == 0) | 782 | drm_dp_link_train_channel_eq_delay(dp_info->dpcd); |
| 890 | udelay(400); | ||
| 891 | else | ||
| 892 | mdelay(dp_info->rd_interval * 4); | ||
| 893 | 783 | ||
| 894 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { | 784 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { |
| 895 | DRM_ERROR("displayport link status failed\n"); | 785 | DRM_ERROR("displayport link status failed\n"); |
| 896 | break; | 786 | break; |
| 897 | } | 787 | } |
| 898 | 788 | ||
| 899 | if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { | 789 | if (drm_dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
| 900 | channel_eq = true; | 790 | channel_eq = true; |
| 901 | break; | 791 | break; |
| 902 | } | 792 | } |
| @@ -974,14 +864,13 @@ void radeon_dp_link_train(struct drm_encoder *encoder, | |||
| 974 | else | 864 | else |
| 975 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; | 865 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; |
| 976 | 866 | ||
| 977 | dp_info.rd_interval = radeon_read_dpcd_reg(radeon_connector, DP_TRAINING_AUX_RD_INTERVAL); | ||
| 978 | tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT); | 867 | tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT); |
| 979 | if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) | 868 | if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) |
| 980 | dp_info.tp3_supported = true; | 869 | dp_info.tp3_supported = true; |
| 981 | else | 870 | else |
| 982 | dp_info.tp3_supported = false; | 871 | dp_info.tp3_supported = false; |
| 983 | 872 | ||
| 984 | memcpy(dp_info.dpcd, dig_connector->dpcd, 8); | 873 | memcpy(dp_info.dpcd, dig_connector->dpcd, DP_RECEIVER_CAP_SIZE); |
| 985 | dp_info.rdev = rdev; | 874 | dp_info.rdev = rdev; |
| 986 | dp_info.encoder = encoder; | 875 | dp_info.encoder = encoder; |
| 987 | dp_info.connector = connector; | 876 | dp_info.connector = connector; |
