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