1 /*
2  * Copyright 2017 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
23  *
24  */
25 
26 
27 #include "display_mode_lib.h"
28 #include "display_mode_vba.h"
29 #include "dml_inline_defs.h"
30 
31 /*
32  * NOTE:
33  *   This file is gcc-parsable HW gospel, coming straight from HW engineers.
34  *
35  * It doesn't adhere to Linux kernel style and sometimes will do things in odd
36  * ways. Unless there is something clearly wrong with it the code should
37  * remain as-is as it provides us with a guarantee from HW that it is correct.
38  */
39 
40 
41 static void fetch_socbb_params(struct display_mode_lib *mode_lib);
42 static void fetch_ip_params(struct display_mode_lib *mode_lib);
43 static void fetch_pipe_params(struct display_mode_lib *mode_lib);
44 static void recalculate_params(
45 		struct display_mode_lib *mode_lib,
46 		const display_e2e_pipe_params_st *pipes,
47 		unsigned int num_pipes);
48 
49 static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp);
50 
51 unsigned int dml_get_voltage_level(
52 		struct display_mode_lib *mode_lib,
53 		const display_e2e_pipe_params_st *pipes,
54 		unsigned int num_pipes)
55 {
56 	bool need_recalculate = memcmp(&mode_lib->soc, &mode_lib->vba.soc, sizeof(mode_lib->vba.soc)) != 0
57 			|| memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0
58 			|| num_pipes != mode_lib->vba.cache_num_pipes
59 			|| memcmp(pipes, mode_lib->vba.cache_pipes,
60 					sizeof(display_e2e_pipe_params_st) * num_pipes) != 0;
61 
62 	mode_lib->vba.soc = mode_lib->soc;
63 	mode_lib->vba.ip = mode_lib->ip;
64 	memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes);
65 	mode_lib->vba.cache_num_pipes = num_pipes;
66 
67 	if (need_recalculate && pipes[0].clks_cfg.dppclk_mhz != 0)
68 		mode_lib->funcs.recalculate(mode_lib);
69 	else {
70 		fetch_socbb_params(mode_lib);
71 		fetch_ip_params(mode_lib);
72 		fetch_pipe_params(mode_lib);
73 		PixelClockAdjustmentForProgressiveToInterlaceUnit(mode_lib);
74 	}
75 	mode_lib->funcs.validate(mode_lib);
76 
77 	return mode_lib->vba.VoltageLevel;
78 }
79 
80 #define dml_get_attr_func(attr, var)  double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes) \
81 { \
82 	recalculate_params(mode_lib, pipes, num_pipes); \
83 	return var; \
84 }
85 
86 dml_get_attr_func(clk_dcf_deepsleep, mode_lib->vba.DCFCLKDeepSleep);
87 dml_get_attr_func(wm_urgent, mode_lib->vba.UrgentWatermark);
88 dml_get_attr_func(wm_memory_trip, mode_lib->vba.UrgentLatency);
89 dml_get_attr_func(wm_writeback_urgent, mode_lib->vba.WritebackUrgentWatermark);
90 dml_get_attr_func(wm_stutter_exit, mode_lib->vba.StutterExitWatermark);
91 dml_get_attr_func(wm_stutter_enter_exit, mode_lib->vba.StutterEnterPlusExitWatermark);
92 dml_get_attr_func(wm_z8_stutter_exit, mode_lib->vba.Z8StutterExitWatermark);
93 dml_get_attr_func(wm_z8_stutter_enter_exit, mode_lib->vba.Z8StutterEnterPlusExitWatermark);
94 dml_get_attr_func(stutter_efficiency_z8, mode_lib->vba.Z8StutterEfficiency);
95 dml_get_attr_func(stutter_num_bursts_z8, mode_lib->vba.Z8NumberOfStutterBurstsPerFrame);
96 dml_get_attr_func(wm_dram_clock_change, mode_lib->vba.DRAMClockChangeWatermark);
97 dml_get_attr_func(wm_writeback_dram_clock_change, mode_lib->vba.WritebackDRAMClockChangeWatermark);
98 dml_get_attr_func(stutter_efficiency, mode_lib->vba.StutterEfficiency);
99 dml_get_attr_func(stutter_efficiency_no_vblank, mode_lib->vba.StutterEfficiencyNotIncludingVBlank);
100 dml_get_attr_func(stutter_period, mode_lib->vba.StutterPeriod);
101 dml_get_attr_func(urgent_latency, mode_lib->vba.UrgentLatency);
102 dml_get_attr_func(urgent_extra_latency, mode_lib->vba.UrgentExtraLatency);
103 dml_get_attr_func(nonurgent_latency, mode_lib->vba.NonUrgentLatencyTolerance);
104 dml_get_attr_func(dram_clock_change_latency, mode_lib->vba.MinActiveDRAMClockChangeLatencySupported);
105 dml_get_attr_func(dispclk_calculated, mode_lib->vba.DISPCLK_calculated);
106 dml_get_attr_func(total_data_read_bw, mode_lib->vba.TotalDataReadBandwidth);
107 dml_get_attr_func(return_bw, mode_lib->vba.ReturnBW);
108 dml_get_attr_func(tcalc, mode_lib->vba.TCalc);
109 dml_get_attr_func(fraction_of_urgent_bandwidth, mode_lib->vba.FractionOfUrgentBandwidth);
110 dml_get_attr_func(fraction_of_urgent_bandwidth_imm_flip, mode_lib->vba.FractionOfUrgentBandwidthImmediateFlip);
111 
112 #define dml_get_pipe_attr_func(attr, var)  double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes, unsigned int which_pipe) \
113 {\
114 	unsigned int which_plane; \
115 	recalculate_params(mode_lib, pipes, num_pipes); \
116 	which_plane = mode_lib->vba.pipe_plane[which_pipe]; \
117 	return var[which_plane]; \
118 }
119 
120 dml_get_pipe_attr_func(dsc_delay, mode_lib->vba.DSCDelay);
121 dml_get_pipe_attr_func(dppclk_calculated, mode_lib->vba.DPPCLK_calculated);
122 dml_get_pipe_attr_func(dscclk_calculated, mode_lib->vba.DSCCLK_calculated);
123 dml_get_pipe_attr_func(min_ttu_vblank, mode_lib->vba.MinTTUVBlank);
124 dml_get_pipe_attr_func(min_ttu_vblank_in_us, mode_lib->vba.MinTTUVBlank);
125 dml_get_pipe_attr_func(vratio_prefetch_l, mode_lib->vba.VRatioPrefetchY);
126 dml_get_pipe_attr_func(vratio_prefetch_c, mode_lib->vba.VRatioPrefetchC);
127 dml_get_pipe_attr_func(dst_x_after_scaler, mode_lib->vba.DSTXAfterScaler);
128 dml_get_pipe_attr_func(dst_y_after_scaler, mode_lib->vba.DSTYAfterScaler);
129 dml_get_pipe_attr_func(dst_y_per_vm_vblank, mode_lib->vba.DestinationLinesToRequestVMInVBlank);
130 dml_get_pipe_attr_func(dst_y_per_row_vblank, mode_lib->vba.DestinationLinesToRequestRowInVBlank);
131 dml_get_pipe_attr_func(dst_y_prefetch, mode_lib->vba.DestinationLinesForPrefetch);
132 dml_get_pipe_attr_func(dst_y_per_vm_flip, mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip);
133 dml_get_pipe_attr_func(dst_y_per_row_flip, mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip);
134 dml_get_pipe_attr_func(refcyc_per_vm_group_vblank, mode_lib->vba.TimePerVMGroupVBlank);
135 dml_get_pipe_attr_func(refcyc_per_vm_group_flip, mode_lib->vba.TimePerVMGroupFlip);
136 dml_get_pipe_attr_func(refcyc_per_vm_req_vblank, mode_lib->vba.TimePerVMRequestVBlank);
137 dml_get_pipe_attr_func(refcyc_per_vm_req_flip, mode_lib->vba.TimePerVMRequestFlip);
138 dml_get_pipe_attr_func(refcyc_per_vm_group_vblank_in_us, mode_lib->vba.TimePerVMGroupVBlank);
139 dml_get_pipe_attr_func(refcyc_per_vm_group_flip_in_us, mode_lib->vba.TimePerVMGroupFlip);
140 dml_get_pipe_attr_func(refcyc_per_vm_req_vblank_in_us, mode_lib->vba.TimePerVMRequestVBlank);
141 dml_get_pipe_attr_func(refcyc_per_vm_req_flip_in_us, mode_lib->vba.TimePerVMRequestFlip);
142 dml_get_pipe_attr_func(refcyc_per_vm_dmdata_in_us, mode_lib->vba.Tdmdl_vm);
143 dml_get_pipe_attr_func(dmdata_dl_delta_in_us, mode_lib->vba.Tdmdl);
144 dml_get_pipe_attr_func(refcyc_per_line_delivery_l_in_us, mode_lib->vba.DisplayPipeLineDeliveryTimeLuma);
145 dml_get_pipe_attr_func(refcyc_per_line_delivery_c_in_us, mode_lib->vba.DisplayPipeLineDeliveryTimeChroma);
146 dml_get_pipe_attr_func(refcyc_per_line_delivery_pre_l_in_us, mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch);
147 dml_get_pipe_attr_func(refcyc_per_line_delivery_pre_c_in_us, mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch);
148 dml_get_pipe_attr_func(refcyc_per_req_delivery_l_in_us, mode_lib->vba.DisplayPipeRequestDeliveryTimeLuma);
149 dml_get_pipe_attr_func(refcyc_per_req_delivery_c_in_us, mode_lib->vba.DisplayPipeRequestDeliveryTimeChroma);
150 dml_get_pipe_attr_func(refcyc_per_req_delivery_pre_l_in_us, mode_lib->vba.DisplayPipeRequestDeliveryTimeLumaPrefetch);
151 dml_get_pipe_attr_func(refcyc_per_req_delivery_pre_c_in_us, mode_lib->vba.DisplayPipeRequestDeliveryTimeChromaPrefetch);
152 dml_get_pipe_attr_func(refcyc_per_cursor_req_delivery_in_us, mode_lib->vba.CursorRequestDeliveryTime);
153 dml_get_pipe_attr_func(refcyc_per_cursor_req_delivery_pre_in_us, mode_lib->vba.CursorRequestDeliveryTimePrefetch);
154 dml_get_pipe_attr_func(refcyc_per_meta_chunk_nom_l_in_us, mode_lib->vba.TimePerMetaChunkNominal);
155 dml_get_pipe_attr_func(refcyc_per_meta_chunk_nom_c_in_us, mode_lib->vba.TimePerChromaMetaChunkNominal);
156 dml_get_pipe_attr_func(refcyc_per_meta_chunk_vblank_l_in_us, mode_lib->vba.TimePerMetaChunkVBlank);
157 dml_get_pipe_attr_func(refcyc_per_meta_chunk_vblank_c_in_us, mode_lib->vba.TimePerChromaMetaChunkVBlank);
158 dml_get_pipe_attr_func(refcyc_per_meta_chunk_flip_l_in_us, mode_lib->vba.TimePerMetaChunkFlip);
159 dml_get_pipe_attr_func(refcyc_per_meta_chunk_flip_c_in_us, mode_lib->vba.TimePerChromaMetaChunkFlip);
160 dml_get_pipe_attr_func(vstartup, mode_lib->vba.VStartup);
161 dml_get_pipe_attr_func(vupdate_offset, mode_lib->vba.VUpdateOffsetPix);
162 dml_get_pipe_attr_func(vupdate_width, mode_lib->vba.VUpdateWidthPix);
163 dml_get_pipe_attr_func(vready_offset, mode_lib->vba.VReadyOffsetPix);
164 dml_get_pipe_attr_func(vready_at_or_after_vsync, mode_lib->vba.VREADY_AT_OR_AFTER_VSYNC);
165 dml_get_pipe_attr_func(min_dst_y_next_start, mode_lib->vba.MIN_DST_Y_NEXT_START);
166 
167 double get_total_immediate_flip_bytes(
168 		struct display_mode_lib *mode_lib,
169 		const display_e2e_pipe_params_st *pipes,
170 		unsigned int num_pipes)
171 {
172 	recalculate_params(mode_lib, pipes, num_pipes);
173 	return mode_lib->vba.TotImmediateFlipBytes;
174 }
175 
176 double get_total_immediate_flip_bw(
177 		struct display_mode_lib *mode_lib,
178 		const display_e2e_pipe_params_st *pipes,
179 		unsigned int num_pipes)
180 {
181 	unsigned int k;
182 	double immediate_flip_bw = 0.0;
183 	recalculate_params(mode_lib, pipes, num_pipes);
184 	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k)
185 		immediate_flip_bw += mode_lib->vba.ImmediateFlipBW[k];
186 	return immediate_flip_bw;
187 }
188 
189 double get_total_prefetch_bw(
190 		struct display_mode_lib *mode_lib,
191 		const display_e2e_pipe_params_st *pipes,
192 		unsigned int num_pipes)
193 {
194 	unsigned int k;
195 	double total_prefetch_bw = 0.0;
196 
197 	recalculate_params(mode_lib, pipes, num_pipes);
198 	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k)
199 		total_prefetch_bw += mode_lib->vba.PrefetchBandwidth[k];
200 	return total_prefetch_bw;
201 }
202 
203 static void fetch_socbb_params(struct display_mode_lib *mode_lib)
204 {
205 	soc_bounding_box_st *soc = &mode_lib->vba.soc;
206 	int i;
207 
208 	// SOC Bounding Box Parameters
209 	mode_lib->vba.ReturnBusWidth = soc->return_bus_width_bytes;
210 	mode_lib->vba.NumberOfChannels = soc->num_chans;
211 	mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelDataOnly =
212 			soc->pct_ideal_dram_sdp_bw_after_urgent_pixel_only; // there's always that one bastard variable that's so long it throws everything out of alignment!
213 	mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData =
214 			soc->pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm;
215 	mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly =
216 			soc->pct_ideal_dram_sdp_bw_after_urgent_vm_only;
217 	mode_lib->vba.MaxAveragePercentOfIdealSDPPortBWDisplayCanUseInNormalSystemOperation =
218 			soc->max_avg_sdp_bw_use_normal_percent;
219 	mode_lib->vba.MaxAveragePercentOfIdealDRAMBWDisplayCanUseInNormalSystemOperation =
220 			soc->max_avg_dram_bw_use_normal_percent;
221 	mode_lib->vba.UrgentLatencyPixelDataOnly = soc->urgent_latency_pixel_data_only_us;
222 	mode_lib->vba.UrgentLatencyPixelMixedWithVMData = soc->urgent_latency_pixel_mixed_with_vm_data_us;
223 	mode_lib->vba.UrgentLatencyVMDataOnly = soc->urgent_latency_vm_data_only_us;
224 	mode_lib->vba.RoundTripPingLatencyCycles = soc->round_trip_ping_latency_dcfclk_cycles;
225 	mode_lib->vba.UrgentOutOfOrderReturnPerChannelPixelDataOnly =
226 			soc->urgent_out_of_order_return_per_channel_pixel_only_bytes;
227 	mode_lib->vba.UrgentOutOfOrderReturnPerChannelPixelMixedWithVMData =
228 			soc->urgent_out_of_order_return_per_channel_pixel_and_vm_bytes;
229 	mode_lib->vba.UrgentOutOfOrderReturnPerChannelVMDataOnly =
230 			soc->urgent_out_of_order_return_per_channel_vm_only_bytes;
231 	mode_lib->vba.WritebackLatency = soc->writeback_latency_us;
232 	mode_lib->vba.SRExitTime = soc->sr_exit_time_us;
233 	mode_lib->vba.SREnterPlusExitTime = soc->sr_enter_plus_exit_time_us;
234 	mode_lib->vba.PercentOfIdealFabricAndSDPPortBWReceivedAfterUrgLatency = soc->pct_ideal_sdp_bw_after_urgent;
235 	mode_lib->vba.PercentOfIdealDRAMBWReceivedAfterUrgLatencyPixelMixedWithVMData = soc->pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm;
236 	mode_lib->vba.PercentOfIdealDRAMBWReceivedAfterUrgLatencyPixelDataOnly = soc->pct_ideal_dram_sdp_bw_after_urgent_pixel_only;
237 	mode_lib->vba.PercentOfIdealDRAMBWReceivedAfterUrgLatencyVMDataOnly = soc->pct_ideal_dram_sdp_bw_after_urgent_vm_only;
238 	mode_lib->vba.MaxAveragePercentOfIdealFabricAndSDPPortBWDisplayCanUseInNormalSystemOperation =
239 			soc->max_avg_sdp_bw_use_normal_percent;
240 	mode_lib->vba.SRExitZ8Time = soc->sr_exit_z8_time_us;
241 	mode_lib->vba.SREnterPlusExitZ8Time = soc->sr_enter_plus_exit_z8_time_us;
242 	mode_lib->vba.DRAMClockChangeLatency = soc->dram_clock_change_latency_us;
243 	mode_lib->vba.DummyPStateCheck = soc->dram_clock_change_latency_us == soc->dummy_pstate_latency_us;
244 	mode_lib->vba.DRAMClockChangeSupportsVActive = !soc->disable_dram_clock_change_vactive_support ||
245 			mode_lib->vba.DummyPStateCheck;
246 	mode_lib->vba.AllowDramClockChangeOneDisplayVactive = soc->allow_dram_clock_one_display_vactive;
247 	mode_lib->vba.AllowDRAMSelfRefreshOrDRAMClockChangeInVblank =
248 		soc->allow_dram_self_refresh_or_dram_clock_change_in_vblank;
249 
250 	mode_lib->vba.Downspreading = soc->downspread_percent;
251 	mode_lib->vba.DRAMChannelWidth = soc->dram_channel_width_bytes;   // new!
252 	mode_lib->vba.FabricDatapathToDCNDataReturn = soc->fabric_datapath_to_dcn_data_return_bytes; // new!
253 	mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading = soc->dcn_downspread_percent;   // new
254 	mode_lib->vba.DISPCLKDPPCLKVCOSpeed = soc->dispclk_dppclk_vco_speed_mhz;   // new
255 	mode_lib->vba.VMMPageSize = soc->vmm_page_size_bytes;
256 	mode_lib->vba.GPUVMMinPageSize = soc->gpuvm_min_page_size_bytes / 1024;
257 	mode_lib->vba.HostVMMinPageSize = soc->hostvm_min_page_size_bytes / 1024;
258 	// Set the voltage scaling clocks as the defaults. Most of these will
259 	// be set to different values by the test
260 	for (i = 0; i < mode_lib->vba.soc.num_states; i++)
261 		if (soc->clock_limits[i].state == mode_lib->vba.VoltageLevel)
262 			break;
263 
264 	mode_lib->vba.DCFCLK = soc->clock_limits[i].dcfclk_mhz;
265 	mode_lib->vba.SOCCLK = soc->clock_limits[i].socclk_mhz;
266 	mode_lib->vba.DRAMSpeed = soc->clock_limits[i].dram_speed_mts;
267 	mode_lib->vba.FabricClock = soc->clock_limits[i].fabricclk_mhz;
268 
269 	mode_lib->vba.XFCBusTransportTime = soc->xfc_bus_transport_time_us;
270 	mode_lib->vba.XFCXBUFLatencyTolerance = soc->xfc_xbuf_latency_tolerance_us;
271 	mode_lib->vba.UseUrgentBurstBandwidth = soc->use_urgent_burst_bw;
272 
273 	mode_lib->vba.SupportGFX7CompatibleTilingIn32bppAnd64bpp = false;
274 	mode_lib->vba.WritebackLumaAndChromaScalingSupported = true;
275 	mode_lib->vba.MaxHSCLRatio = 4;
276 	mode_lib->vba.MaxVSCLRatio = 4;
277 	mode_lib->vba.Cursor64BppSupport = true;
278 	for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
279 		mode_lib->vba.DCFCLKPerState[i] = soc->clock_limits[i].dcfclk_mhz;
280 		mode_lib->vba.FabricClockPerState[i] = soc->clock_limits[i].fabricclk_mhz;
281 		mode_lib->vba.SOCCLKPerState[i] = soc->clock_limits[i].socclk_mhz;
282 		mode_lib->vba.PHYCLKPerState[i] = soc->clock_limits[i].phyclk_mhz;
283 		mode_lib->vba.PHYCLKD18PerState[i] = soc->clock_limits[i].phyclk_d18_mhz;
284 		mode_lib->vba.MaxDppclk[i] = soc->clock_limits[i].dppclk_mhz;
285 		mode_lib->vba.MaxDSCCLK[i] = soc->clock_limits[i].dscclk_mhz;
286 		mode_lib->vba.DRAMSpeedPerState[i] = soc->clock_limits[i].dram_speed_mts;
287 		//mode_lib->vba.DRAMSpeedPerState[i] = soc->clock_limits[i].dram_speed_mhz;
288 		mode_lib->vba.MaxDispclk[i] = soc->clock_limits[i].dispclk_mhz;
289 		mode_lib->vba.DTBCLKPerState[i] = soc->clock_limits[i].dtbclk_mhz;
290 	}
291 
292 	mode_lib->vba.DoUrgentLatencyAdjustment =
293 		soc->do_urgent_latency_adjustment;
294 	mode_lib->vba.UrgentLatencyAdjustmentFabricClockComponent =
295 		soc->urgent_latency_adjustment_fabric_clock_component_us;
296 	mode_lib->vba.UrgentLatencyAdjustmentFabricClockReference =
297 		soc->urgent_latency_adjustment_fabric_clock_reference_mhz;
298 }
299 
300 static void fetch_ip_params(struct display_mode_lib *mode_lib)
301 {
302 	ip_params_st *ip = &mode_lib->vba.ip;
303 
304 	// IP Parameters
305 	mode_lib->vba.UseMinimumRequiredDCFCLK = ip->use_min_dcfclk;
306 	mode_lib->vba.ClampMinDCFCLK = ip->clamp_min_dcfclk;
307 	mode_lib->vba.MaxNumDPP = ip->max_num_dpp;
308 	mode_lib->vba.MaxNumOTG = ip->max_num_otg;
309 	mode_lib->vba.MaxNumHDMIFRLOutputs = ip->max_num_hdmi_frl_outputs;
310 	mode_lib->vba.MaxNumWriteback = ip->max_num_wb;
311 	mode_lib->vba.CursorChunkSize = ip->cursor_chunk_size;
312 	mode_lib->vba.CursorBufferSize = ip->cursor_buffer_size;
313 
314 	mode_lib->vba.MaxDCHUBToPSCLThroughput = ip->max_dchub_pscl_bw_pix_per_clk;
315 	mode_lib->vba.MaxPSCLToLBThroughput = ip->max_pscl_lb_bw_pix_per_clk;
316 	mode_lib->vba.ROBBufferSizeInKByte = ip->rob_buffer_size_kbytes;
317 	mode_lib->vba.DETBufferSizeInKByte[0] = ip->det_buffer_size_kbytes;
318 	mode_lib->vba.ConfigReturnBufferSizeInKByte = ip->config_return_buffer_size_in_kbytes;
319 	mode_lib->vba.CompressedBufferSegmentSizeInkByte = ip->compressed_buffer_segment_size_in_kbytes;
320 	mode_lib->vba.MetaFIFOSizeInKEntries = ip->meta_fifo_size_in_kentries;
321 	mode_lib->vba.ZeroSizeBufferEntries = ip->zero_size_buffer_entries;
322 	mode_lib->vba.COMPBUF_RESERVED_SPACE_64B = ip->compbuf_reserved_space_64b;
323 	mode_lib->vba.COMPBUF_RESERVED_SPACE_ZS = ip->compbuf_reserved_space_zs;
324 	mode_lib->vba.MaximumDSCBitsPerComponent = ip->maximum_dsc_bits_per_component;
325 	mode_lib->vba.DSC422NativeSupport = ip->dsc422_native_support;
326 
327 	mode_lib->vba.PixelChunkSizeInKByte = ip->pixel_chunk_size_kbytes;
328 	mode_lib->vba.MetaChunkSize = ip->meta_chunk_size_kbytes;
329 	mode_lib->vba.MinMetaChunkSizeBytes = ip->min_meta_chunk_size_bytes;
330 	mode_lib->vba.WritebackChunkSize = ip->writeback_chunk_size_kbytes;
331 	mode_lib->vba.LineBufferSize = ip->line_buffer_size_bits;
332 	mode_lib->vba.MaxLineBufferLines = ip->max_line_buffer_lines;
333 	mode_lib->vba.PTEBufferSizeInRequestsLuma = ip->dpte_buffer_size_in_pte_reqs_luma;
334 	mode_lib->vba.PTEBufferSizeInRequestsChroma = ip->dpte_buffer_size_in_pte_reqs_chroma;
335 	mode_lib->vba.DPPOutputBufferPixels = ip->dpp_output_buffer_pixels;
336 	mode_lib->vba.OPPOutputBufferLines = ip->opp_output_buffer_lines;
337 	mode_lib->vba.MaxHSCLRatio = ip->max_hscl_ratio;
338 	mode_lib->vba.MaxVSCLRatio = ip->max_vscl_ratio;
339 	mode_lib->vba.WritebackInterfaceLumaBufferSize = ip->writeback_luma_buffer_size_kbytes * 1024;
340 	mode_lib->vba.WritebackInterfaceChromaBufferSize = ip->writeback_chroma_buffer_size_kbytes * 1024;
341 
342 	mode_lib->vba.WritebackInterfaceBufferSize = ip->writeback_interface_buffer_size_kbytes;
343 	mode_lib->vba.WritebackLineBufferSize = ip->writeback_line_buffer_buffer_size;
344 
345 	mode_lib->vba.WritebackChromaLineBufferWidth =
346 			ip->writeback_chroma_line_buffer_width_pixels;
347 	mode_lib->vba.WritebackLineBufferLumaBufferSize =
348 			ip->writeback_line_buffer_luma_buffer_size;
349 	mode_lib->vba.WritebackLineBufferChromaBufferSize =
350 			ip->writeback_line_buffer_chroma_buffer_size;
351 	mode_lib->vba.Writeback10bpc420Supported = ip->writeback_10bpc420_supported;
352 	mode_lib->vba.WritebackMaxHSCLRatio = ip->writeback_max_hscl_ratio;
353 	mode_lib->vba.WritebackMaxVSCLRatio = ip->writeback_max_vscl_ratio;
354 	mode_lib->vba.WritebackMinHSCLRatio = ip->writeback_min_hscl_ratio;
355 	mode_lib->vba.WritebackMinVSCLRatio = ip->writeback_min_vscl_ratio;
356 	mode_lib->vba.WritebackMaxHSCLTaps = ip->writeback_max_hscl_taps;
357 	mode_lib->vba.WritebackMaxVSCLTaps = ip->writeback_max_vscl_taps;
358 	mode_lib->vba.WritebackConfiguration = dm_normal;
359 	mode_lib->vba.GPUVMMaxPageTableLevels = ip->gpuvm_max_page_table_levels;
360 	mode_lib->vba.HostVMMaxNonCachedPageTableLevels = ip->hostvm_max_page_table_levels;
361 	mode_lib->vba.HostVMMaxPageTableLevels = ip->hostvm_max_page_table_levels;
362 	mode_lib->vba.HostVMCachedPageTableLevels = ip->hostvm_cached_page_table_levels;
363 	mode_lib->vba.MaxInterDCNTileRepeaters = ip->max_inter_dcn_tile_repeaters;
364 	mode_lib->vba.NumberOfDSC = ip->num_dsc;
365 	mode_lib->vba.ODMCapability = ip->odm_capable;
366 	mode_lib->vba.DISPCLKRampingMargin = ip->dispclk_ramp_margin_percent;
367 
368 	mode_lib->vba.XFCSupported = ip->xfc_supported;
369 	mode_lib->vba.XFCFillBWOverhead = ip->xfc_fill_bw_overhead_percent;
370 	mode_lib->vba.XFCFillConstant = ip->xfc_fill_constant_bytes;
371 	mode_lib->vba.DPPCLKDelaySubtotal = ip->dppclk_delay_subtotal;
372 	mode_lib->vba.DPPCLKDelaySCL = ip->dppclk_delay_scl;
373 	mode_lib->vba.DPPCLKDelaySCLLBOnly = ip->dppclk_delay_scl_lb_only;
374 	mode_lib->vba.DPPCLKDelayCNVCFormater = ip->dppclk_delay_cnvc_formatter;
375 	mode_lib->vba.DPPCLKDelayCNVCCursor = ip->dppclk_delay_cnvc_cursor;
376 	mode_lib->vba.DISPCLKDelaySubtotal = ip->dispclk_delay_subtotal;
377 	mode_lib->vba.DynamicMetadataVMEnabled = ip->dynamic_metadata_vm_enabled;
378 	mode_lib->vba.ODMCombine4To1Supported = ip->odm_combine_4to1_supported;
379 	mode_lib->vba.ProgressiveToInterlaceUnitInOPP = ip->ptoi_supported;
380 	mode_lib->vba.PDEProcessingBufIn64KBReqs = ip->pde_proc_buffer_size_64k_reqs;
381 	mode_lib->vba.PTEGroupSize = ip->pte_group_size_bytes;
382 	mode_lib->vba.SupportGFX7CompatibleTilingIn32bppAnd64bpp = ip->gfx7_compat_tiling_supported;
383 }
384 
385 static void fetch_pipe_params(struct display_mode_lib *mode_lib)
386 {
387 	display_e2e_pipe_params_st *pipes = mode_lib->vba.cache_pipes;
388 	ip_params_st *ip = &mode_lib->vba.ip;
389 
390 	unsigned int OTGInstPlane[DC__NUM_DPP__MAX];
391 	unsigned int j, k;
392 	bool PlaneVisited[DC__NUM_DPP__MAX];
393 	bool visited[DC__NUM_DPP__MAX];
394 
395 	// Convert Pipes to Planes
396 	for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k)
397 		visited[k] = false;
398 
399 	mode_lib->vba.NumberOfActivePlanes = 0;
400 	mode_lib->vba.ImmediateFlipSupport = false;
401 	for (j = 0; j < mode_lib->vba.cache_num_pipes; ++j) {
402 		display_pipe_source_params_st *src = &pipes[j].pipe.src;
403 		display_pipe_dest_params_st *dst = &pipes[j].pipe.dest;
404 		scaler_ratio_depth_st *scl = &pipes[j].pipe.scale_ratio_depth;
405 		scaler_taps_st *taps = &pipes[j].pipe.scale_taps;
406 		display_output_params_st *dout = &pipes[j].dout;
407 		display_clocks_and_cfg_st *clks = &pipes[j].clks_cfg;
408 
409 		if (visited[j])
410 			continue;
411 		visited[j] = true;
412 
413 		mode_lib->vba.ImmediateFlipRequirement[j] = dm_immediate_flip_not_required;
414 		mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes;
415 		mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1;
416 		mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] =
417 				(enum scan_direction_class) (src->source_scan);
418 		mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] =
419 				src->viewport_width;
420 		mode_lib->vba.ViewportWidthChroma[mode_lib->vba.NumberOfActivePlanes] =
421 				src->viewport_width_c;
422 		mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] =
423 				src->viewport_height;
424 		mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] =
425 				src->viewport_height_c;
426 		mode_lib->vba.ViewportYStartY[mode_lib->vba.NumberOfActivePlanes] =
427 				src->viewport_y_y;
428 		mode_lib->vba.ViewportYStartC[mode_lib->vba.NumberOfActivePlanes] =
429 				src->viewport_y_c;
430 		mode_lib->vba.PitchY[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch;
431 		mode_lib->vba.SurfaceWidthY[mode_lib->vba.NumberOfActivePlanes] = src->surface_width_y;
432 		mode_lib->vba.SurfaceHeightY[mode_lib->vba.NumberOfActivePlanes] = src->surface_height_y;
433 		mode_lib->vba.PitchC[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch_c;
434 		mode_lib->vba.SurfaceHeightC[mode_lib->vba.NumberOfActivePlanes] = src->surface_height_c;
435 		mode_lib->vba.SurfaceWidthC[mode_lib->vba.NumberOfActivePlanes] = src->surface_width_c;
436 		mode_lib->vba.DCCMetaPitchY[mode_lib->vba.NumberOfActivePlanes] = src->meta_pitch;
437 		mode_lib->vba.DCCMetaPitchC[mode_lib->vba.NumberOfActivePlanes] = src->meta_pitch_c;
438 		mode_lib->vba.HRatio[mode_lib->vba.NumberOfActivePlanes] = scl->hscl_ratio;
439 		mode_lib->vba.HRatioChroma[mode_lib->vba.NumberOfActivePlanes] = scl->hscl_ratio_c;
440 		mode_lib->vba.VRatio[mode_lib->vba.NumberOfActivePlanes] = scl->vscl_ratio;
441 		mode_lib->vba.VRatioChroma[mode_lib->vba.NumberOfActivePlanes] = scl->vscl_ratio_c;
442 		mode_lib->vba.ScalerEnabled[mode_lib->vba.NumberOfActivePlanes] = scl->scl_enable;
443 		mode_lib->vba.Interlace[mode_lib->vba.NumberOfActivePlanes] = dst->interlaced;
444 		if (dst->interlaced && !ip->ptoi_supported) {
445 			mode_lib->vba.VRatio[mode_lib->vba.NumberOfActivePlanes] *= 2.0;
446 			mode_lib->vba.VRatioChroma[mode_lib->vba.NumberOfActivePlanes] *= 2.0;
447 		}
448 		mode_lib->vba.htaps[mode_lib->vba.NumberOfActivePlanes] = taps->htaps;
449 		mode_lib->vba.vtaps[mode_lib->vba.NumberOfActivePlanes] = taps->vtaps;
450 		mode_lib->vba.HTAPsChroma[mode_lib->vba.NumberOfActivePlanes] = taps->htaps_c;
451 		mode_lib->vba.VTAPsChroma[mode_lib->vba.NumberOfActivePlanes] = taps->vtaps_c;
452 		mode_lib->vba.HTotal[mode_lib->vba.NumberOfActivePlanes] = dst->htotal;
453 		mode_lib->vba.VTotal[mode_lib->vba.NumberOfActivePlanes] = dst->vtotal;
454 		mode_lib->vba.VFrontPorch[mode_lib->vba.NumberOfActivePlanes] = dst->vfront_porch;
455 		mode_lib->vba.DCCFractionOfZeroSizeRequestsLuma[mode_lib->vba.NumberOfActivePlanes] = src->dcc_fraction_of_zs_req_luma;
456 		mode_lib->vba.DCCFractionOfZeroSizeRequestsChroma[mode_lib->vba.NumberOfActivePlanes] = src->dcc_fraction_of_zs_req_chroma;
457 		mode_lib->vba.DCCEnable[mode_lib->vba.NumberOfActivePlanes] =
458 				src->dcc_use_global ?
459 						ip->dcc_supported : src->dcc && ip->dcc_supported;
460 		mode_lib->vba.DCCRate[mode_lib->vba.NumberOfActivePlanes] = src->dcc_rate;
461 		/* TODO: Needs to be set based on src->dcc_rate_luma/chroma */
462 		mode_lib->vba.DCCRateLuma[mode_lib->vba.NumberOfActivePlanes] = src->dcc_rate;
463 		mode_lib->vba.DCCRateChroma[mode_lib->vba.NumberOfActivePlanes] = src->dcc_rate_chroma;
464 		mode_lib->vba.SourcePixelFormat[mode_lib->vba.NumberOfActivePlanes] = (enum source_format_class) (src->source_format);
465 		mode_lib->vba.HActive[mode_lib->vba.NumberOfActivePlanes] = dst->hactive;
466 		mode_lib->vba.VActive[mode_lib->vba.NumberOfActivePlanes] = dst->vactive;
467 		mode_lib->vba.SurfaceTiling[mode_lib->vba.NumberOfActivePlanes] =
468 				(enum dm_swizzle_mode) (src->sw_mode);
469 		mode_lib->vba.ScalerRecoutWidth[mode_lib->vba.NumberOfActivePlanes] =
470 				dst->recout_width; // TODO: or should this be full_recout_width???...maybe only when in hsplit mode?
471 		mode_lib->vba.ODMCombineEnabled[mode_lib->vba.NumberOfActivePlanes] =
472 				dst->odm_combine;
473 		mode_lib->vba.OutputFormat[mode_lib->vba.NumberOfActivePlanes] =
474 				(enum output_format_class) (dout->output_format);
475 		mode_lib->vba.OutputBpp[mode_lib->vba.NumberOfActivePlanes] =
476 				dout->output_bpp;
477 		mode_lib->vba.Output[mode_lib->vba.NumberOfActivePlanes] =
478 				(enum output_encoder_class) (dout->output_type);
479 		mode_lib->vba.skip_dio_check[mode_lib->vba.NumberOfActivePlanes] =
480 				dout->is_virtual;
481 
482 		if (!dout->dsc_enable)
483 			mode_lib->vba.ForcedOutputLinkBPP[mode_lib->vba.NumberOfActivePlanes] = dout->output_bpp;
484 		else
485 			mode_lib->vba.ForcedOutputLinkBPP[mode_lib->vba.NumberOfActivePlanes] = 0.0;
486 
487 		mode_lib->vba.OutputLinkDPLanes[mode_lib->vba.NumberOfActivePlanes] =
488 				dout->dp_lanes;
489 		/* TODO: Needs to be set based on dout->audio.audio_sample_rate_khz/sample_layout */
490 		mode_lib->vba.AudioSampleRate[mode_lib->vba.NumberOfActivePlanes] =
491 			dout->max_audio_sample_rate;
492 		mode_lib->vba.AudioSampleLayout[mode_lib->vba.NumberOfActivePlanes] =
493 			1;
494 		mode_lib->vba.DRAMClockChangeLatencyOverride = 0.0;
495 		mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable;
496 		mode_lib->vba.DSCEnable[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable;
497 		mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] =
498 				dout->dsc_slices;
499 		if (!dout->dsc_input_bpc) {
500 			mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] =
501 				ip->maximum_dsc_bits_per_component;
502 		} else {
503 			mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] =
504 				dout->dsc_input_bpc;
505 		}
506 		mode_lib->vba.WritebackEnable[mode_lib->vba.NumberOfActivePlanes] = dout->wb_enable;
507 		mode_lib->vba.ActiveWritebacksPerPlane[mode_lib->vba.NumberOfActivePlanes] =
508 				dout->num_active_wb;
509 		mode_lib->vba.WritebackSourceHeight[mode_lib->vba.NumberOfActivePlanes] =
510 				dout->wb.wb_src_height;
511 		mode_lib->vba.WritebackSourceWidth[mode_lib->vba.NumberOfActivePlanes] =
512 				dout->wb.wb_src_width;
513 		mode_lib->vba.WritebackDestinationWidth[mode_lib->vba.NumberOfActivePlanes] =
514 				dout->wb.wb_dst_width;
515 		mode_lib->vba.WritebackDestinationHeight[mode_lib->vba.NumberOfActivePlanes] =
516 				dout->wb.wb_dst_height;
517 		mode_lib->vba.WritebackHRatio[mode_lib->vba.NumberOfActivePlanes] =
518 				dout->wb.wb_hratio;
519 		mode_lib->vba.WritebackVRatio[mode_lib->vba.NumberOfActivePlanes] =
520 				dout->wb.wb_vratio;
521 		mode_lib->vba.WritebackPixelFormat[mode_lib->vba.NumberOfActivePlanes] =
522 				(enum source_format_class) (dout->wb.wb_pixel_format);
523 		mode_lib->vba.WritebackHTaps[mode_lib->vba.NumberOfActivePlanes] =
524 				dout->wb.wb_htaps_luma;
525 		mode_lib->vba.WritebackVTaps[mode_lib->vba.NumberOfActivePlanes] =
526 				dout->wb.wb_vtaps_luma;
527 		mode_lib->vba.WritebackLumaHTaps[mode_lib->vba.NumberOfActivePlanes] =
528 				dout->wb.wb_htaps_luma;
529 		mode_lib->vba.WritebackLumaVTaps[mode_lib->vba.NumberOfActivePlanes] =
530 				dout->wb.wb_vtaps_luma;
531 		mode_lib->vba.WritebackChromaHTaps[mode_lib->vba.NumberOfActivePlanes] =
532 				dout->wb.wb_htaps_chroma;
533 		mode_lib->vba.WritebackChromaVTaps[mode_lib->vba.NumberOfActivePlanes] =
534 				dout->wb.wb_vtaps_chroma;
535 		mode_lib->vba.WritebackHRatio[mode_lib->vba.NumberOfActivePlanes] =
536 				dout->wb.wb_hratio;
537 		mode_lib->vba.WritebackVRatio[mode_lib->vba.NumberOfActivePlanes] =
538 				dout->wb.wb_vratio;
539 
540 		mode_lib->vba.DynamicMetadataEnable[mode_lib->vba.NumberOfActivePlanes] =
541 				src->dynamic_metadata_enable;
542 		mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[mode_lib->vba.NumberOfActivePlanes] =
543 				src->dynamic_metadata_lines_before_active;
544 		mode_lib->vba.DynamicMetadataTransmittedBytes[mode_lib->vba.NumberOfActivePlanes] =
545 				src->dynamic_metadata_xmit_bytes;
546 
547 		mode_lib->vba.XFCEnabled[mode_lib->vba.NumberOfActivePlanes] = src->xfc_enable
548 				&& ip->xfc_supported;
549 		mode_lib->vba.XFCSlvChunkSize = src->xfc_params.xfc_slv_chunk_size_bytes;
550 		mode_lib->vba.XFCTSlvVupdateOffset = src->xfc_params.xfc_tslv_vupdate_offset_us;
551 		mode_lib->vba.XFCTSlvVupdateWidth = src->xfc_params.xfc_tslv_vupdate_width_us;
552 		mode_lib->vba.XFCTSlvVreadyOffset = src->xfc_params.xfc_tslv_vready_offset_us;
553 		mode_lib->vba.PixelClock[mode_lib->vba.NumberOfActivePlanes] = dst->pixel_rate_mhz;
554 		mode_lib->vba.PixelClockBackEnd[mode_lib->vba.NumberOfActivePlanes] = dst->pixel_rate_mhz;
555 		mode_lib->vba.DPPCLK[mode_lib->vba.NumberOfActivePlanes] = clks->dppclk_mhz;
556 		if (ip->is_line_buffer_bpp_fixed)
557 			mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] =
558 					ip->line_buffer_fixed_bpp;
559 		else {
560 			unsigned int lb_depth;
561 
562 			switch (scl->lb_depth) {
563 			case dm_lb_6:
564 				lb_depth = 18;
565 				break;
566 			case dm_lb_8:
567 				lb_depth = 24;
568 				break;
569 			case dm_lb_10:
570 				lb_depth = 30;
571 				break;
572 			case dm_lb_12:
573 				lb_depth = 36;
574 				break;
575 			case dm_lb_16:
576 				lb_depth = 48;
577 				break;
578 			case dm_lb_19:
579 				lb_depth = 57;
580 				break;
581 			default:
582 				lb_depth = 36;
583 			}
584 			mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] = lb_depth;
585 		}
586 		mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes] = 0;
587 		// The DML spreadsheet assumes that the two cursors utilize the same amount of bandwidth. We'll
588 		// calculate things a little more accurately
589 		for (k = 0; k < DC__NUM_CURSOR__MAX; ++k) {
590 			switch (k) {
591 			case 0:
592 				mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][0] =
593 						CursorBppEnumToBits(
594 								(enum cursor_bpp) (src->cur0_bpp));
595 				mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][0] =
596 						src->cur0_src_width;
597 				if (src->cur0_src_width > 0)
598 					mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++;
599 				break;
600 			case 1:
601 				mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][1] =
602 						CursorBppEnumToBits(
603 								(enum cursor_bpp) (src->cur1_bpp));
604 				mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][1] =
605 						src->cur1_src_width;
606 				if (src->cur1_src_width > 0)
607 					mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++;
608 				break;
609 			default:
610 				dml_print(
611 						"ERROR: Number of cursors specified exceeds supported maximum\n")
612 				;
613 			}
614 		}
615 
616 		OTGInstPlane[mode_lib->vba.NumberOfActivePlanes] = dst->otg_inst;
617 
618 		if (j == 0)
619 			mode_lib->vba.UseMaximumVStartup = dst->use_maximum_vstartup;
620 		else
621 			mode_lib->vba.UseMaximumVStartup = mode_lib->vba.UseMaximumVStartup
622 									|| dst->use_maximum_vstartup;
623 
624 		if (dst->odm_combine && !src->is_hsplit)
625 			dml_print(
626 					"ERROR: ODM Combine is specified but is_hsplit has not be specified for pipe %i\n",
627 					j);
628 
629 		if (src->is_hsplit) {
630 			for (k = j + 1; k < mode_lib->vba.cache_num_pipes; ++k) {
631 				display_pipe_source_params_st *src_k = &pipes[k].pipe.src;
632 				display_pipe_dest_params_st *dst_k = &pipes[k].pipe.dest;
633 
634 				if (src_k->is_hsplit && !visited[k]
635 						&& src->hsplit_grp == src_k->hsplit_grp) {
636 					mode_lib->vba.pipe_plane[k] =
637 							mode_lib->vba.NumberOfActivePlanes;
638 					mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes]++;
639 					if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes]
640 							== dm_horz) {
641 						mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] +=
642 								src_k->viewport_width;
643 						mode_lib->vba.ViewportWidthChroma[mode_lib->vba.NumberOfActivePlanes] +=
644 								src_k->viewport_width_c;
645 						mode_lib->vba.ScalerRecoutWidth[mode_lib->vba.NumberOfActivePlanes] +=
646 								dst_k->recout_width;
647 					} else {
648 						mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] +=
649 								src_k->viewport_height;
650 						mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] +=
651 								src_k->viewport_height_c;
652 					}
653 
654 					visited[k] = true;
655 				}
656 			}
657 		}
658 		if (src->viewport_width_max) {
659 			int hdiv_c = src->source_format >= dm_420_8 && src->source_format <= dm_422_10 ? 2 : 1;
660 			int vdiv_c = src->source_format >= dm_420_8 && src->source_format <= dm_420_12 ? 2 : 1;
661 
662 			if (mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] > src->viewport_width_max)
663 				mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width_max;
664 			if (mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] > src->viewport_height_max)
665 				mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height_max;
666 			if (mode_lib->vba.ViewportWidthChroma[mode_lib->vba.NumberOfActivePlanes] > src->viewport_width_max / hdiv_c)
667 				mode_lib->vba.ViewportWidthChroma[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width_max / hdiv_c;
668 			if (mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] > src->viewport_height_max / vdiv_c)
669 				mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height_max / vdiv_c;
670 		}
671 
672 		if (pipes[j].pipe.src.immediate_flip) {
673 			mode_lib->vba.ImmediateFlipSupport = true;
674 			mode_lib->vba.ImmediateFlipRequirement[j] = dm_immediate_flip_required;
675 		}
676 
677 		mode_lib->vba.NumberOfActivePlanes++;
678 	}
679 
680 	// handle overlays through BlendingAndTiming
681 	// BlendingAndTiming tells you which instance to look at to get timing, the so called 'master'
682 
683 	for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j)
684 		PlaneVisited[j] = false;
685 
686 	for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) {
687 		for (k = j + 1; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
688 			if (!PlaneVisited[k] && OTGInstPlane[j] == OTGInstPlane[k]) {
689 				// doesn't matter, so choose the smaller one
690 				mode_lib->vba.BlendingAndTiming[j] = j;
691 				PlaneVisited[j] = true;
692 				mode_lib->vba.BlendingAndTiming[k] = j;
693 				PlaneVisited[k] = true;
694 			}
695 		}
696 
697 		if (!PlaneVisited[j]) {
698 			mode_lib->vba.BlendingAndTiming[j] = j;
699 			PlaneVisited[j] = true;
700 		}
701 	}
702 
703 	mode_lib->vba.UseUnboundedRequesting = dm_unbounded_requesting;
704 	for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) {
705 		if (pipes[k].pipe.src.unbounded_req_mode == 0)
706 			mode_lib->vba.UseUnboundedRequesting = dm_unbounded_requesting_disable;
707 	}
708 	// TODO: ODMCombineEnabled => 2 * DPPPerPlane...actually maybe not since all pipes are specified
709 	// Do we want the dscclk to automatically be halved? Guess not since the value is specified
710 	mode_lib->vba.SynchronizedVBlank = pipes[0].pipe.dest.synchronized_vblank_all_planes;
711 	for (k = 1; k < mode_lib->vba.cache_num_pipes; ++k) {
712 		ASSERT(mode_lib->vba.SynchronizedVBlank == pipes[k].pipe.dest.synchronized_vblank_all_planes);
713 	}
714 
715 	mode_lib->vba.GPUVMEnable = false;
716 	mode_lib->vba.HostVMEnable = false;
717 	mode_lib->vba.OverrideGPUVMPageTableLevels = 0;
718 	mode_lib->vba.OverrideHostVMPageTableLevels = 0;
719 
720 	for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) {
721 		mode_lib->vba.GPUVMEnable = mode_lib->vba.GPUVMEnable || !!pipes[k].pipe.src.gpuvm || !!pipes[k].pipe.src.vm;
722 		mode_lib->vba.OverrideGPUVMPageTableLevels =
723 				(pipes[k].pipe.src.gpuvm_levels_force_en
724 						&& mode_lib->vba.OverrideGPUVMPageTableLevels
725 								< pipes[k].pipe.src.gpuvm_levels_force) ?
726 						pipes[k].pipe.src.gpuvm_levels_force :
727 						mode_lib->vba.OverrideGPUVMPageTableLevels;
728 
729 		mode_lib->vba.HostVMEnable = mode_lib->vba.HostVMEnable || !!pipes[k].pipe.src.hostvm || !!pipes[k].pipe.src.vm;
730 		mode_lib->vba.OverrideHostVMPageTableLevels =
731 				(pipes[k].pipe.src.hostvm_levels_force_en
732 						&& mode_lib->vba.OverrideHostVMPageTableLevels
733 								< pipes[k].pipe.src.hostvm_levels_force) ?
734 						pipes[k].pipe.src.hostvm_levels_force :
735 						mode_lib->vba.OverrideHostVMPageTableLevels;
736 	}
737 
738 	if (mode_lib->vba.OverrideGPUVMPageTableLevels)
739 		mode_lib->vba.GPUVMMaxPageTableLevels = mode_lib->vba.OverrideGPUVMPageTableLevels;
740 
741 	if (mode_lib->vba.OverrideHostVMPageTableLevels)
742 		mode_lib->vba.HostVMMaxPageTableLevels = mode_lib->vba.OverrideHostVMPageTableLevels;
743 
744 	mode_lib->vba.GPUVMEnable = mode_lib->vba.GPUVMEnable && !!ip->gpuvm_enable;
745 	mode_lib->vba.HostVMEnable = mode_lib->vba.HostVMEnable && !!ip->hostvm_enable;
746 }
747 
748 // in wm mode we pull the parameters needed from the display_e2e_pipe_params_st structs
749 // rather than working them out as in recalculate_ms
750 static void recalculate_params(
751 		struct display_mode_lib *mode_lib,
752 		const display_e2e_pipe_params_st *pipes,
753 		unsigned int num_pipes)
754 {
755 	// This is only safe to use memcmp because there are non-POD types in struct display_mode_lib
756 	if (memcmp(&mode_lib->soc, &mode_lib->vba.soc, sizeof(mode_lib->vba.soc)) != 0
757 			|| memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0
758 			|| num_pipes != mode_lib->vba.cache_num_pipes
759 			|| memcmp(
760 					pipes,
761 					mode_lib->vba.cache_pipes,
762 					sizeof(display_e2e_pipe_params_st) * num_pipes) != 0) {
763 		mode_lib->vba.soc = mode_lib->soc;
764 		mode_lib->vba.ip = mode_lib->ip;
765 		memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes);
766 		mode_lib->vba.cache_num_pipes = num_pipes;
767 		mode_lib->funcs.recalculate(mode_lib);
768 	}
769 }
770 
771 bool Calculate256BBlockSizes(
772 		enum source_format_class SourcePixelFormat,
773 		enum dm_swizzle_mode SurfaceTiling,
774 		unsigned int BytePerPixelY,
775 		unsigned int BytePerPixelC,
776 		unsigned int *BlockHeight256BytesY,
777 		unsigned int *BlockHeight256BytesC,
778 		unsigned int *BlockWidth256BytesY,
779 		unsigned int *BlockWidth256BytesC)
780 {
781 	if ((SourcePixelFormat == dm_444_64 || SourcePixelFormat == dm_444_32
782 			|| SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_8)) {
783 		if (SurfaceTiling == dm_sw_linear) {
784 			*BlockHeight256BytesY = 1;
785 		} else if (SourcePixelFormat == dm_444_64) {
786 			*BlockHeight256BytesY = 4;
787 		} else if (SourcePixelFormat == dm_444_8) {
788 			*BlockHeight256BytesY = 16;
789 		} else {
790 			*BlockHeight256BytesY = 8;
791 		}
792 		*BlockWidth256BytesY = 256 / BytePerPixelY / *BlockHeight256BytesY;
793 		*BlockHeight256BytesC = 0;
794 		*BlockWidth256BytesC = 0;
795 	} else {
796 		if (SurfaceTiling == dm_sw_linear) {
797 			*BlockHeight256BytesY = 1;
798 			*BlockHeight256BytesC = 1;
799 		} else if (SourcePixelFormat == dm_420_8) {
800 			*BlockHeight256BytesY = 16;
801 			*BlockHeight256BytesC = 8;
802 		} else {
803 			*BlockHeight256BytesY = 8;
804 			*BlockHeight256BytesC = 8;
805 		}
806 		*BlockWidth256BytesY = 256 / BytePerPixelY / *BlockHeight256BytesY;
807 		*BlockWidth256BytesC = 256 / BytePerPixelC / *BlockHeight256BytesC;
808 	}
809 	return true;
810 }
811 
812 bool CalculateMinAndMaxPrefetchMode(
813 		enum self_refresh_affinity AllowDRAMSelfRefreshOrDRAMClockChangeInVblank,
814 		unsigned int *MinPrefetchMode,
815 		unsigned int *MaxPrefetchMode)
816 {
817 	if (AllowDRAMSelfRefreshOrDRAMClockChangeInVblank
818 			== dm_neither_self_refresh_nor_mclk_switch) {
819 		*MinPrefetchMode = 2;
820 		*MaxPrefetchMode = 2;
821 		return false;
822 	} else if (AllowDRAMSelfRefreshOrDRAMClockChangeInVblank == dm_allow_self_refresh) {
823 		*MinPrefetchMode = 1;
824 		*MaxPrefetchMode = 1;
825 		return false;
826 	} else if (AllowDRAMSelfRefreshOrDRAMClockChangeInVblank
827 			== dm_allow_self_refresh_and_mclk_switch) {
828 		*MinPrefetchMode = 0;
829 		*MaxPrefetchMode = 0;
830 		return false;
831 	} else if (AllowDRAMSelfRefreshOrDRAMClockChangeInVblank
832 			== dm_try_to_allow_self_refresh_and_mclk_switch) {
833 		*MinPrefetchMode = 0;
834 		*MaxPrefetchMode = 2;
835 		return false;
836 	}
837 	*MinPrefetchMode = 0;
838 	*MaxPrefetchMode = 2;
839 	return true;
840 }
841 
842 void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mode_lib *mode_lib)
843 {
844 	unsigned int k;
845 
846 	//Progressive To Interlace Unit Effect
847 	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
848 		mode_lib->vba.PixelClockBackEnd[k] = mode_lib->vba.PixelClock[k];
849 		if (mode_lib->vba.Interlace[k] == 1
850 				&& mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true) {
851 			mode_lib->vba.PixelClock[k] = 2 * mode_lib->vba.PixelClock[k];
852 		}
853 	}
854 }
855 
856 static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp)
857 {
858 	switch (ebpp) {
859 	case dm_cur_2bit:
860 		return 2;
861 	case dm_cur_32bit:
862 		return 32;
863 	case dm_cur_64bit:
864 		return 64;
865 	default:
866 		return 0;
867 	}
868 }
869 
870 void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib)
871 {
872 	soc_bounding_box_st *soc = &mode_lib->vba.soc;
873 	unsigned int k;
874 	unsigned int total_pipes = 0;
875 
876 	mode_lib->vba.VoltageLevel = mode_lib->vba.cache_pipes[0].clks_cfg.voltage;
877 	mode_lib->vba.ReturnBW = mode_lib->vba.ReturnBWPerState[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb];
878 	if (mode_lib->vba.ReturnBW == 0)
879 		mode_lib->vba.ReturnBW = mode_lib->vba.ReturnBWPerState[mode_lib->vba.VoltageLevel][0];
880 	mode_lib->vba.FabricAndDRAMBandwidth = mode_lib->vba.FabricAndDRAMBandwidthPerState[mode_lib->vba.VoltageLevel];
881 
882 	fetch_socbb_params(mode_lib);
883 	fetch_ip_params(mode_lib);
884 	fetch_pipe_params(mode_lib);
885 
886 	mode_lib->vba.DCFCLK = mode_lib->vba.cache_pipes[0].clks_cfg.dcfclk_mhz;
887 	mode_lib->vba.SOCCLK = mode_lib->vba.cache_pipes[0].clks_cfg.socclk_mhz;
888 	if (mode_lib->vba.cache_pipes[0].clks_cfg.dispclk_mhz > 0.0)
889 		mode_lib->vba.DISPCLK = mode_lib->vba.cache_pipes[0].clks_cfg.dispclk_mhz;
890 	else
891 		mode_lib->vba.DISPCLK = soc->clock_limits[mode_lib->vba.VoltageLevel].dispclk_mhz;
892 
893 	// Total Available Pipes Support Check
894 	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
895 		total_pipes += mode_lib->vba.DPPPerPlane[k];
896 	}
897 	ASSERT(total_pipes <= DC__NUM_DPP__MAX);
898 }
899 
900 double CalculateWriteBackDISPCLK(
901 		enum source_format_class WritebackPixelFormat,
902 		double PixelClock,
903 		double WritebackHRatio,
904 		double WritebackVRatio,
905 		unsigned int WritebackLumaHTaps,
906 		unsigned int WritebackLumaVTaps,
907 		unsigned int WritebackChromaHTaps,
908 		unsigned int WritebackChromaVTaps,
909 		double WritebackDestinationWidth,
910 		unsigned int HTotal,
911 		unsigned int WritebackChromaLineBufferWidth)
912 {
913 	double CalculateWriteBackDISPCLK = 1.01 * PixelClock * dml_max(
914 		dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio,
915 		dml_max((WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) * dml_ceil(WritebackDestinationWidth / 4.0, 1)
916 			+ dml_ceil(WritebackDestinationWidth / 4.0, 1)) / (double) HTotal + dml_ceil(1.0 / WritebackVRatio, 1)
917 			* (dml_ceil(WritebackLumaVTaps / 4.0, 1) + 4.0) / (double) HTotal,
918 			dml_ceil(1.0 / WritebackVRatio, 1) * WritebackDestinationWidth / (double) HTotal));
919 	if (WritebackPixelFormat != dm_444_32) {
920 		CalculateWriteBackDISPCLK = dml_max(CalculateWriteBackDISPCLK, 1.01 * PixelClock * dml_max(
921 			dml_ceil(WritebackChromaHTaps / 2.0, 1) / (2 * WritebackHRatio),
922 			dml_max((WritebackChromaVTaps * dml_ceil(1 / (2 * WritebackVRatio), 1) * dml_ceil(WritebackDestinationWidth / 2.0 / 2.0, 1)
923 				+ dml_ceil(WritebackDestinationWidth / 2.0 / WritebackChromaLineBufferWidth, 1)) / HTotal
924 				+ dml_ceil(1 / (2 * WritebackVRatio), 1) * (dml_ceil(WritebackChromaVTaps / 4.0, 1) + 4) / HTotal,
925 				dml_ceil(1.0 / (2 * WritebackVRatio), 1) * WritebackDestinationWidth / 2.0 / HTotal)));
926 	}
927 	return CalculateWriteBackDISPCLK;
928 }
929 
930