static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation()

in drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c [1463:2803]


static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(
		struct display_mode_lib *mode_lib)
{
	struct vba_vars_st *locals = &mode_lib->vba;
	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;

	// DISPCLK and 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) {
			locals->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 {
			locals->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]
												/ locals->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)) {
			locals->PSCL_THROUGHPUT_CHROMA[k] = 0.0;
			locals->DPPCLKUsingSingleDPP[k] =
					mode_lib->vba.DPPCLKUsingSingleDPPLuma;
		} else {
			if (mode_lib->vba.HRatio[k] > 1) {
				locals->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 {
				locals->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
													/ locals->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];
			}

			locals->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 - 1].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) {
		mode_lib->vba.DPPCLK_calculated[k] = locals->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 and B P-State/DRAM Clock Change Watermark
	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)
			locals->SwathWidthSingleDPPY[k] = mode_lib->vba.ViewportWidth[k];
		else
			locals->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)
			locals->SwathWidthY[k] = dml_min(
					(double) locals->SwathWidthSingleDPPY[k],
					dml_round(
							mode_lib->vba.HActive[k] / 2.0
									* mode_lib->vba.HRatio[k]));
		else
			locals->SwathWidthY[k] = locals->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) {
			locals->BytePerPixelDETY[k] = 8;
			locals->BytePerPixelDETC[k] = 0;
		} else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) {
			locals->BytePerPixelDETY[k] = 4;
			locals->BytePerPixelDETC[k] = 0;
		} else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16 || mode_lib->vba.SourcePixelFormat[k] == dm_mono_16) {
			locals->BytePerPixelDETY[k] = 2;
			locals->BytePerPixelDETC[k] = 0;
		} else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8 || mode_lib->vba.SourcePixelFormat[k] == dm_mono_8) {
			locals->BytePerPixelDETY[k] = 1;
			locals->BytePerPixelDETC[k] = 0;
		} else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) {
			locals->BytePerPixelDETY[k] = 1;
			locals->BytePerPixelDETC[k] = 2;
		} else { // dm_420_10
			locals->BytePerPixelDETY[k] = 4.0 / 3.0;
			locals->BytePerPixelDETC[k] = 8.0 / 3.0;
		}
	}

	mode_lib->vba.TotalDataReadBandwidth = 0.0;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		locals->ReadBandwidthPlaneLuma[k] = locals->SwathWidthSingleDPPY[k]
				* dml_ceil(locals->BytePerPixelDETY[k], 1)
				/ (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k])
				* mode_lib->vba.VRatio[k];
		locals->ReadBandwidthPlaneChroma[k] = locals->SwathWidthSingleDPPY[k]
				/ 2 * dml_ceil(locals->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,
				locals->ReadBandwidthPlaneLuma[k]
						+ locals->ReadBandwidthPlaneChroma[k]);
		mode_lib->vba.TotalDataReadBandwidth += locals->ReadBandwidthPlaneLuma[k]
				+ locals->ReadBandwidthPlaneChroma[k];
	}

	// DCFCLK Deep Sleep
	CalculateDCFCLKDeepSleep(
		mode_lib,
		mode_lib->vba.NumberOfActivePlanes,
		locals->BytePerPixelDETY,
		locals->BytePerPixelDETC,
		mode_lib->vba.VRatio,
		locals->SwathWidthY,
		mode_lib->vba.DPPPerPlane,
		mode_lib->vba.HRatio,
		mode_lib->vba.PixelClock,
		locals->PSCL_THROUGHPUT_LUMA,
		locals->PSCL_THROUGHPUT_CHROMA,
		locals->DPPCLK,
		&mode_lib->vba.DCFCLKDeepSleep);

	// DSCCLK
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if ((mode_lib->vba.BlendingAndTiming[k] != k) || !mode_lib->vba.DSCEnabled[k]) {
			locals->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])
				locals->DSCCLK_calculated[k] =
						mode_lib->vba.PixelClockBackEnd[k] / 6
								/ mode_lib->vba.DSCFormatFactor
								/ (1
										- mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading
												/ 100);
			else
				locals->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]) {
				locals->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 {
				locals->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]));
			}
			locals->DSCDelay[k] = locals->DSCDelay[k]
					* mode_lib->vba.PixelClock[k]
					/ mode_lib->vba.PixelClockBackEnd[k];
		} else {
			locals->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])
				locals->DSCDelay[k] = locals->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;
		bool         PTEBufferSizeNotExceededY;
		bool         PTEBufferSizeNotExceededC;

		Calculate256BBlockSizes(
				mode_lib->vba.SourcePixelFormat[k],
				mode_lib->vba.SurfaceTiling[k],
				dml_ceil(locals->BytePerPixelDETY[k], 1),
				dml_ceil(locals->BytePerPixelDETC[k], 2),
				&locals->BlockHeight256BytesY[k],
				&locals->BlockHeight256BytesC[k],
				&locals->BlockWidth256BytesY[k],
				&locals->BlockWidth256BytesC[k]);

		locals->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],
				&locals->VInitPreFillY[k],
				&locals->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],
							locals->BlockHeight256BytesC[k],
							locals->BlockWidth256BytesC[k],
							mode_lib->vba.SourcePixelFormat[k],
							mode_lib->vba.SurfaceTiling[k],
							dml_ceil(
									locals->BytePerPixelDETC[k],
									2),
							mode_lib->vba.SourceScan[k],
							mode_lib->vba.ViewportWidth[k] / 2,
							mode_lib->vba.ViewportHeight[k] / 2,
							locals->SwathWidthY[k] / 2,
							mode_lib->vba.GPUVMEnable,
							mode_lib->vba.HostVMEnable,
							mode_lib->vba.HostVMMaxPageTableLevels,
							mode_lib->vba.HostVMCachedPageTableLevels,
							mode_lib->vba.VMMPageSize,
							mode_lib->vba.PTEBufferSizeInRequestsChroma,
							mode_lib->vba.PitchC[k],
							mode_lib->vba.DCCMetaPitchC[k],
							&locals->MacroTileWidthC[k],
							&MetaRowByteC,
							&PixelPTEBytesPerRowC,
							&PTEBufferSizeNotExceededC,
							&locals->dpte_row_width_chroma_ub[k],
							&locals->dpte_row_height_chroma[k],
							&locals->meta_req_width_chroma[k],
							&locals->meta_req_height_chroma[k],
							&locals->meta_row_width_chroma[k],
							&locals->meta_row_height_chroma[k],
							&locals->vm_group_bytes_chroma,
							&locals->dpte_group_bytes_chroma,
							&locals->PixelPTEReqWidthC[k],
							&locals->PixelPTEReqHeightC[k],
							&locals->PTERequestSizeC[k],
							&locals->dpde0_bytes_per_frame_ub_c[k],
							&locals->meta_pte_bytes_per_frame_ub_c[k]);

			locals->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],
					&locals->VInitPreFillC[k],
					&locals->MaxNumSwathC[k]);
		} else {
			PixelPTEBytesPerRowC = 0;
			PDEAndMetaPTEBytesFrameC = 0;
			MetaRowByteC = 0;
			locals->MaxNumSwathC[k] = 0;
			locals->PrefetchSourceLinesC[k] = 0;
			locals->PTEBufferSizeInRequestsForLuma = mode_lib->vba.PTEBufferSizeInRequestsLuma + mode_lib->vba.PTEBufferSizeInRequestsChroma;
		}

		PDEAndMetaPTEBytesFrameY = CalculateVMAndRowBytes(
				mode_lib,
				mode_lib->vba.DCCEnable[k],
				locals->BlockHeight256BytesY[k],
				locals->BlockWidth256BytesY[k],
				mode_lib->vba.SourcePixelFormat[k],
				mode_lib->vba.SurfaceTiling[k],
				dml_ceil(locals->BytePerPixelDETY[k], 1),
				mode_lib->vba.SourceScan[k],
				mode_lib->vba.ViewportWidth[k],
				mode_lib->vba.ViewportHeight[k],
				locals->SwathWidthY[k],
				mode_lib->vba.GPUVMEnable,
				mode_lib->vba.HostVMEnable,
				mode_lib->vba.HostVMMaxPageTableLevels,
				mode_lib->vba.HostVMCachedPageTableLevels,
				mode_lib->vba.VMMPageSize,
				locals->PTEBufferSizeInRequestsForLuma,
				mode_lib->vba.PitchY[k],
				mode_lib->vba.DCCMetaPitchY[k],
				&locals->MacroTileWidthY[k],
				&MetaRowByteY,
				&PixelPTEBytesPerRowY,
				&PTEBufferSizeNotExceededY,
				&locals->dpte_row_width_luma_ub[k],
				&locals->dpte_row_height[k],
				&locals->meta_req_width[k],
				&locals->meta_req_height[k],
				&locals->meta_row_width[k],
				&locals->meta_row_height[k],
				&locals->vm_group_bytes[k],
				&locals->dpte_group_bytes[k],
				&locals->PixelPTEReqWidthY[k],
				&locals->PixelPTEReqHeightY[k],
				&locals->PTERequestSizeY[k],
				&locals->dpde0_bytes_per_frame_ub_l[k],
				&locals->meta_pte_bytes_per_frame_ub_l[k]);

		locals->PixelPTEBytesPerRow[k] = PixelPTEBytesPerRowY + PixelPTEBytesPerRowC;
		locals->PDEAndMetaPTEBytesFrame[k] = PDEAndMetaPTEBytesFrameY
				+ PDEAndMetaPTEBytesFrameC;
		locals->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,
				locals->meta_row_height[k],
				locals->meta_row_height_chroma[k],
				PixelPTEBytesPerRowY,
				PixelPTEBytesPerRowC,
				locals->dpte_row_height[k],
				locals->dpte_row_height_chroma[k],
				&locals->meta_row_bw[k],
				&locals->dpte_row_bw[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.UrgentOutOfOrderReturnPerChannel = dml_max3(
			mode_lib->vba.UrgentOutOfOrderReturnPerChannelPixelDataOnly,
			mode_lib->vba.UrgentOutOfOrderReturnPerChannelPixelMixedWithVMData,
			mode_lib->vba.UrgentOutOfOrderReturnPerChannelVMDataOnly);

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

	mode_lib->vba.UrgentExtraLatency = CalculateExtraLatency(
			mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency,
			mode_lib->vba.TotalActiveDPP,
			mode_lib->vba.PixelChunkSizeInKByte,
			mode_lib->vba.TotalDCCActiveDPP,
			mode_lib->vba.MetaChunkSize,
			mode_lib->vba.ReturnBW,
			mode_lib->vba.GPUVMEnable,
			mode_lib->vba.HostVMEnable,
			mode_lib->vba.NumberOfActivePlanes,
			mode_lib->vba.DPPPerPlane,
			locals->dpte_group_bytes,
			mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
			mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly,
			mode_lib->vba.HostVMMaxPageTableLevels,
			mode_lib->vba.HostVMCachedPageTableLevels);


	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) {
				locals->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
				locals->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) {
					locals->WritebackDelay[mode_lib->vba.VoltageLevel][k] =
							dml_max(
									locals->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)
				locals->WritebackDelay[mode_lib->vba.VoltageLevel][k] =
						locals->WritebackDelay[mode_lib->vba.VoltageLevel][j];

	mode_lib->vba.VStartupLines = 13;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		locals->MaxVStartupLines[k] = mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k] - dml_max(1.0, dml_ceil(locals->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)
		locals->MaximumMaxVStartupLines = dml_max(locals->MaximumMaxVStartupLines, locals->MaxVStartupLines[k]);

	// We don't really care to iterate between the various prefetch modes
	//mode_lib->vba.PrefetchERROR = CalculateMinAndMaxPrefetchMode(mode_lib->vba.AllowDRAMSelfRefreshOrDRAMClockChangeInVblank, &mode_lib->vba.MinPrefetchMode, &mode_lib->vba.MaxPrefetchMode);
	mode_lib->vba.UrgentLatency = dml_max3(mode_lib->vba.UrgentLatencyPixelDataOnly, mode_lib->vba.UrgentLatencyPixelMixedWithVMData, mode_lib->vba.UrgentLatencyVMDataOnly);

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

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

			if (mode_lib->vba.XFCEnabled[k] == true) {
				mode_lib->vba.XFCRemoteSurfaceFlipDelay =
						CalculateRemoteSurfaceFlipDelay(
								mode_lib,
								mode_lib->vba.VRatio[k],
								locals->SwathWidthY[k],
								dml_ceil(
										locals->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;
			}

			myPipe.DPPCLK = locals->DPPCLK[k];
			myPipe.DISPCLK = mode_lib->vba.DISPCLK;
			myPipe.PixelClock = mode_lib->vba.PixelClock[k];
			myPipe.DCFCLKDeepSleep = mode_lib->vba.DCFCLKDeepSleep;
			myPipe.DPPPerPlane = mode_lib->vba.DPPPerPlane[k];
			myPipe.ScalerEnabled = mode_lib->vba.ScalerEnabled[k];
			myPipe.SourceScan = mode_lib->vba.SourceScan[k];
			myPipe.BlockWidth256BytesY = locals->BlockWidth256BytesY[k];
			myPipe.BlockHeight256BytesY = locals->BlockHeight256BytesY[k];
			myPipe.BlockWidth256BytesC = locals->BlockWidth256BytesC[k];
			myPipe.BlockHeight256BytesC = locals->BlockHeight256BytesC[k];
			myPipe.InterlaceEnable = mode_lib->vba.Interlace[k];
			myPipe.NumberOfCursors = mode_lib->vba.NumberOfCursors[k];
			myPipe.VBlank = mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k];
			myPipe.HTotal = mode_lib->vba.HTotal[k];


			myHostVM.Enable = mode_lib->vba.HostVMEnable;
			myHostVM.MaxPageTableLevels = mode_lib->vba.HostVMMaxPageTableLevels;
			myHostVM.CachedPageTableLevels = mode_lib->vba.HostVMCachedPageTableLevels;

			mode_lib->vba.ErrorResult[k] =
					CalculatePrefetchSchedule(
							mode_lib,
							mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
							mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly,
							&myPipe,
							locals->DSCDelay[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,
							(unsigned int) (locals->SwathWidthY[k]
									/ mode_lib->vba.HRatio[k]),
							mode_lib->vba.OutputFormat[k],
							mode_lib->vba.MaxInterDCNTileRepeaters,
							dml_min(mode_lib->vba.VStartupLines, locals->MaxVStartupLines[k]),
							locals->MaxVStartupLines[k],
							mode_lib->vba.GPUVMMaxPageTableLevels,
							mode_lib->vba.GPUVMEnable,
							&myHostVM,
							mode_lib->vba.DynamicMetadataEnable[k],
							mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k],
							mode_lib->vba.DynamicMetadataTransmittedBytes[k],
							mode_lib->vba.DCCEnable[k],
							mode_lib->vba.UrgentLatency,
							mode_lib->vba.UrgentExtraLatency,
							mode_lib->vba.TCalc,
							locals->PDEAndMetaPTEBytesFrame[k],
							locals->MetaRowByte[k],
							locals->PixelPTEBytesPerRow[k],
							locals->PrefetchSourceLinesY[k],
							locals->SwathWidthY[k],
							locals->BytePerPixelDETY[k],
							locals->VInitPreFillY[k],
							locals->MaxNumSwathY[k],
							locals->PrefetchSourceLinesC[k],
							locals->BytePerPixelDETC[k],
							locals->VInitPreFillC[k],
							locals->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.ProgressiveToInterlaceUnitInOPP,
							&locals->DSTXAfterScaler[k],
							&locals->DSTYAfterScaler[k],
							&locals->DestinationLinesForPrefetch[k],
							&locals->PrefetchBandwidth[k],
							&locals->DestinationLinesToRequestVMInVBlank[k],
							&locals->DestinationLinesToRequestRowInVBlank[k],
							&locals->VRatioPrefetchY[k],
							&locals->VRatioPrefetchC[k],
							&locals->RequiredPrefetchPixDataBWLuma[k],
							&locals->RequiredPrefetchPixDataBWChroma[k],
							&locals->VStartupRequiredWhenNotEnoughTimeForDynamicMetadata,
							&locals->Tno_bw[k],
							&locals->prefetch_vmrow_bw[k],
							&locals->swath_width_luma_ub[k],
							&locals->swath_width_chroma_ub[k],
							&mode_lib->vba.VUpdateOffsetPix[k],
							&mode_lib->vba.VUpdateWidthPix[k],
							&mode_lib->vba.VReadyOffsetPix[k]);
			if (mode_lib->vba.BlendingAndTiming[k] == k) {
				locals->VStartup[k] = dml_min(
						mode_lib->vba.VStartupLines,
						locals->MaxVStartupLines[k]);
				if (locals->VStartupRequiredWhenNotEnoughTimeForDynamicMetadata
						!= 0) {
					locals->VStartup[k] =
							locals->VStartupRequiredWhenNotEnoughTimeForDynamicMetadata;
				}
			} else {
				locals->VStartup[k] =
						dml_min(
								mode_lib->vba.VStartupLines,
								locals->MaxVStartupLines[mode_lib->vba.BlendingAndTiming[k]]);
			}
		}

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

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

			CalculateUrgentBurstFactor(
					mode_lib->vba.DETBufferSizeInKByte,
					mode_lib->vba.SwathHeightY[k],
					mode_lib->vba.SwathHeightC[k],
					locals->SwathWidthY[k],
					mode_lib->vba.HTotal[k] /
					mode_lib->vba.PixelClock[k],
					mode_lib->vba.UrgentLatency,
					mode_lib->vba.CursorBufferSize,
					mode_lib->vba.CursorWidth[k][0] + mode_lib->vba.CursorWidth[k][1],
					dml_max(mode_lib->vba.CursorBPP[k][0], mode_lib->vba.CursorBPP[k][1]),
					mode_lib->vba.VRatio[k],
					locals->VRatioPrefetchY[k],
					locals->VRatioPrefetchC[k],
					locals->BytePerPixelDETY[k],
					locals->BytePerPixelDETC[k],
					&locals->UrgentBurstFactorCursor[k],
					&locals->UrgentBurstFactorCursorPre[k],
					&locals->UrgentBurstFactorLuma[k],
					&locals->UrgentBurstFactorLumaPre[k],
					&locals->UrgentBurstFactorChroma[k],
					&locals->UrgentBurstFactorChromaPre[k],
					&locals->NotEnoughUrgentLatencyHiding,
					&locals->NotEnoughUrgentLatencyHidingPre);

			if (mode_lib->vba.UseUrgentBurstBandwidth == false) {
				locals->UrgentBurstFactorLuma[k] = 1;
				locals->UrgentBurstFactorChroma[k] = 1;
				locals->UrgentBurstFactorCursor[k] = 1;
				locals->UrgentBurstFactorLumaPre[k] = 1;
				locals->UrgentBurstFactorChromaPre[k] = 1;
				locals->UrgentBurstFactorCursorPre[k] = 1;
			}

			MaxTotalRDBandwidth = MaxTotalRDBandwidth +
				dml_max3(locals->prefetch_vmrow_bw[k],
					locals->ReadBandwidthPlaneLuma[k] * locals->UrgentBurstFactorLuma[k]
					+ locals->ReadBandwidthPlaneChroma[k] * locals->UrgentBurstFactorChroma[k] + locals->cursor_bw[k]
					* locals->UrgentBurstFactorCursor[k] + locals->meta_row_bw[k] + locals->dpte_row_bw[k],
					locals->RequiredPrefetchPixDataBWLuma[k] * locals->UrgentBurstFactorLumaPre[k] + locals->RequiredPrefetchPixDataBWChroma[k]
					* locals->UrgentBurstFactorChromaPre[k] + locals->cursor_bw_pre[k] * locals->UrgentBurstFactorCursorPre[k]);

			MaxTotalRDBandwidthNoUrgentBurst = MaxTotalRDBandwidthNoUrgentBurst +
				dml_max3(locals->prefetch_vmrow_bw[k],
					locals->ReadBandwidthPlaneLuma[k] + locals->ReadBandwidthPlaneChroma[k] + locals->cursor_bw[k]
					+ locals->meta_row_bw[k] + locals->dpte_row_bw[k],
					locals->RequiredPrefetchPixDataBWLuma[k] + locals->RequiredPrefetchPixDataBWChroma[k] + locals->cursor_bw_pre[k]);

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

		if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && locals->NotEnoughUrgentLatencyHiding == 0 && locals->NotEnoughUrgentLatencyHidingPre == 0 && !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) {
			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
							- dml_max(
								locals->ReadBandwidthPlaneLuma[k] * locals->UrgentBurstFactorLuma[k]
								+ locals->ReadBandwidthPlaneChroma[k] * locals->UrgentBurstFactorChroma[k]
								+ locals->cursor_bw[k] * locals->UrgentBurstFactorCursor[k],
								locals->RequiredPrefetchPixDataBWLuma[k] * locals->UrgentBurstFactorLumaPre[k] +
								locals->RequiredPrefetchPixDataBWChroma[k] * locals->UrgentBurstFactorChromaPre[k] +
								locals->cursor_bw_pre[k] * locals->UrgentBurstFactorCursorPre[k]);
			}

			mode_lib->vba.TotImmediateFlipBytes = 0;
			for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
				mode_lib->vba.TotImmediateFlipBytes = mode_lib->vba.TotImmediateFlipBytes + locals->PDEAndMetaPTEBytesFrame[k] + locals->MetaRowByte[k] + locals->PixelPTEBytesPerRow[k];
			}
			for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
				CalculateFlipSchedule(
						mode_lib,
						mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
						mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly,
						mode_lib->vba.UrgentExtraLatency,
						mode_lib->vba.UrgentLatency,
						mode_lib->vba.GPUVMMaxPageTableLevels,
						mode_lib->vba.HostVMEnable,
						mode_lib->vba.HostVMMaxPageTableLevels,
						mode_lib->vba.HostVMCachedPageTableLevels,
						mode_lib->vba.GPUVMEnable,
						locals->PDEAndMetaPTEBytesFrame[k],
						locals->MetaRowByte[k],
						locals->PixelPTEBytesPerRow[k],
						mode_lib->vba.BandwidthAvailableForImmediateFlip,
						mode_lib->vba.TotImmediateFlipBytes,
						mode_lib->vba.SourcePixelFormat[k],
						mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k],
						mode_lib->vba.VRatio[k],
						locals->Tno_bw[k],
						mode_lib->vba.DCCEnable[k],
						locals->dpte_row_height[k],
						locals->meta_row_height[k],
						locals->dpte_row_height_chroma[k],
						locals->meta_row_height_chroma[k],
						&locals->DestinationLinesToRequestVMInImmediateFlip[k],
						&locals->DestinationLinesToRequestRowInImmediateFlip[k],
						&locals->final_flip_bw[k],
						&locals->ImmediateFlipSupportedForPipe[k]);
			}
			mode_lib->vba.total_dcn_read_bw_with_flip = 0.0;
			mode_lib->vba.total_dcn_read_bw_with_flip_no_urgent_burst = 0.0;
			for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
				mode_lib->vba.total_dcn_read_bw_with_flip =
						mode_lib->vba.total_dcn_read_bw_with_flip + dml_max3(
							locals->prefetch_vmrow_bw[k],
							locals->final_flip_bw[k] + locals->ReadBandwidthLuma[k] * locals->UrgentBurstFactorLuma[k]
							+ locals->ReadBandwidthChroma[k] * locals->UrgentBurstFactorChroma[k] + locals->cursor_bw[k] * locals->UrgentBurstFactorCursor[k],
							locals->final_flip_bw[k] + locals->RequiredPrefetchPixDataBWLuma[k] * locals->UrgentBurstFactorLumaPre[k]
							+ locals->RequiredPrefetchPixDataBWChroma[k] * locals->UrgentBurstFactorChromaPre[k]
							+ locals->cursor_bw_pre[k] * locals->UrgentBurstFactorCursorPre[k]);
				mode_lib->vba.total_dcn_read_bw_with_flip_no_urgent_burst =
				mode_lib->vba.total_dcn_read_bw_with_flip_no_urgent_burst +
					dml_max3(locals->prefetch_vmrow_bw[k],
						locals->final_flip_bw[k] + locals->ReadBandwidthPlaneLuma[k] + locals->ReadBandwidthPlaneChroma[k] + locals->cursor_bw[k],
						locals->final_flip_bw[k] + locals->RequiredPrefetchPixDataBWLuma[k] + locals->RequiredPrefetchPixDataBWChroma[k] + locals->cursor_bw_pre[k]);

			}
			mode_lib->vba.FractionOfUrgentBandwidthImmediateFlip = mode_lib->vba.total_dcn_read_bw_with_flip_no_urgent_burst / mode_lib->vba.ReturnBW;

			mode_lib->vba.ImmediateFlipSupported = true;
			if (mode_lib->vba.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 (locals->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.HostVMEnable)
					|| mode_lib->vba.ImmediateFlipSupported))
			|| locals->MaximumMaxVStartupLines < mode_lib->vba.VStartupLines));

	//Watermarks and NB P-State/DRAM Clock Change Support
	{
		enum clock_change_support DRAMClockChangeSupport; // dummy
		CalculateWatermarksAndDRAMSpeedChangeSupport(
				mode_lib,
				mode_lib->vba.PrefetchMode[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb],
				mode_lib->vba.NumberOfActivePlanes,
				mode_lib->vba.MaxLineBufferLines,
				mode_lib->vba.LineBufferSize,
				mode_lib->vba.DPPOutputBufferPixels,
				mode_lib->vba.DETBufferSizeInKByte,
				mode_lib->vba.WritebackInterfaceLumaBufferSize,
				mode_lib->vba.WritebackInterfaceChromaBufferSize,
				mode_lib->vba.DCFCLK,
				mode_lib->vba.UrgentOutOfOrderReturnPerChannel * mode_lib->vba.NumberOfChannels,
				mode_lib->vba.ReturnBW,
				mode_lib->vba.GPUVMEnable,
				locals->dpte_group_bytes,
				mode_lib->vba.MetaChunkSize,
				mode_lib->vba.UrgentLatency,
				mode_lib->vba.UrgentExtraLatency,
				mode_lib->vba.WritebackLatency,
				mode_lib->vba.WritebackChunkSize,
				mode_lib->vba.SOCCLK,
				mode_lib->vba.DRAMClockChangeLatency,
				mode_lib->vba.SRExitTime,
				mode_lib->vba.SREnterPlusExitTime,
				mode_lib->vba.DCFCLKDeepSleep,
				mode_lib->vba.DPPPerPlane,
				mode_lib->vba.DCCEnable,
				locals->DPPCLK,
				locals->SwathWidthSingleDPPY,
				mode_lib->vba.SwathHeightY,
				locals->ReadBandwidthPlaneLuma,
				mode_lib->vba.SwathHeightC,
				locals->ReadBandwidthPlaneChroma,
				mode_lib->vba.LBBitPerPixel,
				locals->SwathWidthY,
				mode_lib->vba.HRatio,
				mode_lib->vba.vtaps,
				mode_lib->vba.VTAPsChroma,
				mode_lib->vba.VRatio,
				mode_lib->vba.HTotal,
				mode_lib->vba.PixelClock,
				mode_lib->vba.BlendingAndTiming,
				locals->BytePerPixelDETY,
				locals->BytePerPixelDETC,
				mode_lib->vba.WritebackEnable,
				mode_lib->vba.WritebackPixelFormat,
				mode_lib->vba.WritebackDestinationWidth,
				mode_lib->vba.WritebackDestinationHeight,
				mode_lib->vba.WritebackSourceHeight,
				&DRAMClockChangeSupport,
				&mode_lib->vba.UrgentWatermark,
				&mode_lib->vba.WritebackUrgentWatermark,
				&mode_lib->vba.DRAMClockChangeWatermark,
				&mode_lib->vba.WritebackDRAMClockChangeWatermark,
				&mode_lib->vba.StutterExitWatermark,
				&mode_lib->vba.StutterEnterPlusExitWatermark,
				&mode_lib->vba.MinActiveDRAMClockChangeLatencySupported);
	}


	//Display Pipeline Delivery Time in Prefetch, Groups
	CalculatePixelDeliveryTimes(
		mode_lib->vba.NumberOfActivePlanes,
		mode_lib->vba.VRatio,
		locals->VRatioPrefetchY,
		locals->VRatioPrefetchC,
		locals->swath_width_luma_ub,
		locals->swath_width_chroma_ub,
		mode_lib->vba.DPPPerPlane,
		mode_lib->vba.HRatio,
		mode_lib->vba.PixelClock,
		locals->PSCL_THROUGHPUT_LUMA,
		locals->PSCL_THROUGHPUT_CHROMA,
		locals->DPPCLK,
		locals->BytePerPixelDETC,
		mode_lib->vba.SourceScan,
		locals->BlockWidth256BytesY,
		locals->BlockHeight256BytesY,
		locals->BlockWidth256BytesC,
		locals->BlockHeight256BytesC,
		locals->DisplayPipeLineDeliveryTimeLuma,
		locals->DisplayPipeLineDeliveryTimeChroma,
		locals->DisplayPipeLineDeliveryTimeLumaPrefetch,
		locals->DisplayPipeLineDeliveryTimeChromaPrefetch,
		locals->DisplayPipeRequestDeliveryTimeLuma,
		locals->DisplayPipeRequestDeliveryTimeChroma,
		locals->DisplayPipeRequestDeliveryTimeLumaPrefetch,
		locals->DisplayPipeRequestDeliveryTimeChromaPrefetch);

	CalculateMetaAndPTETimes(
		mode_lib->vba.NumberOfActivePlanes,
		mode_lib->vba.GPUVMEnable,
		mode_lib->vba.MetaChunkSize,
		mode_lib->vba.MinMetaChunkSizeBytes,
		mode_lib->vba.GPUVMMaxPageTableLevels,
		mode_lib->vba.HTotal,
		mode_lib->vba.VRatio,
		locals->VRatioPrefetchY,
		locals->VRatioPrefetchC,
		locals->DestinationLinesToRequestRowInVBlank,
		locals->DestinationLinesToRequestRowInImmediateFlip,
		locals->DestinationLinesToRequestVMInVBlank,
		locals->DestinationLinesToRequestVMInImmediateFlip,
		mode_lib->vba.DCCEnable,
		mode_lib->vba.PixelClock,
		locals->BytePerPixelDETY,
		locals->BytePerPixelDETC,
		mode_lib->vba.SourceScan,
		locals->dpte_row_height,
		locals->dpte_row_height_chroma,
		locals->meta_row_width,
		locals->meta_row_height,
		locals->meta_req_width,
		locals->meta_req_height,
		locals->dpte_group_bytes,
		locals->PTERequestSizeY,
		locals->PTERequestSizeC,
		locals->PixelPTEReqWidthY,
		locals->PixelPTEReqHeightY,
		locals->PixelPTEReqWidthC,
		locals->PixelPTEReqHeightC,
		locals->dpte_row_width_luma_ub,
		locals->dpte_row_width_chroma_ub,
		locals->vm_group_bytes,
		locals->dpde0_bytes_per_frame_ub_l,
		locals->dpde0_bytes_per_frame_ub_c,
		locals->meta_pte_bytes_per_frame_ub_l,
		locals->meta_pte_bytes_per_frame_ub_c,
		locals->DST_Y_PER_PTE_ROW_NOM_L,
		locals->DST_Y_PER_PTE_ROW_NOM_C,
		locals->DST_Y_PER_META_ROW_NOM_L,
		locals->TimePerMetaChunkNominal,
		locals->TimePerMetaChunkVBlank,
		locals->TimePerMetaChunkFlip,
		locals->time_per_pte_group_nom_luma,
		locals->time_per_pte_group_vblank_luma,
		locals->time_per_pte_group_flip_luma,
		locals->time_per_pte_group_nom_chroma,
		locals->time_per_pte_group_vblank_chroma,
		locals->time_per_pte_group_flip_chroma,
		locals->TimePerVMGroupVBlank,
		locals->TimePerVMGroupFlip,
		locals->TimePerVMRequestVBlank,
		locals->TimePerVMRequestFlip);


	// 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) {
			locals->AllowDRAMClockChangeDuringVBlank[k] = true;
			locals->AllowDRAMSelfRefreshDuringVBlank[k] = true;
			locals->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) {
			locals->AllowDRAMClockChangeDuringVBlank[k] = false;
			locals->AllowDRAMSelfRefreshDuringVBlank[k] = true;
			locals->MinTTUVBlank[k] = dml_max(
					mode_lib->vba.StutterEnterPlusExitWatermark,
					mode_lib->vba.UrgentWatermark);
		} else {
			locals->AllowDRAMClockChangeDuringVBlank[k] = false;
			locals->AllowDRAMSelfRefreshDuringVBlank[k] = false;
			locals->MinTTUVBlank[k] = mode_lib->vba.UrgentWatermark;
		}
		if (!mode_lib->vba.DynamicMetadataEnable[k])
			locals->MinTTUVBlank[k] = mode_lib->vba.TCalc
					+ locals->MinTTUVBlank[k];
	}

	// DCC Configuration
	mode_lib->vba.ActiveDPPs = 0;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		locals->MaximumDCCCompressionYSurface[k] = CalculateDCCConfiguration(
			mode_lib->vba.DCCEnable[k],
			false, // We should always know the direction DCCProgrammingAssumesScanDirectionUnknown,
			mode_lib->vba.ViewportWidth[k],
			mode_lib->vba.ViewportHeight[k],
			mode_lib->vba.DETBufferSizeInKByte * 1024,
			locals->BlockHeight256BytesY[k],
			mode_lib->vba.SwathHeightY[k],
			mode_lib->vba.SurfaceTiling[k],
			locals->BytePerPixelDETY[k],
			mode_lib->vba.SourceScan[k],
			&locals->DCCYMaxUncompressedBlock[k],
			&locals->DCCYMaxCompressedBlock[k],
			&locals->DCCYIndependent64ByteBlock[k]);
	}

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

			locals->XFCSlaveVUpdateOffset[k] = mode_lib->vba.XFCTSlvVupdateOffset;
			locals->XFCSlaveVupdateWidth[k] = mode_lib->vba.XFCTSlvVupdateWidth;
			locals->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.UrgentLatency,
					mode_lib->vba.SREnterPlusExitTime);
			mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay(
					mode_lib,
					mode_lib->vba.VRatio[k],
					locals->SwathWidthY[k],
					dml_ceil(locals->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);
					locals->XFCRemoteSurfaceFlipLatency[k] =
					dml_floor(
							mode_lib->vba.XFCRemoteSurfaceFlipDelay
									/ (mode_lib->vba.HTotal[k]
											/ mode_lib->vba.PixelClock[k]),
							1);
			locals->XFCTransferDelay[k] =
					dml_ceil(
							mode_lib->vba.XFCBusTransportTime
									/ (mode_lib->vba.HTotal[k]
											/ mode_lib->vba.PixelClock[k]),
							1);
			locals->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 =
					(locals->DestinationLinesToRequestVMInVBlank[k]
							+ locals->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);
			locals->XFCPrefetchMargin[k] =
					mode_lib->vba.XFCRemoteSurfaceFlipDelay
							+ mode_lib->vba.TFinalxFill
							+ (locals->DestinationLinesToRequestVMInVBlank[k]
									+ locals->DestinationLinesToRequestRowInVBlank[k])
									* mode_lib->vba.HTotal[k]
									/ mode_lib->vba.PixelClock[k];
		} else {
			locals->XFCSlaveVUpdateOffset[k] = 0;
			locals->XFCSlaveVupdateWidth[k] = 0;
			locals->XFCSlaveVReadyOffset[k] = 0;
			locals->XFCRemoteSurfaceFlipLatency[k] = 0;
			locals->XFCPrechargeDelay[k] = 0;
			locals->XFCTransferDelay[k] = 0;
			locals->XFCPrefetchMargin[k] = 0;
		}
	}

	// Stutter Efficiency
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		CalculateDETBufferSize(
			mode_lib->vba.DETBufferSizeInKByte,
			mode_lib->vba.SwathHeightY[k],
			mode_lib->vba.SwathHeightC[k],
			&locals->DETBufferSizeY[k],
			&locals->DETBufferSizeC[k]);

		locals->LinesInDETY[k] = locals->DETBufferSizeY[k]
				/ locals->BytePerPixelDETY[k] / locals->SwathWidthY[k];
		locals->LinesInDETYRoundedDownToSwath[k] = dml_floor(
				locals->LinesInDETY[k],
				mode_lib->vba.SwathHeightY[k]);
		locals->FullDETBufferingTimeY[k] =
				locals->LinesInDETYRoundedDownToSwath[k]
						* (mode_lib->vba.HTotal[k]
								/ mode_lib->vba.PixelClock[k])
						/ mode_lib->vba.VRatio[k];
	}

	mode_lib->vba.StutterPeriod = 999999.0;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		if (locals->FullDETBufferingTimeY[k] < mode_lib->vba.StutterPeriod) {
			mode_lib->vba.StutterPeriod = locals->FullDETBufferingTimeY[k];
			mode_lib->vba.FrameTimeForMinFullDETBufferingTime =
				(double) mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k]
				/ mode_lib->vba.PixelClock[k];
			locals->BytePerPixelYCriticalPlane = dml_ceil(locals->BytePerPixelDETY[k], 1);
			locals->SwathWidthYCriticalPlane = locals->SwathWidthY[k];
			locals->LinesToFinishSwathTransferStutterCriticalPlane =
				mode_lib->vba.SwathHeightY[k] - (locals->LinesInDETY[k] - locals->LinesInDETYRoundedDownToSwath[k]);
		}
	}

	mode_lib->vba.AverageReadBandwidth = 0.0;
	mode_lib->vba.TotalRowReadBandwidth = 0.0;
	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
		unsigned int DCCRateLimit;

		if (mode_lib->vba.DCCEnable[k]) {
			if (locals->DCCYMaxCompressedBlock[k] == 256)
				DCCRateLimit = 4;
			else
				DCCRateLimit = 2;

			mode_lib->vba.AverageReadBandwidth =
					mode_lib->vba.AverageReadBandwidth
							+ (locals->ReadBandwidthPlaneLuma[k] + locals->ReadBandwidthPlaneChroma[k]) /
								dml_min(mode_lib->vba.DCCRate[k], DCCRateLimit);
		} else {
			mode_lib->vba.AverageReadBandwidth =
					mode_lib->vba.AverageReadBandwidth
							+ locals->ReadBandwidthPlaneLuma[k]
							+ locals->ReadBandwidthPlaneChroma[k];
		}
		mode_lib->vba.TotalRowReadBandwidth = mode_lib->vba.TotalRowReadBandwidth +
		locals->meta_row_bw[k] + locals->dpte_row_bw[k];
	}

	mode_lib->vba.AverageDCCCompressionRate = mode_lib->vba.TotalDataReadBandwidth / mode_lib->vba.AverageReadBandwidth;

	mode_lib->vba.PartOfBurstThatFitsInROB =
			dml_min(
					mode_lib->vba.StutterPeriod
							* mode_lib->vba.TotalDataReadBandwidth,
					mode_lib->vba.ROBBufferSizeInKByte * 1024
							* mode_lib->vba.AverageDCCCompressionRate);
	mode_lib->vba.StutterBurstTime = mode_lib->vba.PartOfBurstThatFitsInROB
			/ mode_lib->vba.AverageDCCCompressionRate / mode_lib->vba.ReturnBW
			+ (mode_lib->vba.StutterPeriod * mode_lib->vba.TotalDataReadBandwidth
					- mode_lib->vba.PartOfBurstThatFitsInROB)
					/ (mode_lib->vba.DCFCLK * 64)
					+ mode_lib->vba.StutterPeriod * mode_lib->vba.TotalRowReadBandwidth / mode_lib->vba.ReturnBW;
	mode_lib->vba.StutterBurstTime = dml_max(
		mode_lib->vba.StutterBurstTime,
		(locals->LinesToFinishSwathTransferStutterCriticalPlane * locals->BytePerPixelYCriticalPlane *
		locals->SwathWidthYCriticalPlane / mode_lib->vba.ReturnBW)
	);

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

	if (mode_lib->vba.TotalActiveWriteback == 0) {
		mode_lib->vba.StutterEfficiencyNotIncludingVBlank = (1
				- (mode_lib->vba.SRExitTime + mode_lib->vba.StutterBurstTime)
						/ mode_lib->vba.StutterPeriod) * 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;
}