@@ -2427,6 +2427,338 @@ static enum link_training_result dp_perform_128b_132b_link_training(
2427
2427
}
2428
2428
#endif
2429
2429
2430
+ static enum link_training_result dc_link_dp_perform_fixed_vs_pe_training_sequence (
2431
+ struct dc_link * link ,
2432
+ struct link_training_settings * lt_settings )
2433
+ {
2434
+ const uint8_t vendor_lttpr_write_data_reset [4 ] = {0x1 , 0x50 , 0x63 , 0xFF };
2435
+ const uint8_t offset = dp_convert_to_count (
2436
+ link -> dpcd_caps .lttpr_caps .phy_repeater_cnt );
2437
+ const uint8_t vendor_lttpr_write_data_intercept_en [4 ] = {0x1 , 0x55 , 0x63 , 0x0 };
2438
+ const uint8_t vendor_lttpr_write_data_intercept_dis [4 ] = {0x1 , 0x55 , 0x63 , 0x68 };
2439
+ uint8_t vendor_lttpr_write_data_vs [4 ] = {0x1 , 0x51 , 0x63 , 0x0 };
2440
+ uint8_t vendor_lttpr_write_data_pe [4 ] = {0x1 , 0x52 , 0x63 , 0x0 };
2441
+ uint32_t vendor_lttpr_write_address = 0xF004F ;
2442
+ enum link_training_result status = LINK_TRAINING_SUCCESS ;
2443
+ uint8_t lane = 0 ;
2444
+ union down_spread_ctrl downspread = {0 };
2445
+ union lane_count_set lane_count_set = {0 };
2446
+ uint8_t toggle_rate ;
2447
+ uint8_t rate ;
2448
+
2449
+ /* Only 8b/10b is supported */
2450
+ ASSERT (dp_get_link_encoding_format (& lt_settings -> link_settings ) ==
2451
+ DP_8b_10b_ENCODING );
2452
+
2453
+ if (offset != 0xFF ) {
2454
+ vendor_lttpr_write_address +=
2455
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE ) * (offset - 1 ));
2456
+ }
2457
+
2458
+ /* Vendor specific: Reset lane settings */
2459
+ core_link_write_dpcd (
2460
+ link ,
2461
+ vendor_lttpr_write_address ,
2462
+ & vendor_lttpr_write_data_reset [0 ],
2463
+ sizeof (vendor_lttpr_write_data_reset ));
2464
+ core_link_write_dpcd (
2465
+ link ,
2466
+ vendor_lttpr_write_address ,
2467
+ & vendor_lttpr_write_data_vs [0 ],
2468
+ sizeof (vendor_lttpr_write_data_vs ));
2469
+ core_link_write_dpcd (
2470
+ link ,
2471
+ vendor_lttpr_write_address ,
2472
+ & vendor_lttpr_write_data_pe [0 ],
2473
+ sizeof (vendor_lttpr_write_data_pe ));
2474
+
2475
+ /* Vendor specific: Enable intercept */
2476
+ core_link_write_dpcd (
2477
+ link ,
2478
+ vendor_lttpr_write_address ,
2479
+ & vendor_lttpr_write_data_intercept_en [0 ],
2480
+ sizeof (vendor_lttpr_write_data_intercept_en ));
2481
+
2482
+ /* 1. set link rate, lane count and spread. */
2483
+
2484
+ downspread .raw = (uint8_t )(lt_settings -> link_settings .link_spread );
2485
+
2486
+ lane_count_set .bits .LANE_COUNT_SET =
2487
+ lt_settings -> link_settings .lane_count ;
2488
+
2489
+ lane_count_set .bits .ENHANCED_FRAMING = lt_settings -> enhanced_framing ;
2490
+ lane_count_set .bits .POST_LT_ADJ_REQ_GRANTED = 0 ;
2491
+
2492
+
2493
+ if (lt_settings -> pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4 ) {
2494
+ lane_count_set .bits .POST_LT_ADJ_REQ_GRANTED =
2495
+ link -> dpcd_caps .max_ln_count .bits .POST_LT_ADJ_REQ_SUPPORTED ;
2496
+ }
2497
+
2498
+ core_link_write_dpcd (link , DP_DOWNSPREAD_CTRL ,
2499
+ & downspread .raw , sizeof (downspread ));
2500
+
2501
+ core_link_write_dpcd (link , DP_LANE_COUNT_SET ,
2502
+ & lane_count_set .raw , 1 );
2503
+
2504
+ #if defined(CONFIG_DRM_AMD_DC_DCN )
2505
+ rate = get_dpcd_link_rate (& lt_settings -> link_settings );
2506
+ #else
2507
+ rate = (uint8_t ) (lt_settings -> link_settings .link_rate );
2508
+ #endif
2509
+
2510
+ /* Vendor specific: Toggle link rate */
2511
+ toggle_rate = (rate == 0x6 ) ? 0xA : 0x6 ;
2512
+
2513
+ if (link -> vendor_specific_lttpr_link_rate_wa == rate ) {
2514
+ core_link_write_dpcd (
2515
+ link ,
2516
+ DP_LINK_BW_SET ,
2517
+ & toggle_rate ,
2518
+ 1 );
2519
+ }
2520
+
2521
+ link -> vendor_specific_lttpr_link_rate_wa = rate ;
2522
+
2523
+ core_link_write_dpcd (link , DP_LINK_BW_SET , & rate , 1 );
2524
+
2525
+ DC_LOG_HW_LINK_TRAINING ("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n" ,
2526
+ __func__ ,
2527
+ DP_LINK_BW_SET ,
2528
+ lt_settings -> link_settings .link_rate ,
2529
+ DP_LANE_COUNT_SET ,
2530
+ lt_settings -> link_settings .lane_count ,
2531
+ lt_settings -> enhanced_framing ,
2532
+ DP_DOWNSPREAD_CTRL ,
2533
+ lt_settings -> link_settings .link_spread );
2534
+
2535
+ /* 2. Perform link training */
2536
+
2537
+ /* Perform Clock Recovery Sequence */
2538
+ if (status == LINK_TRAINING_SUCCESS ) {
2539
+ uint32_t retries_cr ;
2540
+ uint32_t retry_count ;
2541
+ uint32_t wait_time_microsec ;
2542
+ enum dc_lane_count lane_count = lt_settings -> link_settings .lane_count ;
2543
+ union lane_status dpcd_lane_status [LANE_COUNT_DP_MAX ];
2544
+ union lane_align_status_updated dpcd_lane_status_updated ;
2545
+ union lane_adjust dpcd_lane_adjust [LANE_COUNT_DP_MAX ] = {0 };
2546
+
2547
+ retries_cr = 0 ;
2548
+ retry_count = 0 ;
2549
+
2550
+ while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT ) &&
2551
+ (retry_count < LINK_TRAINING_MAX_CR_RETRY )) {
2552
+
2553
+ memset (& dpcd_lane_status , '\0' , sizeof (dpcd_lane_status ));
2554
+ memset (& dpcd_lane_status_updated , '\0' ,
2555
+ sizeof (dpcd_lane_status_updated ));
2556
+
2557
+ /* 1. call HWSS to set lane settings */
2558
+ dp_set_hw_lane_settings (
2559
+ link ,
2560
+ lt_settings ,
2561
+ 0 );
2562
+
2563
+ /* 2. update DPCD of the receiver */
2564
+ if (!retry_count ) {
2565
+ /* EPR #361076 - write as a 5-byte burst,
2566
+ * but only for the 1-st iteration.
2567
+ */
2568
+ dpcd_set_lt_pattern_and_lane_settings (
2569
+ link ,
2570
+ lt_settings ,
2571
+ lt_settings -> pattern_for_cr ,
2572
+ 0 );
2573
+ /* Vendor specific: Disable intercept */
2574
+ core_link_write_dpcd (
2575
+ link ,
2576
+ vendor_lttpr_write_address ,
2577
+ & vendor_lttpr_write_data_intercept_dis [0 ],
2578
+ sizeof (vendor_lttpr_write_data_intercept_dis ));
2579
+ } else {
2580
+ vendor_lttpr_write_data_vs [3 ] = 0 ;
2581
+ vendor_lttpr_write_data_pe [3 ] = 0 ;
2582
+
2583
+ for (lane = 0 ; lane < lane_count ; lane ++ ) {
2584
+ vendor_lttpr_write_data_vs [3 ] |=
2585
+ lt_settings -> dpcd_lane_settings [lane ].bits .VOLTAGE_SWING_SET << (2 * lane );
2586
+ vendor_lttpr_write_data_pe [3 ] |=
2587
+ lt_settings -> dpcd_lane_settings [lane ].bits .PRE_EMPHASIS_SET << (2 * lane );
2588
+ }
2589
+
2590
+ /* Vendor specific: Update VS and PE to DPRX requested value */
2591
+ core_link_write_dpcd (
2592
+ link ,
2593
+ vendor_lttpr_write_address ,
2594
+ & vendor_lttpr_write_data_vs [0 ],
2595
+ sizeof (vendor_lttpr_write_data_vs ));
2596
+ core_link_write_dpcd (
2597
+ link ,
2598
+ vendor_lttpr_write_address ,
2599
+ & vendor_lttpr_write_data_pe [0 ],
2600
+ sizeof (vendor_lttpr_write_data_pe ));
2601
+
2602
+ dpcd_set_lane_settings (
2603
+ link ,
2604
+ lt_settings ,
2605
+ 0 );
2606
+ }
2607
+
2608
+ /* 3. wait receiver to lock-on*/
2609
+ wait_time_microsec = lt_settings -> cr_pattern_time ;
2610
+
2611
+ dp_wait_for_training_aux_rd_interval (
2612
+ link ,
2613
+ wait_time_microsec );
2614
+
2615
+ /* 4. Read lane status and requested drive
2616
+ * settings as set by the sink
2617
+ */
2618
+ dp_get_lane_status_and_lane_adjust (
2619
+ link ,
2620
+ lt_settings ,
2621
+ dpcd_lane_status ,
2622
+ & dpcd_lane_status_updated ,
2623
+ dpcd_lane_adjust ,
2624
+ 0 );
2625
+
2626
+ /* 5. check CR done*/
2627
+ if (dp_is_cr_done (lane_count , dpcd_lane_status )) {
2628
+ status = LINK_TRAINING_SUCCESS ;
2629
+ break ;
2630
+ }
2631
+
2632
+ /* 6. max VS reached*/
2633
+ if (dp_is_max_vs_reached (lt_settings ))
2634
+ break ;
2635
+
2636
+ /* 7. same lane settings */
2637
+ /* Note: settings are the same for all lanes,
2638
+ * so comparing first lane is sufficient
2639
+ */
2640
+ if (lt_settings -> dpcd_lane_settings [0 ].bits .VOLTAGE_SWING_SET ==
2641
+ dpcd_lane_adjust [0 ].bits .VOLTAGE_SWING_LANE )
2642
+ retries_cr ++ ;
2643
+ else
2644
+ retries_cr = 0 ;
2645
+
2646
+ /* 8. update VS/PE/PC2 in lt_settings*/
2647
+ dp_decide_lane_settings (lt_settings , dpcd_lane_adjust ,
2648
+ lt_settings -> hw_lane_settings , lt_settings -> dpcd_lane_settings );
2649
+ retry_count ++ ;
2650
+ }
2651
+
2652
+ if (retry_count >= LINK_TRAINING_MAX_CR_RETRY ) {
2653
+ ASSERT (0 );
2654
+ DC_LOG_ERROR ("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue" ,
2655
+ __func__ ,
2656
+ LINK_TRAINING_MAX_CR_RETRY );
2657
+
2658
+ }
2659
+
2660
+ status = dp_get_cr_failure (lane_count , dpcd_lane_status );
2661
+ }
2662
+
2663
+ /* Perform Channel EQ Sequence */
2664
+ if (status == LINK_TRAINING_SUCCESS ) {
2665
+ enum dc_dp_training_pattern tr_pattern ;
2666
+ uint32_t retries_ch_eq ;
2667
+ uint32_t wait_time_microsec ;
2668
+ enum dc_lane_count lane_count = lt_settings -> link_settings .lane_count ;
2669
+ union lane_align_status_updated dpcd_lane_status_updated = {0 };
2670
+ union lane_status dpcd_lane_status [LANE_COUNT_DP_MAX ] = {0 };
2671
+ union lane_adjust dpcd_lane_adjust [LANE_COUNT_DP_MAX ] = {0 };
2672
+
2673
+ /* Note: also check that TPS4 is a supported feature*/
2674
+ tr_pattern = lt_settings -> pattern_for_eq ;
2675
+
2676
+ dp_set_hw_training_pattern (link , tr_pattern , 0 );
2677
+
2678
+ status = LINK_TRAINING_EQ_FAIL_EQ ;
2679
+
2680
+ for (retries_ch_eq = 0 ; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT ;
2681
+ retries_ch_eq ++ ) {
2682
+
2683
+ dp_set_hw_lane_settings (link , lt_settings , 0 );
2684
+
2685
+ vendor_lttpr_write_data_vs [3 ] = 0 ;
2686
+ vendor_lttpr_write_data_pe [3 ] = 0 ;
2687
+
2688
+ for (lane = 0 ; lane < lane_count ; lane ++ ) {
2689
+ vendor_lttpr_write_data_vs [3 ] |=
2690
+ lt_settings -> dpcd_lane_settings [lane ].bits .VOLTAGE_SWING_SET << (2 * lane );
2691
+ vendor_lttpr_write_data_pe [3 ] |=
2692
+ lt_settings -> dpcd_lane_settings [lane ].bits .PRE_EMPHASIS_SET << (2 * lane );
2693
+ }
2694
+
2695
+ /* Vendor specific: Update VS and PE to DPRX requested value */
2696
+ core_link_write_dpcd (
2697
+ link ,
2698
+ vendor_lttpr_write_address ,
2699
+ & vendor_lttpr_write_data_vs [0 ],
2700
+ sizeof (vendor_lttpr_write_data_vs ));
2701
+ core_link_write_dpcd (
2702
+ link ,
2703
+ vendor_lttpr_write_address ,
2704
+ & vendor_lttpr_write_data_pe [0 ],
2705
+ sizeof (vendor_lttpr_write_data_pe ));
2706
+
2707
+ /* 2. update DPCD*/
2708
+ if (!retries_ch_eq )
2709
+ /* EPR #361076 - write as a 5-byte burst,
2710
+ * but only for the 1-st iteration
2711
+ */
2712
+
2713
+ dpcd_set_lt_pattern_and_lane_settings (
2714
+ link ,
2715
+ lt_settings ,
2716
+ tr_pattern , 0 );
2717
+ else
2718
+ dpcd_set_lane_settings (link , lt_settings , 0 );
2719
+
2720
+ /* 3. wait for receiver to lock-on*/
2721
+ wait_time_microsec = lt_settings -> eq_pattern_time ;
2722
+
2723
+ dp_wait_for_training_aux_rd_interval (
2724
+ link ,
2725
+ wait_time_microsec );
2726
+
2727
+ /* 4. Read lane status and requested
2728
+ * drive settings as set by the sink
2729
+ */
2730
+ dp_get_lane_status_and_lane_adjust (
2731
+ link ,
2732
+ lt_settings ,
2733
+ dpcd_lane_status ,
2734
+ & dpcd_lane_status_updated ,
2735
+ dpcd_lane_adjust ,
2736
+ 0 );
2737
+
2738
+ /* 5. check CR done*/
2739
+ if (!dp_is_cr_done (lane_count , dpcd_lane_status )) {
2740
+ status = LINK_TRAINING_EQ_FAIL_CR ;
2741
+ break ;
2742
+ }
2743
+
2744
+ /* 6. check CHEQ done*/
2745
+ if (dp_is_ch_eq_done (lane_count , dpcd_lane_status ) &&
2746
+ dp_is_symbol_locked (lane_count , dpcd_lane_status ) &&
2747
+ dp_is_interlane_aligned (dpcd_lane_status_updated )) {
2748
+ status = LINK_TRAINING_SUCCESS ;
2749
+ break ;
2750
+ }
2751
+
2752
+ /* 7. update VS/PE/PC2 in lt_settings*/
2753
+ dp_decide_lane_settings (lt_settings , dpcd_lane_adjust ,
2754
+ lt_settings -> hw_lane_settings , lt_settings -> dpcd_lane_settings );
2755
+ }
2756
+ }
2757
+
2758
+ return status ;
2759
+ }
2760
+
2761
+
2430
2762
enum link_training_result dc_link_dp_perform_link_training (
2431
2763
struct dc_link * link ,
2432
2764
const struct dc_link_settings * link_settings ,
@@ -2466,7 +2798,11 @@ enum link_training_result dc_link_dp_perform_link_training(
2466
2798
* Per DP specs starting from here, DPTX device shall not issue
2467
2799
* Non-LT AUX transactions inside training mode.
2468
2800
*/
2469
- if (encoding == DP_8b_10b_ENCODING )
2801
+ if (!link -> dc -> debug .apply_vendor_specific_lttpr_wa &&
2802
+ (link -> chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN ) &&
2803
+ link -> lttpr_mode == LTTPR_MODE_TRANSPARENT )
2804
+ status = dc_link_dp_perform_fixed_vs_pe_training_sequence (link , & lt_settings );
2805
+ else if (encoding == DP_8b_10b_ENCODING )
2470
2806
status = dp_perform_8b_10b_link_training (link , & lt_settings );
2471
2807
#if defined(CONFIG_DRM_AMD_DC_DCN )
2472
2808
else if (encoding == DP_128b_132b_ENCODING )
0 commit comments