@@ -2608,10 +2608,152 @@ static void evergreen_agp_enable(struct radeon_device *rdev)
26082608 WREG32 (VM_CONTEXT1_CNTL , 0 );
26092609}
26102610
2611+ static const unsigned ni_dig_offsets [] =
2612+ {
2613+ NI_DIG0_REGISTER_OFFSET ,
2614+ NI_DIG1_REGISTER_OFFSET ,
2615+ NI_DIG2_REGISTER_OFFSET ,
2616+ NI_DIG3_REGISTER_OFFSET ,
2617+ NI_DIG4_REGISTER_OFFSET ,
2618+ NI_DIG5_REGISTER_OFFSET
2619+ };
2620+
2621+ static const unsigned ni_tx_offsets [] =
2622+ {
2623+ NI_DCIO_UNIPHY0_UNIPHY_TX_CONTROL1 ,
2624+ NI_DCIO_UNIPHY1_UNIPHY_TX_CONTROL1 ,
2625+ NI_DCIO_UNIPHY2_UNIPHY_TX_CONTROL1 ,
2626+ NI_DCIO_UNIPHY3_UNIPHY_TX_CONTROL1 ,
2627+ NI_DCIO_UNIPHY4_UNIPHY_TX_CONTROL1 ,
2628+ NI_DCIO_UNIPHY5_UNIPHY_TX_CONTROL1
2629+ };
2630+
2631+ static const unsigned evergreen_dp_offsets [] =
2632+ {
2633+ EVERGREEN_DP0_REGISTER_OFFSET ,
2634+ EVERGREEN_DP1_REGISTER_OFFSET ,
2635+ EVERGREEN_DP2_REGISTER_OFFSET ,
2636+ EVERGREEN_DP3_REGISTER_OFFSET ,
2637+ EVERGREEN_DP4_REGISTER_OFFSET ,
2638+ EVERGREEN_DP5_REGISTER_OFFSET
2639+ };
2640+
2641+
2642+ /*
2643+ * Assumption is that EVERGREEN_CRTC_MASTER_EN enable for requested crtc
2644+ * We go from crtc to connector and it is not relible since it
2645+ * should be an opposite direction .If crtc is enable then
2646+ * find the dig_fe which selects this crtc and insure that it enable.
2647+ * if such dig_fe is found then find dig_be which selects found dig_be and
2648+ * insure that it enable and in DP_SST mode.
2649+ * if UNIPHY_PLL_CONTROL1.enable then we should disconnect timing
2650+ * from dp symbols clocks .
2651+ */
2652+ static bool evergreen_is_dp_sst_stream_enabled (struct radeon_device * rdev ,
2653+ unsigned crtc_id , unsigned * ret_dig_fe )
2654+ {
2655+ unsigned i ;
2656+ unsigned dig_fe ;
2657+ unsigned dig_be ;
2658+ unsigned dig_en_be ;
2659+ unsigned uniphy_pll ;
2660+ unsigned digs_fe_selected ;
2661+ unsigned dig_be_mode ;
2662+ unsigned dig_fe_mask ;
2663+ bool is_enabled = false;
2664+ bool found_crtc = false;
2665+
2666+ /* loop through all running dig_fe to find selected crtc */
2667+ for (i = 0 ; i < ARRAY_SIZE (ni_dig_offsets ); i ++ ) {
2668+ dig_fe = RREG32 (NI_DIG_FE_CNTL + ni_dig_offsets [i ]);
2669+ if (dig_fe & NI_DIG_FE_CNTL_SYMCLK_FE_ON &&
2670+ crtc_id == NI_DIG_FE_CNTL_SOURCE_SELECT (dig_fe )) {
2671+ /* found running pipe */
2672+ found_crtc = true;
2673+ dig_fe_mask = 1 << i ;
2674+ dig_fe = i ;
2675+ break ;
2676+ }
2677+ }
2678+
2679+ if (found_crtc ) {
2680+ /* loop through all running dig_be to find selected dig_fe */
2681+ for (i = 0 ; i < ARRAY_SIZE (ni_dig_offsets ); i ++ ) {
2682+ dig_be = RREG32 (NI_DIG_BE_CNTL + ni_dig_offsets [i ]);
2683+ /* if dig_fe_selected by dig_be? */
2684+ digs_fe_selected = NI_DIG_BE_CNTL_FE_SOURCE_SELECT (dig_be );
2685+ dig_be_mode = NI_DIG_FE_CNTL_MODE (dig_be );
2686+ if (dig_fe_mask & digs_fe_selected &&
2687+ /* if dig_be in sst mode? */
2688+ dig_be_mode == NI_DIG_BE_DPSST ) {
2689+ dig_en_be = RREG32 (NI_DIG_BE_EN_CNTL +
2690+ ni_dig_offsets [i ]);
2691+ uniphy_pll = RREG32 (NI_DCIO_UNIPHY0_PLL_CONTROL1 +
2692+ ni_tx_offsets [i ]);
2693+ /* dig_be enable and tx is running */
2694+ if (dig_en_be & NI_DIG_BE_EN_CNTL_ENABLE &&
2695+ dig_en_be & NI_DIG_BE_EN_CNTL_SYMBCLK_ON &&
2696+ uniphy_pll & NI_DCIO_UNIPHY0_PLL_CONTROL1_ENABLE ) {
2697+ is_enabled = true;
2698+ * ret_dig_fe = dig_fe ;
2699+ break ;
2700+ }
2701+ }
2702+ }
2703+ }
2704+
2705+ return is_enabled ;
2706+ }
2707+
2708+ /*
2709+ * Blank dig when in dp sst mode
2710+ * Dig ignores crtc timing
2711+ */
2712+ static void evergreen_blank_dp_output (struct radeon_device * rdev ,
2713+ unsigned dig_fe )
2714+ {
2715+ unsigned stream_ctrl ;
2716+ unsigned fifo_ctrl ;
2717+ unsigned counter = 0 ;
2718+
2719+ if (dig_fe >= ARRAY_SIZE (evergreen_dp_offsets )) {
2720+ DRM_ERROR ("invalid dig_fe %d\n" , dig_fe );
2721+ return ;
2722+ }
2723+
2724+ stream_ctrl = RREG32 (EVERGREEN_DP_VID_STREAM_CNTL +
2725+ evergreen_dp_offsets [dig_fe ]);
2726+ if (!(stream_ctrl & EVERGREEN_DP_VID_STREAM_CNTL_ENABLE )) {
2727+ DRM_ERROR ("dig %d , should be enable\n" , dig_fe );
2728+ return ;
2729+ }
2730+
2731+ stream_ctrl &=~EVERGREEN_DP_VID_STREAM_CNTL_ENABLE ;
2732+ WREG32 (EVERGREEN_DP_VID_STREAM_CNTL +
2733+ evergreen_dp_offsets [dig_fe ], stream_ctrl );
2734+
2735+ stream_ctrl = RREG32 (EVERGREEN_DP_VID_STREAM_CNTL +
2736+ evergreen_dp_offsets [dig_fe ]);
2737+ while (counter < 32 && stream_ctrl & EVERGREEN_DP_VID_STREAM_STATUS ) {
2738+ msleep (1 );
2739+ counter ++ ;
2740+ stream_ctrl = RREG32 (EVERGREEN_DP_VID_STREAM_CNTL +
2741+ evergreen_dp_offsets [dig_fe ]);
2742+ }
2743+ if (counter >= 32 )
2744+ DRM_ERROR ("counter exceeds %d\n" , counter );
2745+
2746+ fifo_ctrl = RREG32 (EVERGREEN_DP_STEER_FIFO + evergreen_dp_offsets [dig_fe ]);
2747+ fifo_ctrl |= EVERGREEN_DP_STEER_FIFO_RESET ;
2748+ WREG32 (EVERGREEN_DP_STEER_FIFO + evergreen_dp_offsets [dig_fe ], fifo_ctrl );
2749+
2750+ }
2751+
26112752void evergreen_mc_stop (struct radeon_device * rdev , struct evergreen_mc_save * save )
26122753{
26132754 u32 crtc_enabled , tmp , frame_count , blackout ;
26142755 int i , j ;
2756+ unsigned dig_fe ;
26152757
26162758 if (!ASIC_IS_NODCE (rdev )) {
26172759 save -> vga_render_control = RREG32 (VGA_RENDER_CONTROL );
@@ -2651,7 +2793,17 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
26512793 break ;
26522794 udelay (1 );
26532795 }
2654-
2796+ /*we should disable dig if it drives dp sst*/
2797+ /*but we are in radeon_device_init and the topology is unknown*/
2798+ /*and it is available after radeon_modeset_init*/
2799+ /*the following method radeon_atom_encoder_dpms_dig*/
2800+ /*does the job if we initialize it properly*/
2801+ /*for now we do it this manually*/
2802+ /**/
2803+ if (ASIC_IS_DCE5 (rdev ) &&
2804+ evergreen_is_dp_sst_stream_enabled (rdev , i ,& dig_fe ))
2805+ evergreen_blank_dp_output (rdev , dig_fe );
2806+ /*we could remove 6 lines below*/
26552807 /* XXX this is a hack to avoid strange behavior with EFI on certain systems */
26562808 WREG32 (EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets [i ], 1 );
26572809 tmp = RREG32 (EVERGREEN_CRTC_CONTROL + crtc_offsets [i ]);
0 commit comments