static void dml20v2_DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation()

in drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c [1145:2749]


static void dml20v2_DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(
		struct display_mode_lib *mode_lib)
{
	unsigned int j, k;

	mode_lib->vba.WritebackDISPCLK = 0.0;
	mode_lib->vba.DISPCLKWithRamping = 0;
	mode_lib->vba.DISPCLKWithoutRamping = 0;
	mode_lib->vba.GlobalDPPCLK = 0.0;

	// dml_ml->vba.DISPCLK and dml_ml->vba.DPPCLK Calculation
	//
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.WritebackEnable[k]) {
			mode_lib->vba.WritebackDISPCLK =
					dml_max(
							mode_lib->vba.WritebackDISPCLK,
							CalculateWriteBackDISPCLK(
									mode_lib->vba.WritebackPixelFormat[k],
									mode_lib->vba.PixelClock[k],
									mode_lib->vba.WritebackHRatio[k],
									mode_lib->vba.WritebackVRatio[k],
									mode_lib->vba.WritebackLumaHTaps[k],
									mode_lib->vba.WritebackLumaVTaps[k],
									mode_lib->vba.WritebackChromaHTaps[k],
									mode_lib->vba.WritebackChromaVTaps[k],
									mode_lib->vba.WritebackDestinationWidth[k],
									mode_lib->vba.HTotal[k],
									mode_lib->vba.WritebackChromaLineBufferWidth));
		}
	}

	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.HRatio[k] > 1) {
			mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min(
					mode_lib->vba.MaxDCHUBToPSCLThroughput,
					mode_lib->vba.MaxPSCLToLBThroughput
							* mode_lib->vba.HRatio[k]
							/ dml_ceil(
									mode_lib->vba.htaps[k]
											/ 6.0,
									1));
		} else {
			mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min(
					mode_lib->vba.MaxDCHUBToPSCLThroughput,
					mode_lib->vba.MaxPSCLToLBThroughput);
		}

		mode_lib->vba.DPPCLKUsingSingleDPPLuma =
				mode_lib->vba.PixelClock[k]
						* dml_max(
								mode_lib->vba.vtaps[k] / 6.0
										* dml_min(
												1.0,
												mode_lib->vba.HRatio[k]),
								dml_max(
										mode_lib->vba.HRatio[k]
												* mode_lib->vba.VRatio[k]
												/ mode_lib->vba.PSCL_THROUGHPUT_LUMA[k],
										1.0));

		if ((mode_lib->vba.htaps[k] > 6 || mode_lib->vba.vtaps[k] > 6)
				&& mode_lib->vba.DPPCLKUsingSingleDPPLuma
						< 2 * mode_lib->vba.PixelClock[k]) {
			mode_lib->vba.DPPCLKUsingSingleDPPLuma = 2 * mode_lib->vba.PixelClock[k];
		}

		if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8
				&& mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) {
			mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = 0.0;
			mode_lib->vba.DPPCLKUsingSingleDPP[k] =
					mode_lib->vba.DPPCLKUsingSingleDPPLuma;
		} else {
			if (mode_lib->vba.HRatio[k] > 1) {
				mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] =
						dml_min(
								mode_lib->vba.MaxDCHUBToPSCLThroughput,
								mode_lib->vba.MaxPSCLToLBThroughput
										* mode_lib->vba.HRatio[k]
										/ 2
										/ dml_ceil(
												mode_lib->vba.HTAPsChroma[k]
														/ 6.0,
												1.0));
			} else {
				mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = dml_min(
						mode_lib->vba.MaxDCHUBToPSCLThroughput,
						mode_lib->vba.MaxPSCLToLBThroughput);
			}
			mode_lib->vba.DPPCLKUsingSingleDPPChroma =
					mode_lib->vba.PixelClock[k]
							* dml_max(
									mode_lib->vba.VTAPsChroma[k]
											/ 6.0
											* dml_min(
													1.0,
													mode_lib->vba.HRatio[k]
															/ 2),
									dml_max(
											mode_lib->vba.HRatio[k]
													* mode_lib->vba.VRatio[k]
													/ 4
													/ mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k],
											1.0));

			if ((mode_lib->vba.HTAPsChroma[k] > 6 || mode_lib->vba.VTAPsChroma[k] > 6)
					&& mode_lib->vba.DPPCLKUsingSingleDPPChroma
							< 2 * mode_lib->vba.PixelClock[k]) {
				mode_lib->vba.DPPCLKUsingSingleDPPChroma = 2
						* mode_lib->vba.PixelClock[k];
			}

			mode_lib->vba.DPPCLKUsingSingleDPP[k] = dml_max(
					mode_lib->vba.DPPCLKUsingSingleDPPLuma,
					mode_lib->vba.DPPCLKUsingSingleDPPChroma);
		}
	}

	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.BlendingAndTiming[k] != k)
			continue;
		if (mode_lib->vba.ODMCombineEnabled[k]) {
			mode_lib->vba.DISPCLKWithRamping =
					dml_max(
							mode_lib->vba.DISPCLKWithRamping,
							mode_lib->vba.PixelClock[k] / 2
									* (1
											+ mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading
													/ 100)
									* (1
											+ mode_lib->vba.DISPCLKRampingMargin
													/ 100));
			mode_lib->vba.DISPCLKWithoutRamping =
					dml_max(
							mode_lib->vba.DISPCLKWithoutRamping,
							mode_lib->vba.PixelClock[k] / 2
									* (1
											+ mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading
													/ 100));
		} else if (!mode_lib->vba.ODMCombineEnabled[k]) {
			mode_lib->vba.DISPCLKWithRamping =
					dml_max(
							mode_lib->vba.DISPCLKWithRamping,
							mode_lib->vba.PixelClock[k]
									* (1
											+ mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading
													/ 100)
									* (1
											+ mode_lib->vba.DISPCLKRampingMargin
													/ 100));
			mode_lib->vba.DISPCLKWithoutRamping =
					dml_max(
							mode_lib->vba.DISPCLKWithoutRamping,
							mode_lib->vba.PixelClock[k]
									* (1
											+ mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading
													/ 100));
		}
	}

	mode_lib->vba.DISPCLKWithRamping = dml_max(
			mode_lib->vba.DISPCLKWithRamping,
			mode_lib->vba.WritebackDISPCLK);
	mode_lib->vba.DISPCLKWithoutRamping = dml_max(
			mode_lib->vba.DISPCLKWithoutRamping,
			mode_lib->vba.WritebackDISPCLK);

	ASSERT(mode_lib->vba.DISPCLKDPPCLKVCOSpeed != 0);
	mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity = RoundToDFSGranularityUp(
			mode_lib->vba.DISPCLKWithRamping,
			mode_lib->vba.DISPCLKDPPCLKVCOSpeed);
	mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity = RoundToDFSGranularityUp(
			mode_lib->vba.DISPCLKWithoutRamping,
			mode_lib->vba.DISPCLKDPPCLKVCOSpeed);
	mode_lib->vba.MaxDispclkRoundedToDFSGranularity = RoundToDFSGranularityDown(
			mode_lib->vba.soc.clock_limits[mode_lib->vba.soc.num_states].dispclk_mhz,
			mode_lib->vba.DISPCLKDPPCLKVCOSpeed);
	if (mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity
			> mode_lib->vba.MaxDispclkRoundedToDFSGranularity) {
		mode_lib->vba.DISPCLK_calculated =
				mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity;
	} else if (mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity
			> mode_lib->vba.MaxDispclkRoundedToDFSGranularity) {
		mode_lib->vba.DISPCLK_calculated = mode_lib->vba.MaxDispclkRoundedToDFSGranularity;
	} else {
		mode_lib->vba.DISPCLK_calculated =
				mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity;
	}
	DTRACE("   dispclk_mhz (calculated) = %f", mode_lib->vba.DISPCLK_calculated);

	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.DPPPerPlane[k] == 0) {
			mode_lib->vba.DPPCLK_calculated[k] = 0;
		} else {
			mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.DPPCLKUsingSingleDPP[k]
					/ mode_lib->vba.DPPPerPlane[k]
					* (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100);
		}
		mode_lib->vba.GlobalDPPCLK = dml_max(
				mode_lib->vba.GlobalDPPCLK,
				mode_lib->vba.DPPCLK_calculated[k]);
	}
	mode_lib->vba.GlobalDPPCLK = RoundToDFSGranularityUp(
			mode_lib->vba.GlobalDPPCLK,
			mode_lib->vba.DISPCLKDPPCLKVCOSpeed);
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.GlobalDPPCLK / 255
				* dml_ceil(
						mode_lib->vba.DPPCLK_calculated[k] * 255
								/ mode_lib->vba.GlobalDPPCLK,
						1);
		DTRACE("   dppclk_mhz[%i] (calculated) = %f", k, mode_lib->vba.DPPCLK_calculated[k]);
	}

	// Urgent Watermark
	mode_lib->vba.DCCEnabledAnyPlane = false;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k)
		if (mode_lib->vba.DCCEnable[k])
			mode_lib->vba.DCCEnabledAnyPlane = true;

	mode_lib->vba.ReturnBandwidthToDCN = dml_min(
			mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK,
			mode_lib->vba.FabricAndDRAMBandwidth * 1000)
			* mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelDataOnly / 100;

	mode_lib->vba.ReturnBW = mode_lib->vba.ReturnBandwidthToDCN;
	mode_lib->vba.ReturnBW = adjust_ReturnBW(
			mode_lib,
			mode_lib->vba.ReturnBW,
			mode_lib->vba.DCCEnabledAnyPlane,
			mode_lib->vba.ReturnBandwidthToDCN);

	// Let's do this calculation again??
	mode_lib->vba.ReturnBandwidthToDCN = dml_min(
			mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK,
			mode_lib->vba.FabricAndDRAMBandwidth * 1000);
	mode_lib->vba.ReturnBW = adjust_ReturnBW(
			mode_lib,
			mode_lib->vba.ReturnBW,
			mode_lib->vba.DCCEnabledAnyPlane,
			mode_lib->vba.ReturnBandwidthToDCN);

	DTRACE("   dcfclk_mhz         = %f", mode_lib->vba.DCFCLK);
	DTRACE("   return_bw_to_dcn   = %f", mode_lib->vba.ReturnBandwidthToDCN);
	DTRACE("   return_bus_bw      = %f", mode_lib->vba.ReturnBW);

	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		bool MainPlaneDoesODMCombine = false;

		if (mode_lib->vba.SourceScan[k] == dm_horz)
			mode_lib->vba.SwathWidthSingleDPPY[k] = mode_lib->vba.ViewportWidth[k];
		else
			mode_lib->vba.SwathWidthSingleDPPY[k] = mode_lib->vba.ViewportHeight[k];

		if (mode_lib->vba.ODMCombineEnabled[k] == dm_odm_combine_mode_2to1)
			MainPlaneDoesODMCombine = true;
		for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j)
			if (mode_lib->vba.BlendingAndTiming[k] == j
					&& mode_lib->vba.ODMCombineEnabled[k] == dm_odm_combine_mode_2to1)
				MainPlaneDoesODMCombine = true;

		if (MainPlaneDoesODMCombine == true)
			mode_lib->vba.SwathWidthY[k] = dml_min(
					(double) mode_lib->vba.SwathWidthSingleDPPY[k],
					dml_round(
							mode_lib->vba.HActive[k] / 2.0
									* mode_lib->vba.HRatio[k]));
		else {
			if (mode_lib->vba.DPPPerPlane[k] == 0) {
				mode_lib->vba.SwathWidthY[k] = 0;
			} else {
				mode_lib->vba.SwathWidthY[k] = mode_lib->vba.SwathWidthSingleDPPY[k]
						/ mode_lib->vba.DPPPerPlane[k];
			}
		}
	}

	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) {
			mode_lib->vba.BytePerPixelDETY[k] = 8;
			mode_lib->vba.BytePerPixelDETC[k] = 0;
		} else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) {
			mode_lib->vba.BytePerPixelDETY[k] = 4;
			mode_lib->vba.BytePerPixelDETC[k] = 0;
		} else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16) {
			mode_lib->vba.BytePerPixelDETY[k] = 2;
			mode_lib->vba.BytePerPixelDETC[k] = 0;
		} else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8) {
			mode_lib->vba.BytePerPixelDETY[k] = 1;
			mode_lib->vba.BytePerPixelDETC[k] = 0;
		} else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) {
			mode_lib->vba.BytePerPixelDETY[k] = 1;
			mode_lib->vba.BytePerPixelDETC[k] = 2;
		} else { // dm_420_10
			mode_lib->vba.BytePerPixelDETY[k] = 4.0 / 3.0;
			mode_lib->vba.BytePerPixelDETC[k] = 8.0 / 3.0;
		}
	}

	mode_lib->vba.TotalDataReadBandwidth = 0.0;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		mode_lib->vba.ReadBandwidthPlaneLuma[k] = mode_lib->vba.SwathWidthSingleDPPY[k]
				* dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1)
				/ (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k])
				* mode_lib->vba.VRatio[k];
		mode_lib->vba.ReadBandwidthPlaneChroma[k] = mode_lib->vba.SwathWidthSingleDPPY[k]
				/ 2 * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2)
				/ (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k])
				* mode_lib->vba.VRatio[k] / 2;
		DTRACE(
				"   read_bw[%i] = %fBps",
				k,
				mode_lib->vba.ReadBandwidthPlaneLuma[k]
						+ mode_lib->vba.ReadBandwidthPlaneChroma[k]);
		mode_lib->vba.TotalDataReadBandwidth += mode_lib->vba.ReadBandwidthPlaneLuma[k]
				+ mode_lib->vba.ReadBandwidthPlaneChroma[k];
	}

	mode_lib->vba.TotalDCCActiveDPP = 0;
	mode_lib->vba.TotalActiveDPP = 0;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		mode_lib->vba.TotalActiveDPP = mode_lib->vba.TotalActiveDPP
				+ mode_lib->vba.DPPPerPlane[k];
		if (mode_lib->vba.DCCEnable[k])
			mode_lib->vba.TotalDCCActiveDPP = mode_lib->vba.TotalDCCActiveDPP
					+ mode_lib->vba.DPPPerPlane[k];
	}

	mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency =
			(mode_lib->vba.RoundTripPingLatencyCycles + 32) / mode_lib->vba.DCFCLK
					+ mode_lib->vba.UrgentOutOfOrderReturnPerChannelPixelDataOnly
							* mode_lib->vba.NumberOfChannels
							/ mode_lib->vba.ReturnBW;

	mode_lib->vba.LastPixelOfLineExtraWatermark = 0;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
			if (mode_lib->vba.VRatio[k] <= 1.0)
				mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] =
						(double) mode_lib->vba.SwathWidthY[k]
								* mode_lib->vba.DPPPerPlane[k]
								/ mode_lib->vba.HRatio[k]
								/ mode_lib->vba.PixelClock[k];
			else
				mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] =
						(double) mode_lib->vba.SwathWidthY[k]
								/ mode_lib->vba.PSCL_THROUGHPUT_LUMA[k]
								/ mode_lib->vba.DPPCLK[k];

			if (mode_lib->vba.BytePerPixelDETC[k] == 0)
				mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = 0.0;
			else if (mode_lib->vba.VRatio[k] / 2.0 <= 1.0)
				mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] =
						mode_lib->vba.SwathWidthY[k] / 2.0
								* mode_lib->vba.DPPPerPlane[k]
								/ (mode_lib->vba.HRatio[k] / 2.0)
								/ mode_lib->vba.PixelClock[k];
			else
				mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] =
						mode_lib->vba.SwathWidthY[k] / 2.0
								/ mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k]
								/ mode_lib->vba.DPPCLK[k];
		}

	mode_lib->vba.UrgentExtraLatency = mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency
			+ (mode_lib->vba.TotalActiveDPP * mode_lib->vba.PixelChunkSizeInKByte
					+ mode_lib->vba.TotalDCCActiveDPP
							* mode_lib->vba.MetaChunkSize) * 1024.0
					/ mode_lib->vba.ReturnBW;

	if (mode_lib->vba.GPUVMEnable)
		mode_lib->vba.UrgentExtraLatency += mode_lib->vba.TotalActiveDPP
				* mode_lib->vba.PTEGroupSize / mode_lib->vba.ReturnBW;

	mode_lib->vba.UrgentWatermark = mode_lib->vba.UrgentLatencyPixelDataOnly
			+ mode_lib->vba.LastPixelOfLineExtraWatermark
			+ mode_lib->vba.UrgentExtraLatency;

	DTRACE("   urgent_extra_latency = %fus", mode_lib->vba.UrgentExtraLatency);
	DTRACE("   wm_urgent = %fus", mode_lib->vba.UrgentWatermark);

	mode_lib->vba.UrgentLatency = mode_lib->vba.UrgentLatencyPixelDataOnly;

	mode_lib->vba.TotalActiveWriteback = 0;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.WritebackEnable[k])
			mode_lib->vba.TotalActiveWriteback = mode_lib->vba.TotalActiveWriteback + mode_lib->vba.ActiveWritebacksPerPlane[k];
	}

	if (mode_lib->vba.TotalActiveWriteback <= 1)
		mode_lib->vba.WritebackUrgentWatermark = mode_lib->vba.WritebackLatency;
	else
		mode_lib->vba.WritebackUrgentWatermark = mode_lib->vba.WritebackLatency
				+ mode_lib->vba.WritebackChunkSize * 1024.0 / 32
						/ mode_lib->vba.SOCCLK;

	DTRACE("   wm_wb_urgent = %fus", mode_lib->vba.WritebackUrgentWatermark);

	// NB P-State/DRAM Clock Change Watermark
	mode_lib->vba.DRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency
			+ mode_lib->vba.UrgentWatermark;

	DTRACE("   wm_pstate_change = %fus", mode_lib->vba.DRAMClockChangeWatermark);

	DTRACE("   calculating wb pstate watermark");
	DTRACE("      total wb outputs %d", mode_lib->vba.TotalActiveWriteback);
	DTRACE("      socclk frequency %f Mhz", mode_lib->vba.SOCCLK);

	if (mode_lib->vba.TotalActiveWriteback <= 1)
		mode_lib->vba.WritebackDRAMClockChangeWatermark =
				mode_lib->vba.DRAMClockChangeLatency
						+ mode_lib->vba.WritebackLatency;
	else
		mode_lib->vba.WritebackDRAMClockChangeWatermark =
				mode_lib->vba.DRAMClockChangeLatency
						+ mode_lib->vba.WritebackLatency
						+ mode_lib->vba.WritebackChunkSize * 1024.0 / 32
								/ mode_lib->vba.SOCCLK;

	DTRACE("   wm_wb_pstate %fus", mode_lib->vba.WritebackDRAMClockChangeWatermark);

	// Stutter Efficiency
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		mode_lib->vba.LinesInDETY[k] = mode_lib->vba.DETBufferSizeY[k]
				/ mode_lib->vba.BytePerPixelDETY[k] / mode_lib->vba.SwathWidthY[k];
		mode_lib->vba.LinesInDETYRoundedDownToSwath[k] = dml_floor(
				mode_lib->vba.LinesInDETY[k],
				mode_lib->vba.SwathHeightY[k]);
		mode_lib->vba.FullDETBufferingTimeY[k] =
				mode_lib->vba.LinesInDETYRoundedDownToSwath[k]
						* (mode_lib->vba.HTotal[k]
								/ mode_lib->vba.PixelClock[k])
						/ mode_lib->vba.VRatio[k];
		if (mode_lib->vba.BytePerPixelDETC[k] > 0) {
			mode_lib->vba.LinesInDETC[k] = mode_lib->vba.DETBufferSizeC[k]
					/ mode_lib->vba.BytePerPixelDETC[k]
					/ (mode_lib->vba.SwathWidthY[k] / 2);
			mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = dml_floor(
					mode_lib->vba.LinesInDETC[k],
					mode_lib->vba.SwathHeightC[k]);
			mode_lib->vba.FullDETBufferingTimeC[k] =
					mode_lib->vba.LinesInDETCRoundedDownToSwath[k]
							* (mode_lib->vba.HTotal[k]
									/ mode_lib->vba.PixelClock[k])
							/ (mode_lib->vba.VRatio[k] / 2);
		} else {
			mode_lib->vba.LinesInDETC[k] = 0;
			mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = 0;
			mode_lib->vba.FullDETBufferingTimeC[k] = 999999;
		}
	}

	mode_lib->vba.MinFullDETBufferingTime = 999999.0;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.FullDETBufferingTimeY[k]
				< mode_lib->vba.MinFullDETBufferingTime) {
			mode_lib->vba.MinFullDETBufferingTime =
					mode_lib->vba.FullDETBufferingTimeY[k];
			mode_lib->vba.FrameTimeForMinFullDETBufferingTime =
					(double) mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k]
							/ mode_lib->vba.PixelClock[k];
		}
		if (mode_lib->vba.FullDETBufferingTimeC[k]
				< mode_lib->vba.MinFullDETBufferingTime) {
			mode_lib->vba.MinFullDETBufferingTime =
					mode_lib->vba.FullDETBufferingTimeC[k];
			mode_lib->vba.FrameTimeForMinFullDETBufferingTime =
					(double) mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k]
							/ mode_lib->vba.PixelClock[k];
		}
	}

	mode_lib->vba.AverageReadBandwidthGBytePerSecond = 0.0;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.DCCEnable[k]) {
			mode_lib->vba.AverageReadBandwidthGBytePerSecond =
					mode_lib->vba.AverageReadBandwidthGBytePerSecond
							+ mode_lib->vba.ReadBandwidthPlaneLuma[k]
									/ mode_lib->vba.DCCRate[k]
									/ 1000
							+ mode_lib->vba.ReadBandwidthPlaneChroma[k]
									/ mode_lib->vba.DCCRate[k]
									/ 1000;
		} else {
			mode_lib->vba.AverageReadBandwidthGBytePerSecond =
					mode_lib->vba.AverageReadBandwidthGBytePerSecond
							+ mode_lib->vba.ReadBandwidthPlaneLuma[k]
									/ 1000
							+ mode_lib->vba.ReadBandwidthPlaneChroma[k]
									/ 1000;
		}
		if (mode_lib->vba.DCCEnable[k]) {
			mode_lib->vba.AverageReadBandwidthGBytePerSecond =
					mode_lib->vba.AverageReadBandwidthGBytePerSecond
							+ mode_lib->vba.ReadBandwidthPlaneLuma[k]
									/ 1000 / 256
							+ mode_lib->vba.ReadBandwidthPlaneChroma[k]
									/ 1000 / 256;
		}
		if (mode_lib->vba.GPUVMEnable) {
			mode_lib->vba.AverageReadBandwidthGBytePerSecond =
					mode_lib->vba.AverageReadBandwidthGBytePerSecond
							+ mode_lib->vba.ReadBandwidthPlaneLuma[k]
									/ 1000 / 512
							+ mode_lib->vba.ReadBandwidthPlaneChroma[k]
									/ 1000 / 512;
		}
	}

	mode_lib->vba.PartOfBurstThatFitsInROB =
			dml_min(
					mode_lib->vba.MinFullDETBufferingTime
							* mode_lib->vba.TotalDataReadBandwidth,
					mode_lib->vba.ROBBufferSizeInKByte * 1024
							* mode_lib->vba.TotalDataReadBandwidth
							/ (mode_lib->vba.AverageReadBandwidthGBytePerSecond
									* 1000));
	mode_lib->vba.StutterBurstTime = mode_lib->vba.PartOfBurstThatFitsInROB
			* (mode_lib->vba.AverageReadBandwidthGBytePerSecond * 1000)
			/ mode_lib->vba.TotalDataReadBandwidth / mode_lib->vba.ReturnBW
			+ (mode_lib->vba.MinFullDETBufferingTime
					* mode_lib->vba.TotalDataReadBandwidth
					- mode_lib->vba.PartOfBurstThatFitsInROB)
					/ (mode_lib->vba.DCFCLK * 64);
	if (mode_lib->vba.TotalActiveWriteback == 0) {
		mode_lib->vba.StutterEfficiencyNotIncludingVBlank = (1
				- (mode_lib->vba.SRExitTime + mode_lib->vba.StutterBurstTime)
						/ mode_lib->vba.MinFullDETBufferingTime) * 100;
	} else {
		mode_lib->vba.StutterEfficiencyNotIncludingVBlank = 0;
	}

	mode_lib->vba.SmallestVBlank = 999999;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.SynchronizedVBlank || mode_lib->vba.NumberOfActivePlanes == 1) {
			mode_lib->vba.VBlankTime = (double) (mode_lib->vba.VTotal[k]
					- mode_lib->vba.VActive[k]) * mode_lib->vba.HTotal[k]
					/ mode_lib->vba.PixelClock[k];
		} else {
			mode_lib->vba.VBlankTime = 0;
		}
		mode_lib->vba.SmallestVBlank = dml_min(
				mode_lib->vba.SmallestVBlank,
				mode_lib->vba.VBlankTime);
	}

	mode_lib->vba.StutterEfficiency = (mode_lib->vba.StutterEfficiencyNotIncludingVBlank / 100
			* (mode_lib->vba.FrameTimeForMinFullDETBufferingTime
					- mode_lib->vba.SmallestVBlank)
			+ mode_lib->vba.SmallestVBlank)
			/ mode_lib->vba.FrameTimeForMinFullDETBufferingTime * 100;

	// dml_ml->vba.DCFCLK Deep Sleep
	mode_lib->vba.DCFCLKDeepSleep = 8.0;

	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; k++) {
		if (mode_lib->vba.BytePerPixelDETC[k] > 0) {
			mode_lib->vba.DCFCLKDeepSleepPerPlane[k] =
					dml_max(
							1.1 * mode_lib->vba.SwathWidthY[k]
									* dml_ceil(
											mode_lib->vba.BytePerPixelDETY[k],
											1) / 32
									/ mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k],
							1.1 * mode_lib->vba.SwathWidthY[k] / 2.0
									* dml_ceil(
											mode_lib->vba.BytePerPixelDETC[k],
											2) / 32
									/ mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]);
		} else
			mode_lib->vba.DCFCLKDeepSleepPerPlane[k] = 1.1 * mode_lib->vba.SwathWidthY[k]
					* dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / 64.0
					/ mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k];
		mode_lib->vba.DCFCLKDeepSleepPerPlane[k] = dml_max(
				mode_lib->vba.DCFCLKDeepSleepPerPlane[k],
				mode_lib->vba.PixelClock[k] / 16.0);
		mode_lib->vba.DCFCLKDeepSleep = dml_max(
				mode_lib->vba.DCFCLKDeepSleep,
				mode_lib->vba.DCFCLKDeepSleepPerPlane[k]);

		DTRACE(
				"   dcfclk_deepsleep_per_plane[%i] = %fMHz",
				k,
				mode_lib->vba.DCFCLKDeepSleepPerPlane[k]);
	}

	DTRACE("   dcfclk_deepsleep_mhz = %fMHz", mode_lib->vba.DCFCLKDeepSleep);

	// Stutter Watermark
	mode_lib->vba.StutterExitWatermark = mode_lib->vba.SRExitTime
			+ mode_lib->vba.LastPixelOfLineExtraWatermark
			+ mode_lib->vba.UrgentExtraLatency + 10 / mode_lib->vba.DCFCLKDeepSleep;
	mode_lib->vba.StutterEnterPlusExitWatermark = mode_lib->vba.SREnterPlusExitTime
			+ mode_lib->vba.LastPixelOfLineExtraWatermark
			+ mode_lib->vba.UrgentExtraLatency;

	DTRACE("   wm_cstate_exit       = %fus", mode_lib->vba.StutterExitWatermark);
	DTRACE("   wm_cstate_enter_exit = %fus", mode_lib->vba.StutterEnterPlusExitWatermark);

	// Urgent Latency Supported
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		mode_lib->vba.EffectiveDETPlusLBLinesLuma =
				dml_floor(
						mode_lib->vba.LinesInDETY[k]
								+ dml_min(
										mode_lib->vba.LinesInDETY[k]
												* mode_lib->vba.DPPCLK[k]
												* mode_lib->vba.BytePerPixelDETY[k]
												* mode_lib->vba.PSCL_THROUGHPUT_LUMA[k]
												/ (mode_lib->vba.ReturnBW
														/ mode_lib->vba.DPPPerPlane[k]),
										(double) mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma),
						mode_lib->vba.SwathHeightY[k]);

		mode_lib->vba.UrgentLatencySupportUsLuma = mode_lib->vba.EffectiveDETPlusLBLinesLuma
				* (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k])
				/ mode_lib->vba.VRatio[k]
				- mode_lib->vba.EffectiveDETPlusLBLinesLuma
						* mode_lib->vba.SwathWidthY[k]
						* mode_lib->vba.BytePerPixelDETY[k]
						/ (mode_lib->vba.ReturnBW
								/ mode_lib->vba.DPPPerPlane[k]);

		if (mode_lib->vba.BytePerPixelDETC[k] > 0) {
			mode_lib->vba.EffectiveDETPlusLBLinesChroma =
					dml_floor(
							mode_lib->vba.LinesInDETC[k]
									+ dml_min(
											mode_lib->vba.LinesInDETC[k]
													* mode_lib->vba.DPPCLK[k]
													* mode_lib->vba.BytePerPixelDETC[k]
													* mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k]
													/ (mode_lib->vba.ReturnBW
															/ mode_lib->vba.DPPPerPlane[k]),
											(double) mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma),
							mode_lib->vba.SwathHeightC[k]);
			mode_lib->vba.UrgentLatencySupportUsChroma =
					mode_lib->vba.EffectiveDETPlusLBLinesChroma
							* (mode_lib->vba.HTotal[k]
									/ mode_lib->vba.PixelClock[k])
							/ (mode_lib->vba.VRatio[k] / 2)
							- mode_lib->vba.EffectiveDETPlusLBLinesChroma
									* (mode_lib->vba.SwathWidthY[k]
											/ 2)
									* mode_lib->vba.BytePerPixelDETC[k]
									/ (mode_lib->vba.ReturnBW
											/ mode_lib->vba.DPPPerPlane[k]);
			mode_lib->vba.UrgentLatencySupportUs[k] = dml_min(
					mode_lib->vba.UrgentLatencySupportUsLuma,
					mode_lib->vba.UrgentLatencySupportUsChroma);
		} else {
			mode_lib->vba.UrgentLatencySupportUs[k] =
					mode_lib->vba.UrgentLatencySupportUsLuma;
		}
	}

	mode_lib->vba.MinUrgentLatencySupportUs = 999999;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		mode_lib->vba.MinUrgentLatencySupportUs = dml_min(
				mode_lib->vba.MinUrgentLatencySupportUs,
				mode_lib->vba.UrgentLatencySupportUs[k]);
	}

	// Non-Urgent Latency Tolerance
	mode_lib->vba.NonUrgentLatencyTolerance = mode_lib->vba.MinUrgentLatencySupportUs
			- mode_lib->vba.UrgentWatermark;

	// DSCCLK
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if ((mode_lib->vba.BlendingAndTiming[k] != k) || !mode_lib->vba.DSCEnabled[k]) {
			mode_lib->vba.DSCCLK_calculated[k] = 0.0;
		} else {
			if (mode_lib->vba.OutputFormat[k] == dm_420
					|| mode_lib->vba.OutputFormat[k] == dm_n422)
				mode_lib->vba.DSCFormatFactor = 2;
			else
				mode_lib->vba.DSCFormatFactor = 1;
			if (mode_lib->vba.ODMCombineEnabled[k])
				mode_lib->vba.DSCCLK_calculated[k] =
						mode_lib->vba.PixelClockBackEnd[k] / 6
								/ mode_lib->vba.DSCFormatFactor
								/ (1
										- mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading
												/ 100);
			else
				mode_lib->vba.DSCCLK_calculated[k] =
						mode_lib->vba.PixelClockBackEnd[k] / 3
								/ mode_lib->vba.DSCFormatFactor
								/ (1
										- mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading
												/ 100);
		}
	}

	// DSC Delay
	// TODO
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		double bpp = mode_lib->vba.OutputBpp[k];
		unsigned int slices = mode_lib->vba.NumberOfDSCSlices[k];

		if (mode_lib->vba.DSCEnabled[k] && bpp != 0) {
			if (!mode_lib->vba.ODMCombineEnabled[k]) {
				mode_lib->vba.DSCDelay[k] =
						dscceComputeDelay(
								mode_lib->vba.DSCInputBitPerComponent[k],
								bpp,
								dml_ceil(
										(double) mode_lib->vba.HActive[k]
												/ mode_lib->vba.NumberOfDSCSlices[k],
										1),
								slices,
								mode_lib->vba.OutputFormat[k])
								+ dscComputeDelay(
										mode_lib->vba.OutputFormat[k]);
			} else {
				mode_lib->vba.DSCDelay[k] =
						2
								* (dscceComputeDelay(
										mode_lib->vba.DSCInputBitPerComponent[k],
										bpp,
										dml_ceil(
												(double) mode_lib->vba.HActive[k]
														/ mode_lib->vba.NumberOfDSCSlices[k],
												1),
										slices / 2.0,
										mode_lib->vba.OutputFormat[k])
										+ dscComputeDelay(
												mode_lib->vba.OutputFormat[k]));
			}
			mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[k]
					* mode_lib->vba.PixelClock[k]
					/ mode_lib->vba.PixelClockBackEnd[k];
		} else {
			mode_lib->vba.DSCDelay[k] = 0;
		}
	}

	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k)
		for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) // NumberOfPlanes
			if (j != k && mode_lib->vba.BlendingAndTiming[k] == j
					&& mode_lib->vba.DSCEnabled[j])
				mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[j];

	// Prefetch
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		unsigned int PDEAndMetaPTEBytesFrameY;
		unsigned int PixelPTEBytesPerRowY;
		unsigned int MetaRowByteY;
		unsigned int MetaRowByteC;
		unsigned int PDEAndMetaPTEBytesFrameC;
		unsigned int PixelPTEBytesPerRowC;

		Calculate256BBlockSizes(
				mode_lib->vba.SourcePixelFormat[k],
				mode_lib->vba.SurfaceTiling[k],
				dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1),
				dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2),
				&mode_lib->vba.BlockHeight256BytesY[k],
				&mode_lib->vba.BlockHeight256BytesC[k],
				&mode_lib->vba.BlockWidth256BytesY[k],
				&mode_lib->vba.BlockWidth256BytesC[k]);
		PDEAndMetaPTEBytesFrameY = CalculateVMAndRowBytes(
				mode_lib,
				mode_lib->vba.DCCEnable[k],
				mode_lib->vba.BlockHeight256BytesY[k],
				mode_lib->vba.BlockWidth256BytesY[k],
				mode_lib->vba.SourcePixelFormat[k],
				mode_lib->vba.SurfaceTiling[k],
				dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1),
				mode_lib->vba.SourceScan[k],
				mode_lib->vba.ViewportWidth[k],
				mode_lib->vba.ViewportHeight[k],
				mode_lib->vba.SwathWidthY[k],
				mode_lib->vba.GPUVMEnable,
				mode_lib->vba.VMMPageSize,
				mode_lib->vba.PTEBufferSizeInRequestsLuma,
				mode_lib->vba.PDEProcessingBufIn64KBReqs,
				mode_lib->vba.PitchY[k],
				mode_lib->vba.DCCMetaPitchY[k],
				&mode_lib->vba.MacroTileWidthY[k],
				&MetaRowByteY,
				&PixelPTEBytesPerRowY,
				&mode_lib->vba.PTEBufferSizeNotExceeded[mode_lib->vba.VoltageLevel][0],
				&mode_lib->vba.dpte_row_height[k],
				&mode_lib->vba.meta_row_height[k]);
		mode_lib->vba.PrefetchSourceLinesY[k] = CalculatePrefetchSourceLines(
				mode_lib,
				mode_lib->vba.VRatio[k],
				mode_lib->vba.vtaps[k],
				mode_lib->vba.Interlace[k],
				mode_lib->vba.ProgressiveToInterlaceUnitInOPP,
				mode_lib->vba.SwathHeightY[k],
				mode_lib->vba.ViewportYStartY[k],
				&mode_lib->vba.VInitPreFillY[k],
				&mode_lib->vba.MaxNumSwathY[k]);

		if ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64
				&& mode_lib->vba.SourcePixelFormat[k] != dm_444_32
				&& mode_lib->vba.SourcePixelFormat[k] != dm_444_16
				&& mode_lib->vba.SourcePixelFormat[k] != dm_444_8)) {
			PDEAndMetaPTEBytesFrameC =
					CalculateVMAndRowBytes(
							mode_lib,
							mode_lib->vba.DCCEnable[k],
							mode_lib->vba.BlockHeight256BytesC[k],
							mode_lib->vba.BlockWidth256BytesC[k],
							mode_lib->vba.SourcePixelFormat[k],
							mode_lib->vba.SurfaceTiling[k],
							dml_ceil(
									mode_lib->vba.BytePerPixelDETC[k],
									2),
							mode_lib->vba.SourceScan[k],
							mode_lib->vba.ViewportWidth[k] / 2,
							mode_lib->vba.ViewportHeight[k] / 2,
							mode_lib->vba.SwathWidthY[k] / 2,
							mode_lib->vba.GPUVMEnable,
							mode_lib->vba.VMMPageSize,
							mode_lib->vba.PTEBufferSizeInRequestsLuma,
							mode_lib->vba.PDEProcessingBufIn64KBReqs,
							mode_lib->vba.PitchC[k],
							0,
							&mode_lib->vba.MacroTileWidthC[k],
							&MetaRowByteC,
							&PixelPTEBytesPerRowC,
							&mode_lib->vba.PTEBufferSizeNotExceeded[mode_lib->vba.VoltageLevel][0],
							&mode_lib->vba.dpte_row_height_chroma[k],
							&mode_lib->vba.meta_row_height_chroma[k]);
			mode_lib->vba.PrefetchSourceLinesC[k] = CalculatePrefetchSourceLines(
					mode_lib,
					mode_lib->vba.VRatio[k] / 2,
					mode_lib->vba.VTAPsChroma[k],
					mode_lib->vba.Interlace[k],
					mode_lib->vba.ProgressiveToInterlaceUnitInOPP,
					mode_lib->vba.SwathHeightC[k],
					mode_lib->vba.ViewportYStartC[k],
					&mode_lib->vba.VInitPreFillC[k],
					&mode_lib->vba.MaxNumSwathC[k]);
		} else {
			PixelPTEBytesPerRowC = 0;
			PDEAndMetaPTEBytesFrameC = 0;
			MetaRowByteC = 0;
			mode_lib->vba.MaxNumSwathC[k] = 0;
			mode_lib->vba.PrefetchSourceLinesC[k] = 0;
		}

		mode_lib->vba.PixelPTEBytesPerRow[k] = PixelPTEBytesPerRowY + PixelPTEBytesPerRowC;
		mode_lib->vba.PDEAndMetaPTEBytesFrame[k] = PDEAndMetaPTEBytesFrameY
				+ PDEAndMetaPTEBytesFrameC;
		mode_lib->vba.MetaRowByte[k] = MetaRowByteY + MetaRowByteC;

		CalculateActiveRowBandwidth(
				mode_lib->vba.GPUVMEnable,
				mode_lib->vba.SourcePixelFormat[k],
				mode_lib->vba.VRatio[k],
				mode_lib->vba.DCCEnable[k],
				mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k],
				MetaRowByteY,
				MetaRowByteC,
				mode_lib->vba.meta_row_height[k],
				mode_lib->vba.meta_row_height_chroma[k],
				PixelPTEBytesPerRowY,
				PixelPTEBytesPerRowC,
				mode_lib->vba.dpte_row_height[k],
				mode_lib->vba.dpte_row_height_chroma[k],
				&mode_lib->vba.meta_row_bw[k],
				&mode_lib->vba.dpte_row_bw[k],
				&mode_lib->vba.qual_row_bw[k]);
	}

	mode_lib->vba.TCalc = 24.0 / mode_lib->vba.DCFCLKDeepSleep;

	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.BlendingAndTiming[k] == k) {
			if (mode_lib->vba.WritebackEnable[k] == true) {
				mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] =
						mode_lib->vba.WritebackLatency
								+ CalculateWriteBackDelay(
										mode_lib->vba.WritebackPixelFormat[k],
										mode_lib->vba.WritebackHRatio[k],
										mode_lib->vba.WritebackVRatio[k],
										mode_lib->vba.WritebackLumaHTaps[k],
										mode_lib->vba.WritebackLumaVTaps[k],
										mode_lib->vba.WritebackChromaHTaps[k],
										mode_lib->vba.WritebackChromaVTaps[k],
										mode_lib->vba.WritebackDestinationWidth[k])
										/ mode_lib->vba.DISPCLK;
			} else
				mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = 0;
			for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) {
				if (mode_lib->vba.BlendingAndTiming[j] == k
						&& mode_lib->vba.WritebackEnable[j] == true) {
					mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] =
							dml_max(
									mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k],
									mode_lib->vba.WritebackLatency
											+ CalculateWriteBackDelay(
													mode_lib->vba.WritebackPixelFormat[j],
													mode_lib->vba.WritebackHRatio[j],
													mode_lib->vba.WritebackVRatio[j],
													mode_lib->vba.WritebackLumaHTaps[j],
													mode_lib->vba.WritebackLumaVTaps[j],
													mode_lib->vba.WritebackChromaHTaps[j],
													mode_lib->vba.WritebackChromaVTaps[j],
													mode_lib->vba.WritebackDestinationWidth[j])
													/ mode_lib->vba.DISPCLK);
				}
			}
		}
	}

	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k)
		for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j)
			if (mode_lib->vba.BlendingAndTiming[k] == j)
				mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] =
						mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][j];

	mode_lib->vba.VStartupLines = 13;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		mode_lib->vba.MaxVStartupLines[k] =
				mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k]
						- dml_max(
								1.0,
								dml_ceil(
										mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k]
												/ (mode_lib->vba.HTotal[k]
														/ mode_lib->vba.PixelClock[k]),
										1));
	}

	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k)
		mode_lib->vba.MaximumMaxVStartupLines = dml_max(
				mode_lib->vba.MaximumMaxVStartupLines,
				mode_lib->vba.MaxVStartupLines[k]);

	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		mode_lib->vba.cursor_bw[k] = 0.0;
		for (j = 0; j < mode_lib->vba.NumberOfCursors[k]; ++j)
			mode_lib->vba.cursor_bw[k] += mode_lib->vba.CursorWidth[k][j]
					* mode_lib->vba.CursorBPP[k][j] / 8.0
					/ (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k])
					* mode_lib->vba.VRatio[k];
	}

	do {
		double MaxTotalRDBandwidth = 0;
		bool DestinationLineTimesForPrefetchLessThan2 = false;
		bool VRatioPrefetchMoreThan4 = false;
		bool prefetch_vm_bw_valid = true;
		bool prefetch_row_bw_valid = true;
		double TWait = CalculateTWait(
				mode_lib->vba.PrefetchMode[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb],
				mode_lib->vba.DRAMClockChangeLatency,
				mode_lib->vba.UrgentLatencyPixelDataOnly,
				mode_lib->vba.SREnterPlusExitTime);

		for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
			if (mode_lib->vba.XFCEnabled[k] == true) {
				mode_lib->vba.XFCRemoteSurfaceFlipDelay =
						CalculateRemoteSurfaceFlipDelay(
								mode_lib,
								mode_lib->vba.VRatio[k],
								mode_lib->vba.SwathWidthY[k],
								dml_ceil(
										mode_lib->vba.BytePerPixelDETY[k],
										1),
								mode_lib->vba.HTotal[k]
										/ mode_lib->vba.PixelClock[k],
								mode_lib->vba.XFCTSlvVupdateOffset,
								mode_lib->vba.XFCTSlvVupdateWidth,
								mode_lib->vba.XFCTSlvVreadyOffset,
								mode_lib->vba.XFCXBUFLatencyTolerance,
								mode_lib->vba.XFCFillBWOverhead,
								mode_lib->vba.XFCSlvChunkSize,
								mode_lib->vba.XFCBusTransportTime,
								mode_lib->vba.TCalc,
								TWait,
								&mode_lib->vba.SrcActiveDrainRate,
								&mode_lib->vba.TInitXFill,
								&mode_lib->vba.TslvChk);
			} else {
				mode_lib->vba.XFCRemoteSurfaceFlipDelay = 0;
			}

			CalculateDelayAfterScaler(mode_lib, mode_lib->vba.ReturnBW, mode_lib->vba.ReadBandwidthPlaneLuma[k], mode_lib->vba.ReadBandwidthPlaneChroma[k], mode_lib->vba.TotalDataReadBandwidth,
					mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k], mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k],
					mode_lib->vba.DPPCLK[k], mode_lib->vba.DISPCLK, mode_lib->vba.PixelClock[k], mode_lib->vba.DSCDelay[k], mode_lib->vba.DPPPerPlane[k], mode_lib->vba.ScalerEnabled[k], mode_lib->vba.NumberOfCursors[k],
					mode_lib->vba.DPPCLKDelaySubtotal, mode_lib->vba.DPPCLKDelaySCL, mode_lib->vba.DPPCLKDelaySCLLBOnly, mode_lib->vba.DPPCLKDelayCNVCFormater, mode_lib->vba.DPPCLKDelayCNVCCursor, mode_lib->vba.DISPCLKDelaySubtotal,
					mode_lib->vba.SwathWidthY[k] / mode_lib->vba.HRatio[k], mode_lib->vba.OutputFormat[k], mode_lib->vba.HTotal[k],
					mode_lib->vba.SwathWidthSingleDPPY[k], mode_lib->vba.BytePerPixelDETY[k], mode_lib->vba.BytePerPixelDETC[k], mode_lib->vba.SwathHeightY[k], mode_lib->vba.SwathHeightC[k], mode_lib->vba.Interlace[k],
					mode_lib->vba.ProgressiveToInterlaceUnitInOPP, &mode_lib->vba.DSTXAfterScaler[k], &mode_lib->vba.DSTYAfterScaler[k]);

			mode_lib->vba.ErrorResult[k] =
					CalculatePrefetchSchedule(
							mode_lib,
							mode_lib->vba.DPPCLK[k],
							mode_lib->vba.DISPCLK,
							mode_lib->vba.PixelClock[k],
							mode_lib->vba.DCFCLKDeepSleep,
							mode_lib->vba.DPPPerPlane[k],
							mode_lib->vba.NumberOfCursors[k],
							mode_lib->vba.VTotal[k]
									- mode_lib->vba.VActive[k],
							mode_lib->vba.HTotal[k],
							mode_lib->vba.MaxInterDCNTileRepeaters,
							dml_min(
									mode_lib->vba.VStartupLines,
									mode_lib->vba.MaxVStartupLines[k]),
							mode_lib->vba.GPUVMMaxPageTableLevels,
							mode_lib->vba.GPUVMEnable,
							mode_lib->vba.DynamicMetadataEnable[k],
							mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k],
							mode_lib->vba.DynamicMetadataTransmittedBytes[k],
							mode_lib->vba.DCCEnable[k],
							mode_lib->vba.UrgentLatencyPixelDataOnly,
							mode_lib->vba.UrgentExtraLatency,
							mode_lib->vba.TCalc,
							mode_lib->vba.PDEAndMetaPTEBytesFrame[k],
							mode_lib->vba.MetaRowByte[k],
							mode_lib->vba.PixelPTEBytesPerRow[k],
							mode_lib->vba.PrefetchSourceLinesY[k],
							mode_lib->vba.SwathWidthY[k],
							mode_lib->vba.BytePerPixelDETY[k],
							mode_lib->vba.VInitPreFillY[k],
							mode_lib->vba.MaxNumSwathY[k],
							mode_lib->vba.PrefetchSourceLinesC[k],
							mode_lib->vba.BytePerPixelDETC[k],
							mode_lib->vba.VInitPreFillC[k],
							mode_lib->vba.MaxNumSwathC[k],
							mode_lib->vba.SwathHeightY[k],
							mode_lib->vba.SwathHeightC[k],
							TWait,
							mode_lib->vba.XFCEnabled[k],
							mode_lib->vba.XFCRemoteSurfaceFlipDelay,
							mode_lib->vba.Interlace[k],
							mode_lib->vba.ProgressiveToInterlaceUnitInOPP,
							mode_lib->vba.DSTXAfterScaler[k],
							mode_lib->vba.DSTYAfterScaler[k],
							&mode_lib->vba.DestinationLinesForPrefetch[k],
							&mode_lib->vba.PrefetchBandwidth[k],
							&mode_lib->vba.DestinationLinesToRequestVMInVBlank[k],
							&mode_lib->vba.DestinationLinesToRequestRowInVBlank[k],
							&mode_lib->vba.VRatioPrefetchY[k],
							&mode_lib->vba.VRatioPrefetchC[k],
							&mode_lib->vba.RequiredPrefetchPixDataBWLuma[k],
							&mode_lib->vba.Tno_bw[k],
							&mode_lib->vba.VUpdateOffsetPix[k],
							&mode_lib->vba.VUpdateWidthPix[k],
							&mode_lib->vba.VReadyOffsetPix[k]);

			if (mode_lib->vba.BlendingAndTiming[k] == k) {
				mode_lib->vba.VStartup[k] = dml_min(
						mode_lib->vba.VStartupLines,
						mode_lib->vba.MaxVStartupLines[k]);
				if (mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata
						!= 0) {
					mode_lib->vba.VStartup[k] =
							mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata;
				}
			} else {
				mode_lib->vba.VStartup[k] =
						dml_min(
								mode_lib->vba.VStartupLines,
								mode_lib->vba.MaxVStartupLines[mode_lib->vba.BlendingAndTiming[k]]);
			}
		}

		for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {

			if (mode_lib->vba.PDEAndMetaPTEBytesFrame[k] == 0)
				mode_lib->vba.prefetch_vm_bw[k] = 0;
			else if (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] > 0) {
				mode_lib->vba.prefetch_vm_bw[k] =
						(double) mode_lib->vba.PDEAndMetaPTEBytesFrame[k]
								/ (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k]
										* mode_lib->vba.HTotal[k]
										/ mode_lib->vba.PixelClock[k]);
			} else {
				mode_lib->vba.prefetch_vm_bw[k] = 0;
				prefetch_vm_bw_valid = false;
			}
			if (mode_lib->vba.MetaRowByte[k] + mode_lib->vba.PixelPTEBytesPerRow[k]
					== 0)
				mode_lib->vba.prefetch_row_bw[k] = 0;
			else if (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] > 0) {
				mode_lib->vba.prefetch_row_bw[k] =
						(double) (mode_lib->vba.MetaRowByte[k]
								+ mode_lib->vba.PixelPTEBytesPerRow[k])
								/ (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]
										* mode_lib->vba.HTotal[k]
										/ mode_lib->vba.PixelClock[k]);
			} else {
				mode_lib->vba.prefetch_row_bw[k] = 0;
				prefetch_row_bw_valid = false;
			}

			MaxTotalRDBandwidth =
					MaxTotalRDBandwidth + mode_lib->vba.cursor_bw[k]
							+ dml_max(
									mode_lib->vba.prefetch_vm_bw[k],
									dml_max(
											mode_lib->vba.prefetch_row_bw[k],
											dml_max(
													mode_lib->vba.ReadBandwidthPlaneLuma[k]
															+ mode_lib->vba.ReadBandwidthPlaneChroma[k],
													mode_lib->vba.RequiredPrefetchPixDataBWLuma[k])
													+ mode_lib->vba.meta_row_bw[k]
													+ mode_lib->vba.dpte_row_bw[k]));

			if (mode_lib->vba.DestinationLinesForPrefetch[k] < 2)
				DestinationLineTimesForPrefetchLessThan2 = true;
			if (mode_lib->vba.VRatioPrefetchY[k] > 4
					|| mode_lib->vba.VRatioPrefetchC[k] > 4)
				VRatioPrefetchMoreThan4 = true;
		}

		if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && prefetch_vm_bw_valid
				&& prefetch_row_bw_valid && !VRatioPrefetchMoreThan4
				&& !DestinationLineTimesForPrefetchLessThan2)
			mode_lib->vba.PrefetchModeSupported = true;
		else {
			mode_lib->vba.PrefetchModeSupported = false;
			dml_print(
					"DML: CalculatePrefetchSchedule ***failed***. Bandwidth violation. Results are NOT valid\n");
		}

		if (mode_lib->vba.PrefetchModeSupported == true) {
			double final_flip_bw[DC__NUM_DPP__MAX];
			unsigned int ImmediateFlipBytes[DC__NUM_DPP__MAX];
			double total_dcn_read_bw_with_flip = 0;

			mode_lib->vba.BandwidthAvailableForImmediateFlip = mode_lib->vba.ReturnBW;
			for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
				mode_lib->vba.BandwidthAvailableForImmediateFlip =
						mode_lib->vba.BandwidthAvailableForImmediateFlip
								- mode_lib->vba.cursor_bw[k]
								- dml_max(
										mode_lib->vba.ReadBandwidthPlaneLuma[k]
												+ mode_lib->vba.ReadBandwidthPlaneChroma[k]
												+ mode_lib->vba.qual_row_bw[k],
										mode_lib->vba.PrefetchBandwidth[k]);
			}

			for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
				ImmediateFlipBytes[k] = 0;
				if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8
						&& mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) {
					ImmediateFlipBytes[k] =
							mode_lib->vba.PDEAndMetaPTEBytesFrame[k]
									+ mode_lib->vba.MetaRowByte[k]
									+ mode_lib->vba.PixelPTEBytesPerRow[k];
				}
			}
			mode_lib->vba.TotImmediateFlipBytes = 0;
			for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
				if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8
						&& mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) {
					mode_lib->vba.TotImmediateFlipBytes =
							mode_lib->vba.TotImmediateFlipBytes
									+ ImmediateFlipBytes[k];
				}
			}
			for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
				CalculateFlipSchedule(
						mode_lib,
						mode_lib->vba.UrgentExtraLatency,
						mode_lib->vba.UrgentLatencyPixelDataOnly,
						mode_lib->vba.GPUVMMaxPageTableLevels,
						mode_lib->vba.GPUVMEnable,
						mode_lib->vba.BandwidthAvailableForImmediateFlip,
						mode_lib->vba.TotImmediateFlipBytes,
						mode_lib->vba.SourcePixelFormat[k],
						ImmediateFlipBytes[k],
						mode_lib->vba.HTotal[k]
								/ mode_lib->vba.PixelClock[k],
						mode_lib->vba.VRatio[k],
						mode_lib->vba.Tno_bw[k],
						mode_lib->vba.PDEAndMetaPTEBytesFrame[k],
						mode_lib->vba.MetaRowByte[k],
						mode_lib->vba.PixelPTEBytesPerRow[k],
						mode_lib->vba.DCCEnable[k],
						mode_lib->vba.dpte_row_height[k],
						mode_lib->vba.meta_row_height[k],
						mode_lib->vba.qual_row_bw[k],
						&mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip[k],
						&mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip[k],
						&final_flip_bw[k],
						&mode_lib->vba.ImmediateFlipSupportedForPipe[k]);
			}
			for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
				total_dcn_read_bw_with_flip =
						total_dcn_read_bw_with_flip
								+ mode_lib->vba.cursor_bw[k]
								+ dml_max(
										mode_lib->vba.prefetch_vm_bw[k],
										dml_max(
												mode_lib->vba.prefetch_row_bw[k],
												final_flip_bw[k]
														+ dml_max(
																mode_lib->vba.ReadBandwidthPlaneLuma[k]
																		+ mode_lib->vba.ReadBandwidthPlaneChroma[k],
																mode_lib->vba.RequiredPrefetchPixDataBWLuma[k])));
			}
			mode_lib->vba.ImmediateFlipSupported = true;
			if (total_dcn_read_bw_with_flip > mode_lib->vba.ReturnBW) {
				mode_lib->vba.ImmediateFlipSupported = false;
			}
			for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
				if (mode_lib->vba.ImmediateFlipSupportedForPipe[k] == false) {
					mode_lib->vba.ImmediateFlipSupported = false;
				}
			}
		} else {
			mode_lib->vba.ImmediateFlipSupported = false;
		}

		for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
			if (mode_lib->vba.ErrorResult[k]) {
				mode_lib->vba.PrefetchModeSupported = false;
				dml_print(
						"DML: CalculatePrefetchSchedule ***failed***. Prefetch schedule violation. Results are NOT valid\n");
			}
		}

		mode_lib->vba.VStartupLines = mode_lib->vba.VStartupLines + 1;
	} while (!((mode_lib->vba.PrefetchModeSupported
			&& (!mode_lib->vba.ImmediateFlipSupport
					|| mode_lib->vba.ImmediateFlipSupported))
			|| mode_lib->vba.MaximumMaxVStartupLines < mode_lib->vba.VStartupLines));

	//Display Pipeline Delivery Time in Prefetch
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.VRatioPrefetchY[k] <= 1) {
			mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] =
					mode_lib->vba.SwathWidthY[k] * mode_lib->vba.DPPPerPlane[k]
							/ mode_lib->vba.HRatio[k]
							/ mode_lib->vba.PixelClock[k];
		} else {
			mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] =
					mode_lib->vba.SwathWidthY[k]
							/ mode_lib->vba.PSCL_THROUGHPUT_LUMA[k]
							/ mode_lib->vba.DPPCLK[k];
		}
		if (mode_lib->vba.BytePerPixelDETC[k] == 0) {
			mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = 0;
		} else {
			if (mode_lib->vba.VRatioPrefetchC[k] <= 1) {
				mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] =
						mode_lib->vba.SwathWidthY[k]
								* mode_lib->vba.DPPPerPlane[k]
								/ mode_lib->vba.HRatio[k]
								/ mode_lib->vba.PixelClock[k];
			} else {
				mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] =
						mode_lib->vba.SwathWidthY[k]
								/ mode_lib->vba.PSCL_THROUGHPUT_LUMA[k]
								/ mode_lib->vba.DPPCLK[k];
			}
		}
	}

	// Min TTUVBlank
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.PrefetchMode[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb] == 0) {
			mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = true;
			mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = true;
			mode_lib->vba.MinTTUVBlank[k] = dml_max(
					mode_lib->vba.DRAMClockChangeWatermark,
					dml_max(
							mode_lib->vba.StutterEnterPlusExitWatermark,
							mode_lib->vba.UrgentWatermark));
		} else if (mode_lib->vba.PrefetchMode[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb] == 1) {
			mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = false;
			mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = true;
			mode_lib->vba.MinTTUVBlank[k] = dml_max(
					mode_lib->vba.StutterEnterPlusExitWatermark,
					mode_lib->vba.UrgentWatermark);
		} else {
			mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = false;
			mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = false;
			mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.UrgentWatermark;
		}
		if (!mode_lib->vba.DynamicMetadataEnable[k])
			mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.TCalc
					+ mode_lib->vba.MinTTUVBlank[k];
	}

	// DCC Configuration
	mode_lib->vba.ActiveDPPs = 0;
	// NB P-State/DRAM Clock Change Support
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		mode_lib->vba.ActiveDPPs = mode_lib->vba.ActiveDPPs + mode_lib->vba.DPPPerPlane[k];
	}

	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		double EffectiveLBLatencyHidingY;
		double EffectiveLBLatencyHidingC;
		double DPPOutputBufferLinesY;
		double DPPOutputBufferLinesC;
		double DPPOPPBufferingY;
		double MaxDETBufferingTimeY;
		double ActiveDRAMClockChangeLatencyMarginY;

		mode_lib->vba.LBLatencyHidingSourceLinesY =
				dml_min(
						mode_lib->vba.MaxLineBufferLines,
						(unsigned int) dml_floor(
								(double) mode_lib->vba.LineBufferSize
										/ mode_lib->vba.LBBitPerPixel[k]
										/ (mode_lib->vba.SwathWidthY[k]
												/ dml_max(
														mode_lib->vba.HRatio[k],
														1.0)),
								1)) - (mode_lib->vba.vtaps[k] - 1);

		mode_lib->vba.LBLatencyHidingSourceLinesC =
				dml_min(
						mode_lib->vba.MaxLineBufferLines,
						(unsigned int) dml_floor(
								(double) mode_lib->vba.LineBufferSize
										/ mode_lib->vba.LBBitPerPixel[k]
										/ (mode_lib->vba.SwathWidthY[k]
												/ 2.0
												/ dml_max(
														mode_lib->vba.HRatio[k]
																/ 2,
														1.0)),
								1))
						- (mode_lib->vba.VTAPsChroma[k] - 1);

		EffectiveLBLatencyHidingY = mode_lib->vba.LBLatencyHidingSourceLinesY
				/ mode_lib->vba.VRatio[k]
				* (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]);

		EffectiveLBLatencyHidingC = mode_lib->vba.LBLatencyHidingSourceLinesC
				/ (mode_lib->vba.VRatio[k] / 2)
				* (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]);

		if (mode_lib->vba.SwathWidthY[k] > 2 * mode_lib->vba.DPPOutputBufferPixels) {
			DPPOutputBufferLinesY = mode_lib->vba.DPPOutputBufferPixels
					/ mode_lib->vba.SwathWidthY[k];
		} else if (mode_lib->vba.SwathWidthY[k] > mode_lib->vba.DPPOutputBufferPixels) {
			DPPOutputBufferLinesY = 0.5;
		} else {
			DPPOutputBufferLinesY = 1;
		}

		if (mode_lib->vba.SwathWidthY[k] / 2 > 2 * mode_lib->vba.DPPOutputBufferPixels) {
			DPPOutputBufferLinesC = mode_lib->vba.DPPOutputBufferPixels
					/ (mode_lib->vba.SwathWidthY[k] / 2);
		} else if (mode_lib->vba.SwathWidthY[k] / 2 > mode_lib->vba.DPPOutputBufferPixels) {
			DPPOutputBufferLinesC = 0.5;
		} else {
			DPPOutputBufferLinesC = 1;
		}

		DPPOPPBufferingY = (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k])
				* (DPPOutputBufferLinesY + mode_lib->vba.OPPOutputBufferLines);
		MaxDETBufferingTimeY = mode_lib->vba.FullDETBufferingTimeY[k]
				+ (mode_lib->vba.LinesInDETY[k]
						- mode_lib->vba.LinesInDETYRoundedDownToSwath[k])
						/ mode_lib->vba.SwathHeightY[k]
						* (mode_lib->vba.HTotal[k]
								/ mode_lib->vba.PixelClock[k]);

		ActiveDRAMClockChangeLatencyMarginY = DPPOPPBufferingY + EffectiveLBLatencyHidingY
				+ MaxDETBufferingTimeY - mode_lib->vba.DRAMClockChangeWatermark;

		if (mode_lib->vba.ActiveDPPs > 1) {
			ActiveDRAMClockChangeLatencyMarginY =
					ActiveDRAMClockChangeLatencyMarginY
							- (1 - 1 / (mode_lib->vba.ActiveDPPs - 1))
									* mode_lib->vba.SwathHeightY[k]
									* (mode_lib->vba.HTotal[k]
											/ mode_lib->vba.PixelClock[k]);
		}

		if (mode_lib->vba.BytePerPixelDETC[k] > 0) {
			double DPPOPPBufferingC = (mode_lib->vba.HTotal[k]
					/ mode_lib->vba.PixelClock[k])
					* (DPPOutputBufferLinesC
							+ mode_lib->vba.OPPOutputBufferLines);
			double MaxDETBufferingTimeC =
					mode_lib->vba.FullDETBufferingTimeC[k]
							+ (mode_lib->vba.LinesInDETC[k]
									- mode_lib->vba.LinesInDETCRoundedDownToSwath[k])
									/ mode_lib->vba.SwathHeightC[k]
									* (mode_lib->vba.HTotal[k]
											/ mode_lib->vba.PixelClock[k]);
			double ActiveDRAMClockChangeLatencyMarginC = DPPOPPBufferingC
					+ EffectiveLBLatencyHidingC + MaxDETBufferingTimeC
					- mode_lib->vba.DRAMClockChangeWatermark;

			if (mode_lib->vba.ActiveDPPs > 1) {
				ActiveDRAMClockChangeLatencyMarginC =
						ActiveDRAMClockChangeLatencyMarginC
								- (1
										- 1
												/ (mode_lib->vba.ActiveDPPs
														- 1))
										* mode_lib->vba.SwathHeightC[k]
										* (mode_lib->vba.HTotal[k]
												/ mode_lib->vba.PixelClock[k]);
			}
			mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(
					ActiveDRAMClockChangeLatencyMarginY,
					ActiveDRAMClockChangeLatencyMarginC);
		} else {
			mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] =
					ActiveDRAMClockChangeLatencyMarginY;
		}

		if (mode_lib->vba.WritebackEnable[k]) {
			double WritebackDRAMClockChangeLatencyMargin;

			if (mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) {
				WritebackDRAMClockChangeLatencyMargin =
						(double) (mode_lib->vba.WritebackInterfaceLumaBufferSize
								+ mode_lib->vba.WritebackInterfaceChromaBufferSize)
								/ (mode_lib->vba.WritebackDestinationWidth[k]
										* mode_lib->vba.WritebackDestinationHeight[k]
										/ (mode_lib->vba.WritebackSourceHeight[k]
												* mode_lib->vba.HTotal[k]
												/ mode_lib->vba.PixelClock[k])
										* 4)
								- mode_lib->vba.WritebackDRAMClockChangeWatermark;
			} else if (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) {
				WritebackDRAMClockChangeLatencyMargin =
						dml_min(
								(double) mode_lib->vba.WritebackInterfaceLumaBufferSize
										* 8.0 / 10,
								2.0
										* mode_lib->vba.WritebackInterfaceChromaBufferSize
										* 8 / 10)
								/ (mode_lib->vba.WritebackDestinationWidth[k]
										* mode_lib->vba.WritebackDestinationHeight[k]
										/ (mode_lib->vba.WritebackSourceHeight[k]
												* mode_lib->vba.HTotal[k]
												/ mode_lib->vba.PixelClock[k]))
								- mode_lib->vba.WritebackDRAMClockChangeWatermark;
			} else {
				WritebackDRAMClockChangeLatencyMargin =
						dml_min(
								(double) mode_lib->vba.WritebackInterfaceLumaBufferSize,
								2.0
										* mode_lib->vba.WritebackInterfaceChromaBufferSize)
								/ (mode_lib->vba.WritebackDestinationWidth[k]
										* mode_lib->vba.WritebackDestinationHeight[k]
										/ (mode_lib->vba.WritebackSourceHeight[k]
												* mode_lib->vba.HTotal[k]
												/ mode_lib->vba.PixelClock[k]))
								- mode_lib->vba.WritebackDRAMClockChangeWatermark;
			}
			mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(
					mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k],
					WritebackDRAMClockChangeLatencyMargin);
		}
	}

	mode_lib->vba.MinActiveDRAMClockChangeMargin = 999999;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k]
				< mode_lib->vba.MinActiveDRAMClockChangeMargin) {
			mode_lib->vba.MinActiveDRAMClockChangeMargin =
					mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k];
		}
	}

	mode_lib->vba.MinActiveDRAMClockChangeLatencySupported =
			mode_lib->vba.MinActiveDRAMClockChangeMargin
					+ mode_lib->vba.DRAMClockChangeLatency;

	if (mode_lib->vba.DRAMClockChangeSupportsVActive &&
			mode_lib->vba.MinActiveDRAMClockChangeMargin > 60) {
		mode_lib->vba.DRAMClockChangeWatermark += 25;
		mode_lib->vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive;
	} else if (mode_lib->vba.DummyPStateCheck &&
			mode_lib->vba.MinActiveDRAMClockChangeMargin > 0) {
		mode_lib->vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive;
	} else {
		if (mode_lib->vba.SynchronizedVBlank || mode_lib->vba.NumberOfActivePlanes == 1) {
			mode_lib->vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vblank;
			for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
				if (!mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k]) {
					mode_lib->vba.DRAMClockChangeSupport[0][0] =
							dm_dram_clock_change_unsupported;
				}
			}
		} else {
			mode_lib->vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_unsupported;
		}
	}
	for (k = 0; k <= mode_lib->vba.soc.num_states; k++)
		for (j = 0; j < 2; j++)
			mode_lib->vba.DRAMClockChangeSupport[k][j] = mode_lib->vba.DRAMClockChangeSupport[0][0];

	//XFC Parameters:
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (mode_lib->vba.XFCEnabled[k] == true) {
			double TWait;

			mode_lib->vba.XFCSlaveVUpdateOffset[k] = mode_lib->vba.XFCTSlvVupdateOffset;
			mode_lib->vba.XFCSlaveVupdateWidth[k] = mode_lib->vba.XFCTSlvVupdateWidth;
			mode_lib->vba.XFCSlaveVReadyOffset[k] = mode_lib->vba.XFCTSlvVreadyOffset;
			TWait = CalculateTWait(
					mode_lib->vba.PrefetchMode[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb],
					mode_lib->vba.DRAMClockChangeLatency,
					mode_lib->vba.UrgentLatencyPixelDataOnly,
					mode_lib->vba.SREnterPlusExitTime);
			mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay(
					mode_lib,
					mode_lib->vba.VRatio[k],
					mode_lib->vba.SwathWidthY[k],
					dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1),
					mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k],
					mode_lib->vba.XFCTSlvVupdateOffset,
					mode_lib->vba.XFCTSlvVupdateWidth,
					mode_lib->vba.XFCTSlvVreadyOffset,
					mode_lib->vba.XFCXBUFLatencyTolerance,
					mode_lib->vba.XFCFillBWOverhead,
					mode_lib->vba.XFCSlvChunkSize,
					mode_lib->vba.XFCBusTransportTime,
					mode_lib->vba.TCalc,
					TWait,
					&mode_lib->vba.SrcActiveDrainRate,
					&mode_lib->vba.TInitXFill,
					&mode_lib->vba.TslvChk);
			mode_lib->vba.XFCRemoteSurfaceFlipLatency[k] =
					dml_floor(
							mode_lib->vba.XFCRemoteSurfaceFlipDelay
									/ (mode_lib->vba.HTotal[k]
											/ mode_lib->vba.PixelClock[k]),
							1);
			mode_lib->vba.XFCTransferDelay[k] =
					dml_ceil(
							mode_lib->vba.XFCBusTransportTime
									/ (mode_lib->vba.HTotal[k]
											/ mode_lib->vba.PixelClock[k]),
							1);
			mode_lib->vba.XFCPrechargeDelay[k] =
					dml_ceil(
							(mode_lib->vba.XFCBusTransportTime
									+ mode_lib->vba.TInitXFill
									+ mode_lib->vba.TslvChk)
									/ (mode_lib->vba.HTotal[k]
											/ mode_lib->vba.PixelClock[k]),
							1);
			mode_lib->vba.InitFillLevel = mode_lib->vba.XFCXBUFLatencyTolerance
					* mode_lib->vba.SrcActiveDrainRate;
			mode_lib->vba.FinalFillMargin =
					(mode_lib->vba.DestinationLinesToRequestVMInVBlank[k]
							+ mode_lib->vba.DestinationLinesToRequestRowInVBlank[k])
							* mode_lib->vba.HTotal[k]
							/ mode_lib->vba.PixelClock[k]
							* mode_lib->vba.SrcActiveDrainRate
							+ mode_lib->vba.XFCFillConstant;
			mode_lib->vba.FinalFillLevel = mode_lib->vba.XFCRemoteSurfaceFlipDelay
					* mode_lib->vba.SrcActiveDrainRate
					+ mode_lib->vba.FinalFillMargin;
			mode_lib->vba.RemainingFillLevel = dml_max(
					0.0,
					mode_lib->vba.FinalFillLevel - mode_lib->vba.InitFillLevel);
			mode_lib->vba.TFinalxFill = mode_lib->vba.RemainingFillLevel
					/ (mode_lib->vba.SrcActiveDrainRate
							* mode_lib->vba.XFCFillBWOverhead / 100);
			mode_lib->vba.XFCPrefetchMargin[k] =
					mode_lib->vba.XFCRemoteSurfaceFlipDelay
							+ mode_lib->vba.TFinalxFill
							+ (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k]
									+ mode_lib->vba.DestinationLinesToRequestRowInVBlank[k])
									* mode_lib->vba.HTotal[k]
									/ mode_lib->vba.PixelClock[k];
		} else {
			mode_lib->vba.XFCSlaveVUpdateOffset[k] = 0;
			mode_lib->vba.XFCSlaveVupdateWidth[k] = 0;
			mode_lib->vba.XFCSlaveVReadyOffset[k] = 0;
			mode_lib->vba.XFCRemoteSurfaceFlipLatency[k] = 0;
			mode_lib->vba.XFCPrechargeDelay[k] = 0;
			mode_lib->vba.XFCTransferDelay[k] = 0;
			mode_lib->vba.XFCPrefetchMargin[k] = 0;
		}
	}
	{
		unsigned int VStartupMargin = 0;
		bool FirstMainPlane = true;

		for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
			if (mode_lib->vba.BlendingAndTiming[k] == k) {
				unsigned int Margin = (mode_lib->vba.MaxVStartupLines[k] - mode_lib->vba.VStartup[k])
						* mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k];

				if (FirstMainPlane) {
					VStartupMargin = Margin;
					FirstMainPlane = false;
				} else
					VStartupMargin = dml_min(VStartupMargin, Margin);
		}

		if (mode_lib->vba.UseMaximumVStartup) {
			if (mode_lib->vba.VTotal_Max[k] == mode_lib->vba.VTotal[k]) {
				//only use max vstart if it is not drr or lateflip.
				mode_lib->vba.VStartup[k] = mode_lib->vba.MaxVStartupLines[mode_lib->vba.BlendingAndTiming[k]];
			}
		}
	}
}
}