Rev 2997 | Rev 3764 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2997 | Rev 3192 | ||
---|---|---|---|
Line 32... | Line 32... | ||
32 | #include "atom-bits.h" |
32 | #include "atom-bits.h" |
33 | #include |
33 | #include |
Line 34... | Line 34... | ||
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 |
- | |
37 | #define DP_LINK_STATUS_SIZE 6 |
36 | #define DP_LINK_CONFIGURATION_SIZE 9 |
Line 38... | Line 37... | ||
38 | #define DP_DPCD_SIZE 8 |
37 | #define DP_DPCD_SIZE DP_RECEIVER_CAP_SIZE |
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" |
Line 288... | Line 287... | ||
288 | return -EREMOTEIO; |
287 | return -EREMOTEIO; |
289 | } |
288 | } |
Line 290... | Line 289... | ||
290 | 289 | ||
Line 291... | Line -... | ||
291 | /***** general DP utility functions *****/ |
- | |
292 | - | ||
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 | } |
290 | /***** general DP utility functions *****/ |
364 | 291 | ||
Line 365... | Line 292... | ||
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 |
Line 372... | Line 299... | ||
372 | u8 v = 0; |
299 | u8 v = 0; |
373 | u8 p = 0; |
300 | u8 p = 0; |
374 | int lane; |
301 | int lane; |
Line 375... | Line 302... | ||
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); |
Line 378... | Line 305... | ||
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, |
Line 418... | Line 345... | ||
418 | int bpp) |
345 | int bpp) |
419 | { |
346 | { |
420 | return (link_rate * lane_num * 8) / bpp; |
347 | return (link_rate * lane_num * 8) / bpp; |
421 | } |
348 | } |
Line 422... | Line -... | ||
422 | - | ||
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 | 349 | ||
Line 454... | Line 350... | ||
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 |
Line 460... | Line 356... | ||
460 | static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, |
356 | static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, |
461 | u8 dpcd[DP_DPCD_SIZE], |
357 | u8 dpcd[DP_DPCD_SIZE], |
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; |
Line 469... | Line 365... | ||
469 | 365 | ||
470 | for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) { |
366 | for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) { |
Line 498... | Line 394... | ||
498 | max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp); |
394 | max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp); |
499 | if (pix_clock <= max_pix_clock) |
395 | if (pix_clock <= max_pix_clock) |
500 | return 540000; |
396 | return 540000; |
501 | } |
397 | } |
Line 502... | Line 398... | ||
502 | 398 | ||
503 | return dp_get_max_link_rate(dpcd); |
399 | return drm_dp_max_link_rate(dpcd); |
Line 504... | Line 400... | ||
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, |
Line 549... | Line 445... | ||
549 | } |
445 | } |
Line 550... | Line 446... | ||
550 | 446 | ||
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]; |
Line -... | Line 451... | ||
- | 451 | int ret, i; |
|
- | 452 | ||
555 | int ret, i; |
453 | ENTER(); |
- | 454 | ||
556 | 455 | ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg, |
|
557 | ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg, 8, 0); |
456 | DP_DPCD_SIZE, 0); |
558 | if (ret > 0) { |
457 | if (ret > 0) { |
559 | memcpy(dig_connector->dpcd, msg, 8); |
458 | memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); |
560 | DRM_DEBUG_KMS("DPCD: "); |
459 | DRM_DEBUG_KMS("DPCD: "); |
561 | for (i = 0; i < 8; i++) |
460 | for (i = 0; i < DP_DPCD_SIZE; i++) |
Line 562... | Line 461... | ||
562 | DRM_DEBUG_KMS("%02x ", msg[i]); |
461 | DRM_DEBUG_KMS("%02x ", msg[i]); |
563 | DRM_DEBUG_KMS("\n"); |
- | |
- | 462 | DRM_DEBUG_KMS("\n"); |
|
564 | 463 | ||
565 | radeon_dp_probe_oui(radeon_connector); |
464 | radeon_dp_probe_oui(radeon_connector); |
- | 465 | LEAVE(); |
|
566 | 466 | return true; |
|
567 | return true; |
467 | } |
568 | } |
468 | FAIL(); |
Line 569... | Line 469... | ||
569 | dig_connector->dpcd[0] = 0; |
469 | dig_connector->dpcd[0] = 0; |
Line 662... | Line 562... | ||
662 | u8 link_status[DP_LINK_STATUS_SIZE]; |
562 | u8 link_status[DP_LINK_STATUS_SIZE]; |
663 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; |
563 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; |
Line 664... | Line 564... | ||
664 | 564 | ||
665 | if (!radeon_dp_get_link_status(radeon_connector, link_status)) |
565 | if (!radeon_dp_get_link_status(radeon_connector, link_status)) |
666 | return false; |
566 | return false; |
667 | if (dp_channel_eq_ok(link_status, dig->dp_lane_count)) |
567 | if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count)) |
668 | return false; |
568 | return false; |
669 | return true; |
569 | return true; |
Line 670... | Line 570... | ||
670 | } |
570 | } |
Line 675... | Line 575... | ||
675 | struct drm_connector *connector; |
575 | struct drm_connector *connector; |
676 | struct radeon_connector *radeon_connector; |
576 | struct radeon_connector *radeon_connector; |
677 | int enc_id; |
577 | int enc_id; |
678 | int dp_clock; |
578 | int dp_clock; |
679 | int dp_lane_count; |
579 | int dp_lane_count; |
680 | int rd_interval; |
- | |
681 | bool tp3_supported; |
580 | bool tp3_supported; |
682 | u8 dpcd[8]; |
581 | u8 dpcd[DP_RECEIVER_CAP_SIZE]; |
683 | u8 train_set[4]; |
582 | u8 train_set[4]; |
684 | u8 link_status[DP_LINK_STATUS_SIZE]; |
583 | u8 link_status[DP_LINK_STATUS_SIZE]; |
685 | u8 tries; |
584 | u8 tries; |
686 | bool use_dpencoder; |
585 | bool use_dpencoder; |
687 | }; |
586 | }; |
Line 763... | Line 662... | ||
763 | dp_info->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP) |
662 | dp_info->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP) |
764 | tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN; |
663 | tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN; |
765 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp); |
664 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp); |
Line 766... | Line 665... | ||
766 | 665 | ||
767 | /* set the link rate on the sink */ |
666 | /* set the link rate on the sink */ |
768 | tmp = dp_get_dp_link_rate_coded(dp_info->dp_clock); |
667 | tmp = drm_dp_link_rate_to_bw_code(dp_info->dp_clock); |
Line 769... | Line 668... | ||
769 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp); |
668 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp); |
770 | 669 | ||
771 | /* start training on the source */ |
670 | /* start training on the source */ |
Line 819... | Line 718... | ||
819 | /* clock recovery loop */ |
718 | /* clock recovery loop */ |
820 | clock_recovery = false; |
719 | clock_recovery = false; |
821 | dp_info->tries = 0; |
720 | dp_info->tries = 0; |
822 | voltage = 0xff; |
721 | voltage = 0xff; |
823 | while (1) { |
722 | while (1) { |
824 | if (dp_info->rd_interval == 0) |
- | |
825 | udelay(100); |
- | |
826 | else |
- | |
827 | mdelay(dp_info->rd_interval * 4); |
723 | drm_dp_link_train_clock_recovery_delay(dp_info->dpcd); |
Line 828... | Line 724... | ||
828 | 724 | ||
829 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { |
725 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { |
830 | DRM_ERROR("displayport link status failed\n"); |
726 | DRM_ERROR("displayport link status failed\n"); |
831 | break; |
727 | break; |
Line 832... | Line 728... | ||
832 | } |
728 | } |
833 | 729 | ||
834 | if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
730 | if (drm_dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
835 | clock_recovery = true; |
731 | clock_recovery = true; |
Line 836... | Line 732... | ||
836 | break; |
732 | break; |
Line 884... | Line 780... | ||
884 | 780 | ||
885 | /* channel equalization loop */ |
781 | /* channel equalization loop */ |
886 | dp_info->tries = 0; |
782 | dp_info->tries = 0; |
887 | channel_eq = false; |
783 | channel_eq = false; |
888 | while (1) { |
- | |
889 | if (dp_info->rd_interval == 0) |
- | |
890 | udelay(400); |
- | |
891 | else |
784 | while (1) { |
Line 892... | Line 785... | ||
892 | mdelay(dp_info->rd_interval * 4); |
785 | drm_dp_link_train_channel_eq_delay(dp_info->dpcd); |
893 | 786 | ||
894 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { |
787 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { |
895 | DRM_ERROR("displayport link status failed\n"); |
788 | DRM_ERROR("displayport link status failed\n"); |
Line 896... | Line 789... | ||
896 | break; |
789 | break; |
897 | } |
790 | } |
898 | 791 | ||
899 | if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
792 | if (drm_dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
Line 900... | Line 793... | ||
900 | channel_eq = true; |
793 | channel_eq = true; |
Line 972... | Line 865... | ||
972 | if (dig->linkb) |
865 | if (dig->linkb) |
973 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_B; |
866 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_B; |
974 | else |
867 | else |
975 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; |
868 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; |
Line 976... | Line -... | ||
976 | - | ||
977 | dp_info.rd_interval = radeon_read_dpcd_reg(radeon_connector, DP_TRAINING_AUX_RD_INTERVAL); |
869 | |
978 | tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT); |
870 | tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT); |
979 | if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) |
871 | if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) |
980 | dp_info.tp3_supported = true; |
872 | dp_info.tp3_supported = true; |
981 | else |
873 | else |
Line 982... | Line 874... | ||
982 | dp_info.tp3_supported = false; |
874 | dp_info.tp3_supported = false; |
983 | 875 | ||
984 | memcpy(dp_info.dpcd, dig_connector->dpcd, 8); |
876 | memcpy(dp_info.dpcd, dig_connector->dpcd, DP_RECEIVER_CAP_SIZE); |
985 | dp_info.rdev = rdev; |
877 | dp_info.rdev = rdev; |
986 | dp_info.encoder = encoder; |
878 | dp_info.encoder = encoder; |
987 | dp_info.connector = connector; |
879 | dp_info.connector = connector; |