root/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
/*
 * Copyright 2017 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: AMD
 *
 */


#include "../display_mode_lib.h"
#include "../dml_inline_defs.h"
#include "../display_mode_vba.h"
#include "display_mode_vba_21.h"


/*
 * NOTE:
 *   This file is gcc-parsable HW gospel, coming straight from HW engineers.
 *
 * It doesn't adhere to Linux kernel style and sometimes will do things in odd
 * ways. Unless there is something clearly wrong with it the code should
 * remain as-is as it provides us with a guarantee from HW that it is correct.
 */
typedef struct {
        double DPPCLK;
        double DISPCLK;
        double PixelClock;
        double DCFCLKDeepSleep;
        unsigned int DPPPerPlane;
        bool ScalerEnabled;
        enum scan_direction_class SourceScan;
        unsigned int BlockWidth256BytesY;
        unsigned int BlockHeight256BytesY;
        unsigned int BlockWidth256BytesC;
        unsigned int BlockHeight256BytesC;
        unsigned int InterlaceEnable;
        unsigned int NumberOfCursors;
        unsigned int VBlank;
        unsigned int HTotal;
} Pipe;

typedef struct {
        bool Enable;
        unsigned int MaxPageTableLevels;
        unsigned int CachedPageTableLevels;
} HostVM;

#define BPP_INVALID 0
#define BPP_BLENDED_PIPE 0xffffffff
#define DCN21_MAX_DSC_IMAGE_WIDTH 5184
#define DCN21_MAX_420_IMAGE_WIDTH 4096

static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib);
static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(
                struct display_mode_lib *mode_lib);
static unsigned int dscceComputeDelay(
                unsigned int bpc,
                double bpp,
                unsigned int sliceWidth,
                unsigned int numSlices,
                enum output_format_class pixelFormat);
static unsigned int dscComputeDelay(enum output_format_class pixelFormat);
// Super monster function with some 45 argument
static bool CalculatePrefetchSchedule(
                struct display_mode_lib *mode_lib,
                double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
                double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly,
                Pipe *myPipe,
                unsigned int DSCDelay,
                double DPPCLKDelaySubtotal,
                double DPPCLKDelaySCL,
                double DPPCLKDelaySCLLBOnly,
                double DPPCLKDelayCNVCFormater,
                double DPPCLKDelayCNVCCursor,
                double DISPCLKDelaySubtotal,
                unsigned int ScalerRecoutWidth,
                enum output_format_class OutputFormat,
                unsigned int MaxInterDCNTileRepeaters,
                unsigned int VStartup,
                unsigned int MaxVStartup,
                unsigned int GPUVMPageTableLevels,
                bool GPUVMEnable,
                HostVM *myHostVM,
                bool DynamicMetadataEnable,
                int DynamicMetadataLinesBeforeActiveRequired,
                unsigned int DynamicMetadataTransmittedBytes,
                bool DCCEnable,
                double UrgentLatency,
                double UrgentExtraLatency,
                double TCalc,
                unsigned int PDEAndMetaPTEBytesFrame,
                unsigned int MetaRowByte,
                unsigned int PixelPTEBytesPerRow,
                double PrefetchSourceLinesY,
                unsigned int SwathWidthY,
                double BytePerPixelDETY,
                double VInitPreFillY,
                unsigned int MaxNumSwathY,
                double PrefetchSourceLinesC,
                double BytePerPixelDETC,
                double VInitPreFillC,
                unsigned int MaxNumSwathC,
                unsigned int SwathHeightY,
                unsigned int SwathHeightC,
                double TWait,
                bool XFCEnabled,
                double XFCRemoteSurfaceFlipDelay,
                bool ProgressiveToInterlaceUnitInOPP,
                double *DSTXAfterScaler,
                double *DSTYAfterScaler,
                double *DestinationLinesForPrefetch,
                double *PrefetchBandwidth,
                double *DestinationLinesToRequestVMInVBlank,
                double *DestinationLinesToRequestRowInVBlank,
                double *VRatioPrefetchY,
                double *VRatioPrefetchC,
                double *RequiredPrefetchPixDataBWLuma,
                double *RequiredPrefetchPixDataBWChroma,
                unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata,
                double *Tno_bw,
                double *prefetch_vmrow_bw,
                unsigned int *swath_width_luma_ub,
                unsigned int *swath_width_chroma_ub,
                unsigned int *VUpdateOffsetPix,
                double *VUpdateWidthPix,
                double *VReadyOffsetPix);
static double RoundToDFSGranularityUp(double Clock, double VCOSpeed);
static double RoundToDFSGranularityDown(double Clock, double VCOSpeed);
static double CalculateDCCConfiguration(
                bool                 DCCEnabled,
                bool                 DCCProgrammingAssumesScanDirectionUnknown,
                unsigned int         ViewportWidth,
                unsigned int         ViewportHeight,
                unsigned int         DETBufferSize,
                unsigned int         RequestHeight256Byte,
                unsigned int         SwathHeight,
                enum dm_swizzle_mode TilingFormat,
                unsigned int         BytePerPixel,
                enum scan_direction_class ScanOrientation,
                unsigned int        *MaxUncompressedBlock,
                unsigned int        *MaxCompressedBlock,
                unsigned int        *Independent64ByteBlock);
static double CalculatePrefetchSourceLines(
                struct display_mode_lib *mode_lib,
                double VRatio,
                double vtaps,
                bool Interlace,
                bool ProgressiveToInterlaceUnitInOPP,
                unsigned int SwathHeight,
                unsigned int ViewportYStart,
                double *VInitPreFill,
                unsigned int *MaxNumSwath);
static unsigned int CalculateVMAndRowBytes(
                struct display_mode_lib *mode_lib,
                bool DCCEnable,
                unsigned int BlockHeight256Bytes,
                unsigned int BlockWidth256Bytes,
                enum source_format_class SourcePixelFormat,
                unsigned int SurfaceTiling,
                unsigned int BytePerPixel,
                enum scan_direction_class ScanDirection,
                unsigned int ViewportWidth,
                unsigned int ViewportHeight,
                unsigned int SwathWidthY,
                bool GPUVMEnable,
                bool HostVMEnable,
                unsigned int HostVMMaxPageTableLevels,
                unsigned int HostVMCachedPageTableLevels,
                unsigned int VMMPageSize,
                unsigned int PTEBufferSizeInRequests,
                unsigned int Pitch,
                unsigned int DCCMetaPitch,
                unsigned int *MacroTileWidth,
                unsigned int *MetaRowByte,
                unsigned int *PixelPTEBytesPerRow,
                bool *PTEBufferSizeNotExceeded,
                unsigned int *dpte_row_width_ub,
                unsigned int *dpte_row_height,
                unsigned int *MetaRequestWidth,
                unsigned int *MetaRequestHeight,
                unsigned int *meta_row_width,
                unsigned int *meta_row_height,
                unsigned int *vm_group_bytes,
                unsigned int *dpte_group_bytes,
                unsigned int *PixelPTEReqWidth,
                unsigned int *PixelPTEReqHeight,
                unsigned int *PTERequestSize,
                unsigned int *DPDE0BytesFrame,
                unsigned int *MetaPTEBytesFrame);

static double CalculateTWait(
                unsigned int PrefetchMode,
                double DRAMClockChangeLatency,
                double UrgentLatency,
                double SREnterPlusExitTime);
static double CalculateRemoteSurfaceFlipDelay(
                struct display_mode_lib *mode_lib,
                double VRatio,
                double SwathWidth,
                double Bpp,
                double LineTime,
                double XFCTSlvVupdateOffset,
                double XFCTSlvVupdateWidth,
                double XFCTSlvVreadyOffset,
                double XFCXBUFLatencyTolerance,
                double XFCFillBWOverhead,
                double XFCSlvChunkSize,
                double XFCBusTransportTime,
                double TCalc,
                double TWait,
                double *SrcActiveDrainRate,
                double *TInitXFill,
                double *TslvChk);
static void CalculateActiveRowBandwidth(
                bool GPUVMEnable,
                enum source_format_class SourcePixelFormat,
                double VRatio,
                bool DCCEnable,
                double LineTime,
                unsigned int MetaRowByteLuma,
                unsigned int MetaRowByteChroma,
                unsigned int meta_row_height_luma,
                unsigned int meta_row_height_chroma,
                unsigned int PixelPTEBytesPerRowLuma,
                unsigned int PixelPTEBytesPerRowChroma,
                unsigned int dpte_row_height_luma,
                unsigned int dpte_row_height_chroma,
                double *meta_row_bw,
                double *dpte_row_bw);
static void CalculateFlipSchedule(
                struct display_mode_lib *mode_lib,
                double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
                double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly,
                double UrgentExtraLatency,
                double UrgentLatency,
                unsigned int GPUVMMaxPageTableLevels,
                bool HostVMEnable,
                unsigned int HostVMMaxPageTableLevels,
                unsigned int HostVMCachedPageTableLevels,
                bool GPUVMEnable,
                double PDEAndMetaPTEBytesPerFrame,
                double MetaRowBytes,
                double DPTEBytesPerRow,
                double BandwidthAvailableForImmediateFlip,
                unsigned int TotImmediateFlipBytes,
                enum source_format_class SourcePixelFormat,
                double LineTime,
                double VRatio,
                double Tno_bw,
                bool DCCEnable,
                unsigned int dpte_row_height,
                unsigned int meta_row_height,
                unsigned int dpte_row_height_chroma,
                unsigned int meta_row_height_chroma,
                double *DestinationLinesToRequestVMInImmediateFlip,
                double *DestinationLinesToRequestRowInImmediateFlip,
                double *final_flip_bw,
                bool *ImmediateFlipSupportedForPipe);
static double CalculateWriteBackDelay(
                enum source_format_class WritebackPixelFormat,
                double WritebackHRatio,
                double WritebackVRatio,
                unsigned int WritebackLumaHTaps,
                unsigned int WritebackLumaVTaps,
                unsigned int WritebackChromaHTaps,
                unsigned int WritebackChromaVTaps,
                unsigned int WritebackDestinationWidth);
static void CalculateWatermarksAndDRAMSpeedChangeSupport(
                struct display_mode_lib *mode_lib,
                unsigned int PrefetchMode,
                unsigned int NumberOfActivePlanes,
                unsigned int MaxLineBufferLines,
                unsigned int LineBufferSize,
                unsigned int DPPOutputBufferPixels,
                unsigned int DETBufferSizeInKByte,
                unsigned int WritebackInterfaceLumaBufferSize,
                unsigned int WritebackInterfaceChromaBufferSize,
                double DCFCLK,
                double UrgentOutOfOrderReturn,
                double ReturnBW,
                bool GPUVMEnable,
                int dpte_group_bytes[],
                unsigned int MetaChunkSize,
                double UrgentLatency,
                double ExtraLatency,
                double WritebackLatency,
                double WritebackChunkSize,
                double SOCCLK,
                double DRAMClockChangeLatency,
                double SRExitTime,
                double SREnterPlusExitTime,
                double DCFCLKDeepSleep,
                int DPPPerPlane[],
                bool DCCEnable[],
                double DPPCLK[],
                double SwathWidthSingleDPPY[],
                unsigned int SwathHeightY[],
                double ReadBandwidthPlaneLuma[],
                unsigned int SwathHeightC[],
                double ReadBandwidthPlaneChroma[],
                unsigned int LBBitPerPixel[],
                double SwathWidthY[],
                double HRatio[],
                unsigned int vtaps[],
                unsigned int VTAPsChroma[],
                double VRatio[],
                unsigned int HTotal[],
                double PixelClock[],
                unsigned int BlendingAndTiming[],
                double BytePerPixelDETY[],
                double BytePerPixelDETC[],
                bool WritebackEnable[],
                enum source_format_class WritebackPixelFormat[],
                double WritebackDestinationWidth[],
                double WritebackDestinationHeight[],
                double WritebackSourceHeight[],
                enum clock_change_support *DRAMClockChangeSupport,
                double *UrgentWatermark,
                double *WritebackUrgentWatermark,
                double *DRAMClockChangeWatermark,
                double *WritebackDRAMClockChangeWatermark,
                double *StutterExitWatermark,
                double *StutterEnterPlusExitWatermark,
                double *MinActiveDRAMClockChangeLatencySupported);
static void CalculateDCFCLKDeepSleep(
                struct display_mode_lib *mode_lib,
                unsigned int NumberOfActivePlanes,
                double BytePerPixelDETY[],
                double BytePerPixelDETC[],
                double VRatio[],
                double SwathWidthY[],
                int DPPPerPlane[],
                double HRatio[],
                double PixelClock[],
                double PSCL_THROUGHPUT[],
                double PSCL_THROUGHPUT_CHROMA[],
                double DPPCLK[],
                double *DCFCLKDeepSleep);
static void CalculateDETBufferSize(
                unsigned int DETBufferSizeInKByte,
                unsigned int SwathHeightY,
                unsigned int SwathHeightC,
                unsigned int *DETBufferSizeY,
                unsigned int *DETBufferSizeC);
static void CalculateUrgentBurstFactor(
                unsigned int DETBufferSizeInKByte,
                unsigned int SwathHeightY,
                unsigned int SwathHeightC,
                unsigned int SwathWidthY,
                double LineTime,
                double UrgentLatency,
                double CursorBufferSize,
                unsigned int CursorWidth,
                unsigned int CursorBPP,
                double VRatio,
                double VRatioPreY,
                double VRatioPreC,
                double BytePerPixelInDETY,
                double BytePerPixelInDETC,
                double *UrgentBurstFactorCursor,
                double *UrgentBurstFactorCursorPre,
                double *UrgentBurstFactorLuma,
                double *UrgentBurstFactorLumaPre,
                double *UrgentBurstFactorChroma,
                double *UrgentBurstFactorChromaPre,
                unsigned int *NotEnoughUrgentLatencyHiding,
                unsigned int *NotEnoughUrgentLatencyHidingPre);

static void CalculatePixelDeliveryTimes(
                unsigned int           NumberOfActivePlanes,
                double                 VRatio[],
                double                 VRatioPrefetchY[],
                double                 VRatioPrefetchC[],
                unsigned int           swath_width_luma_ub[],
                unsigned int           swath_width_chroma_ub[],
                int                    DPPPerPlane[],
                double                 HRatio[],
                double                 PixelClock[],
                double                 PSCL_THROUGHPUT[],
                double                 PSCL_THROUGHPUT_CHROMA[],
                double                 DPPCLK[],
                double                 BytePerPixelDETC[],
                enum scan_direction_class SourceScan[],
                unsigned int           BlockWidth256BytesY[],
                unsigned int           BlockHeight256BytesY[],
                unsigned int           BlockWidth256BytesC[],
                unsigned int           BlockHeight256BytesC[],
                double                 DisplayPipeLineDeliveryTimeLuma[],
                double                 DisplayPipeLineDeliveryTimeChroma[],
                double                 DisplayPipeLineDeliveryTimeLumaPrefetch[],
                double                 DisplayPipeLineDeliveryTimeChromaPrefetch[],
                double                 DisplayPipeRequestDeliveryTimeLuma[],
                double                 DisplayPipeRequestDeliveryTimeChroma[],
                double                 DisplayPipeRequestDeliveryTimeLumaPrefetch[],
                double                 DisplayPipeRequestDeliveryTimeChromaPrefetch[]);

static void CalculateMetaAndPTETimes(
                unsigned int           NumberOfActivePlanes,
                bool                   GPUVMEnable,
                unsigned int           MetaChunkSize,
                unsigned int           MinMetaChunkSizeBytes,
                unsigned int           GPUVMMaxPageTableLevels,
                unsigned int           HTotal[],
                double                 VRatio[],
                double                 VRatioPrefetchY[],
                double                 VRatioPrefetchC[],
                double                 DestinationLinesToRequestRowInVBlank[],
                double                 DestinationLinesToRequestRowInImmediateFlip[],
                double                 DestinationLinesToRequestVMInVBlank[],
                double                 DestinationLinesToRequestVMInImmediateFlip[],
                bool                   DCCEnable[],
                double                 PixelClock[],
                double                 BytePerPixelDETY[],
                double                 BytePerPixelDETC[],
                enum scan_direction_class SourceScan[],
                unsigned int           dpte_row_height[],
                unsigned int           dpte_row_height_chroma[],
                unsigned int           meta_row_width[],
                unsigned int           meta_row_height[],
                unsigned int           meta_req_width[],
                unsigned int           meta_req_height[],
                int                   dpte_group_bytes[],
                unsigned int           PTERequestSizeY[],
                unsigned int           PTERequestSizeC[],
                unsigned int           PixelPTEReqWidthY[],
                unsigned int           PixelPTEReqHeightY[],
                unsigned int           PixelPTEReqWidthC[],
                unsigned int           PixelPTEReqHeightC[],
                unsigned int           dpte_row_width_luma_ub[],
                unsigned int           dpte_row_width_chroma_ub[],
                unsigned int           vm_group_bytes[],
                unsigned int           dpde0_bytes_per_frame_ub_l[],
                unsigned int           dpde0_bytes_per_frame_ub_c[],
                unsigned int           meta_pte_bytes_per_frame_ub_l[],
                unsigned int           meta_pte_bytes_per_frame_ub_c[],
                double                 DST_Y_PER_PTE_ROW_NOM_L[],
                double                 DST_Y_PER_PTE_ROW_NOM_C[],
                double                 DST_Y_PER_META_ROW_NOM_L[],
                double                 TimePerMetaChunkNominal[],
                double                 TimePerMetaChunkVBlank[],
                double                 TimePerMetaChunkFlip[],
                double                 time_per_pte_group_nom_luma[],
                double                 time_per_pte_group_vblank_luma[],
                double                 time_per_pte_group_flip_luma[],
                double                 time_per_pte_group_nom_chroma[],
                double                 time_per_pte_group_vblank_chroma[],
                double                 time_per_pte_group_flip_chroma[],
                double                 TimePerVMGroupVBlank[],
                double                 TimePerVMGroupFlip[],
                double                 TimePerVMRequestVBlank[],
                double                 TimePerVMRequestFlip[]);

static double CalculateExtraLatency(
                double UrgentRoundTripAndOutOfOrderLatency,
                int TotalNumberOfActiveDPP,
                int PixelChunkSizeInKByte,
                int TotalNumberOfDCCActiveDPP,
                int MetaChunkSize,
                double ReturnBW,
                bool GPUVMEnable,
                bool HostVMEnable,
                int NumberOfActivePlanes,
                int NumberOfDPP[],
                int dpte_group_bytes[],
                double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
                double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly,
                int HostVMMaxPageTableLevels,
                int HostVMCachedPageTableLevels);

void dml21_recalculate(struct display_mode_lib *mode_lib)
{
        ModeSupportAndSystemConfiguration(mode_lib);
        PixelClockAdjustmentForProgressiveToInterlaceUnit(mode_lib);
        DisplayPipeConfiguration(mode_lib);
        DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(mode_lib);
}

static unsigned int dscceComputeDelay(
                unsigned int bpc,
                double bpp,
                unsigned int sliceWidth,
                unsigned int numSlices,
                enum output_format_class pixelFormat)
{
        // valid bpc         = source bits per component in the set of {8, 10, 12}
        // valid bpp         = increments of 1/16 of a bit
        //                    min = 6/7/8 in N420/N422/444, respectively
        //                    max = such that compression is 1:1
        //valid sliceWidth  = number of pixels per slice line, must be less than or equal to 5184/numSlices (or 4096/numSlices in 420 mode)
        //valid numSlices   = number of slices in the horiziontal direction per DSC engine in the set of {1, 2, 3, 4}
        //valid pixelFormat = pixel/color format in the set of {:N444_RGB, :S422, :N422, :N420}

        // fixed value
        unsigned int rcModelSize = 8192;

        // N422/N420 operate at 2 pixels per clock
        unsigned int pixelsPerClock, lstall, D, initalXmitDelay, w, S, ix, wx, p, l0, a, ax, l,
                        Delay, pixels;

        if (pixelFormat == dm_n422 || pixelFormat == dm_420)
                pixelsPerClock = 2;
        // #all other modes operate at 1 pixel per clock
        else
                pixelsPerClock = 1;

        //initial transmit delay as per PPS
        initalXmitDelay = dml_round(rcModelSize / 2.0 / bpp / pixelsPerClock);

        //compute ssm delay
        if (bpc == 8)
                D = 81;
        else if (bpc == 10)
                D = 89;
        else
                D = 113;

        //divide by pixel per cycle to compute slice width as seen by DSC
        w = sliceWidth / pixelsPerClock;

        //422 mode has an additional cycle of delay
        if (pixelFormat == dm_s422)
                S = 1;
        else
                S = 0;

        //main calculation for the dscce
        ix = initalXmitDelay + 45;
        wx = (w + 2) / 3;
        p = 3 * wx - w;
        l0 = ix / w;
        a = ix + p * l0;
        ax = (a + 2) / 3 + D + 6 + 1;
        l = (ax + wx - 1) / wx;
        if ((ix % w) == 0 && p != 0)
                lstall = 1;
        else
                lstall = 0;
        Delay = l * wx * (numSlices - 1) + ax + S + lstall + 22;

        //dsc processes 3 pixel containers per cycle and a container can contain 1 or 2 pixels
        pixels = Delay * 3 * pixelsPerClock;
        return pixels;
}

static unsigned int dscComputeDelay(enum output_format_class pixelFormat)
{
        unsigned int Delay = 0;

        if (pixelFormat == dm_420) {
                //   sfr
                Delay = Delay + 2;
                //   dsccif
                Delay = Delay + 0;
                //   dscc - input deserializer
                Delay = Delay + 3;
                //   dscc gets pixels every other cycle
                Delay = Delay + 2;
                //   dscc - input cdc fifo
                Delay = Delay + 12;
                //   dscc gets pixels every other cycle
                Delay = Delay + 13;
                //   dscc - cdc uncertainty
                Delay = Delay + 2;
                //   dscc - output cdc fifo
                Delay = Delay + 7;
                //   dscc gets pixels every other cycle
                Delay = Delay + 3;
                //   dscc - cdc uncertainty
                Delay = Delay + 2;
                //   dscc - output serializer
                Delay = Delay + 1;
                //   sft
                Delay = Delay + 1;
        } else if (pixelFormat == dm_n422) {
                //   sfr
                Delay = Delay + 2;
                //   dsccif
                Delay = Delay + 1;
                //   dscc - input deserializer
                Delay = Delay + 5;
                //  dscc - input cdc fifo
                Delay = Delay + 25;
                //   dscc - cdc uncertainty
                Delay = Delay + 2;
                //   dscc - output cdc fifo
                Delay = Delay + 10;
                //   dscc - cdc uncertainty
                Delay = Delay + 2;
                //   dscc - output serializer
                Delay = Delay + 1;
                //   sft
                Delay = Delay + 1;
        } else {
                //   sfr
                Delay = Delay + 2;
                //   dsccif
                Delay = Delay + 0;
                //   dscc - input deserializer
                Delay = Delay + 3;
                //   dscc - input cdc fifo
                Delay = Delay + 12;
                //   dscc - cdc uncertainty
                Delay = Delay + 2;
                //   dscc - output cdc fifo
                Delay = Delay + 7;
                //   dscc - output serializer
                Delay = Delay + 1;
                //   dscc - cdc uncertainty
                Delay = Delay + 2;
                //   sft
                Delay = Delay + 1;
        }

        return Delay;
}

static bool CalculatePrefetchSchedule(
                struct display_mode_lib *mode_lib,
                double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
                double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly,
                Pipe *myPipe,
                unsigned int DSCDelay,
                double DPPCLKDelaySubtotal,
                double DPPCLKDelaySCL,
                double DPPCLKDelaySCLLBOnly,
                double DPPCLKDelayCNVCFormater,
                double DPPCLKDelayCNVCCursor,
                double DISPCLKDelaySubtotal,
                unsigned int ScalerRecoutWidth,
                enum output_format_class OutputFormat,
                unsigned int MaxInterDCNTileRepeaters,
                unsigned int VStartup,
                unsigned int MaxVStartup,
                unsigned int GPUVMPageTableLevels,
                bool GPUVMEnable,
                HostVM *myHostVM,
                bool DynamicMetadataEnable,
                int DynamicMetadataLinesBeforeActiveRequired,
                unsigned int DynamicMetadataTransmittedBytes,
                bool DCCEnable,
                double UrgentLatency,
                double UrgentExtraLatency,
                double TCalc,
                unsigned int PDEAndMetaPTEBytesFrame,
                unsigned int MetaRowByte,
                unsigned int PixelPTEBytesPerRow,
                double PrefetchSourceLinesY,
                unsigned int SwathWidthY,
                double BytePerPixelDETY,
                double VInitPreFillY,
                unsigned int MaxNumSwathY,
                double PrefetchSourceLinesC,
                double BytePerPixelDETC,
                double VInitPreFillC,
                unsigned int MaxNumSwathC,
                unsigned int SwathHeightY,
                unsigned int SwathHeightC,
                double TWait,
                bool XFCEnabled,
                double XFCRemoteSurfaceFlipDelay,
                bool ProgressiveToInterlaceUnitInOPP,
                double *DSTXAfterScaler,
                double *DSTYAfterScaler,
                double *DestinationLinesForPrefetch,
                double *PrefetchBandwidth,
                double *DestinationLinesToRequestVMInVBlank,
                double *DestinationLinesToRequestRowInVBlank,
                double *VRatioPrefetchY,
                double *VRatioPrefetchC,
                double *RequiredPrefetchPixDataBWLuma,
                double *RequiredPrefetchPixDataBWChroma,
                unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata,
                double *Tno_bw,
                double *prefetch_vmrow_bw,
                unsigned int *swath_width_luma_ub,
                unsigned int *swath_width_chroma_ub,
                unsigned int *VUpdateOffsetPix,
                double *VUpdateWidthPix,
                double *VReadyOffsetPix)
{
        bool MyError = false;
        unsigned int DPPCycles, DISPCLKCycles;
        double DSTTotalPixelsAfterScaler, TotalRepeaterDelayTime;
        double Tdm, LineTime, Tsetup;
        double dst_y_prefetch_equ;
        double Tsw_oto;
        double prefetch_bw_oto;
        double Tvm_oto;
        double Tr0_oto;
        double Tvm_oto_lines;
        double Tr0_oto_lines;
        double Tsw_oto_lines;
        double dst_y_prefetch_oto;
        double TimeForFetchingMetaPTE = 0;
        double TimeForFetchingRowInVBlank = 0;
        double LinesToRequestPrefetchPixelData = 0;
        double HostVMInefficiencyFactor;
        unsigned int HostVMDynamicLevels;

        if (GPUVMEnable == true && myHostVM->Enable == true) {
                HostVMInefficiencyFactor =
                                PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData
                                                / PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly;
                HostVMDynamicLevels = myHostVM->MaxPageTableLevels
                                - myHostVM->CachedPageTableLevels;
        } else {
                HostVMInefficiencyFactor = 1;
                HostVMDynamicLevels = 0;
        }

        if (myPipe->ScalerEnabled)
                DPPCycles = DPPCLKDelaySubtotal + DPPCLKDelaySCL;
        else
                DPPCycles = DPPCLKDelaySubtotal + DPPCLKDelaySCLLBOnly;

        DPPCycles = DPPCycles + DPPCLKDelayCNVCFormater + myPipe->NumberOfCursors * DPPCLKDelayCNVCCursor;

        DISPCLKCycles = DISPCLKDelaySubtotal;

        if (myPipe->DPPCLK == 0.0 || myPipe->DISPCLK == 0.0)
                return true;

        *DSTXAfterScaler = DPPCycles * myPipe->PixelClock / myPipe->DPPCLK
                        + DISPCLKCycles * myPipe->PixelClock / myPipe->DISPCLK + DSCDelay;

        if (myPipe->DPPPerPlane > 1)
                *DSTXAfterScaler = *DSTXAfterScaler + ScalerRecoutWidth;

        if (OutputFormat == dm_420 || (myPipe->InterlaceEnable && ProgressiveToInterlaceUnitInOPP))
                *DSTYAfterScaler = 1;
        else
                *DSTYAfterScaler = 0;

        DSTTotalPixelsAfterScaler = ((double) (*DSTYAfterScaler * myPipe->HTotal)) + *DSTXAfterScaler;
        *DSTYAfterScaler = dml_floor(DSTTotalPixelsAfterScaler / myPipe->HTotal, 1);
        *DSTXAfterScaler = DSTTotalPixelsAfterScaler - ((double) (*DSTYAfterScaler * myPipe->HTotal));

        *VUpdateOffsetPix = dml_ceil(myPipe->HTotal / 4.0, 1);
        TotalRepeaterDelayTime = MaxInterDCNTileRepeaters * (2.0 / myPipe->DPPCLK + 3.0 / myPipe->DISPCLK);
        *VUpdateWidthPix = (14.0 / myPipe->DCFCLKDeepSleep + 12.0 / myPipe->DPPCLK + TotalRepeaterDelayTime)
                        * myPipe->PixelClock;

        *VReadyOffsetPix = dml_max(
                        150.0 / myPipe->DPPCLK,
                        TotalRepeaterDelayTime + 20.0 / myPipe->DCFCLKDeepSleep + 10.0 / myPipe->DPPCLK)
                        * myPipe->PixelClock;

        Tsetup = (double) (*VUpdateOffsetPix + *VUpdateWidthPix + *VReadyOffsetPix) / myPipe->PixelClock;

        LineTime = (double) myPipe->HTotal / myPipe->PixelClock;

        if (DynamicMetadataEnable) {
                double Tdmbf, Tdmec, Tdmsks;

                Tdm = dml_max(0.0, UrgentExtraLatency - TCalc);
                Tdmbf = DynamicMetadataTransmittedBytes / 4.0 / myPipe->DISPCLK;
                Tdmec = LineTime;
                if (DynamicMetadataLinesBeforeActiveRequired == -1)
                        Tdmsks = myPipe->VBlank * LineTime / 2.0;
                else
                        Tdmsks = DynamicMetadataLinesBeforeActiveRequired * LineTime;
                if (myPipe->InterlaceEnable && !ProgressiveToInterlaceUnitInOPP)
                        Tdmsks = Tdmsks / 2;
                if (VStartup * LineTime
                                < Tsetup + TWait + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) {
                        MyError = true;
                        *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata = (Tsetup + TWait
                                        + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) / LineTime;
                } else
                        *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata = 0.0;
        } else
                Tdm = 0;

        if (GPUVMEnable) {
                if (GPUVMPageTableLevels >= 3)
                        *Tno_bw = UrgentExtraLatency + UrgentLatency * ((GPUVMPageTableLevels - 2) * (myHostVM->MaxPageTableLevels + 1) - 1);
                else
                        *Tno_bw = 0;
        } else if (!DCCEnable)
                *Tno_bw = LineTime;
        else
                *Tno_bw = LineTime / 4;

        dst_y_prefetch_equ = VStartup - dml_max(TCalc + TWait, XFCRemoteSurfaceFlipDelay) / LineTime
                        - (Tsetup + Tdm) / LineTime
                        - (*DSTYAfterScaler + *DSTXAfterScaler / myPipe->HTotal);

        Tsw_oto = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime;

        if (myPipe->SourceScan == dm_horz) {
                *swath_width_luma_ub = dml_ceil(SwathWidthY - 1, myPipe->BlockWidth256BytesY) + myPipe->BlockWidth256BytesY;
                if (myPipe->BlockWidth256BytesC > 0)
                        *swath_width_chroma_ub = dml_ceil(SwathWidthY / 2 - 1, myPipe->BlockWidth256BytesC) + myPipe->BlockWidth256BytesC;
        } else {
                *swath_width_luma_ub = dml_ceil(SwathWidthY - 1, myPipe->BlockHeight256BytesY) + myPipe->BlockHeight256BytesY;
                if (myPipe->BlockHeight256BytesC > 0)
                        *swath_width_chroma_ub = dml_ceil(SwathWidthY / 2 - 1, myPipe->BlockHeight256BytesC) + myPipe->BlockHeight256BytesC;
        }

        prefetch_bw_oto = (PrefetchSourceLinesY * *swath_width_luma_ub * dml_ceil(BytePerPixelDETY, 1) + PrefetchSourceLinesC * *swath_width_chroma_ub * dml_ceil(BytePerPixelDETC, 2)) / Tsw_oto;


        if (GPUVMEnable == true) {
                Tvm_oto = dml_max(*Tno_bw + PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / prefetch_bw_oto,
                                dml_max(UrgentExtraLatency + UrgentLatency * (GPUVMPageTableLevels * (HostVMDynamicLevels + 1) - 1),
                                        LineTime / 4.0));
        } else
                Tvm_oto = LineTime / 4.0;

        if ((GPUVMEnable == true || DCCEnable == true)) {
                Tr0_oto = dml_max(
                                (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) / prefetch_bw_oto,
                                dml_max(UrgentLatency * (HostVMDynamicLevels + 1), dml_max(LineTime - Tvm_oto, LineTime / 4)));
        } else
                Tr0_oto = (LineTime - Tvm_oto) / 2.0;

        Tvm_oto_lines = dml_ceil(4 * Tvm_oto / LineTime, 1) / 4.0;
        Tr0_oto_lines = dml_ceil(4 * Tr0_oto / LineTime, 1) / 4.0;
        Tsw_oto_lines = dml_ceil(4 * Tsw_oto / LineTime, 1) / 4.0;
        dst_y_prefetch_oto = Tvm_oto_lines + 2 * Tr0_oto_lines + Tsw_oto_lines + 0.75;

        dst_y_prefetch_equ = dml_floor(4.0 * (dst_y_prefetch_equ + 0.125), 1) / 4.0;

        if (dst_y_prefetch_oto < dst_y_prefetch_equ)
                *DestinationLinesForPrefetch = dst_y_prefetch_oto;
        else
                *DestinationLinesForPrefetch = dst_y_prefetch_equ;

        // Limit to prevent overflow in DST_Y_PREFETCH register
        *DestinationLinesForPrefetch = dml_min(*DestinationLinesForPrefetch, 63.75);

        dml_print("DML: VStartup: %d\n", VStartup);
        dml_print("DML: TCalc: %f\n", TCalc);
        dml_print("DML: TWait: %f\n", TWait);
        dml_print("DML: XFCRemoteSurfaceFlipDelay: %f\n", XFCRemoteSurfaceFlipDelay);
        dml_print("DML: LineTime: %f\n", LineTime);
        dml_print("DML: Tsetup: %f\n", Tsetup);
        dml_print("DML: Tdm: %f\n", Tdm);
        dml_print("DML: DSTYAfterScaler: %f\n", *DSTYAfterScaler);
        dml_print("DML: DSTXAfterScaler: %f\n", *DSTXAfterScaler);
        dml_print("DML: HTotal: %d\n", myPipe->HTotal);

        *PrefetchBandwidth = 0;
        *DestinationLinesToRequestVMInVBlank = 0;
        *DestinationLinesToRequestRowInVBlank = 0;
        *VRatioPrefetchY = 0;
        *VRatioPrefetchC = 0;
        *RequiredPrefetchPixDataBWLuma = 0;
        if (*DestinationLinesForPrefetch > 1) {
                double PrefetchBandwidth1 = (PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor + 2 * MetaRowByte
                                + 2 * PixelPTEBytesPerRow * HostVMInefficiencyFactor
                                + PrefetchSourceLinesY * *swath_width_luma_ub * dml_ceil(BytePerPixelDETY, 1)
                                + PrefetchSourceLinesC * *swath_width_chroma_ub * dml_ceil(BytePerPixelDETC, 2))
                                / (*DestinationLinesForPrefetch * LineTime - *Tno_bw);

                double PrefetchBandwidth2 = (PDEAndMetaPTEBytesFrame *
                                HostVMInefficiencyFactor + PrefetchSourceLinesY *
                                *swath_width_luma_ub * dml_ceil(BytePerPixelDETY, 1) +
                                PrefetchSourceLinesC * *swath_width_chroma_ub *
                                dml_ceil(BytePerPixelDETC, 2)) /
                                (*DestinationLinesForPrefetch * LineTime - *Tno_bw - 2 *
                                UrgentLatency * (1 + HostVMDynamicLevels));

                double PrefetchBandwidth3 = (2 * MetaRowByte + 2 * PixelPTEBytesPerRow
                                * HostVMInefficiencyFactor + PrefetchSourceLinesY *
                                *swath_width_luma_ub * dml_ceil(BytePerPixelDETY, 1) +
                                PrefetchSourceLinesC * *swath_width_chroma_ub *
                                dml_ceil(BytePerPixelDETC, 2)) /
                                (*DestinationLinesForPrefetch * LineTime -
                                UrgentExtraLatency - UrgentLatency * (GPUVMPageTableLevels
                                * (HostVMDynamicLevels + 1) - 1));

                double PrefetchBandwidth4 = (PrefetchSourceLinesY * *swath_width_luma_ub *
                                dml_ceil(BytePerPixelDETY, 1) + PrefetchSourceLinesC *
                                *swath_width_chroma_ub * dml_ceil(BytePerPixelDETC, 2)) /
                                (*DestinationLinesForPrefetch * LineTime -
                                UrgentExtraLatency - UrgentLatency * (GPUVMPageTableLevels
                                * (HostVMDynamicLevels + 1) - 1) - 2 * UrgentLatency *
                                (1 + HostVMDynamicLevels));

                if (VStartup == MaxVStartup && (PrefetchBandwidth1 > 4 * prefetch_bw_oto) && (*DestinationLinesForPrefetch - dml_ceil(Tsw_oto_lines, 1) / 4.0 - 0.75) * LineTime - *Tno_bw > 0) {
                        PrefetchBandwidth1 = (PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor + 2 * MetaRowByte + 2 * PixelPTEBytesPerRow * HostVMInefficiencyFactor) / ((*DestinationLinesForPrefetch - dml_ceil(Tsw_oto_lines, 1) / 4.0 - 0.75) * LineTime - *Tno_bw);
                }
                if (*Tno_bw + PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / PrefetchBandwidth1 >= UrgentExtraLatency + UrgentLatency * (GPUVMPageTableLevels * (HostVMDynamicLevels + 1) - 1) && (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) / PrefetchBandwidth1 >= UrgentLatency * (1 + HostVMDynamicLevels)) {
                        *PrefetchBandwidth = PrefetchBandwidth1;
                } else if (*Tno_bw + PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / PrefetchBandwidth2 >= UrgentExtraLatency + UrgentLatency * (GPUVMPageTableLevels * (HostVMDynamicLevels + 1) - 1) && (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) / PrefetchBandwidth2 < UrgentLatency * (1 + HostVMDynamicLevels)) {
                        *PrefetchBandwidth = PrefetchBandwidth2;
                } else if (*Tno_bw + PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / PrefetchBandwidth3 < UrgentExtraLatency + UrgentLatency * (GPUVMPageTableLevels * (HostVMDynamicLevels + 1) - 1) && (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) / PrefetchBandwidth3 >= UrgentLatency * (1 + HostVMDynamicLevels)) {
                        *PrefetchBandwidth = PrefetchBandwidth3;
                } else {
                        *PrefetchBandwidth = PrefetchBandwidth4;
                }

                if (GPUVMEnable) {
                        TimeForFetchingMetaPTE = dml_max(*Tno_bw + (double) PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / *PrefetchBandwidth,
                                        dml_max(UrgentExtraLatency + UrgentLatency * (GPUVMPageTableLevels * (HostVMDynamicLevels + 1) - 1), LineTime / 4));
                } else {
// 5/30/2018 - This was an optimization requested from Sy but now NumberOfCursors is no longer a factor
//             so if this needs to be reinstated, then it should be officially done in the VBA code as well.
//                      if (mode_lib->NumberOfCursors > 0 || XFCEnabled)
                                TimeForFetchingMetaPTE = LineTime / 4;
//                      else
//                              TimeForFetchingMetaPTE = 0.0;
                }

                if ((GPUVMEnable == true || DCCEnable == true)) {
                        TimeForFetchingRowInVBlank =
                                        dml_max(
                                                        (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor)
                                                                        / *PrefetchBandwidth,
                                                        dml_max(
                                                                        UrgentLatency * (1 + HostVMDynamicLevels),
                                                                        dml_max(
                                                                                        (LineTime
                                                                                                        - TimeForFetchingMetaPTE) / 2.0,
                                                                                        LineTime
                                                                                                        / 4.0)));
                } else {
// See note above dated 5/30/2018
//                      if (NumberOfCursors > 0 || XFCEnabled)
                                TimeForFetchingRowInVBlank = (LineTime - TimeForFetchingMetaPTE) / 2.0;
//                      else // TODO: Did someone else add this??
//                              TimeForFetchingRowInVBlank = 0.0;
                }

                *DestinationLinesToRequestVMInVBlank = dml_ceil(4.0 * TimeForFetchingMetaPTE / LineTime, 1.0) / 4.0;

                *DestinationLinesToRequestRowInVBlank = dml_ceil(4.0 * TimeForFetchingRowInVBlank / LineTime, 1.0) / 4.0;

                LinesToRequestPrefetchPixelData = *DestinationLinesForPrefetch
// See note above dated 5/30/2018
//                                              - ((NumberOfCursors > 0 || GPUVMEnable || DCCEnable) ?
                                                - ((GPUVMEnable || DCCEnable) ?
                                                                (*DestinationLinesToRequestVMInVBlank + 2 * *DestinationLinesToRequestRowInVBlank) :
                                                                0.0); // TODO: Did someone else add this??

                if (LinesToRequestPrefetchPixelData > 0) {

                        *VRatioPrefetchY = (double) PrefetchSourceLinesY
                                        / LinesToRequestPrefetchPixelData;
                        *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0);
                        if ((SwathHeightY > 4) && (VInitPreFillY > 3)) {
                                if (LinesToRequestPrefetchPixelData > (VInitPreFillY - 3.0) / 2.0) {
                                        *VRatioPrefetchY =
                                                        dml_max(
                                                                        (double) PrefetchSourceLinesY
                                                                                        / LinesToRequestPrefetchPixelData,
                                                                        (double) MaxNumSwathY
                                                                                        * SwathHeightY
                                                                                        / (LinesToRequestPrefetchPixelData
                                                                                                        - (VInitPreFillY
                                                                                                                        - 3.0)
                                                                                                                        / 2.0));
                                        *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0);
                                } else {
                                        MyError = true;
                                        *VRatioPrefetchY = 0;
                                }
                        }

                        *VRatioPrefetchC = (double) PrefetchSourceLinesC
                                        / LinesToRequestPrefetchPixelData;
                        *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0);

                        if ((SwathHeightC > 4)) {
                                if (LinesToRequestPrefetchPixelData > (VInitPreFillC - 3.0) / 2.0) {
                                        *VRatioPrefetchC =
                                                        dml_max(
                                                                        *VRatioPrefetchC,
                                                                        (double) MaxNumSwathC
                                                                                        * SwathHeightC
                                                                                        / (LinesToRequestPrefetchPixelData
                                                                                                        - (VInitPreFillC
                                                                                                                        - 3.0)
                                                                                                                        / 2.0));
                                        *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0);
                                } else {
                                        MyError = true;
                                        *VRatioPrefetchC = 0;
                                }
                        }

                        *RequiredPrefetchPixDataBWLuma = myPipe->DPPPerPlane
                                        * (double) PrefetchSourceLinesY / LinesToRequestPrefetchPixelData
                                        * dml_ceil(BytePerPixelDETY, 1)
                                        * *swath_width_luma_ub / LineTime;
                        *RequiredPrefetchPixDataBWChroma = myPipe->DPPPerPlane
                                        * (double) PrefetchSourceLinesC / LinesToRequestPrefetchPixelData
                                        * dml_ceil(BytePerPixelDETC, 2)
                                        * *swath_width_chroma_ub / LineTime;
                } else {
                        MyError = true;
                        *VRatioPrefetchY = 0;
                        *VRatioPrefetchC = 0;
                        *RequiredPrefetchPixDataBWLuma = 0;
                        *RequiredPrefetchPixDataBWChroma = 0;
                }

                dml_print("DML: Tvm: %fus\n", TimeForFetchingMetaPTE);
                dml_print("DML: Tr0: %fus\n", TimeForFetchingRowInVBlank);
                dml_print("DML: Tsw: %fus\n", (double)(*DestinationLinesForPrefetch) * LineTime - TimeForFetchingMetaPTE - TimeForFetchingRowInVBlank);
                dml_print("DML: Tpre: %fus\n", (double)(*DestinationLinesForPrefetch) * LineTime);
                dml_print("DML: row_bytes = dpte_row_bytes (per_pipe) = PixelPTEBytesPerRow = : %d\n", PixelPTEBytesPerRow);

        } else {
                MyError = true;
        }

        {
                double prefetch_vm_bw;
                double prefetch_row_bw;

                if (PDEAndMetaPTEBytesFrame == 0) {
                        prefetch_vm_bw = 0;
                } else if (*DestinationLinesToRequestVMInVBlank > 0) {
                        prefetch_vm_bw = PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / (*DestinationLinesToRequestVMInVBlank * LineTime);
                } else {
                        prefetch_vm_bw = 0;
                        MyError = true;
                }
                if (MetaRowByte + PixelPTEBytesPerRow == 0) {
                        prefetch_row_bw = 0;
                } else if (*DestinationLinesToRequestRowInVBlank > 0) {
                        prefetch_row_bw = (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) / (*DestinationLinesToRequestRowInVBlank * LineTime);
                } else {
                        prefetch_row_bw = 0;
                        MyError = true;
                }

                *prefetch_vmrow_bw = dml_max(prefetch_vm_bw, prefetch_row_bw);
        }

        if (MyError) {
                *PrefetchBandwidth = 0;
                *DestinationLinesToRequestVMInVBlank = 0;
                *DestinationLinesToRequestRowInVBlank = 0;
                *DestinationLinesForPrefetch = 0;
                *VRatioPrefetchY = 0;
                *VRatioPrefetchC = 0;
                *RequiredPrefetchPixDataBWLuma = 0;
                *RequiredPrefetchPixDataBWChroma = 0;
        }

        return MyError;
}

static double RoundToDFSGranularityUp(double Clock, double VCOSpeed)
{
        return VCOSpeed * 4 / dml_floor(VCOSpeed * 4 / Clock, 1);
}

static double RoundToDFSGranularityDown(double Clock, double VCOSpeed)
{
        return VCOSpeed * 4 / dml_ceil(VCOSpeed * 4 / Clock, 1);
}

static double CalculateDCCConfiguration(
                bool DCCEnabled,
                bool DCCProgrammingAssumesScanDirectionUnknown,
                unsigned int ViewportWidth,
                unsigned int ViewportHeight,
                unsigned int DETBufferSize,
                unsigned int RequestHeight256Byte,
                unsigned int SwathHeight,
                enum dm_swizzle_mode TilingFormat,
                unsigned int BytePerPixel,
                enum scan_direction_class ScanOrientation,
                unsigned int *MaxUncompressedBlock,
                unsigned int *MaxCompressedBlock,
                unsigned int *Independent64ByteBlock)
{
        double MaximumDCCCompressionSurface = 0.0;
        enum {
                REQ_256Bytes,
                REQ_128BytesNonContiguous,
                REQ_128BytesContiguous,
                REQ_NA
        } Request = REQ_NA;

        if (DCCEnabled == true) {
                if (DCCProgrammingAssumesScanDirectionUnknown == true) {
                        if (DETBufferSize >= RequestHeight256Byte * ViewportWidth * BytePerPixel
                                        && DETBufferSize
                                                        >= 256 / RequestHeight256Byte
                                                                        * ViewportHeight) {
                                Request = REQ_256Bytes;
                        } else if ((DETBufferSize
                                        < RequestHeight256Byte * ViewportWidth * BytePerPixel
                                        && (BytePerPixel == 2 || BytePerPixel == 4))
                                        || (DETBufferSize
                                                        < 256 / RequestHeight256Byte
                                                                        * ViewportHeight
                                                        && BytePerPixel == 8
                                                        && (TilingFormat == dm_sw_4kb_d
                                                                        || TilingFormat
                                                                                        == dm_sw_4kb_d_x
                                                                        || TilingFormat
                                                                                        == dm_sw_var_d
                                                                        || TilingFormat
                                                                                        == dm_sw_var_d_x
                                                                        || TilingFormat
                                                                                        == dm_sw_64kb_d
                                                                        || TilingFormat
                                                                                        == dm_sw_64kb_d_x
                                                                        || TilingFormat
                                                                                        == dm_sw_64kb_d_t
                                                                        || TilingFormat
                                                                                        == dm_sw_64kb_r_x))) {
                                Request = REQ_128BytesNonContiguous;
                        } else {
                                Request = REQ_128BytesContiguous;
                        }
                } else {
                        if (BytePerPixel == 1) {
                                if (ScanOrientation == dm_vert || SwathHeight == 16) {
                                        Request = REQ_256Bytes;
                                } else {
                                        Request = REQ_128BytesContiguous;
                                }
                        } else if (BytePerPixel == 2) {
                                if ((ScanOrientation == dm_vert && SwathHeight == 16) || (ScanOrientation != dm_vert && SwathHeight == 8)) {
                                        Request = REQ_256Bytes;
                                } else if (ScanOrientation == dm_vert) {
                                        Request = REQ_128BytesContiguous;
                                } else {
                                        Request = REQ_128BytesNonContiguous;
                                }
                        } else if (BytePerPixel == 4) {
                                if (SwathHeight == 8) {
                                        Request = REQ_256Bytes;
                                } else if (ScanOrientation == dm_vert) {
                                        Request = REQ_128BytesContiguous;
                                } else {
                                        Request = REQ_128BytesNonContiguous;
                                }
                        } else if (BytePerPixel == 8) {
                                if (TilingFormat == dm_sw_4kb_d || TilingFormat == dm_sw_4kb_d_x
                                                || TilingFormat == dm_sw_var_d
                                                || TilingFormat == dm_sw_var_d_x
                                                || TilingFormat == dm_sw_64kb_d
                                                || TilingFormat == dm_sw_64kb_d_x
                                                || TilingFormat == dm_sw_64kb_d_t
                                                || TilingFormat == dm_sw_64kb_r_x) {
                                        if ((ScanOrientation == dm_vert && SwathHeight == 8)
                                                        || (ScanOrientation != dm_vert
                                                                        && SwathHeight == 4)) {
                                                Request = REQ_256Bytes;
                                        } else if (ScanOrientation != dm_vert) {
                                                Request = REQ_128BytesContiguous;
                                        } else {
                                                Request = REQ_128BytesNonContiguous;
                                        }
                                } else {
                                        if (ScanOrientation != dm_vert || SwathHeight == 8) {
                                                Request = REQ_256Bytes;
                                        } else {
                                                Request = REQ_128BytesContiguous;
                                        }
                                }
                        }
                }
        } else {
                Request = REQ_NA;
        }

        if (Request == REQ_256Bytes) {
                *MaxUncompressedBlock = 256;
                *MaxCompressedBlock = 256;
                *Independent64ByteBlock = false;
                MaximumDCCCompressionSurface = 4.0;
        } else if (Request == REQ_128BytesContiguous) {
                *MaxUncompressedBlock = 128;
                *MaxCompressedBlock = 128;
                *Independent64ByteBlock = false;
                MaximumDCCCompressionSurface = 2.0;
        } else if (Request == REQ_128BytesNonContiguous) {
                *MaxUncompressedBlock = 256;
                *MaxCompressedBlock = 64;
                *Independent64ByteBlock = true;
                MaximumDCCCompressionSurface = 4.0;
        } else {
                *MaxUncompressedBlock = 0;
                *MaxCompressedBlock = 0;
                *Independent64ByteBlock = 0;
                MaximumDCCCompressionSurface = 0.0;
        }

        return MaximumDCCCompressionSurface;
}

static double CalculatePrefetchSourceLines(
                struct display_mode_lib *mode_lib,
                double VRatio,
                double vtaps,
                bool Interlace,
                bool ProgressiveToInterlaceUnitInOPP,
                unsigned int SwathHeight,
                unsigned int ViewportYStart,
                double *VInitPreFill,
                unsigned int *MaxNumSwath)
{
        unsigned int MaxPartialSwath;

        if (ProgressiveToInterlaceUnitInOPP)
                *VInitPreFill = dml_floor((VRatio + vtaps + 1) / 2.0, 1);
        else
                *VInitPreFill = dml_floor((VRatio + vtaps + 1 + Interlace * 0.5 * VRatio) / 2.0, 1);

        if (!mode_lib->vba.IgnoreViewportPositioning) {

                *MaxNumSwath = dml_ceil((*VInitPreFill - 1.0) / SwathHeight, 1) + 1.0;

                if (*VInitPreFill > 1.0)
                        MaxPartialSwath = (unsigned int) (*VInitPreFill - 2) % SwathHeight;
                else
                        MaxPartialSwath = (unsigned int) (*VInitPreFill + SwathHeight - 2)
                                        % SwathHeight;
                MaxPartialSwath = dml_max(1U, MaxPartialSwath);

        } else {

                if (ViewportYStart != 0)
                        dml_print(
                                        "WARNING DML: using viewport y position of 0 even though actual viewport y position is non-zero in prefetch source lines calculation\n");

                *MaxNumSwath = dml_ceil(*VInitPreFill / SwathHeight, 1);

                if (*VInitPreFill > 1.0)
                        MaxPartialSwath = (unsigned int) (*VInitPreFill - 1) % SwathHeight;
                else
                        MaxPartialSwath = (unsigned int) (*VInitPreFill + SwathHeight - 1)
                                        % SwathHeight;
        }

        return *MaxNumSwath * SwathHeight + MaxPartialSwath;
}

static unsigned int CalculateVMAndRowBytes(
                struct display_mode_lib *mode_lib,
                bool DCCEnable,
                unsigned int BlockHeight256Bytes,
                unsigned int BlockWidth256Bytes,
                enum source_format_class SourcePixelFormat,
                unsigned int SurfaceTiling,
                unsigned int BytePerPixel,
                enum scan_direction_class ScanDirection,
                unsigned int ViewportWidth,
                unsigned int ViewportHeight,
                unsigned int SwathWidth,
                bool GPUVMEnable,
                bool HostVMEnable,
                unsigned int HostVMMaxPageTableLevels,
                unsigned int HostVMCachedPageTableLevels,
                unsigned int VMMPageSize,
                unsigned int PTEBufferSizeInRequests,
                unsigned int Pitch,
                unsigned int DCCMetaPitch,
                unsigned int *MacroTileWidth,
                unsigned int *MetaRowByte,
                unsigned int *PixelPTEBytesPerRow,
                bool *PTEBufferSizeNotExceeded,
                unsigned int *dpte_row_width_ub,
                unsigned int *dpte_row_height,
                unsigned int *MetaRequestWidth,
                unsigned int *MetaRequestHeight,
                unsigned int *meta_row_width,
                unsigned int *meta_row_height,
                unsigned int *vm_group_bytes,
                unsigned int *dpte_group_bytes,
                unsigned int *PixelPTEReqWidth,
                unsigned int *PixelPTEReqHeight,
                unsigned int *PTERequestSize,
                unsigned int *DPDE0BytesFrame,
                unsigned int *MetaPTEBytesFrame)
{
        unsigned int MPDEBytesFrame;
        unsigned int DCCMetaSurfaceBytes;
        unsigned int MacroTileSizeBytes;
        unsigned int MacroTileHeight;
        unsigned int ExtraDPDEBytesFrame;
        unsigned int PDEAndMetaPTEBytesFrame;
        unsigned int PixelPTEReqHeightPTEs = 0;

        if (DCCEnable == true) {
                *MetaRequestHeight = 8 * BlockHeight256Bytes;
                *MetaRequestWidth = 8 * BlockWidth256Bytes;
                if (ScanDirection == dm_horz) {
                        *meta_row_height = *MetaRequestHeight;
                        *meta_row_width = dml_ceil((double) SwathWidth - 1, *MetaRequestWidth)
                                        + *MetaRequestWidth;
                        *MetaRowByte = *meta_row_width * *MetaRequestHeight * BytePerPixel / 256.0;
                } else {
                        *meta_row_height = *MetaRequestWidth;
                        *meta_row_width = dml_ceil((double) SwathWidth - 1, *MetaRequestHeight)
                                        + *MetaRequestHeight;
                        *MetaRowByte = *meta_row_width * *MetaRequestWidth * BytePerPixel / 256.0;
                }
                if (ScanDirection == dm_horz) {
                        DCCMetaSurfaceBytes = DCCMetaPitch
                                        * (dml_ceil(ViewportHeight - 1, 64 * BlockHeight256Bytes)
                                                        + 64 * BlockHeight256Bytes) * BytePerPixel
                                        / 256;
                } else {
                        DCCMetaSurfaceBytes = DCCMetaPitch
                                        * (dml_ceil(
                                                        (double) ViewportHeight - 1,
                                                        64 * BlockHeight256Bytes)
                                                        + 64 * BlockHeight256Bytes) * BytePerPixel
                                        / 256;
                }
                if (GPUVMEnable == true) {
                        *MetaPTEBytesFrame = (dml_ceil(
                                        (double) (DCCMetaSurfaceBytes - VMMPageSize)
                                                        / (8 * VMMPageSize),
                                        1) + 1) * 64;
                        MPDEBytesFrame = 128 * ((mode_lib->vba.GPUVMMaxPageTableLevels + 1) * (mode_lib->vba.HostVMMaxPageTableLevels + 1) - 2);
                } else {
                        *MetaPTEBytesFrame = 0;
                        MPDEBytesFrame = 0;
                }
        } else {
                *MetaPTEBytesFrame = 0;
                MPDEBytesFrame = 0;
                *MetaRowByte = 0;
        }

        if (SurfaceTiling == dm_sw_linear || SurfaceTiling == dm_sw_gfx7_2d_thin_gl || SurfaceTiling == dm_sw_gfx7_2d_thin_l_vp) {
                MacroTileSizeBytes = 256;
                MacroTileHeight = BlockHeight256Bytes;
        } else if (SurfaceTiling == dm_sw_4kb_s || SurfaceTiling == dm_sw_4kb_s_x
                        || SurfaceTiling == dm_sw_4kb_d || SurfaceTiling == dm_sw_4kb_d_x) {
                MacroTileSizeBytes = 4096;
                MacroTileHeight = 4 * BlockHeight256Bytes;
        } else if (SurfaceTiling == dm_sw_64kb_s || SurfaceTiling == dm_sw_64kb_s_t
                        || SurfaceTiling == dm_sw_64kb_s_x || SurfaceTiling == dm_sw_64kb_d
                        || SurfaceTiling == dm_sw_64kb_d_t || SurfaceTiling == dm_sw_64kb_d_x
                        || SurfaceTiling == dm_sw_64kb_r_x) {
                MacroTileSizeBytes = 65536;
                MacroTileHeight = 16 * BlockHeight256Bytes;
        } else {
                MacroTileSizeBytes = 262144;
                MacroTileHeight = 32 * BlockHeight256Bytes;
        }
        *MacroTileWidth = MacroTileSizeBytes / BytePerPixel / MacroTileHeight;

        if (GPUVMEnable == true && (mode_lib->vba.GPUVMMaxPageTableLevels + 1) * (mode_lib->vba.HostVMMaxPageTableLevels + 1) > 2) {
                if (ScanDirection == dm_horz) {
                        *DPDE0BytesFrame = 64 * (dml_ceil(((Pitch * (dml_ceil(ViewportHeight - 1, MacroTileHeight) + MacroTileHeight) * BytePerPixel) - MacroTileSizeBytes) / (8 * 2097152), 1) + 1);
                } else {
                        *DPDE0BytesFrame = 64 * (dml_ceil(((Pitch * (dml_ceil((double) SwathWidth - 1, MacroTileHeight) + MacroTileHeight) * BytePerPixel) - MacroTileSizeBytes) / (8 * 2097152), 1) + 1);
                }
                ExtraDPDEBytesFrame = 128 * ((mode_lib->vba.GPUVMMaxPageTableLevels + 1) * (mode_lib->vba.HostVMMaxPageTableLevels + 1) - 3);
        } else {
                *DPDE0BytesFrame = 0;
                ExtraDPDEBytesFrame = 0;
        }

        PDEAndMetaPTEBytesFrame = *MetaPTEBytesFrame + MPDEBytesFrame + *DPDE0BytesFrame
                        + ExtraDPDEBytesFrame;

        if (HostVMEnable == true) {
                PDEAndMetaPTEBytesFrame = PDEAndMetaPTEBytesFrame * (1 + 8 * (HostVMMaxPageTableLevels - HostVMCachedPageTableLevels));
        }

        if (GPUVMEnable == true) {
                double FractionOfPTEReturnDrop;

                if (SurfaceTiling == dm_sw_linear) {
                        PixelPTEReqHeightPTEs = 1;
                        *PixelPTEReqHeight = 1;
                        *PixelPTEReqWidth = 8.0 * VMMPageSize / BytePerPixel;
                        *PTERequestSize = 64;
                        FractionOfPTEReturnDrop = 0;
                } else if (MacroTileSizeBytes == 4096) {
                        PixelPTEReqHeightPTEs = 1;
                        *PixelPTEReqHeight = MacroTileHeight;
                        *PixelPTEReqWidth = 8 * *MacroTileWidth;
                        *PTERequestSize = 64;
                        if (ScanDirection == dm_horz)
                                FractionOfPTEReturnDrop = 0;
                        else
                                FractionOfPTEReturnDrop = 7.0 / 8;
                } else if (VMMPageSize == 4096 && MacroTileSizeBytes > 4096) {
                        PixelPTEReqHeightPTEs = 16;
                        *PixelPTEReqHeight = 16 * BlockHeight256Bytes;
                        *PixelPTEReqWidth = 16 * BlockWidth256Bytes;
                        *PTERequestSize = 128;
                        FractionOfPTEReturnDrop = 0;
                } else {
                        PixelPTEReqHeightPTEs = 1;
                        *PixelPTEReqHeight = MacroTileHeight;
                        *PixelPTEReqWidth = 8 * *MacroTileWidth;
                        *PTERequestSize = 64;
                        FractionOfPTEReturnDrop = 0;
                }

                if (SurfaceTiling == dm_sw_linear) {
                        *dpte_row_height = dml_min(128,
                                        1 << (unsigned int) dml_floor(
                                                dml_log2(
                                                        (double) PTEBufferSizeInRequests * *PixelPTEReqWidth / Pitch),
                                                1));
                        *dpte_row_width_ub = (dml_ceil((double) (Pitch * *dpte_row_height - 1) / *PixelPTEReqWidth, 1) + 1) * *PixelPTEReqWidth;
                        *PixelPTEBytesPerRow = *dpte_row_width_ub / *PixelPTEReqWidth * *PTERequestSize;
                } else if (ScanDirection == dm_horz) {
                        *dpte_row_height = *PixelPTEReqHeight;
                        *dpte_row_width_ub = (dml_ceil((double) (SwathWidth - 1) / *PixelPTEReqWidth, 1) + 1) * *PixelPTEReqWidth;
                        *PixelPTEBytesPerRow = *dpte_row_width_ub / *PixelPTEReqWidth * *PTERequestSize;
                } else {
                        *dpte_row_height = dml_min(*PixelPTEReqWidth, *MacroTileWidth);
                        *dpte_row_width_ub = (dml_ceil((double) (SwathWidth - 1) / *PixelPTEReqHeight, 1) + 1) * *PixelPTEReqHeight;
                        *PixelPTEBytesPerRow = *dpte_row_width_ub / *PixelPTEReqHeight * *PTERequestSize;
                }
                if (*PixelPTEBytesPerRow * (1 - FractionOfPTEReturnDrop)
                                <= 64 * PTEBufferSizeInRequests) {
                        *PTEBufferSizeNotExceeded = true;
                } else {
                        *PTEBufferSizeNotExceeded = false;
                }
        } else {
                *PixelPTEBytesPerRow = 0;
                *PTEBufferSizeNotExceeded = true;
        }
        dml_print("DML: vm_bytes = meta_pte_bytes_per_frame (per_pipe) = MetaPTEBytesFrame = : %d\n", *MetaPTEBytesFrame);

        if (HostVMEnable == true) {
                *PixelPTEBytesPerRow = *PixelPTEBytesPerRow * (1 + 8 * (HostVMMaxPageTableLevels - HostVMCachedPageTableLevels));
        }

        if (HostVMEnable == true) {
                *vm_group_bytes = 512;
                *dpte_group_bytes = 512;
        } else if (GPUVMEnable == true) {
                *vm_group_bytes = 2048;
                if (SurfaceTiling != dm_sw_linear && PixelPTEReqHeightPTEs == 1 && ScanDirection != dm_horz) {
                        *dpte_group_bytes = 512;
                } else {
                        *dpte_group_bytes = 2048;
                }
        } else {
                *vm_group_bytes = 0;
                *dpte_group_bytes = 0;
        }

        return PDEAndMetaPTEBytesFrame;
}

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[0],
                                        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[0][0],
                                        &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][0] == 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[0],
                                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[0] * 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[0],
                        mode_lib->vba.SwathHeightY[k],
                        mode_lib->vba.SwathHeightC[k],
                        &locals->DETBufferSizeY[k],
                        &locals->DETBufferSizeC[k]);

                locals->LinesInDETY[k] = (double)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;
}

static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib)
{
        // Display Pipe Configuration
        double BytePerPixDETY;
        double BytePerPixDETC;
        double Read256BytesBlockHeightY;
        double Read256BytesBlockHeightC;
        double Read256BytesBlockWidthY;
        double Read256BytesBlockWidthC;
        double MaximumSwathHeightY;
        double MaximumSwathHeightC;
        double MinimumSwathHeightY;
        double MinimumSwathHeightC;
        double SwathWidth;
        double SwathWidthGranularityY;
        double SwathWidthGranularityC;
        double RoundedUpMaxSwathSizeBytesY;
        double RoundedUpMaxSwathSizeBytesC;
        unsigned int j, k;

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

                if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) {
                        BytePerPixDETY = 8;
                        BytePerPixDETC = 0;
                } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) {
                        BytePerPixDETY = 4;
                        BytePerPixDETC = 0;
                } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16) {
                        BytePerPixDETY = 2;
                        BytePerPixDETC = 0;
                } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8) {
                        BytePerPixDETY = 1;
                        BytePerPixDETC = 0;
                } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) {
                        BytePerPixDETY = 1;
                        BytePerPixDETC = 2;
                } else {
                        BytePerPixDETY = 4.0 / 3.0;
                        BytePerPixDETC = 8.0 / 3.0;
                }

                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)) {
                        if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) {
                                Read256BytesBlockHeightY = 1;
                        } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) {
                                Read256BytesBlockHeightY = 4;
                        } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32
                                        || mode_lib->vba.SourcePixelFormat[k] == dm_444_16) {
                                Read256BytesBlockHeightY = 8;
                        } else {
                                Read256BytesBlockHeightY = 16;
                        }
                        Read256BytesBlockWidthY = 256 / dml_ceil(BytePerPixDETY, 1)
                                        / Read256BytesBlockHeightY;
                        Read256BytesBlockHeightC = 0;
                        Read256BytesBlockWidthC = 0;
                } else {
                        if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) {
                                Read256BytesBlockHeightY = 1;
                                Read256BytesBlockHeightC = 1;
                        } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) {
                                Read256BytesBlockHeightY = 16;
                                Read256BytesBlockHeightC = 8;
                        } else {
                                Read256BytesBlockHeightY = 8;
                                Read256BytesBlockHeightC = 8;
                        }
                        Read256BytesBlockWidthY = 256 / dml_ceil(BytePerPixDETY, 1)
                                        / Read256BytesBlockHeightY;
                        Read256BytesBlockWidthC = 256 / dml_ceil(BytePerPixDETC, 2)
                                        / Read256BytesBlockHeightC;
                }

                if (mode_lib->vba.SourceScan[k] == dm_horz) {
                        MaximumSwathHeightY = Read256BytesBlockHeightY;
                        MaximumSwathHeightC = Read256BytesBlockHeightC;
                } else {
                        MaximumSwathHeightY = Read256BytesBlockWidthY;
                        MaximumSwathHeightC = Read256BytesBlockWidthC;
                }

                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)) {
                        if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear
                                        || (mode_lib->vba.SourcePixelFormat[k] == dm_444_64
                                                        && (mode_lib->vba.SurfaceTiling[k]
                                                                        == dm_sw_4kb_s
                                                                        || mode_lib->vba.SurfaceTiling[k]
                                                                                        == dm_sw_4kb_s_x
                                                                        || mode_lib->vba.SurfaceTiling[k]
                                                                                        == dm_sw_64kb_s
                                                                        || mode_lib->vba.SurfaceTiling[k]
                                                                                        == dm_sw_64kb_s_t
                                                                        || mode_lib->vba.SurfaceTiling[k]
                                                                                        == dm_sw_64kb_s_x
                                                                        || mode_lib->vba.SurfaceTiling[k]
                                                                                        == dm_sw_var_s
                                                                        || mode_lib->vba.SurfaceTiling[k]
                                                                                        == dm_sw_var_s_x)
                                                        && mode_lib->vba.SourceScan[k] == dm_horz)) {
                                MinimumSwathHeightY = MaximumSwathHeightY;
                        } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8
                                        && mode_lib->vba.SourceScan[k] != dm_horz) {
                                MinimumSwathHeightY = MaximumSwathHeightY;
                        } else {
                                MinimumSwathHeightY = MaximumSwathHeightY / 2.0;
                        }
                        MinimumSwathHeightC = MaximumSwathHeightC;
                } else {
                        if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) {
                                MinimumSwathHeightY = MaximumSwathHeightY;
                                MinimumSwathHeightC = MaximumSwathHeightC;
                        } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8
                                        && mode_lib->vba.SourceScan[k] == dm_horz) {
                                MinimumSwathHeightY = MaximumSwathHeightY / 2.0;
                                MinimumSwathHeightC = MaximumSwathHeightC;
                        } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10
                                        && mode_lib->vba.SourceScan[k] == dm_horz) {
                                MinimumSwathHeightC = MaximumSwathHeightC / 2.0;
                                MinimumSwathHeightY = MaximumSwathHeightY;
                        } else {
                                MinimumSwathHeightY = MaximumSwathHeightY;
                                MinimumSwathHeightC = MaximumSwathHeightC;
                        }
                }

                if (mode_lib->vba.SourceScan[k] == dm_horz) {
                        SwathWidth = mode_lib->vba.ViewportWidth[k];
                } else {
                        SwathWidth = 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) {
                        SwathWidth = dml_min(
                                        SwathWidth,
                                        mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k]);
                } else {
                        SwathWidth = SwathWidth / mode_lib->vba.DPPPerPlane[k];
                }

                SwathWidthGranularityY = 256 / dml_ceil(BytePerPixDETY, 1) / MaximumSwathHeightY;
                RoundedUpMaxSwathSizeBytesY = (dml_ceil(
                                (double) (SwathWidth - 1),
                                SwathWidthGranularityY) + SwathWidthGranularityY) * BytePerPixDETY
                                * MaximumSwathHeightY;
                if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) {
                        RoundedUpMaxSwathSizeBytesY = dml_ceil(RoundedUpMaxSwathSizeBytesY, 256)
                                        + 256;
                }
                if (MaximumSwathHeightC > 0) {
                        SwathWidthGranularityC = 256.0 / dml_ceil(BytePerPixDETC, 2)
                                        / MaximumSwathHeightC;
                        RoundedUpMaxSwathSizeBytesC = (dml_ceil(
                                        (double) (SwathWidth / 2.0 - 1),
                                        SwathWidthGranularityC) + SwathWidthGranularityC)
                                        * BytePerPixDETC * MaximumSwathHeightC;
                        if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) {
                                RoundedUpMaxSwathSizeBytesC = dml_ceil(
                                                RoundedUpMaxSwathSizeBytesC,
                                                256) + 256;
                        }
                } else
                        RoundedUpMaxSwathSizeBytesC = 0.0;

                if (RoundedUpMaxSwathSizeBytesY + RoundedUpMaxSwathSizeBytesC
                                <= mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2.0) {
                        mode_lib->vba.SwathHeightY[k] = MaximumSwathHeightY;
                        mode_lib->vba.SwathHeightC[k] = MaximumSwathHeightC;
                } else {
                        mode_lib->vba.SwathHeightY[k] = MinimumSwathHeightY;
                        mode_lib->vba.SwathHeightC[k] = MinimumSwathHeightC;
                }

                CalculateDETBufferSize(
                                mode_lib->vba.DETBufferSizeInKByte[0],
                                mode_lib->vba.SwathHeightY[k],
                                mode_lib->vba.SwathHeightC[k],
                                &mode_lib->vba.DETBufferSizeY[k],
                                &mode_lib->vba.DETBufferSizeC[k]);
        }
}

static double CalculateTWait(
                unsigned int PrefetchMode,
                double DRAMClockChangeLatency,
                double UrgentLatency,
                double SREnterPlusExitTime)
{
        if (PrefetchMode == 0) {
                return dml_max(
                                DRAMClockChangeLatency + UrgentLatency,
                                dml_max(SREnterPlusExitTime, UrgentLatency));
        } else if (PrefetchMode == 1) {
                return dml_max(SREnterPlusExitTime, UrgentLatency);
        } else {
                return UrgentLatency;
        }
}

static double CalculateRemoteSurfaceFlipDelay(
                struct display_mode_lib *mode_lib,
                double VRatio,
                double SwathWidth,
                double Bpp,
                double LineTime,
                double XFCTSlvVupdateOffset,
                double XFCTSlvVupdateWidth,
                double XFCTSlvVreadyOffset,
                double XFCXBUFLatencyTolerance,
                double XFCFillBWOverhead,
                double XFCSlvChunkSize,
                double XFCBusTransportTime,
                double TCalc,
                double TWait,
                double *SrcActiveDrainRate,
                double *TInitXFill,
                double *TslvChk)
{
        double TSlvSetup, AvgfillRate, result;

        *SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime;
        TSlvSetup = XFCTSlvVupdateOffset + XFCTSlvVupdateWidth + XFCTSlvVreadyOffset;
        *TInitXFill = XFCXBUFLatencyTolerance / (1 + XFCFillBWOverhead / 100);
        AvgfillRate = *SrcActiveDrainRate * (1 + XFCFillBWOverhead / 100);
        *TslvChk = XFCSlvChunkSize / AvgfillRate;
        dml_print(
                        "DML::CalculateRemoteSurfaceFlipDelay: SrcActiveDrainRate: %f\n",
                        *SrcActiveDrainRate);
        dml_print("DML::CalculateRemoteSurfaceFlipDelay: TSlvSetup: %f\n", TSlvSetup);
        dml_print("DML::CalculateRemoteSurfaceFlipDelay: TInitXFill: %f\n", *TInitXFill);
        dml_print("DML::CalculateRemoteSurfaceFlipDelay: AvgfillRate: %f\n", AvgfillRate);
        dml_print("DML::CalculateRemoteSurfaceFlipDelay: TslvChk: %f\n", *TslvChk);
        result = 2 * XFCBusTransportTime + TSlvSetup + TCalc + TWait + *TslvChk + *TInitXFill; // TODO: This doesn't seem to match programming guide
        dml_print("DML::CalculateRemoteSurfaceFlipDelay: RemoteSurfaceFlipDelay: %f\n", result);
        return result;
}

static double CalculateWriteBackDelay(
                enum source_format_class WritebackPixelFormat,
                double WritebackHRatio,
                double WritebackVRatio,
                unsigned int WritebackLumaHTaps,
                unsigned int WritebackLumaVTaps,
                unsigned int WritebackChromaHTaps,
                unsigned int WritebackChromaVTaps,
                unsigned int WritebackDestinationWidth)
{
        double CalculateWriteBackDelay =
                        dml_max(
                                        dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio,
                                        WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1)
                                                        * dml_ceil(
                                                                        WritebackDestinationWidth
                                                                                        / 4.0,
                                                                        1)
                                                        + dml_ceil(1.0 / WritebackVRatio, 1)
                                                                        * (dml_ceil(
                                                                                        WritebackLumaVTaps
                                                                                                        / 4.0,
                                                                                        1) + 4));

        if (WritebackPixelFormat != dm_444_32) {
                CalculateWriteBackDelay =
                                dml_max(
                                                CalculateWriteBackDelay,
                                                dml_max(
                                                                dml_ceil(
                                                                                WritebackChromaHTaps
                                                                                                / 2.0,
                                                                                1)
                                                                                / (2
                                                                                                * WritebackHRatio),
                                                                WritebackChromaVTaps
                                                                                * dml_ceil(
                                                                                                1
                                                                                                                / (2
                                                                                                                                * WritebackVRatio),
                                                                                                1)
                                                                                * dml_ceil(
                                                                                                WritebackDestinationWidth
                                                                                                                / 2.0
                                                                                                                / 2.0,
                                                                                                1)
                                                                                + dml_ceil(
                                                                                                1
                                                                                                                / (2
                                                                                                                                * WritebackVRatio),
                                                                                                1)
                                                                                                * (dml_ceil(
                                                                                                                WritebackChromaVTaps
                                                                                                                                / 4.0,
                                                                                                                1)
                                                                                                                + 4)));
        }
        return CalculateWriteBackDelay;
}

static void CalculateActiveRowBandwidth(
                bool GPUVMEnable,
                enum source_format_class SourcePixelFormat,
                double VRatio,
                bool DCCEnable,
                double LineTime,
                unsigned int MetaRowByteLuma,
                unsigned int MetaRowByteChroma,
                unsigned int meta_row_height_luma,
                unsigned int meta_row_height_chroma,
                unsigned int PixelPTEBytesPerRowLuma,
                unsigned int PixelPTEBytesPerRowChroma,
                unsigned int dpte_row_height_luma,
                unsigned int dpte_row_height_chroma,
                double *meta_row_bw,
                double *dpte_row_bw)
{
        if (DCCEnable != true) {
                *meta_row_bw = 0;
        } else if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) {
                *meta_row_bw = VRatio * MetaRowByteLuma / (meta_row_height_luma * LineTime)
                                + VRatio / 2 * MetaRowByteChroma
                                                / (meta_row_height_chroma * LineTime);
        } else {
                *meta_row_bw = VRatio * MetaRowByteLuma / (meta_row_height_luma * LineTime);
        }

        if (GPUVMEnable != true) {
                *dpte_row_bw = 0;
        } else if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) {
                *dpte_row_bw = VRatio * PixelPTEBytesPerRowLuma / (dpte_row_height_luma * LineTime)
                                + VRatio / 2 * PixelPTEBytesPerRowChroma
                                                / (dpte_row_height_chroma * LineTime);
        } else {
                *dpte_row_bw = VRatio * PixelPTEBytesPerRowLuma / (dpte_row_height_luma * LineTime);
        }
}

static void CalculateFlipSchedule(
                struct display_mode_lib *mode_lib,
                double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
                double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly,
                double UrgentExtraLatency,
                double UrgentLatency,
                unsigned int GPUVMMaxPageTableLevels,
                bool HostVMEnable,
                unsigned int HostVMMaxPageTableLevels,
                unsigned int HostVMCachedPageTableLevels,
                bool GPUVMEnable,
                double PDEAndMetaPTEBytesPerFrame,
                double MetaRowBytes,
                double DPTEBytesPerRow,
                double BandwidthAvailableForImmediateFlip,
                unsigned int TotImmediateFlipBytes,
                enum source_format_class SourcePixelFormat,
                double LineTime,
                double VRatio,
                double Tno_bw,
                bool DCCEnable,
                unsigned int dpte_row_height,
                unsigned int meta_row_height,
                unsigned int dpte_row_height_chroma,
                unsigned int meta_row_height_chroma,
                double *DestinationLinesToRequestVMInImmediateFlip,
                double *DestinationLinesToRequestRowInImmediateFlip,
                double *final_flip_bw,
                bool *ImmediateFlipSupportedForPipe)
{
        double min_row_time = 0.0;
        unsigned int HostVMDynamicLevels;
        double TimeForFetchingMetaPTEImmediateFlip;
        double TimeForFetchingRowInVBlankImmediateFlip;
        double ImmediateFlipBW = 1.0;
        double HostVMInefficiencyFactor;
        double VRatioClamped;

        if (GPUVMEnable == true && HostVMEnable == true) {
                HostVMInefficiencyFactor =
                                PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData
                                                / PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly;
                HostVMDynamicLevels = HostVMMaxPageTableLevels - HostVMCachedPageTableLevels;
        } else {
                HostVMInefficiencyFactor = 1;
                HostVMDynamicLevels = 0;
        }

        ImmediateFlipBW = (PDEAndMetaPTEBytesPerFrame + MetaRowBytes + DPTEBytesPerRow)
                        * BandwidthAvailableForImmediateFlip / TotImmediateFlipBytes;

        if (GPUVMEnable == true) {
                TimeForFetchingMetaPTEImmediateFlip = dml_max3(
                        Tno_bw + PDEAndMetaPTEBytesPerFrame * HostVMInefficiencyFactor / ImmediateFlipBW,
                        UrgentExtraLatency + UrgentLatency * (GPUVMMaxPageTableLevels * (HostVMDynamicLevels + 1) - 1),
                        LineTime / 4.0);
        } else {
                TimeForFetchingMetaPTEImmediateFlip = 0;
        }

        *DestinationLinesToRequestVMInImmediateFlip = dml_ceil(4.0 * (TimeForFetchingMetaPTEImmediateFlip / LineTime), 1) / 4.0;
        if ((GPUVMEnable == true || DCCEnable == true)) {
                TimeForFetchingRowInVBlankImmediateFlip = dml_max3((MetaRowBytes + DPTEBytesPerRow) * HostVMInefficiencyFactor / ImmediateFlipBW, UrgentLatency * (HostVMDynamicLevels + 1), LineTime / 4);
        } else {
                TimeForFetchingRowInVBlankImmediateFlip = 0;
        }

        *DestinationLinesToRequestRowInImmediateFlip = dml_ceil(4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime), 1) / 4.0;
        *final_flip_bw = dml_max(PDEAndMetaPTEBytesPerFrame * HostVMInefficiencyFactor / (*DestinationLinesToRequestVMInImmediateFlip * LineTime), (MetaRowBytes + DPTEBytesPerRow) * HostVMInefficiencyFactor / (*DestinationLinesToRequestRowInImmediateFlip * LineTime));
        VRatioClamped = (VRatio < 1.0) ? 1.0 : VRatio;
        if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) {
                if (GPUVMEnable == true && DCCEnable != true) {
                        min_row_time = dml_min(
                                        dpte_row_height * LineTime / VRatioClamped,
                                        dpte_row_height_chroma * LineTime / (VRatioClamped / 2));
                } else if (GPUVMEnable != true && DCCEnable == true) {
                        min_row_time = dml_min(
                                        meta_row_height * LineTime / VRatioClamped,
                                        meta_row_height_chroma * LineTime / (VRatioClamped / 2));
                } else {
                        min_row_time = dml_min4(
                                        dpte_row_height * LineTime / VRatioClamped,
                                        meta_row_height * LineTime / VRatioClamped,
                                        dpte_row_height_chroma * LineTime / (VRatioClamped / 2),
                                        meta_row_height_chroma * LineTime / (VRatioClamped / 2));
                }
        } else {
                if (GPUVMEnable == true && DCCEnable != true) {
                        min_row_time = dpte_row_height * LineTime / VRatioClamped;
                } else if (GPUVMEnable != true && DCCEnable == true) {
                        min_row_time = meta_row_height * LineTime / VRatioClamped;
                } else {
                        min_row_time = dml_min(
                                        dpte_row_height * LineTime / VRatioClamped,
                                        meta_row_height * LineTime / VRatioClamped);
                }
        }

        if (*DestinationLinesToRequestVMInImmediateFlip >= 32
                        || *DestinationLinesToRequestRowInImmediateFlip >= 16
                        || TimeForFetchingMetaPTEImmediateFlip + 2 * TimeForFetchingRowInVBlankImmediateFlip > min_row_time) {
                *ImmediateFlipSupportedForPipe = false;
        } else {
                *ImmediateFlipSupportedForPipe = true;
        }
}

static unsigned int TruncToValidBPP(
                double DecimalBPP,
                double DesiredBPP,
                bool DSCEnabled,
                enum output_encoder_class Output,
                enum output_format_class Format,
                unsigned int DSCInputBitPerComponent)
{
        if (Output == dm_hdmi) {
                if (Format == dm_420) {
                        if (DecimalBPP >= 18 && (DesiredBPP == 0 || DesiredBPP == 18))
                                return 18;
                        else if (DecimalBPP >= 15 && (DesiredBPP == 0 || DesiredBPP == 15))
                                return 15;
                        else if (DecimalBPP >= 12 && (DesiredBPP == 0 || DesiredBPP == 12))
                                return 12;
                        else
                                return BPP_INVALID;
                } else if (Format == dm_444) {
                        if (DecimalBPP >= 36 && (DesiredBPP == 0 || DesiredBPP == 36))
                                return 36;
                        else if (DecimalBPP >= 30 && (DesiredBPP == 0 || DesiredBPP == 30))
                                return 30;
                        else if (DecimalBPP >= 24 && (DesiredBPP == 0 || DesiredBPP == 24))
                                return 24;
                        else if (DecimalBPP >= 18 && (DesiredBPP == 0 || DesiredBPP == 18))
                                return 18;
                        else
                                return BPP_INVALID;
                } else {
                        if (DecimalBPP / 1.5 >= 24 && (DesiredBPP == 0 || DesiredBPP == 24))
                                return 24;
                        else if (DecimalBPP / 1.5 >= 20 && (DesiredBPP == 0 || DesiredBPP == 20))
                                return 20;
                        else if (DecimalBPP / 1.5 >= 16 && (DesiredBPP == 0 || DesiredBPP == 16))
                                return 16;
                        else
                                return BPP_INVALID;
                }
        } else {
                if (DSCEnabled) {
                        if (Format == dm_420) {
                                if (DesiredBPP == 0) {
                                        if (DecimalBPP < 6)
                                                return BPP_INVALID;
                                        else if (DecimalBPP >= 1.5 * DSCInputBitPerComponent - 1.0 / 16.0)
                                                return 1.5 * DSCInputBitPerComponent - 1.0 / 16.0;
                                        else
                                                return dml_floor(16 * DecimalBPP, 1) / 16.0;
                                } else {
                                        if (DecimalBPP < 6
                                                        || DesiredBPP < 6
                                                        || DesiredBPP > 1.5 * DSCInputBitPerComponent - 1.0 / 16.0
                                                        || DecimalBPP < DesiredBPP) {
                                                return BPP_INVALID;
                                        } else {
                                                return DesiredBPP;
                                        }
                                }
                        } else if (Format == dm_n422) {
                                if (DesiredBPP == 0) {
                                        if (DecimalBPP < 7)
                                                return BPP_INVALID;
                                        else if (DecimalBPP >= 2 * DSCInputBitPerComponent - 1.0 / 16.0)
                                                return 2 * DSCInputBitPerComponent - 1.0 / 16.0;
                                        else
                                                return dml_floor(16 * DecimalBPP, 1) / 16.0;
                                } else {
                                        if (DecimalBPP < 7
                                                        || DesiredBPP < 7
                                                        || DesiredBPP > 2 * DSCInputBitPerComponent - 1.0 / 16.0
                                                        || DecimalBPP < DesiredBPP) {
                                                return BPP_INVALID;
                                        } else {
                                                return DesiredBPP;
                                        }
                                }
                        } else {
                                if (DesiredBPP == 0) {
                                        if (DecimalBPP < 8)
                                                return BPP_INVALID;
                                        else if (DecimalBPP >= 3 * DSCInputBitPerComponent - 1.0 / 16.0)
                                                return 3 * DSCInputBitPerComponent - 1.0 / 16.0;
                                        else
                                                return dml_floor(16 * DecimalBPP, 1) / 16.0;
                                } else {
                                        if (DecimalBPP < 8
                                                        || DesiredBPP < 8
                                                        || DesiredBPP > 3 * DSCInputBitPerComponent - 1.0 / 16.0
                                                        || DecimalBPP < DesiredBPP) {
                                                return BPP_INVALID;
                                        } else {
                                                return DesiredBPP;
                                        }
                                }
                        }
                } else if (Format == dm_420) {
                        if (DecimalBPP >= 18 && (DesiredBPP == 0 || DesiredBPP == 18))
                                return 18;
                        else if (DecimalBPP >= 15 && (DesiredBPP == 0 || DesiredBPP == 15))
                                return 15;
                        else if (DecimalBPP >= 12 && (DesiredBPP == 0 || DesiredBPP == 12))
                                return 12;
                        else
                                return BPP_INVALID;
                } else if (Format == dm_s422 || Format == dm_n422) {
                        if (DecimalBPP >= 24 && (DesiredBPP == 0 || DesiredBPP == 24))
                                return 24;
                        else if (DecimalBPP >= 20 && (DesiredBPP == 0 || DesiredBPP == 20))
                                return 20;
                        else if (DecimalBPP >= 16 && (DesiredBPP == 0 || DesiredBPP == 16))
                                return 16;
                        else
                                return BPP_INVALID;
                } else {
                        if (DecimalBPP >= 36 && (DesiredBPP == 0 || DesiredBPP == 36))
                                return 36;
                        else if (DecimalBPP >= 30 && (DesiredBPP == 0 || DesiredBPP == 30))
                                return 30;
                        else if (DecimalBPP >= 24 && (DesiredBPP == 0 || DesiredBPP == 24))
                                return 24;
                        else if (DecimalBPP >= 18 && (DesiredBPP == 0 || DesiredBPP == 18))
                                return 18;
                        else
                                return BPP_INVALID;
                }
        }
}


static noinline void CalculatePrefetchSchedulePerPlane(
                struct display_mode_lib *mode_lib,
                int i,
                unsigned j,
                unsigned k)
{
        struct vba_vars_st *locals = &mode_lib->vba;
        Pipe myPipe;
        HostVM myHostVM;

        if (mode_lib->vba.XFCEnabled[k] == true) {
                mode_lib->vba.XFCRemoteSurfaceFlipDelay =
                                CalculateRemoteSurfaceFlipDelay(
                                                mode_lib,
                                                mode_lib->vba.VRatio[k],
                                                locals->SwathWidthYThisState[k],
                                                dml_ceil(locals->BytePerPixelInDETY[k], 1.0),
                                                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.TimeCalc,
                                                mode_lib->vba.TWait,
                                                &mode_lib->vba.SrcActiveDrainRate,
                                                &mode_lib->vba.TInitXFill,
                                                &mode_lib->vba.TslvChk);
        } else {
                mode_lib->vba.XFCRemoteSurfaceFlipDelay = 0.0;
        }

        myPipe.DPPCLK = locals->RequiredDPPCLK[i][j][k];
        myPipe.DISPCLK = locals->RequiredDISPCLK[i][j];
        myPipe.PixelClock = mode_lib->vba.PixelClock[k];
        myPipe.DCFCLKDeepSleep = mode_lib->vba.ProjectedDCFCLKDeepSleep[0][0];
        myPipe.DPPPerPlane = locals->NoOfDPP[i][j][k];
        myPipe.ScalerEnabled = mode_lib->vba.ScalerEnabled[k];
        myPipe.SourceScan = mode_lib->vba.SourceScan[k];
        myPipe.BlockWidth256BytesY = locals->Read256BlockWidthY[k];
        myPipe.BlockHeight256BytesY = locals->Read256BlockHeightY[k];
        myPipe.BlockWidth256BytesC = locals->Read256BlockWidthC[k];
        myPipe.BlockHeight256BytesC = locals->Read256BlockHeightC[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.IsErrorResult[i][j][k] = CalculatePrefetchSchedule(
                        mode_lib,
                        mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
                        mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly,
                        &myPipe,
                        locals->DSCDelayPerState[i][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,
                        locals->SwathWidthYThisState[k] / mode_lib->vba.HRatio[k],
                        mode_lib->vba.OutputFormat[k],
                        mode_lib->vba.MaxInterDCNTileRepeaters,
                        dml_min(mode_lib->vba.MaxVStartup, locals->MaximumVStartup[0][0][k]),
                        locals->MaximumVStartup[0][0][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.ExtraLatency,
                        mode_lib->vba.TimeCalc,
                        locals->PDEAndMetaPTEBytesPerFrame[0][0][k],
                        locals->MetaRowBytes[0][0][k],
                        locals->DPTEBytesPerRow[0][0][k],
                        locals->PrefetchLinesY[0][0][k],
                        locals->SwathWidthYThisState[k],
                        locals->BytePerPixelInDETY[k],
                        locals->PrefillY[k],
                        locals->MaxNumSwY[k],
                        locals->PrefetchLinesC[0][0][k],
                        locals->BytePerPixelInDETC[k],
                        locals->PrefillC[k],
                        locals->MaxNumSwC[k],
                        locals->SwathHeightYThisState[k],
                        locals->SwathHeightCThisState[k],
                        mode_lib->vba.TWait,
                        mode_lib->vba.XFCEnabled[k],
                        mode_lib->vba.XFCRemoteSurfaceFlipDelay,
                        mode_lib->vba.ProgressiveToInterlaceUnitInOPP,
                        &locals->dst_x_after_scaler,
                        &locals->dst_y_after_scaler,
                        &locals->LineTimesForPrefetch[k],
                        &locals->PrefetchBW[k],
                        &locals->LinesForMetaPTE[k],
                        &locals->LinesForMetaAndDPTERow[k],
                        &locals->VRatioPreY[i][j][k],
                        &locals->VRatioPreC[i][j][k],
                        &locals->RequiredPrefetchPixelDataBWLuma[i][j][k],
                        &locals->RequiredPrefetchPixelDataBWChroma[i][j][k],
                        &locals->VStartupRequiredWhenNotEnoughTimeForDynamicMetadata,
                        &locals->Tno_bw[k],
                        &locals->prefetch_vmrow_bw[k],
                        locals->swath_width_luma_ub,
                        locals->swath_width_chroma_ub,
                        &mode_lib->vba.VUpdateOffsetPix[k],
                        &mode_lib->vba.VUpdateWidthPix[k],
                        &mode_lib->vba.VReadyOffsetPix[k]);
}
void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib)
{
        struct vba_vars_st *locals = &mode_lib->vba;

        int i;
        unsigned int j, k, m;

        /*MODE SUPPORT, VOLTAGE STATE AND SOC CONFIGURATION*/

        /*Scale Ratio, taps Support Check*/

        mode_lib->vba.ScaleRatioAndTapsSupport = true;
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (mode_lib->vba.ScalerEnabled[k] == false
                                && ((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_mono_16
                                                && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8)
                                                || mode_lib->vba.HRatio[k] != 1.0
                                                || mode_lib->vba.htaps[k] != 1.0
                                                || mode_lib->vba.VRatio[k] != 1.0
                                                || mode_lib->vba.vtaps[k] != 1.0)) {
                        mode_lib->vba.ScaleRatioAndTapsSupport = false;
                } else if (mode_lib->vba.vtaps[k] < 1.0 || mode_lib->vba.vtaps[k] > 8.0
                                || mode_lib->vba.htaps[k] < 1.0 || mode_lib->vba.htaps[k] > 8.0
                                || (mode_lib->vba.htaps[k] > 1.0
                                                && (mode_lib->vba.htaps[k] % 2) == 1)
                                || mode_lib->vba.HRatio[k] > mode_lib->vba.MaxHSCLRatio
                                || mode_lib->vba.VRatio[k] > mode_lib->vba.MaxVSCLRatio
                                || mode_lib->vba.HRatio[k] > mode_lib->vba.htaps[k]
                                || mode_lib->vba.VRatio[k] > mode_lib->vba.vtaps[k]
                                || (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_mono_16
                                                && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8
                                                && (mode_lib->vba.HRatio[k] / 2.0
                                                                > mode_lib->vba.HTAPsChroma[k]
                                                                || mode_lib->vba.VRatio[k] / 2.0
                                                                                > mode_lib->vba.VTAPsChroma[k]))) {
                        mode_lib->vba.ScaleRatioAndTapsSupport = false;
                }
        }
        /*Source Format, Pixel Format and Scan Support Check*/

        mode_lib->vba.SourceFormatPixelAndScanSupport = true;
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if ((mode_lib->vba.SurfaceTiling[k] == dm_sw_linear
                                && mode_lib->vba.SourceScan[k] != dm_horz)
                                || ((mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d
                                                || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d_x
                                                || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d
                                                || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_t
                                                || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_x
                                                || mode_lib->vba.SurfaceTiling[k] == dm_sw_var_d
                                                || mode_lib->vba.SurfaceTiling[k] == dm_sw_var_d_x)
                                                && mode_lib->vba.SourcePixelFormat[k] != dm_444_64)
                                || (mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_r_x
                                                && (mode_lib->vba.SourcePixelFormat[k] == dm_mono_8
                                                                || mode_lib->vba.SourcePixelFormat[k]
                                                                                == dm_420_8
                                                                || mode_lib->vba.SourcePixelFormat[k]
                                                                                == dm_420_10))
                                || (((mode_lib->vba.SurfaceTiling[k] == dm_sw_gfx7_2d_thin_gl
                                                || mode_lib->vba.SurfaceTiling[k]
                                                                == dm_sw_gfx7_2d_thin_l_vp)
                                                && !((mode_lib->vba.SourcePixelFormat[k]
                                                                == dm_444_64
                                                                || mode_lib->vba.SourcePixelFormat[k]
                                                                                == dm_444_32)
                                                                && mode_lib->vba.SourceScan[k]
                                                                                == dm_horz
                                                                && mode_lib->vba.SupportGFX7CompatibleTilingIn32bppAnd64bpp
                                                                                == true
                                                                && mode_lib->vba.DCCEnable[k]
                                                                                == false))
                                                || (mode_lib->vba.DCCEnable[k] == true
                                                                && (mode_lib->vba.SurfaceTiling[k]
                                                                                == dm_sw_linear
                                                                                || mode_lib->vba.SourcePixelFormat[k]
                                                                                                == dm_420_8
                                                                                || mode_lib->vba.SourcePixelFormat[k]
                                                                                                == dm_420_10)))) {
                        mode_lib->vba.SourceFormatPixelAndScanSupport = false;
                }
        }
        /*Bandwidth Support Check*/

        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) {
                        locals->BytePerPixelInDETY[k] = 8.0;
                        locals->BytePerPixelInDETC[k] = 0.0;
                } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) {
                        locals->BytePerPixelInDETY[k] = 4.0;
                        locals->BytePerPixelInDETC[k] = 0.0;
                } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16
                                || mode_lib->vba.SourcePixelFormat[k] == dm_mono_16) {
                        locals->BytePerPixelInDETY[k] = 2.0;
                        locals->BytePerPixelInDETC[k] = 0.0;
                } else if (mode_lib->vba.SourcePixelFormat[k] == dm_mono_8) {
                        locals->BytePerPixelInDETY[k] = 1.0;
                        locals->BytePerPixelInDETC[k] = 0.0;
                } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) {
                        locals->BytePerPixelInDETY[k] = 1.0;
                        locals->BytePerPixelInDETC[k] = 2.0;
                } else {
                        locals->BytePerPixelInDETY[k] = 4.0 / 3;
                        locals->BytePerPixelInDETC[k] = 8.0 / 3;
                }
                if (mode_lib->vba.SourceScan[k] == dm_horz) {
                        locals->SwathWidthYSingleDPP[k] = mode_lib->vba.ViewportWidth[k];
                } else {
                        locals->SwathWidthYSingleDPP[k] = mode_lib->vba.ViewportHeight[k];
                }
        }
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                locals->ReadBandwidthLuma[k] = locals->SwathWidthYSingleDPP[k] * dml_ceil(locals->BytePerPixelInDETY[k], 1.0)
                                / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) * mode_lib->vba.VRatio[k];
                locals->ReadBandwidthChroma[k] = locals->SwathWidthYSingleDPP[k] / 2 * dml_ceil(locals->BytePerPixelInDETC[k], 2.0)
                                / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) * mode_lib->vba.VRatio[k] / 2.0;
                locals->ReadBandwidth[k] = locals->ReadBandwidthLuma[k] + locals->ReadBandwidthChroma[k];
        }
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (mode_lib->vba.WritebackEnable[k] == true
                                && mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) {
                        locals->WriteBandwidth[k] = mode_lib->vba.WritebackDestinationWidth[k]
                                        * mode_lib->vba.WritebackDestinationHeight[k]
                                        / (mode_lib->vba.WritebackSourceHeight[k]
                                                        * mode_lib->vba.HTotal[k]
                                                        / mode_lib->vba.PixelClock[k]) * 4.0;
                } else if (mode_lib->vba.WritebackEnable[k] == true
                                && mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) {
                        locals->WriteBandwidth[k] = mode_lib->vba.WritebackDestinationWidth[k]
                                        * mode_lib->vba.WritebackDestinationHeight[k]
                                        / (mode_lib->vba.WritebackSourceHeight[k]
                                                        * mode_lib->vba.HTotal[k]
                                                        / mode_lib->vba.PixelClock[k]) * 3.0;
                } else if (mode_lib->vba.WritebackEnable[k] == true) {
                        locals->WriteBandwidth[k] = mode_lib->vba.WritebackDestinationWidth[k]
                                        * mode_lib->vba.WritebackDestinationHeight[k]
                                        / (mode_lib->vba.WritebackSourceHeight[k]
                                                        * mode_lib->vba.HTotal[k]
                                                        / mode_lib->vba.PixelClock[k]) * 1.5;
                } else {
                        locals->WriteBandwidth[k] = 0.0;
                }
        }
        mode_lib->vba.DCCEnabledInAnyPlane = false;
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (mode_lib->vba.DCCEnable[k] == true) {
                        mode_lib->vba.DCCEnabledInAnyPlane = true;
                }
        }
        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
                locals->IdealSDPPortBandwidthPerState[i][0] = dml_min3(
                                mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i],
                                mode_lib->vba.DRAMSpeedPerState[i] * mode_lib->vba.NumberOfChannels
                                                * mode_lib->vba.DRAMChannelWidth,
                                mode_lib->vba.FabricClockPerState[i]
                                                * mode_lib->vba.FabricDatapathToDCNDataReturn);
                if (mode_lib->vba.HostVMEnable == false) {
                        locals->ReturnBWPerState[i][0] = locals->IdealSDPPortBandwidthPerState[i][0]
                                        * mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelDataOnly / 100.0;
                } else {
                        locals->ReturnBWPerState[i][0] = locals->IdealSDPPortBandwidthPerState[i][0]
                                        * mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData / 100.0;
                }
        }
        /*Writeback Latency support check*/

        mode_lib->vba.WritebackLatencySupport = true;
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (mode_lib->vba.WritebackEnable[k] == true) {
                        if (mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) {
                                if (locals->WriteBandwidth[k]
                                                > (mode_lib->vba.WritebackInterfaceLumaBufferSize
                                                                + mode_lib->vba.WritebackInterfaceChromaBufferSize)
                                                                / mode_lib->vba.WritebackLatency) {
                                        mode_lib->vba.WritebackLatencySupport = false;
                                }
                        } else {
                                if (locals->WriteBandwidth[k]
                                                > 1.5
                                                                * dml_min(
                                                                                mode_lib->vba.WritebackInterfaceLumaBufferSize,
                                                                                2.0
                                                                                                * mode_lib->vba.WritebackInterfaceChromaBufferSize)
                                                                / mode_lib->vba.WritebackLatency) {
                                        mode_lib->vba.WritebackLatencySupport = false;
                                }
                        }
                }
        }
        /*Re-ordering Buffer Support Check*/

        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
                locals->UrgentRoundTripAndOutOfOrderLatencyPerState[i] =
                                (mode_lib->vba.RoundTripPingLatencyCycles + 32.0) / mode_lib->vba.DCFCLKPerState[i]
                                + dml_max3(mode_lib->vba.UrgentOutOfOrderReturnPerChannelPixelDataOnly,
                                                mode_lib->vba.UrgentOutOfOrderReturnPerChannelPixelMixedWithVMData,
                                                mode_lib->vba.UrgentOutOfOrderReturnPerChannelVMDataOnly)
                                        * mode_lib->vba.NumberOfChannels / locals->ReturnBWPerState[i][0];
                if ((mode_lib->vba.ROBBufferSizeInKByte - mode_lib->vba.PixelChunkSizeInKByte) * 1024.0 / locals->ReturnBWPerState[i][0]
                                > locals->UrgentRoundTripAndOutOfOrderLatencyPerState[i]) {
                        locals->ROBSupport[i][0] = true;
                } else {
                        locals->ROBSupport[i][0] = false;
                }
        }
        /*Writeback Mode Support Check*/

        mode_lib->vba.TotalNumberOfActiveWriteback = 0;
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (mode_lib->vba.WritebackEnable[k] == true) {
                        if (mode_lib->vba.ActiveWritebacksPerPlane[k] == 0)
                                mode_lib->vba.ActiveWritebacksPerPlane[k] = 1;
                        mode_lib->vba.TotalNumberOfActiveWriteback =
                                        mode_lib->vba.TotalNumberOfActiveWriteback
                                                        + mode_lib->vba.ActiveWritebacksPerPlane[k];
                }
        }
        mode_lib->vba.WritebackModeSupport = true;
        if (mode_lib->vba.TotalNumberOfActiveWriteback > mode_lib->vba.MaxNumWriteback) {
                mode_lib->vba.WritebackModeSupport = false;
        }
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (mode_lib->vba.WritebackEnable[k] == true
                                && mode_lib->vba.Writeback10bpc420Supported != true
                                && mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) {
                        mode_lib->vba.WritebackModeSupport = false;
                }
        }
        /*Writeback Scale Ratio and Taps Support Check*/

        mode_lib->vba.WritebackScaleRatioAndTapsSupport = true;
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (mode_lib->vba.WritebackEnable[k] == true) {
                        if (mode_lib->vba.WritebackLumaAndChromaScalingSupported == false
                                        && (mode_lib->vba.WritebackHRatio[k] != 1.0
                                                        || mode_lib->vba.WritebackVRatio[k] != 1.0)) {
                                mode_lib->vba.WritebackScaleRatioAndTapsSupport = false;
                        }
                        if (mode_lib->vba.WritebackHRatio[k] > mode_lib->vba.WritebackMaxHSCLRatio
                                        || mode_lib->vba.WritebackVRatio[k]
                                                        > mode_lib->vba.WritebackMaxVSCLRatio
                                        || mode_lib->vba.WritebackHRatio[k]
                                                        < mode_lib->vba.WritebackMinHSCLRatio
                                        || mode_lib->vba.WritebackVRatio[k]
                                                        < mode_lib->vba.WritebackMinVSCLRatio
                                        || mode_lib->vba.WritebackLumaHTaps[k]
                                                        > mode_lib->vba.WritebackMaxHSCLTaps
                                        || mode_lib->vba.WritebackLumaVTaps[k]
                                                        > mode_lib->vba.WritebackMaxVSCLTaps
                                        || mode_lib->vba.WritebackHRatio[k]
                                                        > mode_lib->vba.WritebackLumaHTaps[k]
                                        || mode_lib->vba.WritebackVRatio[k]
                                                        > mode_lib->vba.WritebackLumaVTaps[k]
                                        || (mode_lib->vba.WritebackLumaHTaps[k] > 2.0
                                                        && ((mode_lib->vba.WritebackLumaHTaps[k] % 2)
                                                                        == 1))
                                        || (mode_lib->vba.WritebackPixelFormat[k] != dm_444_32
                                                        && (mode_lib->vba.WritebackChromaHTaps[k]
                                                                        > mode_lib->vba.WritebackMaxHSCLTaps
                                                                        || mode_lib->vba.WritebackChromaVTaps[k]
                                                                                        > mode_lib->vba.WritebackMaxVSCLTaps
                                                                        || 2.0
                                                                                        * mode_lib->vba.WritebackHRatio[k]
                                                                                        > mode_lib->vba.WritebackChromaHTaps[k]
                                                                        || 2.0
                                                                                        * mode_lib->vba.WritebackVRatio[k]
                                                                                        > mode_lib->vba.WritebackChromaVTaps[k]
                                                                        || (mode_lib->vba.WritebackChromaHTaps[k] > 2.0
                                                                                && ((mode_lib->vba.WritebackChromaHTaps[k] % 2) == 1))))) {
                                mode_lib->vba.WritebackScaleRatioAndTapsSupport = false;
                        }
                        if (mode_lib->vba.WritebackVRatio[k] < 1.0) {
                                mode_lib->vba.WritebackLumaVExtra =
                                                dml_max(1.0 - 2.0 / dml_ceil(1.0 / mode_lib->vba.WritebackVRatio[k], 1.0), 0.0);
                        } else {
                                mode_lib->vba.WritebackLumaVExtra = -1;
                        }
                        if ((mode_lib->vba.WritebackPixelFormat[k] == dm_444_32
                                        && mode_lib->vba.WritebackLumaVTaps[k]
                                                        > (mode_lib->vba.WritebackLineBufferLumaBufferSize
                                                                        + mode_lib->vba.WritebackLineBufferChromaBufferSize)
                                                                        / 3.0
                                                                        / mode_lib->vba.WritebackDestinationWidth[k]
                                                                        - mode_lib->vba.WritebackLumaVExtra)
                                        || (mode_lib->vba.WritebackPixelFormat[k] == dm_420_8
                                                        && mode_lib->vba.WritebackLumaVTaps[k]
                                                                        > mode_lib->vba.WritebackLineBufferLumaBufferSize
                                                                                        * 8.0 / 10.0 / mode_lib->vba.WritebackDestinationWidth[k]
                                                                                        - mode_lib->vba.WritebackLumaVExtra)
                                        || (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10
                                                        && mode_lib->vba.WritebackLumaVTaps[k]
                                                                        > mode_lib->vba.WritebackLineBufferLumaBufferSize
                                                                                        * 8.0 / 10.0
                                                                                        / mode_lib->vba.WritebackDestinationWidth[k]
                                                                                        - mode_lib->vba.WritebackLumaVExtra)) {
                                mode_lib->vba.WritebackScaleRatioAndTapsSupport = false;
                        }
                        if (2.0 * mode_lib->vba.WritebackVRatio[k] < 1) {
                                mode_lib->vba.WritebackChromaVExtra = 0.0;
                        } else {
                                mode_lib->vba.WritebackChromaVExtra = -1;
                        }
                        if ((mode_lib->vba.WritebackPixelFormat[k] == dm_420_8
                                        && mode_lib->vba.WritebackChromaVTaps[k]
                                                        > mode_lib->vba.WritebackLineBufferChromaBufferSize
                                                                        * 8.0 / 10.0 / mode_lib->vba.WritebackDestinationWidth[k]
                                                                        - mode_lib->vba.WritebackChromaVExtra)
                                        || (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10
                                                        && mode_lib->vba.WritebackChromaVTaps[k]
                                                                        > mode_lib->vba.WritebackLineBufferChromaBufferSize
                                                                                        * 8.0 / 10.0
                                                                                        / mode_lib->vba.WritebackDestinationWidth[k]
                                                                                        - mode_lib->vba.WritebackChromaVExtra)) {
                                mode_lib->vba.WritebackScaleRatioAndTapsSupport = false;
                        }
                }
        }
        /*Maximum DISPCLK/DPPCLK Support check*/

        mode_lib->vba.WritebackRequiredDISPCLK = 0.0;
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (mode_lib->vba.WritebackEnable[k] == true) {
                        mode_lib->vba.WritebackRequiredDISPCLK =
                                        dml_max(
                                                        mode_lib->vba.WritebackRequiredDISPCLK,
                                                        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 - 1; k++) {
                if (mode_lib->vba.HRatio[k] > 1.0) {
                        locals->PSCL_FACTOR[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.0));
                } else {
                        locals->PSCL_FACTOR[k] = dml_min(
                                        mode_lib->vba.MaxDCHUBToPSCLThroughput,
                                        mode_lib->vba.MaxPSCLToLBThroughput);
                }
                if (locals->BytePerPixelInDETC[k] == 0.0) {
                        locals->PSCL_FACTOR_CHROMA[k] = 0.0;
                        locals->MinDPPCLKUsingSingleDPP[k] =
                                        mode_lib->vba.PixelClock[k]
                                                        * dml_max3(
                                                                        mode_lib->vba.vtaps[k] / 6.0
                                                                                        * dml_min(
                                                                                                        1.0,
                                                                                                        mode_lib->vba.HRatio[k]),
                                                                        mode_lib->vba.HRatio[k]
                                                                                        * mode_lib->vba.VRatio[k]
                                                                                        / locals->PSCL_FACTOR[k],
                                                                        1.0);
                        if ((mode_lib->vba.htaps[k] > 6.0 || mode_lib->vba.vtaps[k] > 6.0)
                                        && locals->MinDPPCLKUsingSingleDPP[k]
                                                        < 2.0 * mode_lib->vba.PixelClock[k]) {
                                locals->MinDPPCLKUsingSingleDPP[k] = 2.0
                                                * mode_lib->vba.PixelClock[k];
                        }
                } else {
                        if (mode_lib->vba.HRatio[k] / 2.0 > 1.0) {
                                locals->PSCL_FACTOR_CHROMA[k] =
                                                dml_min(
                                                                mode_lib->vba.MaxDCHUBToPSCLThroughput,
                                                                mode_lib->vba.MaxPSCLToLBThroughput
                                                                                * mode_lib->vba.HRatio[k]
                                                                                / 2.0
                                                                                / dml_ceil(
                                                                                                mode_lib->vba.HTAPsChroma[k]
                                                                                                                / 6.0,
                                                                                                1.0));
                        } else {
                                locals->PSCL_FACTOR_CHROMA[k] = dml_min(
                                                mode_lib->vba.MaxDCHUBToPSCLThroughput,
                                                mode_lib->vba.MaxPSCLToLBThroughput);
                        }
                        locals->MinDPPCLKUsingSingleDPP[k] =
                                        mode_lib->vba.PixelClock[k]
                                                        * dml_max5(
                                                                        mode_lib->vba.vtaps[k] / 6.0
                                                                                        * dml_min(
                                                                                                        1.0,
                                                                                                        mode_lib->vba.HRatio[k]),
                                                                        mode_lib->vba.HRatio[k]
                                                                                        * mode_lib->vba.VRatio[k]
                                                                                        / locals->PSCL_FACTOR[k],
                                                                        mode_lib->vba.VTAPsChroma[k]
                                                                                        / 6.0
                                                                                        * dml_min(
                                                                                                        1.0,
                                                                                                        mode_lib->vba.HRatio[k]
                                                                                                                        / 2.0),
                                                                        mode_lib->vba.HRatio[k]
                                                                                        * mode_lib->vba.VRatio[k]
                                                                                        / 4.0
                                                                                        / locals->PSCL_FACTOR_CHROMA[k],
                                                                        1.0);
                        if ((mode_lib->vba.htaps[k] > 6.0 || mode_lib->vba.vtaps[k] > 6.0
                                        || mode_lib->vba.HTAPsChroma[k] > 6.0
                                        || mode_lib->vba.VTAPsChroma[k] > 6.0)
                                        && locals->MinDPPCLKUsingSingleDPP[k]
                                                        < 2.0 * mode_lib->vba.PixelClock[k]) {
                                locals->MinDPPCLKUsingSingleDPP[k] = 2.0
                                                * mode_lib->vba.PixelClock[k];
                        }
                }
        }
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                Calculate256BBlockSizes(
                                mode_lib->vba.SourcePixelFormat[k],
                                mode_lib->vba.SurfaceTiling[k],
                                dml_ceil(locals->BytePerPixelInDETY[k], 1.0),
                                dml_ceil(locals->BytePerPixelInDETC[k], 2.0),
                                &locals->Read256BlockHeightY[k],
                                &locals->Read256BlockHeightC[k],
                                &locals->Read256BlockWidthY[k],
                                &locals->Read256BlockWidthC[k]);
                if (mode_lib->vba.SourceScan[k] == dm_horz) {
                        locals->MaxSwathHeightY[k] = locals->Read256BlockHeightY[k];
                        locals->MaxSwathHeightC[k] = locals->Read256BlockHeightC[k];
                } else {
                        locals->MaxSwathHeightY[k] = locals->Read256BlockWidthY[k];
                        locals->MaxSwathHeightC[k] = locals->Read256BlockWidthC[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_mono_16
                                || mode_lib->vba.SourcePixelFormat[k] == dm_mono_8)) {
                        if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear
                                        || (mode_lib->vba.SourcePixelFormat[k] == dm_444_64
                                                        && (mode_lib->vba.SurfaceTiling[k]
                                                                        == dm_sw_4kb_s
                                                                        || mode_lib->vba.SurfaceTiling[k]
                                                                                        == dm_sw_4kb_s_x
                                                                        || mode_lib->vba.SurfaceTiling[k]
                                                                                        == dm_sw_64kb_s
                                                                        || mode_lib->vba.SurfaceTiling[k]
                                                                                        == dm_sw_64kb_s_t
                                                                        || mode_lib->vba.SurfaceTiling[k]
                                                                                        == dm_sw_64kb_s_x
                                                                        || mode_lib->vba.SurfaceTiling[k]
                                                                                        == dm_sw_var_s
                                                                        || mode_lib->vba.SurfaceTiling[k]
                                                                                        == dm_sw_var_s_x)
                                                        && mode_lib->vba.SourceScan[k] == dm_horz)) {
                                locals->MinSwathHeightY[k] = locals->MaxSwathHeightY[k];
                        } else {
                                locals->MinSwathHeightY[k] = locals->MaxSwathHeightY[k]
                                                / 2.0;
                        }
                        locals->MinSwathHeightC[k] = locals->MaxSwathHeightC[k];
                } else {
                        if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) {
                                locals->MinSwathHeightY[k] = locals->MaxSwathHeightY[k];
                                locals->MinSwathHeightC[k] = locals->MaxSwathHeightC[k];
                        } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8
                                        && mode_lib->vba.SourceScan[k] == dm_horz) {
                                locals->MinSwathHeightY[k] = locals->MaxSwathHeightY[k]
                                                / 2.0;
                                locals->MinSwathHeightC[k] = locals->MaxSwathHeightC[k];
                        } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10
                                        && mode_lib->vba.SourceScan[k] == dm_horz) {
                                locals->MinSwathHeightC[k] = locals->MaxSwathHeightC[k]
                                                / 2.0;
                                locals->MinSwathHeightY[k] = locals->MaxSwathHeightY[k];
                        } else {
                                locals->MinSwathHeightY[k] = locals->MaxSwathHeightY[k];
                                locals->MinSwathHeightC[k] = locals->MaxSwathHeightC[k];
                        }
                }
                if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) {
                        mode_lib->vba.MaximumSwathWidthSupport = 8192.0;
                } else {
                        mode_lib->vba.MaximumSwathWidthSupport = 5120.0;
                }
                mode_lib->vba.MaximumSwathWidthInDETBuffer =
                                dml_min(
                                                mode_lib->vba.MaximumSwathWidthSupport,
                                                mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2.0
                                                                / (locals->BytePerPixelInDETY[k]
                                                                                * locals->MinSwathHeightY[k]
                                                                                + locals->BytePerPixelInDETC[k]
                                                                                                / 2.0
                                                                                                * locals->MinSwathHeightC[k]));
                if (locals->BytePerPixelInDETC[k] == 0.0) {
                        mode_lib->vba.MaximumSwathWidthInLineBuffer =
                                        mode_lib->vba.LineBufferSize
                                                        * dml_max(mode_lib->vba.HRatio[k], 1.0)
                                                        / mode_lib->vba.LBBitPerPixel[k]
                                                        / (mode_lib->vba.vtaps[k]
                                                                        + dml_max(
                                                                                        dml_ceil(
                                                                                                        mode_lib->vba.VRatio[k],
                                                                                                        1.0)
                                                                                                        - 2,
                                                                                        0.0));
                } else {
                        mode_lib->vba.MaximumSwathWidthInLineBuffer =
                                        dml_min(
                                                        mode_lib->vba.LineBufferSize
                                                                        * dml_max(
                                                                                        mode_lib->vba.HRatio[k],
                                                                                        1.0)
                                                                        / mode_lib->vba.LBBitPerPixel[k]
                                                                        / (mode_lib->vba.vtaps[k]
                                                                                        + dml_max(
                                                                                                        dml_ceil(
                                                                                                                        mode_lib->vba.VRatio[k],
                                                                                                                        1.0)
                                                                                                                        - 2,
                                                                                                        0.0)),
                                                        2.0 * mode_lib->vba.LineBufferSize
                                                                        * dml_max(
                                                                                        mode_lib->vba.HRatio[k]
                                                                                                        / 2.0,
                                                                                        1.0)
                                                                        / mode_lib->vba.LBBitPerPixel[k]
                                                                        / (mode_lib->vba.VTAPsChroma[k]
                                                                                        + dml_max(
                                                                                                        dml_ceil(
                                                                                                                        mode_lib->vba.VRatio[k]
                                                                                                                                        / 2.0,
                                                                                                                        1.0)
                                                                                                                        - 2,
                                                                                                        0.0)));
                }
                locals->MaximumSwathWidth[k] = dml_min(
                                mode_lib->vba.MaximumSwathWidthInDETBuffer,
                                mode_lib->vba.MaximumSwathWidthInLineBuffer);
        }
        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
                double MaxMaxDispclkRoundedDown = RoundToDFSGranularityDown(
                        mode_lib->vba.MaxDispclk[mode_lib->vba.soc.num_states],
                        mode_lib->vba.DISPCLKDPPCLKVCOSpeed);

                for (j = 0; j < 2; j++) {
                        mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity = RoundToDFSGranularityDown(
                                mode_lib->vba.MaxDispclk[i],
                                mode_lib->vba.DISPCLKDPPCLKVCOSpeed);
                        mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity = RoundToDFSGranularityDown(
                                mode_lib->vba.MaxDppclk[i],
                                mode_lib->vba.DISPCLKDPPCLKVCOSpeed);
                        locals->RequiredDISPCLK[i][j] = 0.0;
                        locals->DISPCLK_DPPCLK_Support[i][j] = true;
                        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine =
                                                mode_lib->vba.PixelClock[k]
                                                                * (1.0
                                                                                + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading
                                                                                                / 100.0)
                                                                * (1.0
                                                                                + mode_lib->vba.DISPCLKRampingMargin
                                                                                                / 100.0);
                                if (mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine >= mode_lib->vba.MaxDispclk[i]
                                                && i == mode_lib->vba.soc.num_states)
                                        mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine = mode_lib->vba.PixelClock[k]
                                                        * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0);

                                mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine = mode_lib->vba.PixelClock[k] / 2
                                        * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * (1 + mode_lib->vba.DISPCLKRampingMargin / 100.0);
                                if (mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine >= mode_lib->vba.MaxDispclk[i]
                                                && i == mode_lib->vba.soc.num_states)
                                        mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine = mode_lib->vba.PixelClock[k] / 2
                                                        * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0);

                                locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled;
                                mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine;
                                if (mode_lib->vba.ODMCapability) {
                                        if (locals->PlaneRequiredDISPCLKWithoutODMCombine > MaxMaxDispclkRoundedDown) {
                                                locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1;
                                                mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine;
                                        } else if (locals->DSCEnabled[k] && (locals->HActive[k] > DCN21_MAX_DSC_IMAGE_WIDTH)) {
                                                locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1;
                                                mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine;
                                        } else if (locals->HActive[k] > DCN21_MAX_420_IMAGE_WIDTH && locals->OutputFormat[k] == dm_420) {
                                                locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1;
                                                mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine;
                                        }
                                }

                                if (locals->MinDPPCLKUsingSingleDPP[k] * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) <= mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity
                                                && locals->SwathWidthYSingleDPP[k] <= locals->MaximumSwathWidth[k]
                                                && locals->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_disabled) {
                                        locals->NoOfDPP[i][j][k] = 1;
                                        locals->RequiredDPPCLK[i][j][k] =
                                                locals->MinDPPCLKUsingSingleDPP[k] * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0);
                                } else {
                                        locals->NoOfDPP[i][j][k] = 2;
                                        locals->RequiredDPPCLK[i][j][k] =
                                                locals->MinDPPCLKUsingSingleDPP[k] * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) / 2.0;
                                }
                                locals->RequiredDISPCLK[i][j] = dml_max(
                                                locals->RequiredDISPCLK[i][j],
                                                mode_lib->vba.PlaneRequiredDISPCLK);
                                if ((locals->MinDPPCLKUsingSingleDPP[k] / locals->NoOfDPP[i][j][k] * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0)
                                                > mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity)
                                                || (mode_lib->vba.PlaneRequiredDISPCLK > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity)) {
                                        locals->DISPCLK_DPPCLK_Support[i][j] = false;
                                }
                        }
                        locals->TotalNumberOfActiveDPP[i][j] = 0.0;
                        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++)
                                locals->TotalNumberOfActiveDPP[i][j] = locals->TotalNumberOfActiveDPP[i][j] + locals->NoOfDPP[i][j][k];
                        if (j == 1) {
                                while (locals->TotalNumberOfActiveDPP[i][j] < mode_lib->vba.MaxNumDPP
                                                && locals->TotalNumberOfActiveDPP[i][j] < 2 * mode_lib->vba.NumberOfActivePlanes) {
                                        double BWOfNonSplitPlaneOfMaximumBandwidth;
                                        unsigned int NumberOfNonSplitPlaneOfMaximumBandwidth;

                                        BWOfNonSplitPlaneOfMaximumBandwidth = 0;
                                        NumberOfNonSplitPlaneOfMaximumBandwidth = 0;
                                        for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
                                                if (locals->ReadBandwidth[k] > BWOfNonSplitPlaneOfMaximumBandwidth && locals->NoOfDPP[i][j][k] == 1) {
                                                        BWOfNonSplitPlaneOfMaximumBandwidth = locals->ReadBandwidth[k];
                                                        NumberOfNonSplitPlaneOfMaximumBandwidth = k;
                                                }
                                        }
                                        locals->NoOfDPP[i][j][NumberOfNonSplitPlaneOfMaximumBandwidth] = 2;
                                        locals->RequiredDPPCLK[i][j][NumberOfNonSplitPlaneOfMaximumBandwidth] =
                                                locals->MinDPPCLKUsingSingleDPP[NumberOfNonSplitPlaneOfMaximumBandwidth]
                                                        * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100) / 2;
                                        locals->TotalNumberOfActiveDPP[i][j] = locals->TotalNumberOfActiveDPP[i][j] + 1;
                                }
                        }
                        if (locals->TotalNumberOfActiveDPP[i][j] > mode_lib->vba.MaxNumDPP) {
                                locals->RequiredDISPCLK[i][j] = 0.0;
                                locals->DISPCLK_DPPCLK_Support[i][j] = true;
                                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                        locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled;
                                        if (locals->SwathWidthYSingleDPP[k] <= locals->MaximumSwathWidth[k]) {
                                                locals->NoOfDPP[i][j][k] = 1;
                                                locals->RequiredDPPCLK[i][j][k] = locals->MinDPPCLKUsingSingleDPP[k]
                                                        * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0);
                                        } else {
                                                locals->NoOfDPP[i][j][k] = 2;
                                                locals->RequiredDPPCLK[i][j][k] = locals->MinDPPCLKUsingSingleDPP[k]
                                                                                * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) / 2.0;
                                        }
                                        if (i != mode_lib->vba.soc.num_states) {
                                                mode_lib->vba.PlaneRequiredDISPCLK =
                                                                mode_lib->vba.PixelClock[k]
                                                                                * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0)
                                                                                * (1.0 + mode_lib->vba.DISPCLKRampingMargin / 100.0);
                                        } else {
                                                mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PixelClock[k]
                                                        * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0);
                                        }
                                        locals->RequiredDISPCLK[i][j] = dml_max(
                                                        locals->RequiredDISPCLK[i][j],
                                                        mode_lib->vba.PlaneRequiredDISPCLK);
                                        if (locals->MinDPPCLKUsingSingleDPP[k] / locals->NoOfDPP[i][j][k] * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0)
                                                        > mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity
                                                        || mode_lib->vba.PlaneRequiredDISPCLK > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity)
                                                locals->DISPCLK_DPPCLK_Support[i][j] = false;
                                }
                                locals->TotalNumberOfActiveDPP[i][j] = 0.0;
                                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++)
                                        locals->TotalNumberOfActiveDPP[i][j] = locals->TotalNumberOfActiveDPP[i][j] + locals->NoOfDPP[i][j][k];
                        }
                        locals->RequiredDISPCLK[i][j] = dml_max(
                                        locals->RequiredDISPCLK[i][j],
                                        mode_lib->vba.WritebackRequiredDISPCLK);
                        if (mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity
                                        < mode_lib->vba.WritebackRequiredDISPCLK) {
                                locals->DISPCLK_DPPCLK_Support[i][j] = false;
                        }
                }
        }
        /*Viewport Size Check*/

        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
                locals->ViewportSizeSupport[i][0] = true;
                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                        if (locals->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_2to1) {
                                if (dml_min(locals->SwathWidthYSingleDPP[k], dml_round(mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k]))
                                                > locals->MaximumSwathWidth[k]) {
                                        locals->ViewportSizeSupport[i][0] = false;
                                }
                        } else {
                                if (locals->SwathWidthYSingleDPP[k] / 2.0 > locals->MaximumSwathWidth[k]) {
                                        locals->ViewportSizeSupport[i][0] = false;
                                }
                        }
                }
        }
        /*Total Available Pipes Support Check*/

        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
                for (j = 0; j < 2; j++) {
                        if (locals->TotalNumberOfActiveDPP[i][j] <= mode_lib->vba.MaxNumDPP)
                                locals->TotalAvailablePipesSupport[i][j] = true;
                        else
                                locals->TotalAvailablePipesSupport[i][j] = false;
                }
        }
        /*Total Available OTG Support Check*/

        mode_lib->vba.TotalNumberOfActiveOTG = 0.0;
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (mode_lib->vba.BlendingAndTiming[k] == k) {
                        mode_lib->vba.TotalNumberOfActiveOTG = mode_lib->vba.TotalNumberOfActiveOTG
                                        + 1.0;
                }
        }
        if (mode_lib->vba.TotalNumberOfActiveOTG <= mode_lib->vba.MaxNumOTG) {
                mode_lib->vba.NumberOfOTGSupport = true;
        } else {
                mode_lib->vba.NumberOfOTGSupport = false;
        }
        /*Display IO and DSC Support Check*/

        mode_lib->vba.NonsupportedDSCInputBPC = false;
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (!(mode_lib->vba.DSCInputBitPerComponent[k] == 12.0
                                || mode_lib->vba.DSCInputBitPerComponent[k] == 10.0
                                || mode_lib->vba.DSCInputBitPerComponent[k] == 8.0)) {
                        mode_lib->vba.NonsupportedDSCInputBPC = true;
                }
        }
        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                        locals->RequiresDSC[i][k] = false;
                        locals->RequiresFEC[i][k] = 0;
                        if (mode_lib->vba.BlendingAndTiming[k] == k) {
                                if (mode_lib->vba.Output[k] == dm_hdmi) {
                                        locals->RequiresDSC[i][k] = false;
                                        locals->RequiresFEC[i][k] = 0;
                                        locals->OutputBppPerState[i][k] = TruncToValidBPP(
                                                        dml_min(600.0, mode_lib->vba.PHYCLKPerState[i]) / mode_lib->vba.PixelClockBackEnd[k] * 24,
                                                        mode_lib->vba.ForcedOutputLinkBPP[k],
                                                        false,
                                                        mode_lib->vba.Output[k],
                                                        mode_lib->vba.OutputFormat[k],
                                                        mode_lib->vba.DSCInputBitPerComponent[k]);
                                } else if (mode_lib->vba.Output[k] == dm_dp
                                                || mode_lib->vba.Output[k] == dm_edp) {
                                        if (mode_lib->vba.Output[k] == dm_edp) {
                                                mode_lib->vba.EffectiveFECOverhead = 0.0;
                                        } else {
                                                mode_lib->vba.EffectiveFECOverhead =
                                                                mode_lib->vba.FECOverhead;
                                        }
                                        if (mode_lib->vba.PHYCLKPerState[i] >= 270.0) {
                                                mode_lib->vba.Outbpp = TruncToValidBPP(
                                                                (1.0 - mode_lib->vba.Downspreading / 100.0) * 270.0
                                                                * mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0,
                                                                mode_lib->vba.ForcedOutputLinkBPP[k],
                                                                false,
                                                                mode_lib->vba.Output[k],
                                                                mode_lib->vba.OutputFormat[k],
                                                                mode_lib->vba.DSCInputBitPerComponent[k]);
                                                mode_lib->vba.OutbppDSC = TruncToValidBPP(
                                                                (1.0 - mode_lib->vba.Downspreading / 100.0) * (1.0 - mode_lib->vba.EffectiveFECOverhead / 100.0) * 270.0
                                                                * mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0,
                                                                mode_lib->vba.ForcedOutputLinkBPP[k],
                                                                true,
                                                                mode_lib->vba.Output[k],
                                                                mode_lib->vba.OutputFormat[k],
                                                                mode_lib->vba.DSCInputBitPerComponent[k]);
                                                if (mode_lib->vba.DSCEnabled[k] == true) {
                                                        locals->RequiresDSC[i][k] = true;
                                                        if (mode_lib->vba.Output[k] == dm_dp) {
                                                                locals->RequiresFEC[i][k] = true;
                                                        } else {
                                                                locals->RequiresFEC[i][k] = false;
                                                        }
                                                        mode_lib->vba.Outbpp = mode_lib->vba.OutbppDSC;
                                                } else {
                                                        locals->RequiresDSC[i][k] = false;
                                                        locals->RequiresFEC[i][k] = false;
                                                }
                                                locals->OutputBppPerState[i][k] = mode_lib->vba.Outbpp;
                                        }
                                        if (mode_lib->vba.Outbpp == BPP_INVALID && mode_lib->vba.PHYCLKPerState[i] >= 540.0) {
                                                mode_lib->vba.Outbpp = TruncToValidBPP(
                                                                (1.0 - mode_lib->vba.Downspreading / 100.0) * 540.0
                                                                * mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0,
                                                                mode_lib->vba.ForcedOutputLinkBPP[k],
                                                                        false,
                                                                        mode_lib->vba.Output[k],
                                                                        mode_lib->vba.OutputFormat[k],
                                                                        mode_lib->vba.DSCInputBitPerComponent[k]);
                                                mode_lib->vba.OutbppDSC = TruncToValidBPP(
                                                                (1.0 - mode_lib->vba.Downspreading / 100.0) * (1.0 - mode_lib->vba.EffectiveFECOverhead / 100.0) * 540.0
                                                                * mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0,
                                                                mode_lib->vba.ForcedOutputLinkBPP[k],
                                                                true,
                                                                mode_lib->vba.Output[k],
                                                                mode_lib->vba.OutputFormat[k],
                                                                mode_lib->vba.DSCInputBitPerComponent[k]);
                                                if (mode_lib->vba.DSCEnabled[k] == true) {
                                                        locals->RequiresDSC[i][k] = true;
                                                        if (mode_lib->vba.Output[k] == dm_dp) {
                                                                locals->RequiresFEC[i][k] = true;
                                                        } else {
                                                                locals->RequiresFEC[i][k] = false;
                                                        }
                                                        mode_lib->vba.Outbpp = mode_lib->vba.OutbppDSC;
                                                } else {
                                                        locals->RequiresDSC[i][k] = false;
                                                        locals->RequiresFEC[i][k] = false;
                                                }
                                                locals->OutputBppPerState[i][k] = mode_lib->vba.Outbpp;
                                        }
                                        if (mode_lib->vba.Outbpp == BPP_INVALID
                                                        && mode_lib->vba.PHYCLKPerState[i]
                                                                        >= 810.0) {
                                                mode_lib->vba.Outbpp = TruncToValidBPP(
                                                                (1.0 - mode_lib->vba.Downspreading / 100.0) * 810.0
                                                                * mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0,
                                                                mode_lib->vba.ForcedOutputLinkBPP[k],
                                                                false,
                                                                mode_lib->vba.Output[k],
                                                                mode_lib->vba.OutputFormat[k],
                                                                mode_lib->vba.DSCInputBitPerComponent[k]);
                                                mode_lib->vba.OutbppDSC = TruncToValidBPP(
                                                                (1.0 - mode_lib->vba.Downspreading / 100.0) * (1.0 - mode_lib->vba.EffectiveFECOverhead / 100.0) * 810.0
                                                                * mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0,
                                                                mode_lib->vba.ForcedOutputLinkBPP[k],
                                                                true,
                                                                mode_lib->vba.Output[k],
                                                                mode_lib->vba.OutputFormat[k],
                                                                mode_lib->vba.DSCInputBitPerComponent[k]);
                                                if (mode_lib->vba.DSCEnabled[k] == true || mode_lib->vba.Outbpp == BPP_INVALID) {
                                                        locals->RequiresDSC[i][k] = true;
                                                        if (mode_lib->vba.Output[k] == dm_dp) {
                                                                locals->RequiresFEC[i][k] = true;
                                                        } else {
                                                                locals->RequiresFEC[i][k] = false;
                                                        }
                                                        mode_lib->vba.Outbpp = mode_lib->vba.OutbppDSC;
                                                } else {
                                                        locals->RequiresDSC[i][k] = false;
                                                        locals->RequiresFEC[i][k] = false;
                                                }
                                                locals->OutputBppPerState[i][k] =
                                                                mode_lib->vba.Outbpp;
                                        }
                                }
                        } else {
                                locals->OutputBppPerState[i][k] = BPP_BLENDED_PIPE;
                        }
                }
        }
        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
                locals->DIOSupport[i] = true;
                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                        if (!mode_lib->vba.skip_dio_check[k]
                                        && (locals->OutputBppPerState[i][k] == BPP_INVALID
                                                || (mode_lib->vba.OutputFormat[k] == dm_420
                                                        && mode_lib->vba.Interlace[k] == true
                                                        && mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true))) {
                                locals->DIOSupport[i] = false;
                        }
                }
        }
        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                        locals->DSCCLKRequiredMoreThanSupported[i] = false;
                        if (mode_lib->vba.BlendingAndTiming[k] == k) {
                                if ((mode_lib->vba.Output[k] == dm_dp
                                                || mode_lib->vba.Output[k] == dm_edp)) {
                                        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 (locals->RequiresDSC[i][k] == true) {
                                                if (locals->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_2to1) {
                                                        if (mode_lib->vba.PixelClockBackEnd[k] / 6.0 / mode_lib->vba.DSCFormatFactor
                                                                        > (1.0 - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * mode_lib->vba.MaxDSCCLK[i]) {
                                                                locals->DSCCLKRequiredMoreThanSupported[i] =
                                                                                true;
                                                        }
                                                } else {
                                                        if (mode_lib->vba.PixelClockBackEnd[k] / 3.0 / mode_lib->vba.DSCFormatFactor
                                                                        > (1.0 - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * mode_lib->vba.MaxDSCCLK[i]) {
                                                                locals->DSCCLKRequiredMoreThanSupported[i] =
                                                                                true;
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
                locals->NotEnoughDSCUnits[i] = false;
                mode_lib->vba.TotalDSCUnitsRequired = 0.0;
                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                        if (locals->RequiresDSC[i][k] == true) {
                                if (locals->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_2to1) {
                                        mode_lib->vba.TotalDSCUnitsRequired =
                                                        mode_lib->vba.TotalDSCUnitsRequired + 2.0;
                                } else {
                                        mode_lib->vba.TotalDSCUnitsRequired =
                                                        mode_lib->vba.TotalDSCUnitsRequired + 1.0;
                                }
                        }
                }
                if (mode_lib->vba.TotalDSCUnitsRequired > mode_lib->vba.NumberOfDSC) {
                        locals->NotEnoughDSCUnits[i] = true;
                }
        }
        /*DSC Delay per state*/

        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                        if (mode_lib->vba.BlendingAndTiming[k] != k) {
                                mode_lib->vba.slices = 0;
                        } else if (locals->RequiresDSC[i][k] == 0
                                        || locals->RequiresDSC[i][k] == false) {
                                mode_lib->vba.slices = 0;
                        } else if (mode_lib->vba.PixelClockBackEnd[k] > 3200.0) {
                                mode_lib->vba.slices = dml_ceil(
                                                mode_lib->vba.PixelClockBackEnd[k] / 400.0,
                                                4.0);
                        } else if (mode_lib->vba.PixelClockBackEnd[k] > 1360.0) {
                                mode_lib->vba.slices = 8.0;
                        } else if (mode_lib->vba.PixelClockBackEnd[k] > 680.0) {
                                mode_lib->vba.slices = 4.0;
                        } else if (mode_lib->vba.PixelClockBackEnd[k] > 340.0) {
                                mode_lib->vba.slices = 2.0;
                        } else {
                                mode_lib->vba.slices = 1.0;
                        }
                        if (locals->OutputBppPerState[i][k] == BPP_BLENDED_PIPE
                                        || locals->OutputBppPerState[i][k] == BPP_INVALID) {
                                mode_lib->vba.bpp = 0.0;
                        } else {
                                mode_lib->vba.bpp = locals->OutputBppPerState[i][k];
                        }
                        if (locals->RequiresDSC[i][k] == true && mode_lib->vba.bpp != 0.0) {
                                if (locals->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_disabled) {
                                        locals->DSCDelayPerState[i][k] =
                                                        dscceComputeDelay(
                                                                        mode_lib->vba.DSCInputBitPerComponent[k],
                                                                        mode_lib->vba.bpp,
                                                                        dml_ceil(
                                                                                        mode_lib->vba.HActive[k]
                                                                                                        / mode_lib->vba.slices,
                                                                                        1.0),
                                                                        mode_lib->vba.slices,
                                                                        mode_lib->vba.OutputFormat[k])
                                                                        + dscComputeDelay(
                                                                                        mode_lib->vba.OutputFormat[k]);
                                } else {
                                        locals->DSCDelayPerState[i][k] =
                                                        2.0 * (dscceComputeDelay(
                                                                                        mode_lib->vba.DSCInputBitPerComponent[k],
                                                                                        mode_lib->vba.bpp,
                                                                                        dml_ceil(mode_lib->vba.HActive[k] / mode_lib->vba.slices, 1.0),
                                                                                        mode_lib->vba.slices / 2,
                                                                                        mode_lib->vba.OutputFormat[k])
                                                                        + dscComputeDelay(mode_lib->vba.OutputFormat[k]));
                                }
                                locals->DSCDelayPerState[i][k] =
                                                locals->DSCDelayPerState[i][k] * mode_lib->vba.PixelClock[k] / mode_lib->vba.PixelClockBackEnd[k];
                        } else {
                                locals->DSCDelayPerState[i][k] = 0.0;
                        }
                }
                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                        for (m = 0; m <= mode_lib->vba.NumberOfActivePlanes - 1; m++) {
                                for (j = 0; j <= mode_lib->vba.NumberOfActivePlanes - 1; j++) {
                                        if (mode_lib->vba.BlendingAndTiming[k] == m && locals->RequiresDSC[i][m] == true)
                                                locals->DSCDelayPerState[i][k] = locals->DSCDelayPerState[i][m];
                                }
                        }
                }
        }

        //Prefetch Check
        for (i = 0; i <= mode_lib->vba.soc.num_states; ++i) {
                for (j = 0; j <= 1; ++j) {
                        locals->TotalNumberOfDCCActiveDPP[i][j] = 0;
                        for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
                                if (mode_lib->vba.DCCEnable[k] == true)
                                        locals->TotalNumberOfDCCActiveDPP[i][j] = locals->TotalNumberOfDCCActiveDPP[i][j] + locals->NoOfDPP[i][j][k];
                        }
                }
        }

        mode_lib->vba.UrgentLatency = dml_max3(
                        mode_lib->vba.UrgentLatencyPixelDataOnly,
                        mode_lib->vba.UrgentLatencyPixelMixedWithVMData,
                        mode_lib->vba.UrgentLatencyVMDataOnly);
        mode_lib->vba.PrefetchERROR = CalculateMinAndMaxPrefetchMode(
                        mode_lib->vba.AllowDRAMSelfRefreshOrDRAMClockChangeInVblank,
                        &mode_lib->vba.MinPrefetchMode,
                        &mode_lib->vba.MaxPrefetchMode);

        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
                for (j = 0; j < 2; j++) {
                        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                locals->RequiredDPPCLKThisState[k] = locals->RequiredDPPCLK[i][j][k];
                                locals->NoOfDPPThisState[k]        = locals->NoOfDPP[i][j][k];
                                if (locals->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_2to1) {
                                        locals->SwathWidthYThisState[k] =
                                                dml_min(locals->SwathWidthYSingleDPP[k], dml_round(mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k]));
                                } else {
                                        locals->SwathWidthYThisState[k] = locals->SwathWidthYSingleDPP[k] / locals->NoOfDPP[i][j][k];
                                }
                                mode_lib->vba.SwathWidthGranularityY = 256.0
                                        / dml_ceil(locals->BytePerPixelInDETY[k], 1.0)
                                        / locals->MaxSwathHeightY[k];
                                mode_lib->vba.RoundedUpMaxSwathSizeBytesY =
                                        (dml_ceil(locals->SwathWidthYThisState[k] - 1.0, mode_lib->vba.SwathWidthGranularityY)
                                        + mode_lib->vba.SwathWidthGranularityY) * locals->BytePerPixelInDETY[k] * locals->MaxSwathHeightY[k];
                                if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) {
                                        mode_lib->vba.RoundedUpMaxSwathSizeBytesY = dml_ceil(
                                                        mode_lib->vba.RoundedUpMaxSwathSizeBytesY,
                                                        256.0) + 256;
                                }
                                if (locals->MaxSwathHeightC[k] > 0.0) {
                                        mode_lib->vba.SwathWidthGranularityC = 256.0 / dml_ceil(locals->BytePerPixelInDETC[k], 2.0) / locals->MaxSwathHeightC[k];
                                        mode_lib->vba.RoundedUpMaxSwathSizeBytesC = (dml_ceil(locals->SwathWidthYThisState[k] / 2.0 - 1.0, mode_lib->vba.SwathWidthGranularityC)
                                                        + mode_lib->vba.SwathWidthGranularityC) * locals->BytePerPixelInDETC[k] * locals->MaxSwathHeightC[k];
                                        if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) {
                                                mode_lib->vba.RoundedUpMaxSwathSizeBytesC = dml_ceil(mode_lib->vba.RoundedUpMaxSwathSizeBytesC, 256.0) + 256;
                                        }
                                } else {
                                        mode_lib->vba.RoundedUpMaxSwathSizeBytesC = 0.0;
                                }
                                if (mode_lib->vba.RoundedUpMaxSwathSizeBytesY + mode_lib->vba.RoundedUpMaxSwathSizeBytesC
                                                <= mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2.0) {
                                        locals->SwathHeightYThisState[k] = locals->MaxSwathHeightY[k];
                                        locals->SwathHeightCThisState[k] = locals->MaxSwathHeightC[k];
                                } else {
                                        locals->SwathHeightYThisState[k] =
                                                        locals->MinSwathHeightY[k];
                                        locals->SwathHeightCThisState[k] =
                                                        locals->MinSwathHeightC[k];
                                }
                        }

                        CalculateDCFCLKDeepSleep(
                                        mode_lib,
                                        mode_lib->vba.NumberOfActivePlanes,
                                        locals->BytePerPixelInDETY,
                                        locals->BytePerPixelInDETC,
                                        mode_lib->vba.VRatio,
                                        locals->SwathWidthYThisState,
                                        locals->NoOfDPPThisState,
                                        mode_lib->vba.HRatio,
                                        mode_lib->vba.PixelClock,
                                        locals->PSCL_FACTOR,
                                        locals->PSCL_FACTOR_CHROMA,
                                        locals->RequiredDPPCLKThisState,
                                        &mode_lib->vba.ProjectedDCFCLKDeepSleep[0][0]);

                        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; 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_mono_16
                                                && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8)) {
                                        mode_lib->vba.PDEAndMetaPTEBytesPerFrameC = CalculateVMAndRowBytes(
                                                        mode_lib,
                                                        mode_lib->vba.DCCEnable[k],
                                                        locals->Read256BlockHeightC[k],
                                                        locals->Read256BlockWidthC[k],
                                                        mode_lib->vba.SourcePixelFormat[k],
                                                        mode_lib->vba.SurfaceTiling[k],
                                                        dml_ceil(locals->BytePerPixelInDETC[k], 2.0),
                                                        mode_lib->vba.SourceScan[k],
                                                        mode_lib->vba.ViewportWidth[k] / 2.0,
                                                        mode_lib->vba.ViewportHeight[k] / 2.0,
                                                        locals->SwathWidthYThisState[k] / 2.0,
                                                        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],
                                                        0.0,
                                                        &locals->MacroTileWidthC[k],
                                                        &mode_lib->vba.MetaRowBytesC,
                                                        &mode_lib->vba.DPTEBytesPerRowC,
                                                        &locals->PTEBufferSizeNotExceededC[i][j][k],
                                                        locals->dpte_row_width_chroma_ub,
                                                        &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,
                                                        locals->PixelPTEReqHeightC,
                                                        locals->PTERequestSizeC,
                                                        locals->dpde0_bytes_per_frame_ub_c,
                                                        locals->meta_pte_bytes_per_frame_ub_c);
                                        locals->PrefetchLinesC[0][0][k] = CalculatePrefetchSourceLines(
                                                        mode_lib,
                                                        mode_lib->vba.VRatio[k]/2,
                                                        mode_lib->vba.VTAPsChroma[k],
                                                        mode_lib->vba.Interlace[k],
                                                        mode_lib->vba.ProgressiveToInterlaceUnitInOPP,
                                                        locals->SwathHeightCThisState[k],
                                                        mode_lib->vba.ViewportYStartC[k],
                                                        &locals->PrefillC[k],
                                                        &locals->MaxNumSwC[k]);
                                        locals->PTEBufferSizeInRequestsForLuma = mode_lib->vba.PTEBufferSizeInRequestsLuma;
                                } else {
                                        mode_lib->vba.PDEAndMetaPTEBytesPerFrameC = 0.0;
                                        mode_lib->vba.MetaRowBytesC = 0.0;
                                        mode_lib->vba.DPTEBytesPerRowC = 0.0;
                                        locals->PrefetchLinesC[0][0][k] = 0.0;
                                        locals->PTEBufferSizeNotExceededC[i][j][k] = true;
                                        locals->PTEBufferSizeInRequestsForLuma = mode_lib->vba.PTEBufferSizeInRequestsLuma + mode_lib->vba.PTEBufferSizeInRequestsChroma;
                                }
                                mode_lib->vba.PDEAndMetaPTEBytesPerFrameY = CalculateVMAndRowBytes(
                                                mode_lib,
                                                mode_lib->vba.DCCEnable[k],
                                                locals->Read256BlockHeightY[k],
                                                locals->Read256BlockWidthY[k],
                                                mode_lib->vba.SourcePixelFormat[k],
                                                mode_lib->vba.SurfaceTiling[k],
                                                dml_ceil(locals->BytePerPixelInDETY[k], 1.0),
                                                mode_lib->vba.SourceScan[k],
                                                mode_lib->vba.ViewportWidth[k],
                                                mode_lib->vba.ViewportHeight[k],
                                                locals->SwathWidthYThisState[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],
                                                &mode_lib->vba.MetaRowBytesY,
                                                &mode_lib->vba.DPTEBytesPerRowY,
                                                &locals->PTEBufferSizeNotExceededY[i][j][k],
                                                locals->dpte_row_width_luma_ub,
                                                &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,
                                                locals->PixelPTEReqHeightY,
                                                locals->PTERequestSizeY,
                                                locals->dpde0_bytes_per_frame_ub_l,
                                                locals->meta_pte_bytes_per_frame_ub_l);
                                locals->PrefetchLinesY[0][0][k] = CalculatePrefetchSourceLines(
                                                mode_lib,
                                                mode_lib->vba.VRatio[k],
                                                mode_lib->vba.vtaps[k],
                                                mode_lib->vba.Interlace[k],
                                                mode_lib->vba.ProgressiveToInterlaceUnitInOPP,
                                                locals->SwathHeightYThisState[k],
                                                mode_lib->vba.ViewportYStartY[k],
                                                &locals->PrefillY[k],
                                                &locals->MaxNumSwY[k]);
                                locals->PDEAndMetaPTEBytesPerFrame[0][0][k] =
                                                mode_lib->vba.PDEAndMetaPTEBytesPerFrameY + mode_lib->vba.PDEAndMetaPTEBytesPerFrameC;
                                locals->MetaRowBytes[0][0][k] = mode_lib->vba.MetaRowBytesY + mode_lib->vba.MetaRowBytesC;
                                locals->DPTEBytesPerRow[0][0][k] = mode_lib->vba.DPTEBytesPerRowY + mode_lib->vba.DPTEBytesPerRowC;

                                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],
                                                mode_lib->vba.MetaRowBytesY,
                                                mode_lib->vba.MetaRowBytesC,
                                                locals->meta_row_height[k],
                                                locals->meta_row_height_chroma[k],
                                                mode_lib->vba.DPTEBytesPerRowY,
                                                mode_lib->vba.DPTEBytesPerRowC,
                                                locals->dpte_row_height[k],
                                                locals->dpte_row_height_chroma[k],
                                                &locals->meta_row_bw[k],
                                                &locals->dpte_row_bw[k]);
                        }
                        mode_lib->vba.ExtraLatency = CalculateExtraLatency(
                                        locals->UrgentRoundTripAndOutOfOrderLatencyPerState[i],
                                        locals->TotalNumberOfActiveDPP[i][j],
                                        mode_lib->vba.PixelChunkSizeInKByte,
                                        locals->TotalNumberOfDCCActiveDPP[i][j],
                                        mode_lib->vba.MetaChunkSize,
                                        locals->ReturnBWPerState[i][0],
                                        mode_lib->vba.GPUVMEnable,
                                        mode_lib->vba.HostVMEnable,
                                        mode_lib->vba.NumberOfActivePlanes,
                                        locals->NoOfDPPThisState,
                                        locals->dpte_group_bytes,
                                        mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
                                        mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly,
                                        mode_lib->vba.HostVMMaxPageTableLevels,
                                        mode_lib->vba.HostVMCachedPageTableLevels);

                        mode_lib->vba.TimeCalc = 24.0 / mode_lib->vba.ProjectedDCFCLKDeepSleep[0][0];
                        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                if (mode_lib->vba.BlendingAndTiming[k] == k) {
                                        if (mode_lib->vba.WritebackEnable[k] == true) {
                                                locals->WritebackDelay[i][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]) / locals->RequiredDISPCLK[i][j];
                                        } else {
                                                locals->WritebackDelay[i][k] = 0.0;
                                        }
                                        for (m = 0; m <= mode_lib->vba.NumberOfActivePlanes - 1; m++) {
                                                if (mode_lib->vba.BlendingAndTiming[m] == k
                                                                && mode_lib->vba.WritebackEnable[m]
                                                                                == true) {
                                                        locals->WritebackDelay[i][k] = dml_max(locals->WritebackDelay[i][k],
                                                                                        mode_lib->vba.WritebackLatency + CalculateWriteBackDelay(
                                                                                                        mode_lib->vba.WritebackPixelFormat[m],
                                                                                                        mode_lib->vba.WritebackHRatio[m],
                                                                                                        mode_lib->vba.WritebackVRatio[m],
                                                                                                        mode_lib->vba.WritebackLumaHTaps[m],
                                                                                                        mode_lib->vba.WritebackLumaVTaps[m],
                                                                                                        mode_lib->vba.WritebackChromaHTaps[m],
                                                                                                        mode_lib->vba.WritebackChromaVTaps[m],
                                                                                                        mode_lib->vba.WritebackDestinationWidth[m]) / locals->RequiredDISPCLK[i][j]);
                                                }
                                        }
                                }
                        }
                        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                for (m = 0; m <= mode_lib->vba.NumberOfActivePlanes - 1; m++) {
                                        if (mode_lib->vba.BlendingAndTiming[k] == m) {
                                                locals->WritebackDelay[i][k] = locals->WritebackDelay[i][m];
                                        }
                                }
                        }
                        mode_lib->vba.MaxMaxVStartup[0][0] = 0;
                        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                locals->MaximumVStartup[0][0][k] = mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k]
                                        - dml_max(1.0, dml_ceil(locals->WritebackDelay[i][k] / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), 1.0));
                                mode_lib->vba.MaxMaxVStartup[0][0] = dml_max(mode_lib->vba.MaxMaxVStartup[0][0], locals->MaximumVStartup[0][0][k]);
                        }

                        mode_lib->vba.NextPrefetchMode = mode_lib->vba.MinPrefetchMode;
                        mode_lib->vba.NextMaxVStartup = mode_lib->vba.MaxMaxVStartup[0][0];
                        do {
                                mode_lib->vba.PrefetchMode[i][j] = mode_lib->vba.NextPrefetchMode;
                                mode_lib->vba.MaxVStartup = mode_lib->vba.NextMaxVStartup;

                                mode_lib->vba.TWait = CalculateTWait(
                                                mode_lib->vba.PrefetchMode[i][j],
                                                mode_lib->vba.DRAMClockChangeLatency,
                                                mode_lib->vba.UrgentLatency,
                                                mode_lib->vba.SREnterPlusExitTime);
                                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++)
                                        CalculatePrefetchSchedulePerPlane(mode_lib, i, j, k);

                                mode_lib->vba.MaximumReadBandwidthWithoutPrefetch = 0.0;
                                mode_lib->vba.MaximumReadBandwidthWithPrefetch = 0.0;
                                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; 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->VRatioPreY[i][j][k];
                                        }

                                        CalculateUrgentBurstFactor(
                                                        mode_lib->vba.DETBufferSizeInKByte[0],
                                                        locals->SwathHeightYThisState[k],
                                                        locals->SwathHeightCThisState[k],
                                                        locals->SwathWidthYThisState[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->VRatioPreY[i][j][k],
                                                        locals->VRatioPreC[i][j][k],
                                                        locals->BytePerPixelInDETY[k],
                                                        locals->BytePerPixelInDETC[k],
                                                        &locals->UrgentBurstFactorCursor[k],
                                                        &locals->UrgentBurstFactorCursorPre[k],
                                                        &locals->UrgentBurstFactorLuma[k],
                                                        &locals->UrgentBurstFactorLumaPre[k],
                                                        &locals->UrgentBurstFactorChroma[k],
                                                        &locals->UrgentBurstFactorChromaPre[k],
                                                        &locals->NotEnoughUrgentLatencyHiding[0][0],
                                                        &locals->NotEnoughUrgentLatencyHidingPre);

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

                                        mode_lib->vba.MaximumReadBandwidthWithoutPrefetch = mode_lib->vba.MaximumReadBandwidthWithoutPrefetch
                                                + locals->cursor_bw[k] * locals->UrgentBurstFactorCursor[k] + locals->ReadBandwidthLuma[k]
                                                * locals->UrgentBurstFactorLuma[k] + locals->ReadBandwidthChroma[k]
                                                * locals->UrgentBurstFactorChroma[k] + locals->meta_row_bw[k] + locals->dpte_row_bw[k];
                                        mode_lib->vba.MaximumReadBandwidthWithPrefetch = mode_lib->vba.MaximumReadBandwidthWithPrefetch
                                                + dml_max3(locals->prefetch_vmrow_bw[k],
                                                locals->ReadBandwidthLuma[k] * locals->UrgentBurstFactorLuma[k] + locals->ReadBandwidthChroma[k]
                                                * locals->UrgentBurstFactorChroma[k] + locals->cursor_bw[k] * locals->UrgentBurstFactorCursor[k]
                                                + locals->meta_row_bw[k] + locals->dpte_row_bw[k],
                                                locals->RequiredPrefetchPixelDataBWLuma[i][j][k] * locals->UrgentBurstFactorLumaPre[k]
                                                + locals->RequiredPrefetchPixelDataBWChroma[i][j][k] * locals->UrgentBurstFactorChromaPre[k]
                                                + locals->cursor_bw_pre[k] * locals->UrgentBurstFactorCursorPre[k]);
                                }
                                locals->BandwidthWithoutPrefetchSupported[i][0] = true;
                                if (mode_lib->vba.MaximumReadBandwidthWithoutPrefetch > locals->ReturnBWPerState[i][0]
                                                || locals->NotEnoughUrgentLatencyHiding[0][0] == 1) {
                                        locals->BandwidthWithoutPrefetchSupported[i][0] = false;
                                }

                                locals->PrefetchSupported[i][j] = true;
                                if (mode_lib->vba.MaximumReadBandwidthWithPrefetch > locals->ReturnBWPerState[i][0]
                                                || locals->NotEnoughUrgentLatencyHiding[0][0] == 1
                                                || locals->NotEnoughUrgentLatencyHidingPre == 1) {
                                        locals->PrefetchSupported[i][j] = false;
                                }
                                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                        if (locals->LineTimesForPrefetch[k] < 2.0
                                                        || locals->LinesForMetaPTE[k] >= 32.0
                                                        || locals->LinesForMetaAndDPTERow[k] >= 16.0
                                                        || mode_lib->vba.IsErrorResult[i][j][k] == true) {
                                                locals->PrefetchSupported[i][j] = false;
                                        }
                                }
                                locals->VRatioInPrefetchSupported[i][j] = true;
                                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                        if (locals->VRatioPreY[i][j][k] > 4.0
                                                        || locals->VRatioPreC[i][j][k] > 4.0
                                                        || mode_lib->vba.IsErrorResult[i][j][k] == true) {
                                                locals->VRatioInPrefetchSupported[i][j] = false;
                                        }
                                }
                                mode_lib->vba.AnyLinesForVMOrRowTooLarge = false;
                                for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
                                        if (locals->LinesForMetaAndDPTERow[k] >= 16 || locals->LinesForMetaPTE[k] >= 32) {
                                                mode_lib->vba.AnyLinesForVMOrRowTooLarge = true;
                                        }
                                }

                                if (mode_lib->vba.MaxVStartup <= 13 || mode_lib->vba.AnyLinesForVMOrRowTooLarge == false) {
                                        mode_lib->vba.NextMaxVStartup = mode_lib->vba.MaxMaxVStartup[0][0];
                                        mode_lib->vba.NextPrefetchMode = mode_lib->vba.NextPrefetchMode + 1;
                                } else {
                                        mode_lib->vba.NextMaxVStartup = mode_lib->vba.NextMaxVStartup - 1;
                                }
                        } while ((locals->PrefetchSupported[i][j] != true || locals->VRatioInPrefetchSupported[i][j] != true)
                                        && (mode_lib->vba.NextMaxVStartup != mode_lib->vba.MaxMaxVStartup[0][0]
                                                || mode_lib->vba.NextPrefetchMode <= mode_lib->vba.MaxPrefetchMode));

                        if (locals->PrefetchSupported[i][j] == true && locals->VRatioInPrefetchSupported[i][j] == true) {
                                mode_lib->vba.BandwidthAvailableForImmediateFlip = locals->ReturnBWPerState[i][0];
                                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                        mode_lib->vba.BandwidthAvailableForImmediateFlip = mode_lib->vba.BandwidthAvailableForImmediateFlip
                                                - dml_max(locals->ReadBandwidthLuma[k] * locals->UrgentBurstFactorLuma[k]
                                                        + locals->ReadBandwidthChroma[k] * locals->UrgentBurstFactorChroma[k]
                                                        + locals->cursor_bw[k] * locals->UrgentBurstFactorCursor[k],
                                                        locals->RequiredPrefetchPixelDataBWLuma[i][j][k] * locals->UrgentBurstFactorLumaPre[k]
                                                        + locals->RequiredPrefetchPixelDataBWChroma[i][j][k] * locals->UrgentBurstFactorChromaPre[k]
                                                        + locals->cursor_bw_pre[k] * locals->UrgentBurstFactorCursorPre[k]);
                                }
                                mode_lib->vba.TotImmediateFlipBytes = 0.0;
                                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                        mode_lib->vba.TotImmediateFlipBytes = mode_lib->vba.TotImmediateFlipBytes
                                                + locals->PDEAndMetaPTEBytesPerFrame[0][0][k] + locals->MetaRowBytes[0][0][k] + locals->DPTEBytesPerRow[0][0][k];
                                }

                                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                        CalculateFlipSchedule(
                                                        mode_lib,
                                                        mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
                                                        mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly,
                                                        mode_lib->vba.ExtraLatency,
                                                        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->PDEAndMetaPTEBytesPerFrame[0][0][k],
                                                        locals->MetaRowBytes[0][0][k],
                                                        locals->DPTEBytesPerRow[0][0][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;
                                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; 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->RequiredPrefetchPixelDataBWLuma[i][j][k]
                                                * locals->UrgentBurstFactorLumaPre[k] + locals->RequiredPrefetchPixelDataBWChroma[i][j][k]
                                                * locals->UrgentBurstFactorChromaPre[k] + locals->cursor_bw_pre[k]
                                                * locals->UrgentBurstFactorCursorPre[k]);
                                }
                                locals->ImmediateFlipSupportedForState[i][j] = true;
                                if (mode_lib->vba.total_dcn_read_bw_with_flip
                                                > locals->ReturnBWPerState[i][0]) {
                                        locals->ImmediateFlipSupportedForState[i][j] = false;
                                }
                                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                        if (locals->ImmediateFlipSupportedForPipe[k] == false) {
                                                locals->ImmediateFlipSupportedForState[i][j] = false;
                                        }
                                }
                        } else {
                                locals->ImmediateFlipSupportedForState[i][j] = false;
                        }
                        mode_lib->vba.UrgentOutOfOrderReturnPerChannel = dml_max3(
                                        mode_lib->vba.UrgentOutOfOrderReturnPerChannelPixelDataOnly,
                                        mode_lib->vba.UrgentOutOfOrderReturnPerChannelPixelMixedWithVMData,
                                        mode_lib->vba.UrgentOutOfOrderReturnPerChannelVMDataOnly);
                        CalculateWatermarksAndDRAMSpeedChangeSupport(
                                        mode_lib,
                                        mode_lib->vba.PrefetchMode[i][j],
                                        mode_lib->vba.NumberOfActivePlanes,
                                        mode_lib->vba.MaxLineBufferLines,
                                        mode_lib->vba.LineBufferSize,
                                        mode_lib->vba.DPPOutputBufferPixels,
                                        mode_lib->vba.DETBufferSizeInKByte[0],
                                        mode_lib->vba.WritebackInterfaceLumaBufferSize,
                                        mode_lib->vba.WritebackInterfaceChromaBufferSize,
                                        mode_lib->vba.DCFCLKPerState[i],
                                        mode_lib->vba.UrgentOutOfOrderReturnPerChannel * mode_lib->vba.NumberOfChannels,
                                        locals->ReturnBWPerState[i][0],
                                        mode_lib->vba.GPUVMEnable,
                                        locals->dpte_group_bytes,
                                        mode_lib->vba.MetaChunkSize,
                                        mode_lib->vba.UrgentLatency,
                                        mode_lib->vba.ExtraLatency,
                                        mode_lib->vba.WritebackLatency,
                                        mode_lib->vba.WritebackChunkSize,
                                        mode_lib->vba.SOCCLKPerState[i],
                                        mode_lib->vba.DRAMClockChangeLatency,
                                        mode_lib->vba.SRExitTime,
                                        mode_lib->vba.SREnterPlusExitTime,
                                        mode_lib->vba.ProjectedDCFCLKDeepSleep[0][0],
                                        locals->NoOfDPPThisState,
                                        mode_lib->vba.DCCEnable,
                                        locals->RequiredDPPCLKThisState,
                                        locals->SwathWidthYSingleDPP,
                                        locals->SwathHeightYThisState,
                                        locals->ReadBandwidthLuma,
                                        locals->SwathHeightCThisState,
                                        locals->ReadBandwidthChroma,
                                        mode_lib->vba.LBBitPerPixel,
                                        locals->SwathWidthYThisState,
                                        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->BytePerPixelInDETY,
                                        locals->BytePerPixelInDETC,
                                        mode_lib->vba.WritebackEnable,
                                        mode_lib->vba.WritebackPixelFormat,
                                        mode_lib->vba.WritebackDestinationWidth,
                                        mode_lib->vba.WritebackDestinationHeight,
                                        mode_lib->vba.WritebackSourceHeight,
                                        &locals->DRAMClockChangeSupport[i][j],
                                        &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);
                        }
                }

                /*Vertical Active BW support*/
                {
                        double MaxTotalVActiveRDBandwidth = 0.0;
                        for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
                                MaxTotalVActiveRDBandwidth = MaxTotalVActiveRDBandwidth + locals->ReadBandwidth[k];
                }
                for (i = 0; i <= mode_lib->vba.soc.num_states; ++i) {
                        locals->MaxTotalVerticalActiveAvailableBandwidth[i][0] = dml_min(
                                locals->IdealSDPPortBandwidthPerState[i][0] *
                                mode_lib->vba.MaxAveragePercentOfIdealSDPPortBWDisplayCanUseInNormalSystemOperation
                                / 100.0, mode_lib->vba.DRAMSpeedPerState[i] *
                                mode_lib->vba.NumberOfChannels *
                                mode_lib->vba.DRAMChannelWidth *
                                mode_lib->vba.MaxAveragePercentOfIdealDRAMBWDisplayCanUseInNormalSystemOperation
                                / 100.0);

                        if (MaxTotalVActiveRDBandwidth <= locals->MaxTotalVerticalActiveAvailableBandwidth[i][0]) {
                                locals->TotalVerticalActiveBandwidthSupport[i][0] = true;
                        } else {
                                locals->TotalVerticalActiveBandwidthSupport[i][0] = false;
                        }
                }
        }

        /*PTE Buffer Size Check*/

        for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
                for (j = 0; j < 2; j++) {
                        locals->PTEBufferSizeNotExceeded[i][j] = true;
                        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                                if (locals->PTEBufferSizeNotExceededY[i][j][k] == false
                                                || locals->PTEBufferSizeNotExceededC[i][j][k] == false) {
                                        locals->PTEBufferSizeNotExceeded[i][j] = false;
                                }
                        }
                }
        }
        /*Cursor Support Check*/

        mode_lib->vba.CursorSupport = true;
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (mode_lib->vba.CursorWidth[k][0] > 0.0) {
                        for (m = 0; m < mode_lib->vba.NumberOfCursors[k]; m++) {
                                if (mode_lib->vba.CursorBPP[k][m] == 64 && mode_lib->vba.Cursor64BppSupport == false) {
                                        mode_lib->vba.CursorSupport = false;
                                }
                        }
                }
        }
        /*Valid Pitch Check*/

        mode_lib->vba.PitchSupport = true;
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                locals->AlignedYPitch[k] = dml_ceil(
                                dml_max(mode_lib->vba.PitchY[k], mode_lib->vba.ViewportWidth[k]),
                                locals->MacroTileWidthY[k]);
                if (locals->AlignedYPitch[k] > mode_lib->vba.PitchY[k]) {
                        mode_lib->vba.PitchSupport = false;
                }
                if (mode_lib->vba.DCCEnable[k] == true) {
                        locals->AlignedDCCMetaPitch[k] = dml_ceil(
                                        dml_max(
                                                        mode_lib->vba.DCCMetaPitchY[k],
                                                        mode_lib->vba.ViewportWidth[k]),
                                        64.0 * locals->Read256BlockWidthY[k]);
                } else {
                        locals->AlignedDCCMetaPitch[k] = mode_lib->vba.DCCMetaPitchY[k];
                }
                if (locals->AlignedDCCMetaPitch[k] > mode_lib->vba.DCCMetaPitchY[k]) {
                        mode_lib->vba.PitchSupport = false;
                }
                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_mono_16
                                && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8) {
                        locals->AlignedCPitch[k] = dml_ceil(
                                        dml_max(
                                                        mode_lib->vba.PitchC[k],
                                                        mode_lib->vba.ViewportWidth[k] / 2.0),
                                        locals->MacroTileWidthC[k]);
                } else {
                        locals->AlignedCPitch[k] = mode_lib->vba.PitchC[k];
                }
                if (locals->AlignedCPitch[k] > mode_lib->vba.PitchC[k]) {
                        mode_lib->vba.PitchSupport = false;
                }
        }
        /*Mode Support, Voltage State and SOC Configuration*/

        for (i = mode_lib->vba.soc.num_states; i >= 0; i--) {
                for (j = 0; j < 2; j++) {
                        enum dm_validation_status status = DML_VALIDATION_OK;

                        if (!mode_lib->vba.ScaleRatioAndTapsSupport) {
                                status = DML_FAIL_SCALE_RATIO_TAP;
                        } else if (!mode_lib->vba.SourceFormatPixelAndScanSupport) {
                                status = DML_FAIL_SOURCE_PIXEL_FORMAT;
                        } else if (!locals->ViewportSizeSupport[i][0]) {
                                status = DML_FAIL_VIEWPORT_SIZE;
                        } else if (!locals->DIOSupport[i]) {
                                status = DML_FAIL_DIO_SUPPORT;
                        } else if (locals->NotEnoughDSCUnits[i]) {
                                status = DML_FAIL_NOT_ENOUGH_DSC;
                        } else if (locals->DSCCLKRequiredMoreThanSupported[i]) {
                                status = DML_FAIL_DSC_CLK_REQUIRED;
                        } else if (!locals->ROBSupport[i][0]) {
                                status = DML_FAIL_REORDERING_BUFFER;
                        } else if (!locals->DISPCLK_DPPCLK_Support[i][j]) {
                                status = DML_FAIL_DISPCLK_DPPCLK;
                        } else if (!locals->TotalAvailablePipesSupport[i][j]) {
                                status = DML_FAIL_TOTAL_AVAILABLE_PIPES;
                        } else if (!mode_lib->vba.NumberOfOTGSupport) {
                                status = DML_FAIL_NUM_OTG;
                        } else if (!mode_lib->vba.WritebackModeSupport) {
                                status = DML_FAIL_WRITEBACK_MODE;
                        } else if (!mode_lib->vba.WritebackLatencySupport) {
                                status = DML_FAIL_WRITEBACK_LATENCY;
                        } else if (!mode_lib->vba.WritebackScaleRatioAndTapsSupport) {
                                status = DML_FAIL_WRITEBACK_SCALE_RATIO_TAP;
                        } else if (!mode_lib->vba.CursorSupport) {
                                status = DML_FAIL_CURSOR_SUPPORT;
                        } else if (!mode_lib->vba.PitchSupport) {
                                status = DML_FAIL_PITCH_SUPPORT;
                        } else if (!locals->TotalVerticalActiveBandwidthSupport[i][0]) {
                                status = DML_FAIL_TOTAL_V_ACTIVE_BW;
                        } else if (!locals->PTEBufferSizeNotExceeded[i][j]) {
                                status = DML_FAIL_PTE_BUFFER_SIZE;
                        } else if (mode_lib->vba.NonsupportedDSCInputBPC) {
                                status = DML_FAIL_DSC_INPUT_BPC;
                        } else if ((mode_lib->vba.HostVMEnable
                                        && !locals->ImmediateFlipSupportedForState[i][j])) {
                                status = DML_FAIL_HOST_VM_IMMEDIATE_FLIP;
                        } else if (!locals->PrefetchSupported[i][j]) {
                                status = DML_FAIL_PREFETCH_SUPPORT;
                        } else if (!locals->VRatioInPrefetchSupported[i][j]) {
                                status = DML_FAIL_V_RATIO_PREFETCH;
                        }

                        if (status == DML_VALIDATION_OK) {
                                locals->ModeSupport[i][j] = true;
                        } else {
                                locals->ModeSupport[i][j] = false;
                        }
                        locals->ValidationStatus[i] = status;
                }
        }
        {
                unsigned int MaximumMPCCombine = 0;
                mode_lib->vba.VoltageLevel = mode_lib->vba.soc.num_states + 1;
                for (i = mode_lib->vba.VoltageOverrideLevel; i <= mode_lib->vba.soc.num_states; i++) {
                        if (locals->ModeSupport[i][0] == true || locals->ModeSupport[i][1] == true) {
                                mode_lib->vba.VoltageLevel = i;
                                if (locals->ModeSupport[i][1] == true && (locals->ModeSupport[i][0] == false
                                                || mode_lib->vba.WhenToDoMPCCombine == dm_mpc_always_when_possible
                                                || (mode_lib->vba.WhenToDoMPCCombine == dm_mpc_reduce_voltage_and_clocks
                                                        && ((locals->DRAMClockChangeSupport[i][1] == dm_dram_clock_change_vactive
                                                                && locals->DRAMClockChangeSupport[i][0] != dm_dram_clock_change_vactive)
                                                        || (locals->DRAMClockChangeSupport[i][1] == dm_dram_clock_change_vblank
                                                                && locals->DRAMClockChangeSupport[i][0] == dm_dram_clock_change_unsupported))))) {
                                        MaximumMPCCombine = 1;
                                } else {
                                        MaximumMPCCombine = 0;
                                }
                                break;
                        }
                }
                mode_lib->vba.ImmediateFlipSupport =
                        locals->ImmediateFlipSupportedForState[mode_lib->vba.VoltageLevel][MaximumMPCCombine];
                for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                        mode_lib->vba.DPPPerPlane[k] = locals->NoOfDPP[mode_lib->vba.VoltageLevel][MaximumMPCCombine][k];
                        locals->DPPCLK[k] = locals->RequiredDPPCLK[mode_lib->vba.VoltageLevel][MaximumMPCCombine][k];
                }
                mode_lib->vba.DISPCLK = locals->RequiredDISPCLK[mode_lib->vba.VoltageLevel][MaximumMPCCombine];
                mode_lib->vba.maxMpcComb = MaximumMPCCombine;
        }
        mode_lib->vba.DCFCLK = mode_lib->vba.DCFCLKPerState[mode_lib->vba.VoltageLevel];
        mode_lib->vba.DRAMSpeed = mode_lib->vba.DRAMSpeedPerState[mode_lib->vba.VoltageLevel];
        mode_lib->vba.FabricClock = mode_lib->vba.FabricClockPerState[mode_lib->vba.VoltageLevel];
        mode_lib->vba.SOCCLK = mode_lib->vba.SOCCLKPerState[mode_lib->vba.VoltageLevel];
        mode_lib->vba.ReturnBW = locals->ReturnBWPerState[mode_lib->vba.VoltageLevel][0];
        for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) {
                if (mode_lib->vba.BlendingAndTiming[k] == k) {
                        mode_lib->vba.ODMCombineEnabled[k] =
                                        locals->ODMCombineEnablePerState[mode_lib->vba.VoltageLevel][k];
                } else {
                        mode_lib->vba.ODMCombineEnabled[k] = dm_odm_combine_mode_disabled;
                }
                mode_lib->vba.DSCEnabled[k] =
                                locals->RequiresDSC[mode_lib->vba.VoltageLevel][k];
                mode_lib->vba.OutputBpp[k] =
                                locals->OutputBppPerState[mode_lib->vba.VoltageLevel][k];
        }
}

static void CalculateWatermarksAndDRAMSpeedChangeSupport(
                struct display_mode_lib *mode_lib,
                unsigned int PrefetchMode,
                unsigned int NumberOfActivePlanes,
                unsigned int MaxLineBufferLines,
                unsigned int LineBufferSize,
                unsigned int DPPOutputBufferPixels,
                unsigned int DETBufferSizeInKByte,
                unsigned int WritebackInterfaceLumaBufferSize,
                unsigned int WritebackInterfaceChromaBufferSize,
                double DCFCLK,
                double UrgentOutOfOrderReturn,
                double ReturnBW,
                bool GPUVMEnable,
                int dpte_group_bytes[],
                unsigned int MetaChunkSize,
                double UrgentLatency,
                double ExtraLatency,
                double WritebackLatency,
                double WritebackChunkSize,
                double SOCCLK,
                double DRAMClockChangeLatency,
                double SRExitTime,
                double SREnterPlusExitTime,
                double DCFCLKDeepSleep,
                int DPPPerPlane[],
                bool DCCEnable[],
                double DPPCLK[],
                double SwathWidthSingleDPPY[],
                unsigned int SwathHeightY[],
                double ReadBandwidthPlaneLuma[],
                unsigned int SwathHeightC[],
                double ReadBandwidthPlaneChroma[],
                unsigned int LBBitPerPixel[],
                double SwathWidthY[],
                double HRatio[],
                unsigned int vtaps[],
                unsigned int VTAPsChroma[],
                double VRatio[],
                unsigned int HTotal[],
                double PixelClock[],
                unsigned int BlendingAndTiming[],
                double BytePerPixelDETY[],
                double BytePerPixelDETC[],
                bool WritebackEnable[],
                enum source_format_class WritebackPixelFormat[],
                double WritebackDestinationWidth[],
                double WritebackDestinationHeight[],
                double WritebackSourceHeight[],
                enum clock_change_support *DRAMClockChangeSupport,
                double *UrgentWatermark,
                double *WritebackUrgentWatermark,
                double *DRAMClockChangeWatermark,
                double *WritebackDRAMClockChangeWatermark,
                double *StutterExitWatermark,
                double *StutterEnterPlusExitWatermark,
                double *MinActiveDRAMClockChangeLatencySupported)
{
        double EffectiveLBLatencyHidingY;
        double EffectiveLBLatencyHidingC;
        double DPPOutputBufferLinesY;
        double DPPOutputBufferLinesC;
        unsigned int DETBufferSizeY;
        unsigned int DETBufferSizeC;
        double LinesInDETY[DC__NUM_DPP__MAX];
        double LinesInDETC;
        unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_DPP__MAX];
        unsigned int LinesInDETCRoundedDownToSwath;
        double FullDETBufferingTimeY[DC__NUM_DPP__MAX];
        double FullDETBufferingTimeC;
        double ActiveDRAMClockChangeLatencyMarginY;
        double ActiveDRAMClockChangeLatencyMarginC;
        double WritebackDRAMClockChangeLatencyMargin;
        double PlaneWithMinActiveDRAMClockChangeMargin;
        double SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank;
        double FullDETBufferingTimeYStutterCriticalPlane = 0;
        double TimeToFinishSwathTransferStutterCriticalPlane = 0;
        unsigned int k, j;

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

        mode_lib->vba.TotalDataReadBandwidth = 0;
        for (k = 0; k < NumberOfActivePlanes; ++k) {
                mode_lib->vba.TotalDataReadBandwidth = mode_lib->vba.TotalDataReadBandwidth
                                + ReadBandwidthPlaneLuma[k] + ReadBandwidthPlaneChroma[k];
        }

        *UrgentWatermark = UrgentLatency + ExtraLatency;

        *DRAMClockChangeWatermark = DRAMClockChangeLatency + *UrgentWatermark;

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

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

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

        for (k = 0; k < NumberOfActivePlanes; ++k) {

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

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

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

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

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

                if (SwathWidthY[k] / 2.0 > 2 * DPPOutputBufferPixels) {
                        DPPOutputBufferLinesC = (double) DPPOutputBufferPixels
                                        / (SwathWidthY[k] / 2.0);
                } else if (SwathWidthY[k] / 2.0 > DPPOutputBufferPixels) {
                        DPPOutputBufferLinesC = 0.5;
                } else {
                        DPPOutputBufferLinesC = 1;
                }

                CalculateDETBufferSize(
                                DETBufferSizeInKByte,
                                SwathHeightY[k],
                                SwathHeightC[k],
                                &DETBufferSizeY,
                                &DETBufferSizeC);

                LinesInDETY[k] = (double)DETBufferSizeY / BytePerPixelDETY[k] / SwathWidthY[k];
                LinesInDETYRoundedDownToSwath[k] = dml_floor(LinesInDETY[k], SwathHeightY[k]);
                FullDETBufferingTimeY[k] = LinesInDETYRoundedDownToSwath[k]
                                * (HTotal[k] / PixelClock[k]) / VRatio[k];
                if (BytePerPixelDETC[k] > 0) {
                        LinesInDETC = (double)DETBufferSizeC / BytePerPixelDETC[k] / (SwathWidthY[k] / 2.0);
                        LinesInDETCRoundedDownToSwath = dml_floor(LinesInDETC, SwathHeightC[k]);
                        FullDETBufferingTimeC = LinesInDETCRoundedDownToSwath
                                        * (HTotal[k] / PixelClock[k]) / (VRatio[k] / 2);
                } else {
                        LinesInDETC = 0;
                        FullDETBufferingTimeC = 999999;
                }

                ActiveDRAMClockChangeLatencyMarginY = HTotal[k] / PixelClock[k]
                                * DPPOutputBufferLinesY + EffectiveLBLatencyHidingY
                                + FullDETBufferingTimeY[k] - *DRAMClockChangeWatermark;

                if (NumberOfActivePlanes > 1) {
                        ActiveDRAMClockChangeLatencyMarginY = ActiveDRAMClockChangeLatencyMarginY
                                - (1 - 1.0 / NumberOfActivePlanes) * SwathHeightY[k] * HTotal[k] / PixelClock[k] / VRatio[k];
                }

                if (BytePerPixelDETC[k] > 0) {
                        ActiveDRAMClockChangeLatencyMarginC = HTotal[k] / PixelClock[k]
                                        * DPPOutputBufferLinesC + EffectiveLBLatencyHidingC
                                        + FullDETBufferingTimeC - *DRAMClockChangeWatermark;
                        if (NumberOfActivePlanes > 1) {
                                ActiveDRAMClockChangeLatencyMarginC = ActiveDRAMClockChangeLatencyMarginC
                                        - (1 - 1.0 / NumberOfActivePlanes) * SwathHeightC[k] * HTotal[k] / PixelClock[k] / (VRatio[k] / 2);
                        }
                        mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(
                                        ActiveDRAMClockChangeLatencyMarginY,
                                        ActiveDRAMClockChangeLatencyMarginC);
                } else {
                        mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = ActiveDRAMClockChangeLatencyMarginY;
                }

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

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

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

        SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank = 999999;
        for (k = 0; k < NumberOfActivePlanes; ++k) {
                if (!((k == PlaneWithMinActiveDRAMClockChangeMargin) && (BlendingAndTiming[k] == k))
                                && !(BlendingAndTiming[k] == PlaneWithMinActiveDRAMClockChangeMargin)
                                && mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k]
                                                < SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank) {
                        SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank =
                                        mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k];
                }
        }

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

        if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0 && PrefetchMode == 0) {
                *DRAMClockChangeSupport = dm_dram_clock_change_vactive;
        } else if (((mode_lib->vba.SynchronizedVBlank == true
                        || mode_lib->vba.TotalNumberOfActiveOTG == 1
                        || SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank > 0)
                        && PrefetchMode == 0)) {
                *DRAMClockChangeSupport = dm_dram_clock_change_vblank;
        } else {
                *DRAMClockChangeSupport = dm_dram_clock_change_unsupported;
        }

        FullDETBufferingTimeYStutterCriticalPlane = FullDETBufferingTimeY[0];
        for (k = 0; k < NumberOfActivePlanes; ++k) {
                if (FullDETBufferingTimeY[k] <= FullDETBufferingTimeYStutterCriticalPlane) {
                        TimeToFinishSwathTransferStutterCriticalPlane = (SwathHeightY[k]
                                        - (LinesInDETY[k] - LinesInDETYRoundedDownToSwath[k]))
                                        * (HTotal[k] / PixelClock[k]) / VRatio[k];
                }
        }

        *StutterExitWatermark = SRExitTime + mode_lib->vba.LastPixelOfLineExtraWatermark
                        + ExtraLatency + 10 / DCFCLKDeepSleep;
        *StutterEnterPlusExitWatermark = dml_max(
                        SREnterPlusExitTime + mode_lib->vba.LastPixelOfLineExtraWatermark
                                        + ExtraLatency + 10 / DCFCLKDeepSleep,
                        TimeToFinishSwathTransferStutterCriticalPlane);

}

static void CalculateDCFCLKDeepSleep(
                struct display_mode_lib *mode_lib,
                unsigned int NumberOfActivePlanes,
                double BytePerPixelDETY[],
                double BytePerPixelDETC[],
                double VRatio[],
                double SwathWidthY[],
                int DPPPerPlane[],
                double HRatio[],
                double PixelClock[],
                double PSCL_THROUGHPUT[],
                double PSCL_THROUGHPUT_CHROMA[],
                double DPPCLK[],
                double *DCFCLKDeepSleep)
{
        unsigned int k;
        double DisplayPipeLineDeliveryTimeLuma;
        double DisplayPipeLineDeliveryTimeChroma;
        //double   DCFCLKDeepSleepPerPlane[DC__NUM_DPP__MAX];

        for (k = 0; k < NumberOfActivePlanes; ++k) {
                if (VRatio[k] <= 1) {
                        DisplayPipeLineDeliveryTimeLuma = SwathWidthY[k] * DPPPerPlane[k]
                                        / HRatio[k] / PixelClock[k];
                } else {
                        DisplayPipeLineDeliveryTimeLuma = SwathWidthY[k] / PSCL_THROUGHPUT[k]
                                        / DPPCLK[k];
                }
                if (BytePerPixelDETC[k] == 0) {
                        DisplayPipeLineDeliveryTimeChroma = 0;
                } else {
                        if (VRatio[k] / 2 <= 1) {
                                DisplayPipeLineDeliveryTimeChroma = SwathWidthY[k] / 2.0
                                                * DPPPerPlane[k] / (HRatio[k] / 2) / PixelClock[k];
                        } else {
                                DisplayPipeLineDeliveryTimeChroma = SwathWidthY[k] / 2.0
                                                / PSCL_THROUGHPUT_CHROMA[k] / DPPCLK[k];
                        }
                }

                if (BytePerPixelDETC[k] > 0) {
                        mode_lib->vba.DCFCLKDeepSleepPerPlane[k] = dml_max(
                                        1.1 * SwathWidthY[k] * dml_ceil(BytePerPixelDETY[k], 1)
                                                        / 32.0 / DisplayPipeLineDeliveryTimeLuma,
                                        1.1 * SwathWidthY[k] / 2.0
                                                        * dml_ceil(BytePerPixelDETC[k], 2) / 32.0
                                                        / DisplayPipeLineDeliveryTimeChroma);
                } else {
                        mode_lib->vba.DCFCLKDeepSleepPerPlane[k] = 1.1 * SwathWidthY[k]
                                        * dml_ceil(BytePerPixelDETY[k], 1) / 64.0
                                        / DisplayPipeLineDeliveryTimeLuma;
                }
                mode_lib->vba.DCFCLKDeepSleepPerPlane[k] = dml_max(
                                mode_lib->vba.DCFCLKDeepSleepPerPlane[k],
                                PixelClock[k] / 16);

        }

        *DCFCLKDeepSleep = 8;
        for (k = 0; k < NumberOfActivePlanes; ++k) {
                *DCFCLKDeepSleep = dml_max(
                                *DCFCLKDeepSleep,
                                mode_lib->vba.DCFCLKDeepSleepPerPlane[k]);
        }
}

static void CalculateDETBufferSize(
                unsigned int DETBufferSizeInKByte,
                unsigned int SwathHeightY,
                unsigned int SwathHeightC,
                unsigned int *DETBufferSizeY,
                unsigned int *DETBufferSizeC)
{
        if (SwathHeightC == 0) {
                *DETBufferSizeY = DETBufferSizeInKByte * 1024;
                *DETBufferSizeC = 0;
        } else if (SwathHeightY <= SwathHeightC) {
                *DETBufferSizeY = DETBufferSizeInKByte * 1024 / 2;
                *DETBufferSizeC = DETBufferSizeInKByte * 1024 / 2;
        } else {
                *DETBufferSizeY = DETBufferSizeInKByte * 1024 * 2 / 3;
                *DETBufferSizeC = DETBufferSizeInKByte * 1024 / 3;
        }
}

static void CalculateUrgentBurstFactor(
                unsigned int DETBufferSizeInKByte,
                unsigned int SwathHeightY,
                unsigned int SwathHeightC,
                unsigned int SwathWidthY,
                double LineTime,
                double UrgentLatency,
                double CursorBufferSize,
                unsigned int CursorWidth,
                unsigned int CursorBPP,
                double VRatio,
                double VRatioPreY,
                double VRatioPreC,
                double BytePerPixelInDETY,
                double BytePerPixelInDETC,
                double *UrgentBurstFactorCursor,
                double *UrgentBurstFactorCursorPre,
                double *UrgentBurstFactorLuma,
                double *UrgentBurstFactorLumaPre,
                double *UrgentBurstFactorChroma,
                double *UrgentBurstFactorChromaPre,
                unsigned int *NotEnoughUrgentLatencyHiding,
                unsigned int *NotEnoughUrgentLatencyHidingPre)
{
        double LinesInDETLuma;
        double LinesInDETChroma;
        unsigned int LinesInCursorBuffer;
        double CursorBufferSizeInTime;
        double CursorBufferSizeInTimePre;
        double DETBufferSizeInTimeLuma;
        double DETBufferSizeInTimeLumaPre;
        double DETBufferSizeInTimeChroma;
        double DETBufferSizeInTimeChromaPre;
        unsigned int DETBufferSizeY;
        unsigned int DETBufferSizeC;

        *NotEnoughUrgentLatencyHiding = 0;
        *NotEnoughUrgentLatencyHidingPre = 0;

        if (CursorWidth > 0) {
                LinesInCursorBuffer = 1 << (unsigned int) dml_floor(
                        dml_log2(CursorBufferSize * 1024.0 / (CursorWidth * CursorBPP / 8.0)), 1.0);
                CursorBufferSizeInTime = LinesInCursorBuffer * LineTime / VRatio;
                if (CursorBufferSizeInTime - UrgentLatency <= 0) {
                        *NotEnoughUrgentLatencyHiding = 1;
                        *UrgentBurstFactorCursor = 0;
                } else {
                        *UrgentBurstFactorCursor = CursorBufferSizeInTime
                                        / (CursorBufferSizeInTime - UrgentLatency);
                }
                if (VRatioPreY > 0) {
                        CursorBufferSizeInTimePre = LinesInCursorBuffer * LineTime / VRatioPreY;
                        if (CursorBufferSizeInTimePre - UrgentLatency <= 0) {
                                *NotEnoughUrgentLatencyHidingPre = 1;
                                *UrgentBurstFactorCursorPre = 0;
                        } else {
                                *UrgentBurstFactorCursorPre = CursorBufferSizeInTimePre
                                                / (CursorBufferSizeInTimePre - UrgentLatency);
                        }
                } else {
                        *UrgentBurstFactorCursorPre = 1;
                }
        }

        CalculateDETBufferSize(
                        DETBufferSizeInKByte,
                        SwathHeightY,
                        SwathHeightC,
                        &DETBufferSizeY,
                        &DETBufferSizeC);

        LinesInDETLuma = (double)DETBufferSizeY / BytePerPixelInDETY / SwathWidthY;
        DETBufferSizeInTimeLuma = dml_floor(LinesInDETLuma, SwathHeightY) * LineTime / VRatio;
        if (DETBufferSizeInTimeLuma - UrgentLatency <= 0) {
                *NotEnoughUrgentLatencyHiding = 1;
                *UrgentBurstFactorLuma = 0;
        } else {
                *UrgentBurstFactorLuma = DETBufferSizeInTimeLuma
                                / (DETBufferSizeInTimeLuma - UrgentLatency);
        }
        if (VRatioPreY > 0) {
                DETBufferSizeInTimeLumaPre = dml_floor(LinesInDETLuma, SwathHeightY) * LineTime
                                / VRatioPreY;
                if (DETBufferSizeInTimeLumaPre - UrgentLatency <= 0) {
                        *NotEnoughUrgentLatencyHidingPre = 1;
                        *UrgentBurstFactorLumaPre = 0;
                } else {
                        *UrgentBurstFactorLumaPre = DETBufferSizeInTimeLumaPre
                                        / (DETBufferSizeInTimeLumaPre - UrgentLatency);
                }
        } else {
                *UrgentBurstFactorLumaPre = 1;
        }

        if (BytePerPixelInDETC > 0) {
                LinesInDETChroma = (double)DETBufferSizeC / BytePerPixelInDETC / (SwathWidthY / 2);
                DETBufferSizeInTimeChroma = dml_floor(LinesInDETChroma, SwathHeightC) * LineTime
                                / (VRatio / 2);
                if (DETBufferSizeInTimeChroma - UrgentLatency <= 0) {
                        *NotEnoughUrgentLatencyHiding = 1;
                        *UrgentBurstFactorChroma = 0;
                } else {
                        *UrgentBurstFactorChroma = DETBufferSizeInTimeChroma
                                        / (DETBufferSizeInTimeChroma - UrgentLatency);
                }
                if (VRatioPreC > 0) {
                        DETBufferSizeInTimeChromaPre = dml_floor(LinesInDETChroma, SwathHeightC)
                                        * LineTime / VRatioPreC;
                        if (DETBufferSizeInTimeChromaPre - UrgentLatency <= 0) {
                                *NotEnoughUrgentLatencyHidingPre = 1;
                                *UrgentBurstFactorChromaPre = 0;
                        } else {
                                *UrgentBurstFactorChromaPre = DETBufferSizeInTimeChromaPre
                                                / (DETBufferSizeInTimeChromaPre - UrgentLatency);
                        }
                } else {
                        *UrgentBurstFactorChromaPre = 1;
                }
        }
}

static void CalculatePixelDeliveryTimes(
                unsigned int NumberOfActivePlanes,
                double VRatio[],
                double VRatioPrefetchY[],
                double VRatioPrefetchC[],
                unsigned int swath_width_luma_ub[],
                unsigned int swath_width_chroma_ub[],
                int DPPPerPlane[],
                double HRatio[],
                double PixelClock[],
                double PSCL_THROUGHPUT[],
                double PSCL_THROUGHPUT_CHROMA[],
                double DPPCLK[],
                double BytePerPixelDETC[],
                enum scan_direction_class SourceScan[],
                unsigned int BlockWidth256BytesY[],
                unsigned int BlockHeight256BytesY[],
                unsigned int BlockWidth256BytesC[],
                unsigned int BlockHeight256BytesC[],
                double DisplayPipeLineDeliveryTimeLuma[],
                double DisplayPipeLineDeliveryTimeChroma[],
                double DisplayPipeLineDeliveryTimeLumaPrefetch[],
                double DisplayPipeLineDeliveryTimeChromaPrefetch[],
                double DisplayPipeRequestDeliveryTimeLuma[],
                double DisplayPipeRequestDeliveryTimeChroma[],
                double DisplayPipeRequestDeliveryTimeLumaPrefetch[],
                double DisplayPipeRequestDeliveryTimeChromaPrefetch[])
{
        double req_per_swath_ub;
        unsigned int k;

        for (k = 0; k < NumberOfActivePlanes; ++k) {
                if (VRatio[k] <= 1) {
                        DisplayPipeLineDeliveryTimeLuma[k] = swath_width_luma_ub[k] * DPPPerPlane[k]
                                        / HRatio[k] / PixelClock[k];
                } else {
                        DisplayPipeLineDeliveryTimeLuma[k] = swath_width_luma_ub[k]
                                        / PSCL_THROUGHPUT[k] / DPPCLK[k];
                }

                if (BytePerPixelDETC[k] == 0) {
                        DisplayPipeLineDeliveryTimeChroma[k] = 0;
                } else {
                        if (VRatio[k] / 2 <= 1) {
                                DisplayPipeLineDeliveryTimeChroma[k] = swath_width_chroma_ub[k]
                                                * DPPPerPlane[k] / (HRatio[k] / 2) / PixelClock[k];
                        } else {
                                DisplayPipeLineDeliveryTimeChroma[k] = swath_width_chroma_ub[k]
                                                / PSCL_THROUGHPUT_CHROMA[k] / DPPCLK[k];
                        }
                }

                if (VRatioPrefetchY[k] <= 1) {
                        DisplayPipeLineDeliveryTimeLumaPrefetch[k] = swath_width_luma_ub[k]
                                        * DPPPerPlane[k] / HRatio[k] / PixelClock[k];
                } else {
                        DisplayPipeLineDeliveryTimeLumaPrefetch[k] = swath_width_luma_ub[k]
                                        / PSCL_THROUGHPUT[k] / DPPCLK[k];
                }

                if (BytePerPixelDETC[k] == 0) {
                        DisplayPipeLineDeliveryTimeChromaPrefetch[k] = 0;
                } else {
                        if (VRatioPrefetchC[k] <= 1) {
                                DisplayPipeLineDeliveryTimeChromaPrefetch[k] =
                                                swath_width_chroma_ub[k] * DPPPerPlane[k]
                                                                / (HRatio[k] / 2) / PixelClock[k];
                        } else {
                                DisplayPipeLineDeliveryTimeChromaPrefetch[k] =
                                                swath_width_chroma_ub[k] / PSCL_THROUGHPUT_CHROMA[k] / DPPCLK[k];
                        }
                }
        }

        for (k = 0; k < NumberOfActivePlanes; ++k) {
                if (SourceScan[k] == dm_horz) {
                        req_per_swath_ub = swath_width_luma_ub[k] / BlockWidth256BytesY[k];
                } else {
                        req_per_swath_ub = swath_width_luma_ub[k] / BlockHeight256BytesY[k];
                }
                DisplayPipeRequestDeliveryTimeLuma[k] = DisplayPipeLineDeliveryTimeLuma[k]
                                / req_per_swath_ub;
                DisplayPipeRequestDeliveryTimeLumaPrefetch[k] =
                                DisplayPipeLineDeliveryTimeLumaPrefetch[k] / req_per_swath_ub;
                if (BytePerPixelDETC[k] == 0) {
                        DisplayPipeRequestDeliveryTimeChroma[k] = 0;
                        DisplayPipeRequestDeliveryTimeChromaPrefetch[k] = 0;
                } else {
                        if (SourceScan[k] == dm_horz) {
                                req_per_swath_ub = swath_width_chroma_ub[k]
                                                / BlockWidth256BytesC[k];
                        } else {
                                req_per_swath_ub = swath_width_chroma_ub[k]
                                                / BlockHeight256BytesC[k];
                        }
                        DisplayPipeRequestDeliveryTimeChroma[k] =
                                        DisplayPipeLineDeliveryTimeChroma[k] / req_per_swath_ub;
                        DisplayPipeRequestDeliveryTimeChromaPrefetch[k] =
                                        DisplayPipeLineDeliveryTimeChromaPrefetch[k] / req_per_swath_ub;
                }
        }
}

static void CalculateMetaAndPTETimes(
                unsigned int NumberOfActivePlanes,
                bool GPUVMEnable,
                unsigned int MetaChunkSize,
                unsigned int MinMetaChunkSizeBytes,
                unsigned int GPUVMMaxPageTableLevels,
                unsigned int HTotal[],
                double VRatio[],
                double VRatioPrefetchY[],
                double VRatioPrefetchC[],
                double DestinationLinesToRequestRowInVBlank[],
                double DestinationLinesToRequestRowInImmediateFlip[],
                double DestinationLinesToRequestVMInVBlank[],
                double DestinationLinesToRequestVMInImmediateFlip[],
                bool DCCEnable[],
                double PixelClock[],
                double BytePerPixelDETY[],
                double BytePerPixelDETC[],
                enum scan_direction_class SourceScan[],
                unsigned int dpte_row_height[],
                unsigned int dpte_row_height_chroma[],
                unsigned int meta_row_width[],
                unsigned int meta_row_height[],
                unsigned int meta_req_width[],
                unsigned int meta_req_height[],
                int dpte_group_bytes[],
                unsigned int PTERequestSizeY[],
                unsigned int PTERequestSizeC[],
                unsigned int PixelPTEReqWidthY[],
                unsigned int PixelPTEReqHeightY[],
                unsigned int PixelPTEReqWidthC[],
                unsigned int PixelPTEReqHeightC[],
                unsigned int dpte_row_width_luma_ub[],
                unsigned int dpte_row_width_chroma_ub[],
                unsigned int vm_group_bytes[],
                unsigned int dpde0_bytes_per_frame_ub_l[],
                unsigned int dpde0_bytes_per_frame_ub_c[],
                unsigned int meta_pte_bytes_per_frame_ub_l[],
                unsigned int meta_pte_bytes_per_frame_ub_c[],
                double DST_Y_PER_PTE_ROW_NOM_L[],
                double DST_Y_PER_PTE_ROW_NOM_C[],
                double DST_Y_PER_META_ROW_NOM_L[],
                double TimePerMetaChunkNominal[],
                double TimePerMetaChunkVBlank[],
                double TimePerMetaChunkFlip[],
                double time_per_pte_group_nom_luma[],
                double time_per_pte_group_vblank_luma[],
                double time_per_pte_group_flip_luma[],
                double time_per_pte_group_nom_chroma[],
                double time_per_pte_group_vblank_chroma[],
                double time_per_pte_group_flip_chroma[],
                double TimePerVMGroupVBlank[],
                double TimePerVMGroupFlip[],
                double TimePerVMRequestVBlank[],
                double TimePerVMRequestFlip[])
{
        unsigned int meta_chunk_width;
        unsigned int min_meta_chunk_width;
        unsigned int meta_chunk_per_row_int;
        unsigned int meta_row_remainder;
        unsigned int meta_chunk_threshold;
        unsigned int meta_chunks_per_row_ub;
        unsigned int dpte_group_width_luma;
        unsigned int dpte_group_width_chroma;
        unsigned int dpte_groups_per_row_luma_ub;
        unsigned int dpte_groups_per_row_chroma_ub;
        unsigned int num_group_per_lower_vm_stage;
        unsigned int num_req_per_lower_vm_stage;
        unsigned int k;

        for (k = 0; k < NumberOfActivePlanes; ++k) {
                if (GPUVMEnable == true) {
                        DST_Y_PER_PTE_ROW_NOM_L[k] = dpte_row_height[k] / VRatio[k];
                        if (BytePerPixelDETC[k] == 0) {
                                DST_Y_PER_PTE_ROW_NOM_C[k] = 0;
                        } else {
                                DST_Y_PER_PTE_ROW_NOM_C[k] = dpte_row_height_chroma[k] / (VRatio[k] / 2);
                        }
                } else {
                        DST_Y_PER_PTE_ROW_NOM_L[k] = 0;
                        DST_Y_PER_PTE_ROW_NOM_C[k] = 0;
                }
                if (DCCEnable[k] == true) {
                        DST_Y_PER_META_ROW_NOM_L[k] = meta_row_height[k] / VRatio[k];
                } else {
                        DST_Y_PER_META_ROW_NOM_L[k] = 0;
                }
        }

        for (k = 0; k < NumberOfActivePlanes; ++k) {
                if (DCCEnable[k] == true) {
                        meta_chunk_width = MetaChunkSize * 1024 * 256
                                        / dml_ceil(BytePerPixelDETY[k], 1) / meta_row_height[k];
                        min_meta_chunk_width = MinMetaChunkSizeBytes * 256
                                        / dml_ceil(BytePerPixelDETY[k], 1) / meta_row_height[k];
                        meta_chunk_per_row_int = meta_row_width[k] / meta_chunk_width;
                        meta_row_remainder = meta_row_width[k] % meta_chunk_width;
                        if (SourceScan[k] == dm_horz) {
                                meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_width[k];
                        } else {
                                meta_chunk_threshold = 2 * min_meta_chunk_width
                                                - meta_req_height[k];
                        }
                        if (meta_row_remainder <= meta_chunk_threshold) {
                                meta_chunks_per_row_ub = meta_chunk_per_row_int + 1;
                        } else {
                                meta_chunks_per_row_ub = meta_chunk_per_row_int + 2;
                        }
                        TimePerMetaChunkNominal[k] = meta_row_height[k] / VRatio[k] * HTotal[k]
                                        / PixelClock[k] / meta_chunks_per_row_ub;
                        TimePerMetaChunkVBlank[k] = DestinationLinesToRequestRowInVBlank[k]
                                        * HTotal[k] / PixelClock[k] / meta_chunks_per_row_ub;
                        TimePerMetaChunkFlip[k] = DestinationLinesToRequestRowInImmediateFlip[k]
                                        * HTotal[k] / PixelClock[k] / meta_chunks_per_row_ub;
                } else {
                        TimePerMetaChunkNominal[k] = 0;
                        TimePerMetaChunkVBlank[k] = 0;
                        TimePerMetaChunkFlip[k] = 0;
                }
        }

        for (k = 0; k < NumberOfActivePlanes; ++k) {
                if (GPUVMEnable == true) {
                        if (SourceScan[k] == dm_horz) {
                                dpte_group_width_luma = dpte_group_bytes[k] / PTERequestSizeY[k]
                                                * PixelPTEReqWidthY[k];
                        } else {
                                dpte_group_width_luma = dpte_group_bytes[k] / PTERequestSizeY[k]
                                                * PixelPTEReqHeightY[k];
                        }
                        dpte_groups_per_row_luma_ub = dml_ceil(
                                        (float) dpte_row_width_luma_ub[k] / dpte_group_width_luma,
                                        1);
                        time_per_pte_group_nom_luma[k] = DST_Y_PER_PTE_ROW_NOM_L[k] * HTotal[k]
                                        / PixelClock[k] / dpte_groups_per_row_luma_ub;
                        time_per_pte_group_vblank_luma[k] = DestinationLinesToRequestRowInVBlank[k]
                                        * HTotal[k] / PixelClock[k] / dpte_groups_per_row_luma_ub;
                        time_per_pte_group_flip_luma[k] =
                                        DestinationLinesToRequestRowInImmediateFlip[k] * HTotal[k]
                                                        / PixelClock[k]
                                                        / dpte_groups_per_row_luma_ub;
                        if (BytePerPixelDETC[k] == 0) {
                                time_per_pte_group_nom_chroma[k] = 0;
                                time_per_pte_group_vblank_chroma[k] = 0;
                                time_per_pte_group_flip_chroma[k] = 0;
                        } else {
                                if (SourceScan[k] == dm_horz) {
                                        dpte_group_width_chroma = dpte_group_bytes[k]
                                                        / PTERequestSizeC[k] * PixelPTEReqWidthC[k];
                                } else {
                                        dpte_group_width_chroma = dpte_group_bytes[k]
                                                        / PTERequestSizeC[k]
                                                        * PixelPTEReqHeightC[k];
                                }
                                dpte_groups_per_row_chroma_ub = dml_ceil(
                                                (float) dpte_row_width_chroma_ub[k]
                                                                / dpte_group_width_chroma,
                                                1);
                                time_per_pte_group_nom_chroma[k] = DST_Y_PER_PTE_ROW_NOM_C[k]
                                                * HTotal[k] / PixelClock[k]
                                                / dpte_groups_per_row_chroma_ub;
                                time_per_pte_group_vblank_chroma[k] =
                                                DestinationLinesToRequestRowInVBlank[k] * HTotal[k]
                                                                / PixelClock[k]
                                                                / dpte_groups_per_row_chroma_ub;
                                time_per_pte_group_flip_chroma[k] =
                                                DestinationLinesToRequestRowInImmediateFlip[k]
                                                                * HTotal[k] / PixelClock[k]
                                                                / dpte_groups_per_row_chroma_ub;
                        }
                } else {
                        time_per_pte_group_nom_luma[k] = 0;
                        time_per_pte_group_vblank_luma[k] = 0;
                        time_per_pte_group_flip_luma[k] = 0;
                        time_per_pte_group_nom_chroma[k] = 0;
                        time_per_pte_group_vblank_chroma[k] = 0;
                        time_per_pte_group_flip_chroma[k] = 0;
                }
        }

        for (k = 0; k < NumberOfActivePlanes; ++k) {
                if (GPUVMEnable == true && (DCCEnable[k] == true || GPUVMMaxPageTableLevels > 1)) {
                        if (DCCEnable[k] == false) {
                                if (BytePerPixelDETC[k] > 0) {
                                        num_group_per_lower_vm_stage =
                                                dml_ceil((double) (dpde0_bytes_per_frame_ub_l[k]) / (double) (vm_group_bytes[k]), 1)
                                                + dml_ceil((double) (dpde0_bytes_per_frame_ub_c[k]) / (double) (vm_group_bytes[k]), 1);
                                } else {
                                        num_group_per_lower_vm_stage =
                                                        dml_ceil((double) (dpde0_bytes_per_frame_ub_l[k]) / (double) (vm_group_bytes[k]), 1);
                                }
                        } else {
                                if (GPUVMMaxPageTableLevels == 1) {
                                        if (BytePerPixelDETC[k] > 0) {
                                                num_group_per_lower_vm_stage =
                                                        dml_ceil((double) (meta_pte_bytes_per_frame_ub_l[k]) / (double) (vm_group_bytes[k]), 1)
                                                        + dml_ceil((double) (meta_pte_bytes_per_frame_ub_c[k]) / (double) (vm_group_bytes[k]), 1);
                                        } else {
                                                num_group_per_lower_vm_stage =
                                                        dml_ceil((double) (meta_pte_bytes_per_frame_ub_l[k]) / (double) (vm_group_bytes[k]), 1);
                                        }
                                } else {
                                        if (BytePerPixelDETC[k] > 0) {
                                                num_group_per_lower_vm_stage =
                                                        dml_ceil((double) (dpde0_bytes_per_frame_ub_l[k]) / (double) (vm_group_bytes[k]), 1)
                                                        + dml_ceil((double) (dpde0_bytes_per_frame_ub_c[k]) / (double) (vm_group_bytes[k]), 1)
                                                        + dml_ceil((double) (meta_pte_bytes_per_frame_ub_l[k]) / (double) (vm_group_bytes[k]), 1)
                                                        + dml_ceil((double) (meta_pte_bytes_per_frame_ub_c[k]) / (double) (vm_group_bytes[k]), 1);
                                        } else {
                                                num_group_per_lower_vm_stage =
                                                        dml_ceil((double) (dpde0_bytes_per_frame_ub_l[k]) / (double) (vm_group_bytes[k]), 1)
                                                        + dml_ceil((double) (meta_pte_bytes_per_frame_ub_l[k]) / (double) (vm_group_bytes[k]), 1);
                                        }
                                }
                        }

                        if (DCCEnable[k] == false) {
                                if (BytePerPixelDETC[k] > 0) {
                                        num_req_per_lower_vm_stage = dpde0_bytes_per_frame_ub_l[k]
                                                        / 64 + dpde0_bytes_per_frame_ub_c[k] / 64;
                                } else {
                                        num_req_per_lower_vm_stage = dpde0_bytes_per_frame_ub_l[k]
                                                        / 64;
                                }
                        } else {
                                if (GPUVMMaxPageTableLevels == 1) {
                                        if (BytePerPixelDETC[k] > 0) {
                                                num_req_per_lower_vm_stage = meta_pte_bytes_per_frame_ub_l[k] / 64
                                                        + meta_pte_bytes_per_frame_ub_c[k] / 64;
                                        } else {
                                                num_req_per_lower_vm_stage = meta_pte_bytes_per_frame_ub_l[k] / 64;
                                        }
                                } else {
                                        if (BytePerPixelDETC[k] > 0) {
                                                num_req_per_lower_vm_stage = dpde0_bytes_per_frame_ub_l[k] / 64
                                                        + dpde0_bytes_per_frame_ub_c[k] / 64
                                                        + meta_pte_bytes_per_frame_ub_l[k] / 64
                                                        + meta_pte_bytes_per_frame_ub_c[k] / 64;
                                        } else {
                                                num_req_per_lower_vm_stage = dpde0_bytes_per_frame_ub_l[k] / 64
                                                        + meta_pte_bytes_per_frame_ub_l[k] / 64;
                                        }
                                }
                        }

                        TimePerVMGroupVBlank[k] = DestinationLinesToRequestVMInVBlank[k] * HTotal[k]
                                        / PixelClock[k] / num_group_per_lower_vm_stage;
                        TimePerVMGroupFlip[k] = DestinationLinesToRequestVMInImmediateFlip[k]
                                        * HTotal[k] / PixelClock[k] / num_group_per_lower_vm_stage;
                        TimePerVMRequestVBlank[k] = DestinationLinesToRequestVMInVBlank[k]
                                        * HTotal[k] / PixelClock[k] / num_req_per_lower_vm_stage;
                        TimePerVMRequestFlip[k] = DestinationLinesToRequestVMInImmediateFlip[k]
                                        * HTotal[k] / PixelClock[k] / num_req_per_lower_vm_stage;

                        if (GPUVMMaxPageTableLevels > 2) {
                                TimePerVMGroupVBlank[k] = TimePerVMGroupVBlank[k] / 2;
                                TimePerVMGroupFlip[k] = TimePerVMGroupFlip[k] / 2;
                                TimePerVMRequestVBlank[k] = TimePerVMRequestVBlank[k] / 2;
                                TimePerVMRequestFlip[k] = TimePerVMRequestFlip[k] / 2;
                        }

                } else {
                        TimePerVMGroupVBlank[k] = 0;
                        TimePerVMGroupFlip[k] = 0;
                        TimePerVMRequestVBlank[k] = 0;
                        TimePerVMRequestFlip[k] = 0;
                }
        }
}

static double CalculateExtraLatency(
                double UrgentRoundTripAndOutOfOrderLatency,
                int TotalNumberOfActiveDPP,
                int PixelChunkSizeInKByte,
                int TotalNumberOfDCCActiveDPP,
                int MetaChunkSize,
                double ReturnBW,
                bool GPUVMEnable,
                bool HostVMEnable,
                int NumberOfActivePlanes,
                int NumberOfDPP[],
                int dpte_group_bytes[],
                double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData,
                double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly,
                int HostVMMaxPageTableLevels,
                int HostVMCachedPageTableLevels)
{
        double CalculateExtraLatency;
        double HostVMInefficiencyFactor;
        int HostVMDynamicLevels;

        if (GPUVMEnable && HostVMEnable) {
                HostVMInefficiencyFactor =
                                PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData
                                                / PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly;
                HostVMDynamicLevels = HostVMMaxPageTableLevels - HostVMCachedPageTableLevels;
        } else {
                HostVMInefficiencyFactor = 1;
                HostVMDynamicLevels = 0;
        }

        CalculateExtraLatency = UrgentRoundTripAndOutOfOrderLatency
                        + (TotalNumberOfActiveDPP * PixelChunkSizeInKByte
                                        + TotalNumberOfDCCActiveDPP * MetaChunkSize) * 1024.0
                                        / ReturnBW;

        if (GPUVMEnable) {
                int k;

                for (k = 0; k < NumberOfActivePlanes; k++) {
                        CalculateExtraLatency = CalculateExtraLatency
                                        + NumberOfDPP[k] * dpte_group_bytes[k]
                                                        * (1 + 8 * HostVMDynamicLevels)
                                                        * HostVMInefficiencyFactor / ReturnBW;
                }
        }
        return CalculateExtraLatency;
}