Exemplo n.º 1
0
status_t
pll_adjust(pll_info* pll, display_mode* mode, uint8 crtcID)
{
	radeon_shared_info &info = *gInfo->shared_info;

	uint32 pixelClock = pll->pixelClock;
		// original as pixel_clock will be adjusted

	uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
	connector_info* connector = gConnector[connectorIndex];

	uint32 encoderID = connector->encoder.objectID;
	uint32 encoderMode = display_get_encoder_mode(connectorIndex);
	uint32 connectorFlags = connector->flags;

	uint32 externalEncoderID = 0;
	pll->adjustedClock = pll->pixelClock;
	if (connector->encoderExternal.isDPBridge)
		externalEncoderID = connector->encoderExternal.objectID;

	if (info.dceMajor >= 3) {

		uint8 tableMajor;
		uint8 tableMinor;

		int index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
		if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
			!= B_OK) {
			ERROR("%s: Couldn't find AtomBIOS PLL adjustment\n", __func__);
			return B_ERROR;
		}

		TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__,
			tableMajor, tableMinor);

		// Prepare arguments for AtomBIOS call
		union adjustPixelClock {
			ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
			ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3;
		};
		union adjustPixelClock args;
		memset(&args, 0, sizeof(args));

		switch (tableMajor) {
			case 1:
				switch (tableMinor) {
					case 1:
					case 2:
						args.v1.usPixelClock
							= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
						args.v1.ucTransmitterID = encoderID;
						args.v1.ucEncodeMode = encoderMode;
						if (pll->ssPercentage > 0) {
							args.v1.ucConfig
								|= ADJUST_DISPLAY_CONFIG_SS_ENABLE;
						}

						atom_execute_table(gAtomContext, index, (uint32*)&args);
						// get returned adjusted clock
						pll->adjustedClock
							= B_LENDIAN_TO_HOST_INT16(args.v1.usPixelClock);
						pll->adjustedClock *= 10;
						break;
					case 3:
						args.v3.sInput.usPixelClock
							= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
						args.v3.sInput.ucTransmitterID = encoderID;
						args.v3.sInput.ucEncodeMode = encoderMode;
						args.v3.sInput.ucDispPllConfig = 0;
						if (pll->ssPercentage > 0) {
							args.v3.sInput.ucDispPllConfig
								|= DISPPLL_CONFIG_SS_ENABLE;
						}

						// Handle DP adjustments
						if (encoderMode == ATOM_ENCODER_MODE_DP
							|| encoderMode == ATOM_ENCODER_MODE_DP_MST) {
							TRACE("%s: encoderMode is DP\n", __func__);
							args.v3.sInput.ucDispPllConfig
								|= DISPPLL_CONFIG_COHERENT_MODE;
							/* 162000 or 270000 */
							uint32 dpLinkSpeed
								= dp_get_link_rate(connectorIndex, mode);
							/* 16200 or 27000 */
							args.v3.sInput.usPixelClock
								= B_HOST_TO_LENDIAN_INT16(dpLinkSpeed / 10);
						} else if ((connectorFlags & ATOM_DEVICE_DFP_SUPPORT)
							!= 0) {
							#if 0
							if (encoderMode == ATOM_ENCODER_MODE_HDMI) {
								/* deep color support */
								args.v3.sInput.usPixelClock =
									cpu_to_le16((mode->clock * bpc / 8) / 10);
							}
							#endif
							if (pixelClock > 165000) {
								args.v3.sInput.ucDispPllConfig
									|= DISPPLL_CONFIG_DUAL_LINK;
							}
							if (1) {	// dig coherent mode?
								args.v3.sInput.ucDispPllConfig
									|= DISPPLL_CONFIG_COHERENT_MODE;
							}
						}

						args.v3.sInput.ucExtTransmitterID = externalEncoderID;

						atom_execute_table(gAtomContext, index, (uint32*)&args);

						// get returned adjusted clock
						pll->adjustedClock = B_LENDIAN_TO_HOST_INT32(
								args.v3.sOutput.ulDispPllFreq);
						pll->adjustedClock *= 10;
							// convert to kHz for storage

						if (args.v3.sOutput.ucRefDiv) {
							pll->flags |= PLL_USE_FRAC_FB_DIV;
							pll->flags |= PLL_USE_REF_DIV;
							pll->referenceDiv = args.v3.sOutput.ucRefDiv;
						}
						if (args.v3.sOutput.ucPostDiv) {
							pll->flags |= PLL_USE_FRAC_FB_DIV;
							pll->flags |= PLL_USE_POST_DIV;
							pll->postDiv = args.v3.sOutput.ucPostDiv;
						}
						break;
					default:
						TRACE("%s: ERROR: table version %" B_PRIu8 ".%" B_PRIu8
							" unknown\n", __func__, tableMajor, tableMinor);
						return B_ERROR;
				}
				break;
			default:
				TRACE("%s: ERROR: table version %" B_PRIu8 ".%" B_PRIu8
					" unknown\n", __func__, tableMajor, tableMinor);
				return B_ERROR;
		}
	}

	TRACE("%s: was: %" B_PRIu32 ", now: %" B_PRIu32 "\n", __func__,
		pixelClock, pll->adjustedClock);

	return B_OK;
}
Exemplo n.º 2
0
Arquivo: mode.cpp Projeto: DonCN/haiku
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;
}
Exemplo n.º 3
0
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;
}