static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation()

in drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c [2052:3382]


static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(struct display_mode_lib *mode_lib)
{
	struct vba_vars_st *v = &mode_lib->vba;
	unsigned int j, k;
	double HostVMInefficiencyFactor = 1.0;
	bool NoChromaPlanes = true;
	int ReorderBytes;
	double VMDataOnlyReturnBW;
	double MaxTotalRDBandwidth = 0;
	int PrefetchMode = v->PrefetchModePerState[v->VoltageLevel][v->maxMpcComb];

	v->WritebackDISPCLK = 0.0;
	v->DISPCLKWithRamping = 0;
	v->DISPCLKWithoutRamping = 0;
	v->GlobalDPPCLK = 0.0;
	/* DAL custom code: need to update ReturnBW in case min dcfclk is overriden */
	{
	double IdealFabricAndSDPPortBandwidthPerState = dml_min(
			v->ReturnBusWidth * v->DCFCLKState[v->VoltageLevel][v->maxMpcComb],
			v->FabricClockPerState[v->VoltageLevel] * v->FabricDatapathToDCNDataReturn);
	double IdealDRAMBandwidthPerState = v->DRAMSpeedPerState[v->VoltageLevel] * v->NumberOfChannels * v->DRAMChannelWidth;
	if (v->HostVMEnable != true) {
		v->ReturnBW = dml_min(
				IdealFabricAndSDPPortBandwidthPerState * v->PercentOfIdealFabricAndSDPPortBWReceivedAfterUrgLatency / 100.0,
				IdealDRAMBandwidthPerState * v->PercentOfIdealDRAMBWReceivedAfterUrgLatencyPixelDataOnly / 100.0);
	} else {
		v->ReturnBW = dml_min(
				IdealFabricAndSDPPortBandwidthPerState * v->PercentOfIdealFabricAndSDPPortBWReceivedAfterUrgLatency / 100.0,
				IdealDRAMBandwidthPerState * v->PercentOfIdealDRAMBWReceivedAfterUrgLatencyPixelMixedWithVMData / 100.0);
	}
	}
	/* End DAL custom code */

	// DISPCLK and DPPCLK Calculation
	//
	for (k = 0; k < v->NumberOfActivePlanes; ++k) {
		if (v->WritebackEnable[k]) {
			v->WritebackDISPCLK = dml_max(
					v->WritebackDISPCLK,
					dml31_CalculateWriteBackDISPCLK(
							v->WritebackPixelFormat[k],
							v->PixelClock[k],
							v->WritebackHRatio[k],
							v->WritebackVRatio[k],
							v->WritebackHTaps[k],
							v->WritebackVTaps[k],
							v->WritebackSourceWidth[k],
							v->WritebackDestinationWidth[k],
							v->HTotal[k],
							v->WritebackLineBufferSize));
		}
	}

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

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

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

		if ((v->SourcePixelFormat[k] != dm_420_8 && v->SourcePixelFormat[k] != dm_420_10 && v->SourcePixelFormat[k] != dm_420_12
				&& v->SourcePixelFormat[k] != dm_rgbe_alpha)) {
			v->PSCL_THROUGHPUT_CHROMA[k] = 0.0;
			v->DPPCLKUsingSingleDPP[k] = v->DPPCLKUsingSingleDPPLuma;
		} else {
			if (v->HRatioChroma[k] > 1) {
				v->PSCL_THROUGHPUT_CHROMA[k] = dml_min(
						v->MaxDCHUBToPSCLThroughput,
						v->MaxPSCLToLBThroughput * v->HRatioChroma[k] / dml_ceil(v->HTAPsChroma[k] / 6.0, 1.0));
			} else {
				v->PSCL_THROUGHPUT_CHROMA[k] = dml_min(v->MaxDCHUBToPSCLThroughput, v->MaxPSCLToLBThroughput);
			}
			v->DPPCLKUsingSingleDPPChroma = v->PixelClock[k]
					* dml_max3(
							v->VTAPsChroma[k] / 6.0 * dml_min(1.0, v->HRatioChroma[k]),
							v->HRatioChroma[k] * v->VRatioChroma[k] / v->PSCL_THROUGHPUT_CHROMA[k],
							1.0);

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

			v->DPPCLKUsingSingleDPP[k] = dml_max(v->DPPCLKUsingSingleDPPLuma, v->DPPCLKUsingSingleDPPChroma);
		}
	}

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

	v->DISPCLKWithRamping = dml_max(v->DISPCLKWithRamping, v->WritebackDISPCLK);
	v->DISPCLKWithoutRamping = dml_max(v->DISPCLKWithoutRamping, v->WritebackDISPCLK);

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

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

	for (k = 0; k < v->NumberOfActivePlanes; ++k) {
		v->DPPCLK[k] = v->DPPCLK_calculated[k];
	}

	// Urgent and B P-State/DRAM Clock Change Watermark
	DTRACE("   dcfclk_mhz         = %f", v->DCFCLK);
	DTRACE("   return_bus_bw      = %f", v->ReturnBW);

	for (k = 0; k < v->NumberOfActivePlanes; ++k) {
		CalculateBytePerPixelAnd256BBlockSizes(
				v->SourcePixelFormat[k],
				v->SurfaceTiling[k],
				&v->BytePerPixelY[k],
				&v->BytePerPixelC[k],
				&v->BytePerPixelDETY[k],
				&v->BytePerPixelDETC[k],
				&v->BlockHeight256BytesY[k],
				&v->BlockHeight256BytesC[k],
				&v->BlockWidth256BytesY[k],
				&v->BlockWidth256BytesC[k]);
	}

	CalculateSwathWidth(
			false,
			v->NumberOfActivePlanes,
			v->SourcePixelFormat,
			v->SourceScan,
			v->ViewportWidth,
			v->ViewportHeight,
			v->SurfaceWidthY,
			v->SurfaceWidthC,
			v->SurfaceHeightY,
			v->SurfaceHeightC,
			v->ODMCombineEnabled,
			v->BytePerPixelY,
			v->BytePerPixelC,
			v->BlockHeight256BytesY,
			v->BlockHeight256BytesC,
			v->BlockWidth256BytesY,
			v->BlockWidth256BytesC,
			v->BlendingAndTiming,
			v->HActive,
			v->HRatio,
			v->DPPPerPlane,
			v->SwathWidthSingleDPPY,
			v->SwathWidthSingleDPPC,
			v->SwathWidthY,
			v->SwathWidthC,
			v->dummyinteger3,
			v->dummyinteger4,
			v->swath_width_luma_ub,
			v->swath_width_chroma_ub);

	for (k = 0; k < v->NumberOfActivePlanes; ++k) {
		v->ReadBandwidthPlaneLuma[k] = v->SwathWidthSingleDPPY[k] * v->BytePerPixelY[k] / (v->HTotal[k] / v->PixelClock[k])
				* v->VRatio[k];
		v->ReadBandwidthPlaneChroma[k] = v->SwathWidthSingleDPPC[k] * v->BytePerPixelC[k] / (v->HTotal[k] / v->PixelClock[k])
				* v->VRatioChroma[k];
		DTRACE("   read_bw[%i] = %fBps", k, v->ReadBandwidthPlaneLuma[k] + v->ReadBandwidthPlaneChroma[k]);
	}

	// DCFCLK Deep Sleep
	CalculateDCFCLKDeepSleep(
			mode_lib,
			v->NumberOfActivePlanes,
			v->BytePerPixelY,
			v->BytePerPixelC,
			v->VRatio,
			v->VRatioChroma,
			v->SwathWidthY,
			v->SwathWidthC,
			v->DPPPerPlane,
			v->HRatio,
			v->HRatioChroma,
			v->PixelClock,
			v->PSCL_THROUGHPUT_LUMA,
			v->PSCL_THROUGHPUT_CHROMA,
			v->DPPCLK,
			v->ReadBandwidthPlaneLuma,
			v->ReadBandwidthPlaneChroma,
			v->ReturnBusWidth,
			&v->DCFCLKDeepSleep);

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

	// DSC Delay
	for (k = 0; k < v->NumberOfActivePlanes; ++k) {
		double BPP = v->OutputBpp[k];

		if (v->DSCEnabled[k] && BPP != 0) {
			if (v->ODMCombineEnabled[k] == dm_odm_combine_mode_disabled) {
				v->DSCDelay[k] = dscceComputeDelay(
						v->DSCInputBitPerComponent[k],
						BPP,
						dml_ceil((double) v->HActive[k] / v->NumberOfDSCSlices[k], 1),
						v->NumberOfDSCSlices[k],
						v->OutputFormat[k],
						v->Output[k]) + dscComputeDelay(v->OutputFormat[k], v->Output[k]);
			} else if (v->ODMCombineEnabled[k] == dm_odm_combine_mode_2to1) {
				v->DSCDelay[k] = 2
						* (dscceComputeDelay(
								v->DSCInputBitPerComponent[k],
								BPP,
								dml_ceil((double) v->HActive[k] / v->NumberOfDSCSlices[k], 1),
								v->NumberOfDSCSlices[k] / 2.0,
								v->OutputFormat[k],
								v->Output[k]) + dscComputeDelay(v->OutputFormat[k], v->Output[k]));
			} else {
				v->DSCDelay[k] = 4
						* (dscceComputeDelay(
								v->DSCInputBitPerComponent[k],
								BPP,
								dml_ceil((double) v->HActive[k] / v->NumberOfDSCSlices[k], 1),
								v->NumberOfDSCSlices[k] / 4.0,
								v->OutputFormat[k],
								v->Output[k]) + dscComputeDelay(v->OutputFormat[k], v->Output[k]));
			}
			v->DSCDelay[k] = v->DSCDelay[k] * v->PixelClock[k] / v->PixelClockBackEnd[k];
		} else {
			v->DSCDelay[k] = 0;
		}
	}

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

	// Prefetch
	for (k = 0; k < v->NumberOfActivePlanes; ++k) {
		unsigned int PDEAndMetaPTEBytesFrameY;
		unsigned int PixelPTEBytesPerRowY;
		unsigned int MetaRowByteY;
		unsigned int MetaRowByteC;
		unsigned int PDEAndMetaPTEBytesFrameC;
		unsigned int PixelPTEBytesPerRowC;
		bool PTEBufferSizeNotExceededY;
		bool PTEBufferSizeNotExceededC;

		if (v->SourcePixelFormat[k] == dm_420_8 || v->SourcePixelFormat[k] == dm_420_10 || v->SourcePixelFormat[k] == dm_420_12
				|| v->SourcePixelFormat[k] == dm_rgbe_alpha) {
			if ((v->SourcePixelFormat[k] == dm_420_10 || v->SourcePixelFormat[k] == dm_420_12) && v->SourceScan[k] != dm_vert) {
				v->PTEBufferSizeInRequestsForLuma = (v->PTEBufferSizeInRequestsLuma + v->PTEBufferSizeInRequestsChroma) / 2;
				v->PTEBufferSizeInRequestsForChroma = v->PTEBufferSizeInRequestsForLuma;
			} else {
				v->PTEBufferSizeInRequestsForLuma = v->PTEBufferSizeInRequestsLuma;
				v->PTEBufferSizeInRequestsForChroma = v->PTEBufferSizeInRequestsChroma;
			}

			PDEAndMetaPTEBytesFrameC = CalculateVMAndRowBytes(
					mode_lib,
					v->DCCEnable[k],
					v->BlockHeight256BytesC[k],
					v->BlockWidth256BytesC[k],
					v->SourcePixelFormat[k],
					v->SurfaceTiling[k],
					v->BytePerPixelC[k],
					v->SourceScan[k],
					v->SwathWidthC[k],
					v->ViewportHeightChroma[k],
					v->GPUVMEnable,
					v->HostVMEnable,
					v->HostVMMaxNonCachedPageTableLevels,
					v->GPUVMMinPageSize,
					v->HostVMMinPageSize,
					v->PTEBufferSizeInRequestsForChroma,
					v->PitchC[k],
					v->DCCMetaPitchC[k],
					&v->MacroTileWidthC[k],
					&MetaRowByteC,
					&PixelPTEBytesPerRowC,
					&PTEBufferSizeNotExceededC,
					&v->dpte_row_width_chroma_ub[k],
					&v->dpte_row_height_chroma[k],
					&v->meta_req_width_chroma[k],
					&v->meta_req_height_chroma[k],
					&v->meta_row_width_chroma[k],
					&v->meta_row_height_chroma[k],
					&v->dummyinteger1,
					&v->dummyinteger2,
					&v->PixelPTEReqWidthC[k],
					&v->PixelPTEReqHeightC[k],
					&v->PTERequestSizeC[k],
					&v->dpde0_bytes_per_frame_ub_c[k],
					&v->meta_pte_bytes_per_frame_ub_c[k]);

			v->PrefetchSourceLinesC[k] = CalculatePrefetchSourceLines(
					mode_lib,
					v->VRatioChroma[k],
					v->VTAPsChroma[k],
					v->Interlace[k],
					v->ProgressiveToInterlaceUnitInOPP,
					v->SwathHeightC[k],
					v->ViewportYStartC[k],
					&v->VInitPreFillC[k],
					&v->MaxNumSwathC[k]);
		} else {
			v->PTEBufferSizeInRequestsForLuma = v->PTEBufferSizeInRequestsLuma + v->PTEBufferSizeInRequestsChroma;
			v->PTEBufferSizeInRequestsForChroma = 0;
			PixelPTEBytesPerRowC = 0;
			PDEAndMetaPTEBytesFrameC = 0;
			MetaRowByteC = 0;
			v->MaxNumSwathC[k] = 0;
			v->PrefetchSourceLinesC[k] = 0;
		}

		PDEAndMetaPTEBytesFrameY = CalculateVMAndRowBytes(
				mode_lib,
				v->DCCEnable[k],
				v->BlockHeight256BytesY[k],
				v->BlockWidth256BytesY[k],
				v->SourcePixelFormat[k],
				v->SurfaceTiling[k],
				v->BytePerPixelY[k],
				v->SourceScan[k],
				v->SwathWidthY[k],
				v->ViewportHeight[k],
				v->GPUVMEnable,
				v->HostVMEnable,
				v->HostVMMaxNonCachedPageTableLevels,
				v->GPUVMMinPageSize,
				v->HostVMMinPageSize,
				v->PTEBufferSizeInRequestsForLuma,
				v->PitchY[k],
				v->DCCMetaPitchY[k],
				&v->MacroTileWidthY[k],
				&MetaRowByteY,
				&PixelPTEBytesPerRowY,
				&PTEBufferSizeNotExceededY,
				&v->dpte_row_width_luma_ub[k],
				&v->dpte_row_height[k],
				&v->meta_req_width[k],
				&v->meta_req_height[k],
				&v->meta_row_width[k],
				&v->meta_row_height[k],
				&v->vm_group_bytes[k],
				&v->dpte_group_bytes[k],
				&v->PixelPTEReqWidthY[k],
				&v->PixelPTEReqHeightY[k],
				&v->PTERequestSizeY[k],
				&v->dpde0_bytes_per_frame_ub_l[k],
				&v->meta_pte_bytes_per_frame_ub_l[k]);

		v->PrefetchSourceLinesY[k] = CalculatePrefetchSourceLines(
				mode_lib,
				v->VRatio[k],
				v->vtaps[k],
				v->Interlace[k],
				v->ProgressiveToInterlaceUnitInOPP,
				v->SwathHeightY[k],
				v->ViewportYStartY[k],
				&v->VInitPreFillY[k],
				&v->MaxNumSwathY[k]);
		v->PixelPTEBytesPerRow[k] = PixelPTEBytesPerRowY + PixelPTEBytesPerRowC;
		v->PDEAndMetaPTEBytesFrame[k] = PDEAndMetaPTEBytesFrameY + PDEAndMetaPTEBytesFrameC;
		v->MetaRowByte[k] = MetaRowByteY + MetaRowByteC;

		CalculateRowBandwidth(
				v->GPUVMEnable,
				v->SourcePixelFormat[k],
				v->VRatio[k],
				v->VRatioChroma[k],
				v->DCCEnable[k],
				v->HTotal[k] / v->PixelClock[k],
				MetaRowByteY,
				MetaRowByteC,
				v->meta_row_height[k],
				v->meta_row_height_chroma[k],
				PixelPTEBytesPerRowY,
				PixelPTEBytesPerRowC,
				v->dpte_row_height[k],
				v->dpte_row_height_chroma[k],
				&v->meta_row_bw[k],
				&v->dpte_row_bw[k]);
	}

	v->TotalDCCActiveDPP = 0;
	v->TotalActiveDPP = 0;
	for (k = 0; k < v->NumberOfActivePlanes; ++k) {
		v->TotalActiveDPP = v->TotalActiveDPP + v->DPPPerPlane[k];
		if (v->DCCEnable[k])
			v->TotalDCCActiveDPP = v->TotalDCCActiveDPP + v->DPPPerPlane[k];
		if (v->SourcePixelFormat[k] == dm_420_8 || v->SourcePixelFormat[k] == dm_420_10 || v->SourcePixelFormat[k] == dm_420_12
				|| v->SourcePixelFormat[k] == dm_rgbe_alpha)
			NoChromaPlanes = false;
	}

	ReorderBytes = v->NumberOfChannels
			* dml_max3(
					v->UrgentOutOfOrderReturnPerChannelPixelDataOnly,
					v->UrgentOutOfOrderReturnPerChannelPixelMixedWithVMData,
					v->UrgentOutOfOrderReturnPerChannelVMDataOnly);

	VMDataOnlyReturnBW = dml_min(
			dml_min(v->ReturnBusWidth * v->DCFCLK, v->FabricClock * v->FabricDatapathToDCNDataReturn)
					* v->PercentOfIdealFabricAndSDPPortBWReceivedAfterUrgLatency / 100.0,
			v->DRAMSpeed * v->NumberOfChannels * v->DRAMChannelWidth
					* v->PercentOfIdealDRAMBWReceivedAfterUrgLatencyVMDataOnly / 100.0);

#ifdef __DML_VBA_DEBUG__
	dml_print("DML::%s: v->ReturnBusWidth = %f\n", __func__, v->ReturnBusWidth);
	dml_print("DML::%s: v->DCFCLK = %f\n", __func__, v->DCFCLK);
	dml_print("DML::%s: v->FabricClock = %f\n", __func__, v->FabricClock);
	dml_print("DML::%s: v->FabricDatapathToDCNDataReturn = %f\n", __func__, v->FabricDatapathToDCNDataReturn);
	dml_print("DML::%s: v->PercentOfIdealFabricAndSDPPortBWReceivedAfterUrgLatency = %f\n", __func__, v->PercentOfIdealFabricAndSDPPortBWReceivedAfterUrgLatency);
	dml_print("DML::%s: v->DRAMSpeed = %f\n", __func__, v->DRAMSpeed);
	dml_print("DML::%s: v->NumberOfChannels = %f\n", __func__, v->NumberOfChannels);
	dml_print("DML::%s: v->DRAMChannelWidth = %f\n", __func__, v->DRAMChannelWidth);
	dml_print("DML::%s: v->PercentOfIdealDRAMBWReceivedAfterUrgLatencyVMDataOnly = %f\n", __func__, v->PercentOfIdealDRAMBWReceivedAfterUrgLatencyVMDataOnly);
	dml_print("DML::%s: VMDataOnlyReturnBW = %f\n", __func__, VMDataOnlyReturnBW);
	dml_print("DML::%s: ReturnBW = %f\n", __func__, v->ReturnBW);
#endif

	if (v->GPUVMEnable && v->HostVMEnable)
		HostVMInefficiencyFactor = v->ReturnBW / VMDataOnlyReturnBW;

	v->UrgentExtraLatency = CalculateExtraLatency(
			v->RoundTripPingLatencyCycles,
			ReorderBytes,
			v->DCFCLK,
			v->TotalActiveDPP,
			v->PixelChunkSizeInKByte,
			v->TotalDCCActiveDPP,
			v->MetaChunkSize,
			v->ReturnBW,
			v->GPUVMEnable,
			v->HostVMEnable,
			v->NumberOfActivePlanes,
			v->DPPPerPlane,
			v->dpte_group_bytes,
			HostVMInefficiencyFactor,
			v->HostVMMinPageSize,
			v->HostVMMaxNonCachedPageTableLevels);

	v->TCalc = 24.0 / v->DCFCLKDeepSleep;

	for (k = 0; k < v->NumberOfActivePlanes; ++k) {
		if (v->BlendingAndTiming[k] == k) {
			if (v->WritebackEnable[k] == true) {
				v->WritebackDelay[v->VoltageLevel][k] = v->WritebackLatency
						+ CalculateWriteBackDelay(
								v->WritebackPixelFormat[k],
								v->WritebackHRatio[k],
								v->WritebackVRatio[k],
								v->WritebackVTaps[k],
								v->WritebackDestinationWidth[k],
								v->WritebackDestinationHeight[k],
								v->WritebackSourceHeight[k],
								v->HTotal[k]) / v->DISPCLK;
			} else
				v->WritebackDelay[v->VoltageLevel][k] = 0;
			for (j = 0; j < v->NumberOfActivePlanes; ++j) {
				if (v->BlendingAndTiming[j] == k && v->WritebackEnable[j] == true) {
					v->WritebackDelay[v->VoltageLevel][k] = dml_max(
							v->WritebackDelay[v->VoltageLevel][k],
							v->WritebackLatency
									+ CalculateWriteBackDelay(
											v->WritebackPixelFormat[j],
											v->WritebackHRatio[j],
											v->WritebackVRatio[j],
											v->WritebackVTaps[j],
											v->WritebackDestinationWidth[j],
											v->WritebackDestinationHeight[j],
											v->WritebackSourceHeight[j],
											v->HTotal[k]) / v->DISPCLK);
				}
			}
		}
	}

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

	for (k = 0; k < v->NumberOfActivePlanes; ++k) {
		v->MaxVStartupLines[k] =
				(v->Interlace[k] && !v->ProgressiveToInterlaceUnitInOPP) ?
						dml_floor((v->VTotal[k] - v->VActive[k]) / 2.0, 1.0) :
						v->VTotal[k] - v->VActive[k]
								- dml_max(
										1.0,
										dml_ceil(
												(double) v->WritebackDelay[v->VoltageLevel][k]
														/ (v->HTotal[k] / v->PixelClock[k]),
												1));
		if (v->MaxVStartupLines[k] > 1023)
			v->MaxVStartupLines[k] = 1023;

#ifdef __DML_VBA_DEBUG__
		dml_print("DML::%s: k=%d MaxVStartupLines = %d\n", __func__, k, v->MaxVStartupLines[k]);
		dml_print("DML::%s: k=%d VoltageLevel = %d\n", __func__, k, v->VoltageLevel);
		dml_print("DML::%s: k=%d WritebackDelay = %f\n", __func__, k, v->WritebackDelay[v->VoltageLevel][k]);
#endif
	}

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

	// VBA_DELTA
	// We don't really care to iterate between the various prefetch modes
	//v->PrefetchERROR = CalculateMinAndMaxPrefetchMode(v->AllowDRAMSelfRefreshOrDRAMClockChangeInVblank, &v->MinPrefetchMode, &v->MaxPrefetchMode);

	v->UrgentLatency = CalculateUrgentLatency(
			v->UrgentLatencyPixelDataOnly,
			v->UrgentLatencyPixelMixedWithVMData,
			v->UrgentLatencyVMDataOnly,
			v->DoUrgentLatencyAdjustment,
			v->UrgentLatencyAdjustmentFabricClockComponent,
			v->UrgentLatencyAdjustmentFabricClockReference,
			v->FabricClock);

	v->FractionOfUrgentBandwidth = 0.0;
	v->FractionOfUrgentBandwidthImmediateFlip = 0.0;

	v->VStartupLines = __DML_VBA_MIN_VSTARTUP__;

	do {
		double MaxTotalRDBandwidthNoUrgentBurst = 0.0;
		bool DestinationLineTimesForPrefetchLessThan2 = false;
		bool VRatioPrefetchMoreThan4 = false;
		double TWait = CalculateTWait(PrefetchMode, v->DRAMClockChangeLatency, v->UrgentLatency, v->SREnterPlusExitTime);
		MaxTotalRDBandwidth = 0;

		dml_print("DML::%s: Start loop: VStartup = %d\n", __func__, v->VStartupLines);

		for (k = 0; k < v->NumberOfActivePlanes; ++k) {
			Pipe myPipe;

			myPipe.DPPCLK = v->DPPCLK[k];
			myPipe.DISPCLK = v->DISPCLK;
			myPipe.PixelClock = v->PixelClock[k];
			myPipe.DCFCLKDeepSleep = v->DCFCLKDeepSleep;
			myPipe.DPPPerPlane = v->DPPPerPlane[k];
			myPipe.ScalerEnabled = v->ScalerEnabled[k];
			myPipe.SourceScan = v->SourceScan[k];
			myPipe.BlockWidth256BytesY = v->BlockWidth256BytesY[k];
			myPipe.BlockHeight256BytesY = v->BlockHeight256BytesY[k];
			myPipe.BlockWidth256BytesC = v->BlockWidth256BytesC[k];
			myPipe.BlockHeight256BytesC = v->BlockHeight256BytesC[k];
			myPipe.InterlaceEnable = v->Interlace[k];
			myPipe.NumberOfCursors = v->NumberOfCursors[k];
			myPipe.VBlank = v->VTotal[k] - v->VActive[k];
			myPipe.HTotal = v->HTotal[k];
			myPipe.DCCEnable = v->DCCEnable[k];
			myPipe.ODMCombineIsEnabled = v->ODMCombineEnabled[k] == dm_odm_combine_mode_4to1
					|| v->ODMCombineEnabled[k] == dm_odm_combine_mode_2to1;
			myPipe.SourcePixelFormat = v->SourcePixelFormat[k];
			myPipe.BytePerPixelY = v->BytePerPixelY[k];
			myPipe.BytePerPixelC = v->BytePerPixelC[k];
			myPipe.ProgressiveToInterlaceUnitInOPP = v->ProgressiveToInterlaceUnitInOPP;
			v->ErrorResult[k] = CalculatePrefetchSchedule(
					mode_lib,
					HostVMInefficiencyFactor,
					&myPipe,
					v->DSCDelay[k],
					v->DPPCLKDelaySubtotal + v->DPPCLKDelayCNVCFormater,
					v->DPPCLKDelaySCL,
					v->DPPCLKDelaySCLLBOnly,
					v->DPPCLKDelayCNVCCursor,
					v->DISPCLKDelaySubtotal,
					(unsigned int) (v->SwathWidthY[k] / v->HRatio[k]),
					v->OutputFormat[k],
					v->MaxInterDCNTileRepeaters,
					dml_min(v->VStartupLines, v->MaxVStartupLines[k]),
					v->MaxVStartupLines[k],
					v->GPUVMMaxPageTableLevels,
					v->GPUVMEnable,
					v->HostVMEnable,
					v->HostVMMaxNonCachedPageTableLevels,
					v->HostVMMinPageSize,
					v->DynamicMetadataEnable[k],
					v->DynamicMetadataVMEnabled,
					v->DynamicMetadataLinesBeforeActiveRequired[k],
					v->DynamicMetadataTransmittedBytes[k],
					v->UrgentLatency,
					v->UrgentExtraLatency,
					v->TCalc,
					v->PDEAndMetaPTEBytesFrame[k],
					v->MetaRowByte[k],
					v->PixelPTEBytesPerRow[k],
					v->PrefetchSourceLinesY[k],
					v->SwathWidthY[k],
					v->VInitPreFillY[k],
					v->MaxNumSwathY[k],
					v->PrefetchSourceLinesC[k],
					v->SwathWidthC[k],
					v->VInitPreFillC[k],
					v->MaxNumSwathC[k],
					v->swath_width_luma_ub[k],
					v->swath_width_chroma_ub[k],
					v->SwathHeightY[k],
					v->SwathHeightC[k],
					TWait,
					&v->DSTXAfterScaler[k],
					&v->DSTYAfterScaler[k],
					&v->DestinationLinesForPrefetch[k],
					&v->PrefetchBandwidth[k],
					&v->DestinationLinesToRequestVMInVBlank[k],
					&v->DestinationLinesToRequestRowInVBlank[k],
					&v->VRatioPrefetchY[k],
					&v->VRatioPrefetchC[k],
					&v->RequiredPrefetchPixDataBWLuma[k],
					&v->RequiredPrefetchPixDataBWChroma[k],
					&v->NotEnoughTimeForDynamicMetadata[k],
					&v->Tno_bw[k],
					&v->prefetch_vmrow_bw[k],
					&v->Tdmdl_vm[k],
					&v->Tdmdl[k],
					&v->TSetup[k],
					&v->VUpdateOffsetPix[k],
					&v->VUpdateWidthPix[k],
					&v->VReadyOffsetPix[k]);

#ifdef __DML_VBA_DEBUG__
			dml_print("DML::%s: k=%0d Prefetch cal result=%0d\n", __func__, k, v->ErrorResult[k]);
#endif
			v->VStartup[k] = dml_min(v->VStartupLines, v->MaxVStartupLines[k]);
		}

		v->NoEnoughUrgentLatencyHiding = false;
		v->NoEnoughUrgentLatencyHidingPre = false;

		for (k = 0; k < v->NumberOfActivePlanes; ++k) {
			v->cursor_bw[k] = v->NumberOfCursors[k] * v->CursorWidth[k][0] * v->CursorBPP[k][0] / 8.0
					/ (v->HTotal[k] / v->PixelClock[k]) * v->VRatio[k];
			v->cursor_bw_pre[k] = v->NumberOfCursors[k] * v->CursorWidth[k][0] * v->CursorBPP[k][0] / 8.0
					/ (v->HTotal[k] / v->PixelClock[k]) * v->VRatioPrefetchY[k];

			CalculateUrgentBurstFactor(
					v->swath_width_luma_ub[k],
					v->swath_width_chroma_ub[k],
					v->SwathHeightY[k],
					v->SwathHeightC[k],
					v->HTotal[k] / v->PixelClock[k],
					v->UrgentLatency,
					v->CursorBufferSize,
					v->CursorWidth[k][0],
					v->CursorBPP[k][0],
					v->VRatio[k],
					v->VRatioChroma[k],
					v->BytePerPixelDETY[k],
					v->BytePerPixelDETC[k],
					v->DETBufferSizeY[k],
					v->DETBufferSizeC[k],
					&v->UrgBurstFactorCursor[k],
					&v->UrgBurstFactorLuma[k],
					&v->UrgBurstFactorChroma[k],
					&v->NoUrgentLatencyHiding[k]);

			CalculateUrgentBurstFactor(
					v->swath_width_luma_ub[k],
					v->swath_width_chroma_ub[k],
					v->SwathHeightY[k],
					v->SwathHeightC[k],
					v->HTotal[k] / v->PixelClock[k],
					v->UrgentLatency,
					v->CursorBufferSize,
					v->CursorWidth[k][0],
					v->CursorBPP[k][0],
					v->VRatioPrefetchY[k],
					v->VRatioPrefetchC[k],
					v->BytePerPixelDETY[k],
					v->BytePerPixelDETC[k],
					v->DETBufferSizeY[k],
					v->DETBufferSizeC[k],
					&v->UrgBurstFactorCursorPre[k],
					&v->UrgBurstFactorLumaPre[k],
					&v->UrgBurstFactorChromaPre[k],
					&v->NoUrgentLatencyHidingPre[k]);

			MaxTotalRDBandwidth = MaxTotalRDBandwidth
					+ dml_max3(
							v->DPPPerPlane[k] * v->prefetch_vmrow_bw[k],
							v->ReadBandwidthPlaneLuma[k] * v->UrgBurstFactorLuma[k]
									+ v->ReadBandwidthPlaneChroma[k] * v->UrgBurstFactorChroma[k]
									+ v->cursor_bw[k] * v->UrgBurstFactorCursor[k]
									+ v->DPPPerPlane[k] * (v->meta_row_bw[k] + v->dpte_row_bw[k]),
							v->DPPPerPlane[k]
									* (v->RequiredPrefetchPixDataBWLuma[k] * v->UrgBurstFactorLumaPre[k]
											+ v->RequiredPrefetchPixDataBWChroma[k] * v->UrgBurstFactorChromaPre[k])
									+ v->cursor_bw_pre[k] * v->UrgBurstFactorCursorPre[k]);

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

#ifdef __DML_VBA_DEBUG__
			dml_print("DML::%s: k=%0d DPPPerPlane=%d\n", __func__, k, v->DPPPerPlane[k]);
			dml_print("DML::%s: k=%0d UrgBurstFactorLuma=%f\n", __func__, k, v->UrgBurstFactorLuma[k]);
			dml_print("DML::%s: k=%0d UrgBurstFactorChroma=%f\n", __func__, k, v->UrgBurstFactorChroma[k]);
			dml_print("DML::%s: k=%0d UrgBurstFactorLumaPre=%f\n", __func__, k, v->UrgBurstFactorLumaPre[k]);
			dml_print("DML::%s: k=%0d UrgBurstFactorChromaPre=%f\n", __func__, k, v->UrgBurstFactorChromaPre[k]);

			dml_print("DML::%s: k=%0d VRatioPrefetchY=%f\n", __func__, k, v->VRatioPrefetchY[k]);
			dml_print("DML::%s: k=%0d VRatioY=%f\n", __func__, k, v->VRatio[k]);

			dml_print("DML::%s: k=%0d prefetch_vmrow_bw=%f\n", __func__, k, v->prefetch_vmrow_bw[k]);
			dml_print("DML::%s: k=%0d ReadBandwidthPlaneLuma=%f\n", __func__, k, v->ReadBandwidthPlaneLuma[k]);
			dml_print("DML::%s: k=%0d ReadBandwidthPlaneChroma=%f\n", __func__, k, v->ReadBandwidthPlaneChroma[k]);
			dml_print("DML::%s: k=%0d cursor_bw=%f\n", __func__, k, v->cursor_bw[k]);
			dml_print("DML::%s: k=%0d meta_row_bw=%f\n", __func__, k, v->meta_row_bw[k]);
			dml_print("DML::%s: k=%0d dpte_row_bw=%f\n", __func__, k, v->dpte_row_bw[k]);
			dml_print("DML::%s: k=%0d RequiredPrefetchPixDataBWLuma=%f\n", __func__, k, v->RequiredPrefetchPixDataBWLuma[k]);
			dml_print("DML::%s: k=%0d RequiredPrefetchPixDataBWChroma=%f\n", __func__, k, v->RequiredPrefetchPixDataBWChroma[k]);
			dml_print("DML::%s: k=%0d cursor_bw_pre=%f\n", __func__, k, v->cursor_bw_pre[k]);
			dml_print("DML::%s: k=%0d MaxTotalRDBandwidthNoUrgentBurst=%f\n", __func__, k, MaxTotalRDBandwidthNoUrgentBurst);
#endif

			if (v->DestinationLinesForPrefetch[k] < 2)
				DestinationLineTimesForPrefetchLessThan2 = true;

			if (v->VRatioPrefetchY[k] > 4 || v->VRatioPrefetchC[k] > 4)
				VRatioPrefetchMoreThan4 = true;

			if (v->NoUrgentLatencyHiding[k] == true)
				v->NoEnoughUrgentLatencyHiding = true;

			if (v->NoUrgentLatencyHidingPre[k] == true)
				v->NoEnoughUrgentLatencyHidingPre = true;
		}

		v->FractionOfUrgentBandwidth = MaxTotalRDBandwidthNoUrgentBurst / v->ReturnBW;

#ifdef __DML_VBA_DEBUG__
		dml_print("DML::%s: MaxTotalRDBandwidthNoUrgentBurst=%f \n", __func__, MaxTotalRDBandwidthNoUrgentBurst);
		dml_print("DML::%s: ReturnBW=%f \n", __func__, v->ReturnBW);
		dml_print("DML::%s: FractionOfUrgentBandwidth=%f \n", __func__, v->FractionOfUrgentBandwidth);
#endif

		if (MaxTotalRDBandwidth <= v->ReturnBW && v->NoEnoughUrgentLatencyHiding == 0 && v->NoEnoughUrgentLatencyHidingPre == 0
				&& !VRatioPrefetchMoreThan4 && !DestinationLineTimesForPrefetchLessThan2)
			v->PrefetchModeSupported = true;
		else {
			v->PrefetchModeSupported = false;
			dml_print("DML::%s: ***failed***. Bandwidth violation. Results are NOT valid\n", __func__);
			dml_print("DML::%s: MaxTotalRDBandwidth:%f AvailReturnBandwidth:%f\n", __func__, MaxTotalRDBandwidth, v->ReturnBW);
			dml_print("DML::%s: VRatioPrefetch %s more than 4\n", __func__, (VRatioPrefetchMoreThan4) ? "is" : "is not");
			dml_print("DML::%s: DestinationLines for Prefetch %s less than 2\n", __func__, (DestinationLineTimesForPrefetchLessThan2) ? "is" : "is not");
		}

		// PREVIOUS_ERROR
		// This error result check was done after the PrefetchModeSupported. So we will
		// still try to calculate flip schedule even prefetch mode not supported
		for (k = 0; k < v->NumberOfActivePlanes; ++k) {
			if (v->ErrorResult[k] == true || v->NotEnoughTimeForDynamicMetadata[k] == true) {
				v->PrefetchModeSupported = false;
				dml_print("DML::%s: ***failed***. Prefetch schedule violation. Results are NOT valid\n", __func__);
			}
		}

		if (v->PrefetchModeSupported == true && v->ImmediateFlipSupport == true) {
			v->BandwidthAvailableForImmediateFlip = v->ReturnBW;
			for (k = 0; k < v->NumberOfActivePlanes; ++k) {
				v->BandwidthAvailableForImmediateFlip = v->BandwidthAvailableForImmediateFlip
						- dml_max(
								v->ReadBandwidthPlaneLuma[k] * v->UrgBurstFactorLuma[k]
										+ v->ReadBandwidthPlaneChroma[k] * v->UrgBurstFactorChroma[k]
										+ v->cursor_bw[k] * v->UrgBurstFactorCursor[k],
								v->DPPPerPlane[k]
										* (v->RequiredPrefetchPixDataBWLuma[k] * v->UrgBurstFactorLumaPre[k]
												+ v->RequiredPrefetchPixDataBWChroma[k] * v->UrgBurstFactorChromaPre[k])
										+ v->cursor_bw_pre[k] * v->UrgBurstFactorCursorPre[k]);
			}

			v->TotImmediateFlipBytes = 0;
			for (k = 0; k < v->NumberOfActivePlanes; ++k) {
				v->TotImmediateFlipBytes = v->TotImmediateFlipBytes
						+ v->DPPPerPlane[k] * (v->PDEAndMetaPTEBytesFrame[k] + v->MetaRowByte[k] + v->PixelPTEBytesPerRow[k]);
			}
			for (k = 0; k < v->NumberOfActivePlanes; ++k) {
				CalculateFlipSchedule(
						mode_lib,
						HostVMInefficiencyFactor,
						v->UrgentExtraLatency,
						v->UrgentLatency,
						v->GPUVMMaxPageTableLevels,
						v->HostVMEnable,
						v->HostVMMaxNonCachedPageTableLevels,
						v->GPUVMEnable,
						v->HostVMMinPageSize,
						v->PDEAndMetaPTEBytesFrame[k],
						v->MetaRowByte[k],
						v->PixelPTEBytesPerRow[k],
						v->BandwidthAvailableForImmediateFlip,
						v->TotImmediateFlipBytes,
						v->SourcePixelFormat[k],
						v->HTotal[k] / v->PixelClock[k],
						v->VRatio[k],
						v->VRatioChroma[k],
						v->Tno_bw[k],
						v->DCCEnable[k],
						v->dpte_row_height[k],
						v->meta_row_height[k],
						v->dpte_row_height_chroma[k],
						v->meta_row_height_chroma[k],
						&v->DestinationLinesToRequestVMInImmediateFlip[k],
						&v->DestinationLinesToRequestRowInImmediateFlip[k],
						&v->final_flip_bw[k],
						&v->ImmediateFlipSupportedForPipe[k]);
			}

			v->total_dcn_read_bw_with_flip = 0.0;
			v->total_dcn_read_bw_with_flip_no_urgent_burst = 0.0;
			for (k = 0; k < v->NumberOfActivePlanes; ++k) {
				v->total_dcn_read_bw_with_flip = v->total_dcn_read_bw_with_flip
						+ dml_max3(
								v->DPPPerPlane[k] * v->prefetch_vmrow_bw[k],
								v->DPPPerPlane[k] * v->final_flip_bw[k]
										+ v->ReadBandwidthLuma[k] * v->UrgBurstFactorLuma[k]
										+ v->ReadBandwidthChroma[k] * v->UrgBurstFactorChroma[k]
										+ v->cursor_bw[k] * v->UrgBurstFactorCursor[k],
								v->DPPPerPlane[k]
										* (v->final_flip_bw[k]
												+ v->RequiredPrefetchPixDataBWLuma[k] * v->UrgBurstFactorLumaPre[k]
												+ v->RequiredPrefetchPixDataBWChroma[k] * v->UrgBurstFactorChromaPre[k])
										+ v->cursor_bw_pre[k] * v->UrgBurstFactorCursorPre[k]);
				v->total_dcn_read_bw_with_flip_no_urgent_burst = v->total_dcn_read_bw_with_flip_no_urgent_burst
						+ dml_max3(
								v->DPPPerPlane[k] * v->prefetch_vmrow_bw[k],
								v->DPPPerPlane[k] * v->final_flip_bw[k] + v->ReadBandwidthPlaneLuma[k]
										+ v->ReadBandwidthPlaneChroma[k] + v->cursor_bw[k],
								v->DPPPerPlane[k]
										* (v->final_flip_bw[k] + v->RequiredPrefetchPixDataBWLuma[k]
												+ v->RequiredPrefetchPixDataBWChroma[k]) + v->cursor_bw_pre[k]);
			}
			v->FractionOfUrgentBandwidthImmediateFlip = v->total_dcn_read_bw_with_flip_no_urgent_burst / v->ReturnBW;

			v->ImmediateFlipSupported = true;
			if (v->total_dcn_read_bw_with_flip > v->ReturnBW) {
#ifdef __DML_VBA_DEBUG__
				dml_print("DML::%s: total_dcn_read_bw_with_flip %f (bw w/ flip too high!)\n", __func__, v->total_dcn_read_bw_with_flip);
#endif
				v->ImmediateFlipSupported = false;
				v->total_dcn_read_bw_with_flip = MaxTotalRDBandwidth;
			}
			for (k = 0; k < v->NumberOfActivePlanes; ++k) {
				if (v->ImmediateFlipSupportedForPipe[k] == false) {
#ifdef __DML_VBA_DEBUG__
					dml_print("DML::%s: Pipe %0d not supporting iflip\n",
						  __func__, k);
#endif
					v->ImmediateFlipSupported = false;
				}
			}
		} else {
			v->ImmediateFlipSupported = false;
		}

		v->PrefetchAndImmediateFlipSupported =
				(v->PrefetchModeSupported == true && ((!v->ImmediateFlipSupport && !v->HostVMEnable
				&& v->ImmediateFlipRequirement[0] != dm_immediate_flip_required) ||
				v->ImmediateFlipSupported)) ? true : false;
#ifdef __DML_VBA_DEBUG__
		dml_print("DML::%s: PrefetchModeSupported %d\n", __func__, v->PrefetchModeSupported);
		dml_print("DML::%s: ImmediateFlipRequirement %d\n", __func__, v->ImmediateFlipRequirement == dm_immediate_flip_required);
		dml_print("DML::%s: ImmediateFlipSupported %d\n", __func__, v->ImmediateFlipSupported);
		dml_print("DML::%s: ImmediateFlipSupport %d\n", __func__, v->ImmediateFlipSupport);
		dml_print("DML::%s: HostVMEnable %d\n", __func__, v->HostVMEnable);
		dml_print("DML::%s: PrefetchAndImmediateFlipSupported %d\n", __func__, v->PrefetchAndImmediateFlipSupported);
#endif
		dml_print("DML::%s: Done loop: Vstartup=%d, Max Vstartup is %d\n", __func__, v->VStartupLines, v->MaximumMaxVStartupLines);

		v->VStartupLines = v->VStartupLines + 1;
	} while (!v->PrefetchAndImmediateFlipSupported && v->VStartupLines <= v->MaximumMaxVStartupLines);
	ASSERT(v->PrefetchAndImmediateFlipSupported);

	// Unbounded Request Enabled
	CalculateUnboundedRequestAndCompressedBufferSize(
			v->DETBufferSizeInKByte[0],
			v->ConfigReturnBufferSizeInKByte,
			v->UseUnboundedRequesting,
			v->TotalActiveDPP,
			NoChromaPlanes,
			v->MaxNumDPP,
			v->CompressedBufferSegmentSizeInkByte,
			v->Output,
			&v->UnboundedRequestEnabled,
			&v->CompressedBufferSizeInkByte);

	//Watermarks and NB P-State/DRAM Clock Change Support
	{
		enum clock_change_support DRAMClockChangeSupport; // dummy
		CalculateWatermarksAndDRAMSpeedChangeSupport(
				mode_lib,
				PrefetchMode,
				v->NumberOfActivePlanes,
				v->MaxLineBufferLines,
				v->LineBufferSize,
				v->WritebackInterfaceBufferSize,
				v->DCFCLK,
				v->ReturnBW,
				v->SynchronizedVBlank,
				v->dpte_group_bytes,
				v->MetaChunkSize,
				v->UrgentLatency,
				v->UrgentExtraLatency,
				v->WritebackLatency,
				v->WritebackChunkSize,
				v->SOCCLK,
				v->DRAMClockChangeLatency,
				v->SRExitTime,
				v->SREnterPlusExitTime,
				v->SRExitZ8Time,
				v->SREnterPlusExitZ8Time,
				v->DCFCLKDeepSleep,
				v->DETBufferSizeY,
				v->DETBufferSizeC,
				v->SwathHeightY,
				v->SwathHeightC,
				v->LBBitPerPixel,
				v->SwathWidthY,
				v->SwathWidthC,
				v->HRatio,
				v->HRatioChroma,
				v->vtaps,
				v->VTAPsChroma,
				v->VRatio,
				v->VRatioChroma,
				v->HTotal,
				v->PixelClock,
				v->BlendingAndTiming,
				v->DPPPerPlane,
				v->BytePerPixelDETY,
				v->BytePerPixelDETC,
				v->DSTXAfterScaler,
				v->DSTYAfterScaler,
				v->WritebackEnable,
				v->WritebackPixelFormat,
				v->WritebackDestinationWidth,
				v->WritebackDestinationHeight,
				v->WritebackSourceHeight,
				v->UnboundedRequestEnabled,
				v->CompressedBufferSizeInkByte,
				&DRAMClockChangeSupport,
				&v->UrgentWatermark,
				&v->WritebackUrgentWatermark,
				&v->DRAMClockChangeWatermark,
				&v->WritebackDRAMClockChangeWatermark,
				&v->StutterExitWatermark,
				&v->StutterEnterPlusExitWatermark,
				&v->Z8StutterExitWatermark,
				&v->Z8StutterEnterPlusExitWatermark,
				&v->MinActiveDRAMClockChangeLatencySupported);

		for (k = 0; k < v->NumberOfActivePlanes; ++k) {
			if (v->WritebackEnable[k] == true) {
				v->WritebackAllowDRAMClockChangeEndPosition[k] = dml_max(
						0,
						v->VStartup[k] * v->HTotal[k] / v->PixelClock[k] - v->WritebackDRAMClockChangeWatermark);
			} else {
				v->WritebackAllowDRAMClockChangeEndPosition[k] = 0;
			}
		}
	}

	//Display Pipeline Delivery Time in Prefetch, Groups
	CalculatePixelDeliveryTimes(
			v->NumberOfActivePlanes,
			v->VRatio,
			v->VRatioChroma,
			v->VRatioPrefetchY,
			v->VRatioPrefetchC,
			v->swath_width_luma_ub,
			v->swath_width_chroma_ub,
			v->DPPPerPlane,
			v->HRatio,
			v->HRatioChroma,
			v->PixelClock,
			v->PSCL_THROUGHPUT_LUMA,
			v->PSCL_THROUGHPUT_CHROMA,
			v->DPPCLK,
			v->BytePerPixelC,
			v->SourceScan,
			v->NumberOfCursors,
			v->CursorWidth,
			v->CursorBPP,
			v->BlockWidth256BytesY,
			v->BlockHeight256BytesY,
			v->BlockWidth256BytesC,
			v->BlockHeight256BytesC,
			v->DisplayPipeLineDeliveryTimeLuma,
			v->DisplayPipeLineDeliveryTimeChroma,
			v->DisplayPipeLineDeliveryTimeLumaPrefetch,
			v->DisplayPipeLineDeliveryTimeChromaPrefetch,
			v->DisplayPipeRequestDeliveryTimeLuma,
			v->DisplayPipeRequestDeliveryTimeChroma,
			v->DisplayPipeRequestDeliveryTimeLumaPrefetch,
			v->DisplayPipeRequestDeliveryTimeChromaPrefetch,
			v->CursorRequestDeliveryTime,
			v->CursorRequestDeliveryTimePrefetch);

	CalculateMetaAndPTETimes(
			v->NumberOfActivePlanes,
			v->GPUVMEnable,
			v->MetaChunkSize,
			v->MinMetaChunkSizeBytes,
			v->HTotal,
			v->VRatio,
			v->VRatioChroma,
			v->DestinationLinesToRequestRowInVBlank,
			v->DestinationLinesToRequestRowInImmediateFlip,
			v->DCCEnable,
			v->PixelClock,
			v->BytePerPixelY,
			v->BytePerPixelC,
			v->SourceScan,
			v->dpte_row_height,
			v->dpte_row_height_chroma,
			v->meta_row_width,
			v->meta_row_width_chroma,
			v->meta_row_height,
			v->meta_row_height_chroma,
			v->meta_req_width,
			v->meta_req_width_chroma,
			v->meta_req_height,
			v->meta_req_height_chroma,
			v->dpte_group_bytes,
			v->PTERequestSizeY,
			v->PTERequestSizeC,
			v->PixelPTEReqWidthY,
			v->PixelPTEReqHeightY,
			v->PixelPTEReqWidthC,
			v->PixelPTEReqHeightC,
			v->dpte_row_width_luma_ub,
			v->dpte_row_width_chroma_ub,
			v->DST_Y_PER_PTE_ROW_NOM_L,
			v->DST_Y_PER_PTE_ROW_NOM_C,
			v->DST_Y_PER_META_ROW_NOM_L,
			v->DST_Y_PER_META_ROW_NOM_C,
			v->TimePerMetaChunkNominal,
			v->TimePerChromaMetaChunkNominal,
			v->TimePerMetaChunkVBlank,
			v->TimePerChromaMetaChunkVBlank,
			v->TimePerMetaChunkFlip,
			v->TimePerChromaMetaChunkFlip,
			v->time_per_pte_group_nom_luma,
			v->time_per_pte_group_vblank_luma,
			v->time_per_pte_group_flip_luma,
			v->time_per_pte_group_nom_chroma,
			v->time_per_pte_group_vblank_chroma,
			v->time_per_pte_group_flip_chroma);

	CalculateVMGroupAndRequestTimes(
			v->NumberOfActivePlanes,
			v->GPUVMEnable,
			v->GPUVMMaxPageTableLevels,
			v->HTotal,
			v->BytePerPixelC,
			v->DestinationLinesToRequestVMInVBlank,
			v->DestinationLinesToRequestVMInImmediateFlip,
			v->DCCEnable,
			v->PixelClock,
			v->dpte_row_width_luma_ub,
			v->dpte_row_width_chroma_ub,
			v->vm_group_bytes,
			v->dpde0_bytes_per_frame_ub_l,
			v->dpde0_bytes_per_frame_ub_c,
			v->meta_pte_bytes_per_frame_ub_l,
			v->meta_pte_bytes_per_frame_ub_c,
			v->TimePerVMGroupVBlank,
			v->TimePerVMGroupFlip,
			v->TimePerVMRequestVBlank,
			v->TimePerVMRequestFlip);

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

	// DCC Configuration
	v->ActiveDPPs = 0;
	for (k = 0; k < v->NumberOfActivePlanes; ++k) {
		CalculateDCCConfiguration(v->DCCEnable[k], false, // We should always know the direction DCCProgrammingAssumesScanDirectionUnknown,
				v->SourcePixelFormat[k],
				v->SurfaceWidthY[k],
				v->SurfaceWidthC[k],
				v->SurfaceHeightY[k],
				v->SurfaceHeightC[k],
				v->DETBufferSizeInKByte[0] * 1024,
				v->BlockHeight256BytesY[k],
				v->BlockHeight256BytesC[k],
				v->SurfaceTiling[k],
				v->BytePerPixelY[k],
				v->BytePerPixelC[k],
				v->BytePerPixelDETY[k],
				v->BytePerPixelDETC[k],
				v->SourceScan[k],
				&v->DCCYMaxUncompressedBlock[k],
				&v->DCCCMaxUncompressedBlock[k],
				&v->DCCYMaxCompressedBlock[k],
				&v->DCCCMaxCompressedBlock[k],
				&v->DCCYIndependentBlock[k],
				&v->DCCCIndependentBlock[k]);
	}

	// VStartup Adjustment
	for (k = 0; k < v->NumberOfActivePlanes; ++k) {
		bool isInterlaceTiming;
		double Tvstartup_margin = (v->MaxVStartupLines[k] - v->VStartup[k]) * v->HTotal[k] / v->PixelClock[k];
#ifdef __DML_VBA_DEBUG__
		dml_print("DML::%s: k=%d, MinTTUVBlank = %f (before margin)\n", __func__, k, v->MinTTUVBlank[k]);
#endif

		v->MinTTUVBlank[k] = v->MinTTUVBlank[k] + Tvstartup_margin;

#ifdef __DML_VBA_DEBUG__
		dml_print("DML::%s: k=%d, Tvstartup_margin = %f\n", __func__, k, Tvstartup_margin);
		dml_print("DML::%s: k=%d, MaxVStartupLines = %d\n", __func__, k, v->MaxVStartupLines[k]);
		dml_print("DML::%s: k=%d, VStartup = %d\n", __func__, k, v->VStartup[k]);
		dml_print("DML::%s: k=%d, MinTTUVBlank = %f\n", __func__, k, v->MinTTUVBlank[k]);
#endif

		v->Tdmdl[k] = v->Tdmdl[k] + Tvstartup_margin;
		if (v->DynamicMetadataEnable[k] && v->DynamicMetadataVMEnabled) {
			v->Tdmdl_vm[k] = v->Tdmdl_vm[k] + Tvstartup_margin;
		}

		isInterlaceTiming = (v->Interlace[k] && !v->ProgressiveToInterlaceUnitInOPP);

		v->MIN_DST_Y_NEXT_START[k] = ((isInterlaceTiming ? dml_floor((v->VTotal[k] - v->VFrontPorch[k]) / 2.0, 1.0) : v->VTotal[k])
				- v->VFrontPorch[k])
				+ dml_max(1.0, dml_ceil(v->WritebackDelay[v->VoltageLevel][k] / (v->HTotal[k] / v->PixelClock[k]), 1.0))
				+ dml_floor(4.0 * v->TSetup[k] / (v->HTotal[k] / v->PixelClock[k]), 1.0) / 4.0;

		v->VStartup[k] = (isInterlaceTiming ? (2 * v->MaxVStartupLines[k]) : v->MaxVStartupLines[k]);

		if (((v->VUpdateOffsetPix[k] + v->VUpdateWidthPix[k] + v->VReadyOffsetPix[k]) / v->HTotal[k])
				<= (isInterlaceTiming ?
						dml_floor((v->VTotal[k] - v->VActive[k] - v->VFrontPorch[k] - v->VStartup[k]) / 2.0, 1.0) :
						(int) (v->VTotal[k] - v->VActive[k] - v->VFrontPorch[k] - v->VStartup[k]))) {
			v->VREADY_AT_OR_AFTER_VSYNC[k] = true;
		} else {
			v->VREADY_AT_OR_AFTER_VSYNC[k] = false;
		}
#ifdef __DML_VBA_DEBUG__
		dml_print("DML::%s: k=%d, VStartup = %d (max)\n", __func__, k, v->VStartup[k]);
		dml_print("DML::%s: k=%d, VUpdateOffsetPix = %d\n", __func__, k, v->VUpdateOffsetPix[k]);
		dml_print("DML::%s: k=%d, VUpdateWidthPix = %d\n", __func__, k, v->VUpdateWidthPix[k]);
		dml_print("DML::%s: k=%d, VReadyOffsetPix = %d\n", __func__, k, v->VReadyOffsetPix[k]);
		dml_print("DML::%s: k=%d, HTotal = %d\n", __func__, k, v->HTotal[k]);
		dml_print("DML::%s: k=%d, VTotal = %d\n", __func__, k, v->VTotal[k]);
		dml_print("DML::%s: k=%d, VActive = %d\n", __func__, k, v->VActive[k]);
		dml_print("DML::%s: k=%d, VFrontPorch = %d\n", __func__, k, v->VFrontPorch[k]);
		dml_print("DML::%s: k=%d, VStartup = %d\n", __func__, k, v->VStartup[k]);
		dml_print("DML::%s: k=%d, MIN_DST_Y_NEXT_START = %f\n", __func__, k, v->MIN_DST_Y_NEXT_START[k]);
		dml_print("DML::%s: k=%d, VREADY_AT_OR_AFTER_VSYNC = %d\n", __func__, k, v->VREADY_AT_OR_AFTER_VSYNC[k]);
#endif
	}

	{
		//Maximum Bandwidth Used
		double TotalWRBandwidth = 0;
		double MaxPerPlaneVActiveWRBandwidth = 0;
		double WRBandwidth = 0;
		for (k = 0; k < v->NumberOfActivePlanes; ++k) {
			if (v->WritebackEnable[k] == true && v->WritebackPixelFormat[k] == dm_444_32) {
				WRBandwidth = v->WritebackDestinationWidth[k] * v->WritebackDestinationHeight[k]
						/ (v->HTotal[k] * v->WritebackSourceHeight[k] / v->PixelClock[k]) * 4;
			} else if (v->WritebackEnable[k] == true) {
				WRBandwidth = v->WritebackDestinationWidth[k] * v->WritebackDestinationHeight[k]
						/ (v->HTotal[k] * v->WritebackSourceHeight[k] / v->PixelClock[k]) * 8;
			}
			TotalWRBandwidth = TotalWRBandwidth + WRBandwidth;
			MaxPerPlaneVActiveWRBandwidth = dml_max(MaxPerPlaneVActiveWRBandwidth, WRBandwidth);
		}

		v->TotalDataReadBandwidth = 0;
		for (k = 0; k < v->NumberOfActivePlanes; ++k) {
			v->TotalDataReadBandwidth = v->TotalDataReadBandwidth + v->ReadBandwidthPlaneLuma[k] + v->ReadBandwidthPlaneChroma[k];
		}
	}
	// Stutter Efficiency
	CalculateStutterEfficiency(
			mode_lib,
			v->CompressedBufferSizeInkByte,
			v->UnboundedRequestEnabled,
			v->ConfigReturnBufferSizeInKByte,
			v->MetaFIFOSizeInKEntries,
			v->ZeroSizeBufferEntries,
			v->NumberOfActivePlanes,
			v->ROBBufferSizeInKByte,
			v->TotalDataReadBandwidth,
			v->DCFCLK,
			v->ReturnBW,
			v->COMPBUF_RESERVED_SPACE_64B,
			v->COMPBUF_RESERVED_SPACE_ZS,
			v->SRExitTime,
			v->SRExitZ8Time,
			v->SynchronizedVBlank,
			v->StutterEnterPlusExitWatermark,
			v->Z8StutterEnterPlusExitWatermark,
			v->ProgressiveToInterlaceUnitInOPP,
			v->Interlace,
			v->MinTTUVBlank,
			v->DPPPerPlane,
			v->DETBufferSizeY,
			v->BytePerPixelY,
			v->BytePerPixelDETY,
			v->SwathWidthY,
			v->SwathHeightY,
			v->SwathHeightC,
			v->DCCRateLuma,
			v->DCCRateChroma,
			v->DCCFractionOfZeroSizeRequestsLuma,
			v->DCCFractionOfZeroSizeRequestsChroma,
			v->HTotal,
			v->VTotal,
			v->PixelClock,
			v->VRatio,
			v->SourceScan,
			v->BlockHeight256BytesY,
			v->BlockWidth256BytesY,
			v->BlockHeight256BytesC,
			v->BlockWidth256BytesC,
			v->DCCYMaxUncompressedBlock,
			v->DCCCMaxUncompressedBlock,
			v->VActive,
			v->DCCEnable,
			v->WritebackEnable,
			v->ReadBandwidthPlaneLuma,
			v->ReadBandwidthPlaneChroma,
			v->meta_row_bw,
			v->dpte_row_bw,
			&v->StutterEfficiencyNotIncludingVBlank,
			&v->StutterEfficiency,
			&v->NumberOfStutterBurstsPerFrame,
			&v->Z8StutterEfficiencyNotIncludingVBlank,
			&v->Z8StutterEfficiency,
			&v->Z8NumberOfStutterBurstsPerFrame,
			&v->StutterPeriod);
}