uint32 dp_get_link_rate(uint32 connectorIndex, display_mode* mode) { uint16 encoderID = gConnector[connectorIndex]->encoderExternal.objectID; if (encoderID == ENCODER_OBJECT_ID_NUTMEG) return 270000; dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo; uint32 laneCount = dp_get_lane_count(connectorIndex, mode); size_t pixelChunk; size_t pixelsPerChunk; status_t result = dp_get_pixel_size_for((color_space)mode->space, &pixelChunk, NULL, &pixelsPerChunk); if (result != B_OK) { TRACE("%s: Invalid color space!\n", __func__); return 0; } uint32 bitsPerPixel = (pixelChunk / pixelsPerChunk) * 8; uint32 maxPixelClock = dp_get_pixel_clock_max(162000, laneCount, bitsPerPixel); if (mode->timing.pixel_clock <= maxPixelClock) return 162000; maxPixelClock = dp_get_pixel_clock_max(270000, laneCount, bitsPerPixel); if (mode->timing.pixel_clock <= maxPixelClock) return 270000; // TODO: DisplayPort 1.2 #if 0 if (is_dp12_capable(connectorIndex)) { maxPixelClock = dp_get_pixel_clock_max(540000, laneCount, bitsPerPixel); if (mode->timing.pixel_clock <= maxPixelClock) return 540000; } #endif return dp_get_link_rate_max(dpInfo); }
status_t radeon_set_display_mode(display_mode* mode) { radeon_shared_info &info = *gInfo->shared_info; // Set mode on each display for (uint8 id = 0; id < MAX_DISPLAY; id++) { if (gDisplay[id]->attached == false) continue; uint32 connectorIndex = gDisplay[id]->connectorIndex; dp_info *dpInfo = &gConnector[connectorIndex]->dpInfo; // Determine DP lanes if DP if (connector_is_dp(connectorIndex)) dpInfo->laneCount = dp_get_lane_count(dpInfo, mode); // *** crtc and encoder prep encoder_output_lock(true); encoder_dpms_set(id, B_DPMS_OFF); display_crtc_lock(id, ATOM_ENABLE); display_crtc_dpms(id, B_DPMS_OFF); // *** Set up encoder -> crtc routing encoder_assign_crtc(id); // *** CRT controler mode set // TODO: program SS pll_set(ATOM_PPLL1, mode->timing.pixel_clock, id); // TODO: check if ATOM_PPLL1 is used and use ATOM_PPLL2 if so display_crtc_set_dtd(id, mode); display_crtc_fb_set(id, mode); // atombios_overscan_setup display_crtc_scale(id, mode); // *** encoder mode set encoder_mode_set(id); // *** CRT controler commit display_crtc_dpms(id, B_DPMS_ON); display_crtc_lock(id, ATOM_DISABLE); // *** encoder commit // handle DisplayPort link training if (connector_is_dp(connectorIndex)) { if (info.dceMajor >= 4) encoder_dig_setup(connectorIndex, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); dp_link_train(id, mode); if (info.dceMajor >= 4) encoder_dig_setup(connectorIndex, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); } encoder_dpms_set(id, B_DPMS_ON); encoder_output_lock(false); } // for debugging TRACE("D1CRTC_STATUS Value: 0x%X\n", Read32(CRT, AVIVO_D1CRTC_STATUS)); TRACE("D2CRTC_STATUS Value: 0x%X\n", Read32(CRT, AVIVO_D2CRTC_STATUS)); TRACE("D1CRTC_CONTROL Value: 0x%X\n", Read32(CRT, AVIVO_D1CRTC_CONTROL)); TRACE("D2CRTC_CONTROL Value: 0x%X\n", Read32(CRT, AVIVO_D2CRTC_CONTROL)); TRACE("D1GRPH_ENABLE Value: 0x%X\n", Read32(CRT, AVIVO_D1GRPH_ENABLE)); TRACE("D2GRPH_ENABLE Value: 0x%X\n", Read32(CRT, AVIVO_D2GRPH_ENABLE)); TRACE("D1SCL_ENABLE Value: 0x%X\n", Read32(CRT, AVIVO_D1SCL_SCALER_ENABLE)); TRACE("D2SCL_ENABLE Value: 0x%X\n", Read32(CRT, AVIVO_D2SCL_SCALER_ENABLE)); TRACE("D1CRTC_BLANK_CONTROL Value: 0x%X\n", Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); TRACE("D2CRTC_BLANK_CONTROL Value: 0x%X\n", Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); return B_OK; }
status_t radeon_set_display_mode(display_mode* mode) { // TODO: multi-monitor? For now we set the mode on // all displays (this is very incorrect). This also // causes a lot of problems on DisplayPort devices // Set mode on each display for (uint8 id = 0; id < MAX_DISPLAY; id++) { if (gDisplay[id]->attached == false) continue; // Copy this display mode into the "current mode" for the display memcpy(&gDisplay[id]->currentMode, mode, sizeof(display_mode)); uint32 connectorIndex = gDisplay[id]->connectorIndex; // Determine DP lanes if DP if (connector_is_dp(connectorIndex)) { dp_info *dpInfo = &gConnector[connectorIndex]->dpInfo; dpInfo->laneCount = dp_get_lane_count(connectorIndex, mode); dpInfo->linkRate = dp_get_link_rate(connectorIndex, mode); } // *** crtc and encoder prep encoder_output_lock(true); display_crtc_lock(id, ATOM_ENABLE); radeon_dpms_set(id, B_DPMS_OFF); // *** Set up encoder -> crtc routing encoder_assign_crtc(id); // *** CRT controler mode set // Set up PLL for connector pll_pick(connectorIndex); pll_info* pll = &gConnector[connectorIndex]->encoder.pll; TRACE("%s: pll %d selected for connector %" B_PRIu32 "\n", __func__, pll->id, connectorIndex); pll_set(mode, id); display_crtc_set_dtd(id, mode); display_crtc_fb_set(id, mode); // atombios_overscan_setup display_crtc_scale(id, mode); // *** encoder mode set encoder_mode_set(id); // *** encoder and CRT controller commit radeon_dpms_set(id, B_DPMS_ON); display_crtc_lock(id, ATOM_DISABLE); encoder_output_lock(false); } #ifdef TRACE_MODE // for debugging debug_dp_info(); TRACE("D1CRTC_STATUS Value: 0x%X\n", Read32(CRT, AVIVO_D1CRTC_STATUS)); TRACE("D2CRTC_STATUS Value: 0x%X\n", Read32(CRT, AVIVO_D2CRTC_STATUS)); TRACE("D1CRTC_CONTROL Value: 0x%X\n", Read32(CRT, AVIVO_D1CRTC_CONTROL)); TRACE("D2CRTC_CONTROL Value: 0x%X\n", Read32(CRT, AVIVO_D2CRTC_CONTROL)); TRACE("D1GRPH_ENABLE Value: 0x%X\n", Read32(CRT, AVIVO_D1GRPH_ENABLE)); TRACE("D2GRPH_ENABLE Value: 0x%X\n", Read32(CRT, AVIVO_D2GRPH_ENABLE)); TRACE("D1SCL_ENABLE Value: 0x%X\n", Read32(CRT, AVIVO_D1SCL_SCALER_ENABLE)); TRACE("D2SCL_ENABLE Value: 0x%X\n", Read32(CRT, AVIVO_D2SCL_SCALER_ENABLE)); TRACE("D1CRTC_BLANK_CONTROL Value: 0x%X\n", Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); TRACE("D2CRTC_BLANK_CONTROL Value: 0x%X\n", Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); #endif return B_OK; }
status_t radeon_set_display_mode(display_mode* mode) { radeon_shared_info &info = *gInfo->shared_info; // Set mode on each display for (uint8 id = 0; id < MAX_DISPLAY; id++) { if (gDisplay[id]->attached == false) continue; uint32 connectorIndex = gDisplay[id]->connectorIndex; // Determine DP lanes if DP if (connector_is_dp(connectorIndex)) { dp_info *dpInfo = &gConnector[connectorIndex]->dpInfo; dpInfo->laneCount = dp_get_lane_count(connectorIndex, mode); dpInfo->linkRate = dp_get_link_rate(connectorIndex, mode); } // *** crtc and encoder prep encoder_output_lock(true); encoder_dpms_set(id, B_DPMS_OFF); display_crtc_lock(id, ATOM_ENABLE); display_crtc_dpms(id, B_DPMS_OFF); // *** Set up encoder -> crtc routing encoder_assign_crtc(id); // *** CRT controler mode set // Set up PLL for connector pll_pick(connectorIndex); pll_info* pll = &gConnector[connectorIndex]->encoder.pll; TRACE("%s: pll %d selected for connector %" B_PRIu32 "\n", __func__, pll->id, connectorIndex); pll_set(mode, id); display_crtc_set_dtd(id, mode); display_crtc_fb_set(id, mode); // atombios_overscan_setup display_crtc_scale(id, mode); // *** encoder mode set encoder_mode_set(id); // *** CRT controler commit display_crtc_dpms(id, B_DPMS_ON); display_crtc_lock(id, ATOM_DISABLE); // *** encoder commit // handle DisplayPort link training if (connector_is_dp(connectorIndex)) { if (info.dceMajor >= 4) encoder_dig_setup(connectorIndex, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); dp_link_train(connectorIndex, mode); if (info.dceMajor >= 4) encoder_dig_setup(connectorIndex, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); } encoder_dpms_set(id, B_DPMS_ON); encoder_output_lock(false); } // for debugging // debug_dp_info(); TRACE("D1CRTC_STATUS Value: 0x%X\n", Read32(CRT, AVIVO_D1CRTC_STATUS)); TRACE("D2CRTC_STATUS Value: 0x%X\n", Read32(CRT, AVIVO_D2CRTC_STATUS)); TRACE("D1CRTC_CONTROL Value: 0x%X\n", Read32(CRT, AVIVO_D1CRTC_CONTROL)); TRACE("D2CRTC_CONTROL Value: 0x%X\n", Read32(CRT, AVIVO_D2CRTC_CONTROL)); TRACE("D1GRPH_ENABLE Value: 0x%X\n", Read32(CRT, AVIVO_D1GRPH_ENABLE)); TRACE("D2GRPH_ENABLE Value: 0x%X\n", Read32(CRT, AVIVO_D2GRPH_ENABLE)); TRACE("D1SCL_ENABLE Value: 0x%X\n", Read32(CRT, AVIVO_D1SCL_SCALER_ENABLE)); TRACE("D2SCL_ENABLE Value: 0x%X\n", Read32(CRT, AVIVO_D2SCL_SCALER_ENABLE)); TRACE("D1CRTC_BLANK_CONTROL Value: 0x%X\n", Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); TRACE("D2CRTC_BLANK_CONTROL Value: 0x%X\n", Read32(CRT, AVIVO_D1CRTC_BLANK_CONTROL)); return B_OK; }