|
@@ -2608,10 +2608,152 @@ static void evergreen_agp_enable(struct radeon_device *rdev)
|
|
|
WREG32(VM_CONTEXT1_CNTL, 0);
|
|
|
}
|
|
|
|
|
|
+static const unsigned ni_dig_offsets[] =
|
|
|
+{
|
|
|
+ NI_DIG0_REGISTER_OFFSET,
|
|
|
+ NI_DIG1_REGISTER_OFFSET,
|
|
|
+ NI_DIG2_REGISTER_OFFSET,
|
|
|
+ NI_DIG3_REGISTER_OFFSET,
|
|
|
+ NI_DIG4_REGISTER_OFFSET,
|
|
|
+ NI_DIG5_REGISTER_OFFSET
|
|
|
+};
|
|
|
+
|
|
|
+static const unsigned ni_tx_offsets[] =
|
|
|
+{
|
|
|
+ NI_DCIO_UNIPHY0_UNIPHY_TX_CONTROL1,
|
|
|
+ NI_DCIO_UNIPHY1_UNIPHY_TX_CONTROL1,
|
|
|
+ NI_DCIO_UNIPHY2_UNIPHY_TX_CONTROL1,
|
|
|
+ NI_DCIO_UNIPHY3_UNIPHY_TX_CONTROL1,
|
|
|
+ NI_DCIO_UNIPHY4_UNIPHY_TX_CONTROL1,
|
|
|
+ NI_DCIO_UNIPHY5_UNIPHY_TX_CONTROL1
|
|
|
+};
|
|
|
+
|
|
|
+static const unsigned evergreen_dp_offsets[] =
|
|
|
+{
|
|
|
+ EVERGREEN_DP0_REGISTER_OFFSET,
|
|
|
+ EVERGREEN_DP1_REGISTER_OFFSET,
|
|
|
+ EVERGREEN_DP2_REGISTER_OFFSET,
|
|
|
+ EVERGREEN_DP3_REGISTER_OFFSET,
|
|
|
+ EVERGREEN_DP4_REGISTER_OFFSET,
|
|
|
+ EVERGREEN_DP5_REGISTER_OFFSET
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * Assumption is that EVERGREEN_CRTC_MASTER_EN enable for requested crtc
|
|
|
+ * We go from crtc to connector and it is not relible since it
|
|
|
+ * should be an opposite direction .If crtc is enable then
|
|
|
+ * find the dig_fe which selects this crtc and insure that it enable.
|
|
|
+ * if such dig_fe is found then find dig_be which selects found dig_be and
|
|
|
+ * insure that it enable and in DP_SST mode.
|
|
|
+ * if UNIPHY_PLL_CONTROL1.enable then we should disconnect timing
|
|
|
+ * from dp symbols clocks .
|
|
|
+ */
|
|
|
+static bool evergreen_is_dp_sst_stream_enabled(struct radeon_device *rdev,
|
|
|
+ unsigned crtc_id, unsigned *ret_dig_fe)
|
|
|
+{
|
|
|
+ unsigned i;
|
|
|
+ unsigned dig_fe;
|
|
|
+ unsigned dig_be;
|
|
|
+ unsigned dig_en_be;
|
|
|
+ unsigned uniphy_pll;
|
|
|
+ unsigned digs_fe_selected;
|
|
|
+ unsigned dig_be_mode;
|
|
|
+ unsigned dig_fe_mask;
|
|
|
+ bool is_enabled = false;
|
|
|
+ bool found_crtc = false;
|
|
|
+
|
|
|
+ /* loop through all running dig_fe to find selected crtc */
|
|
|
+ for (i = 0; i < ARRAY_SIZE(ni_dig_offsets); i++) {
|
|
|
+ dig_fe = RREG32(NI_DIG_FE_CNTL + ni_dig_offsets[i]);
|
|
|
+ if (dig_fe & NI_DIG_FE_CNTL_SYMCLK_FE_ON &&
|
|
|
+ crtc_id == NI_DIG_FE_CNTL_SOURCE_SELECT(dig_fe)) {
|
|
|
+ /* found running pipe */
|
|
|
+ found_crtc = true;
|
|
|
+ dig_fe_mask = 1 << i;
|
|
|
+ dig_fe = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (found_crtc) {
|
|
|
+ /* loop through all running dig_be to find selected dig_fe */
|
|
|
+ for (i = 0; i < ARRAY_SIZE(ni_dig_offsets); i++) {
|
|
|
+ dig_be = RREG32(NI_DIG_BE_CNTL + ni_dig_offsets[i]);
|
|
|
+ /* if dig_fe_selected by dig_be? */
|
|
|
+ digs_fe_selected = NI_DIG_BE_CNTL_FE_SOURCE_SELECT(dig_be);
|
|
|
+ dig_be_mode = NI_DIG_FE_CNTL_MODE(dig_be);
|
|
|
+ if (dig_fe_mask & digs_fe_selected &&
|
|
|
+ /* if dig_be in sst mode? */
|
|
|
+ dig_be_mode == NI_DIG_BE_DPSST) {
|
|
|
+ dig_en_be = RREG32(NI_DIG_BE_EN_CNTL +
|
|
|
+ ni_dig_offsets[i]);
|
|
|
+ uniphy_pll = RREG32(NI_DCIO_UNIPHY0_PLL_CONTROL1 +
|
|
|
+ ni_tx_offsets[i]);
|
|
|
+ /* dig_be enable and tx is running */
|
|
|
+ if (dig_en_be & NI_DIG_BE_EN_CNTL_ENABLE &&
|
|
|
+ dig_en_be & NI_DIG_BE_EN_CNTL_SYMBCLK_ON &&
|
|
|
+ uniphy_pll & NI_DCIO_UNIPHY0_PLL_CONTROL1_ENABLE) {
|
|
|
+ is_enabled = true;
|
|
|
+ *ret_dig_fe = dig_fe;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return is_enabled;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Blank dig when in dp sst mode
|
|
|
+ * Dig ignores crtc timing
|
|
|
+ */
|
|
|
+static void evergreen_blank_dp_output(struct radeon_device *rdev,
|
|
|
+ unsigned dig_fe)
|
|
|
+{
|
|
|
+ unsigned stream_ctrl;
|
|
|
+ unsigned fifo_ctrl;
|
|
|
+ unsigned counter = 0;
|
|
|
+
|
|
|
+ if (dig_fe >= ARRAY_SIZE(evergreen_dp_offsets)) {
|
|
|
+ DRM_ERROR("invalid dig_fe %d\n", dig_fe);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ stream_ctrl = RREG32(EVERGREEN_DP_VID_STREAM_CNTL +
|
|
|
+ evergreen_dp_offsets[dig_fe]);
|
|
|
+ if (!(stream_ctrl & EVERGREEN_DP_VID_STREAM_CNTL_ENABLE)) {
|
|
|
+ DRM_ERROR("dig %d , should be enable\n", dig_fe);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ stream_ctrl &=~EVERGREEN_DP_VID_STREAM_CNTL_ENABLE;
|
|
|
+ WREG32(EVERGREEN_DP_VID_STREAM_CNTL +
|
|
|
+ evergreen_dp_offsets[dig_fe], stream_ctrl);
|
|
|
+
|
|
|
+ stream_ctrl = RREG32(EVERGREEN_DP_VID_STREAM_CNTL +
|
|
|
+ evergreen_dp_offsets[dig_fe]);
|
|
|
+ while (counter < 32 && stream_ctrl & EVERGREEN_DP_VID_STREAM_STATUS) {
|
|
|
+ msleep(1);
|
|
|
+ counter++;
|
|
|
+ stream_ctrl = RREG32(EVERGREEN_DP_VID_STREAM_CNTL +
|
|
|
+ evergreen_dp_offsets[dig_fe]);
|
|
|
+ }
|
|
|
+ if (counter >= 32 )
|
|
|
+ DRM_ERROR("counter exceeds %d\n", counter);
|
|
|
+
|
|
|
+ fifo_ctrl = RREG32(EVERGREEN_DP_STEER_FIFO + evergreen_dp_offsets[dig_fe]);
|
|
|
+ fifo_ctrl |= EVERGREEN_DP_STEER_FIFO_RESET;
|
|
|
+ WREG32(EVERGREEN_DP_STEER_FIFO + evergreen_dp_offsets[dig_fe], fifo_ctrl);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save)
|
|
|
{
|
|
|
u32 crtc_enabled, tmp, frame_count, blackout;
|
|
|
int i, j;
|
|
|
+ unsigned dig_fe;
|
|
|
|
|
|
if (!ASIC_IS_NODCE(rdev)) {
|
|
|
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
|
|
|
break;
|
|
|
udelay(1);
|
|
|
}
|
|
|
-
|
|
|
+ /*we should disable dig if it drives dp sst*/
|
|
|
+ /*but we are in radeon_device_init and the topology is unknown*/
|
|
|
+ /*and it is available after radeon_modeset_init*/
|
|
|
+ /*the following method radeon_atom_encoder_dpms_dig*/
|
|
|
+ /*does the job if we initialize it properly*/
|
|
|
+ /*for now we do it this manually*/
|
|
|
+ /**/
|
|
|
+ if (ASIC_IS_DCE5(rdev) &&
|
|
|
+ evergreen_is_dp_sst_stream_enabled(rdev, i ,&dig_fe))
|
|
|
+ evergreen_blank_dp_output(rdev, dig_fe);
|
|
|
+ /*we could remove 6 lines below*/
|
|
|
/* XXX this is a hack to avoid strange behavior with EFI on certain systems */
|
|
|
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
|
|
|
tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
|