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 
248 	mode_lib->vba.Downspreading = soc->downspread_percent;
249 	mode_lib->vba.DRAMChannelWidth = soc->dram_channel_width_bytes;   // new!
250 	mode_lib->vba.FabricDatapathToDCNDataReturn = soc->fabric_datapath_to_dcn_data_return_bytes; // new!
251 	mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading = soc->dcn_downspread_percent;   // new
252 	mode_lib->vba.DISPCLKDPPCLKVCOSpeed = soc->dispclk_dppclk_vco_speed_mhz;   // new
253 	mode_lib->vba.VMMPageSize = soc->vmm_page_size_bytes;
254 	mode_lib->vba.GPUVMMinPageSize = soc->gpuvm_min_page_size_bytes / 1024;
255 	mode_lib->vba.HostVMMinPageSize = soc->hostvm_min_page_size_bytes / 1024;
256 	// Set the voltage scaling clocks as the defaults. Most of these will
257 	// be set to different values by the test
258 	for (i = 0; i < mode_lib->vba.soc.num_states; i++)
259 		if (soc->clock_limits[i].state == mode_lib->vba.VoltageLevel)
260 			break;
261 
262 	mode_lib->vba.DCFCLK = soc->clock_limits[i].dcfclk_mhz;
263 	mode_lib->vba.SOCCLK = soc->clock_limits[i].socclk_mhz;
264 	mode_lib->vba.DRAMSpeed = soc->clock_limits[i].dram_speed_mts;
265 	mode_lib->vba.FabricClock = soc->clock_limits[i].fabricclk_mhz;
266 
267 	mode_lib->vba.XFCBusTransportTime = soc->xfc_bus_transport_time_us;
268 	mode_lib->vba.XFCXBUFLatencyTolerance = soc->xfc_xbuf_latency_tolerance_us;
269 	mode_lib->vba.UseUrgentBurstBandwidth = soc->use_urgent_burst_bw;
270 
271 	mode_lib->vba.SupportGFX7CompatibleTilingIn32bppAnd64bpp = false;
272 	mode_lib->vba.WritebackLumaAndChromaScalingSupported = true;
273 	mode_lib->vba.MaxHSCLRatio = 4;
274 	mode_lib->vba.MaxVSCLRatio = 4;
275 	mode_lib->vba.Cursor64BppSupport = true;
276 	for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
277 		mode_lib->vba.DCFCLKPerState[i] = soc->clock_limits[i].dcfclk_mhz;
278 		mode_lib->vba.FabricClockPerState[i] = soc->clock_limits[i].fabricclk_mhz;
279 		mode_lib->vba.SOCCLKPerState[i] = soc->clock_limits[i].socclk_mhz;
280 		mode_lib->vba.PHYCLKPerState[i] = soc->clock_limits[i].phyclk_mhz;
281 		mode_lib->vba.PHYCLKD18PerState[i] = soc->clock_limits[i].phyclk_d18_mhz;
282 		mode_lib->vba.MaxDppclk[i] = soc->clock_limits[i].dppclk_mhz;
283 		mode_lib->vba.MaxDSCCLK[i] = soc->clock_limits[i].dscclk_mhz;
284 		mode_lib->vba.DRAMSpeedPerState[i] = soc->clock_limits[i].dram_speed_mts;
285 		//mode_lib->vba.DRAMSpeedPerState[i] = soc->clock_limits[i].dram_speed_mhz;
286 		mode_lib->vba.MaxDispclk[i] = soc->clock_limits[i].dispclk_mhz;
287 		mode_lib->vba.DTBCLKPerState[i] = soc->clock_limits[i].dtbclk_mhz;
288 	}
289 
290 	mode_lib->vba.DoUrgentLatencyAdjustment =
291 		soc->do_urgent_latency_adjustment;
292 	mode_lib->vba.UrgentLatencyAdjustmentFabricClockComponent =
293 		soc->urgent_latency_adjustment_fabric_clock_component_us;
294 	mode_lib->vba.UrgentLatencyAdjustmentFabricClockReference =
295 		soc->urgent_latency_adjustment_fabric_clock_reference_mhz;
296 }
297 
298 static void fetch_ip_params(struct display_mode_lib *mode_lib)
299 {
300 	ip_params_st *ip = &mode_lib->vba.ip;
301 
302 	// IP Parameters
303 	mode_lib->vba.UseMinimumRequiredDCFCLK = ip->use_min_dcfclk;
304 	mode_lib->vba.ClampMinDCFCLK = ip->clamp_min_dcfclk;
305 	mode_lib->vba.MaxNumDPP = ip->max_num_dpp;
306 	mode_lib->vba.MaxNumOTG = ip->max_num_otg;
307 	mode_lib->vba.MaxNumHDMIFRLOutputs = ip->max_num_hdmi_frl_outputs;
308 	mode_lib->vba.MaxNumWriteback = ip->max_num_wb;
309 	mode_lib->vba.CursorChunkSize = ip->cursor_chunk_size;
310 	mode_lib->vba.CursorBufferSize = ip->cursor_buffer_size;
311 
312 	mode_lib->vba.MaxDCHUBToPSCLThroughput = ip->max_dchub_pscl_bw_pix_per_clk;
313 	mode_lib->vba.MaxPSCLToLBThroughput = ip->max_pscl_lb_bw_pix_per_clk;
314 	mode_lib->vba.ROBBufferSizeInKByte = ip->rob_buffer_size_kbytes;
315 	mode_lib->vba.DETBufferSizeInKByte[0] = ip->det_buffer_size_kbytes;
316 	mode_lib->vba.ConfigReturnBufferSizeInKByte = ip->config_return_buffer_size_in_kbytes;
317 	mode_lib->vba.CompressedBufferSegmentSizeInkByte = ip->compressed_buffer_segment_size_in_kbytes;
318 	mode_lib->vba.MetaFIFOSizeInKEntries = ip->meta_fifo_size_in_kentries;
319 	mode_lib->vba.ZeroSizeBufferEntries = ip->zero_size_buffer_entries;
320 	mode_lib->vba.COMPBUF_RESERVED_SPACE_64B = ip->compbuf_reserved_space_64b;
321 	mode_lib->vba.COMPBUF_RESERVED_SPACE_ZS = ip->compbuf_reserved_space_zs;
322 	mode_lib->vba.MaximumDSCBitsPerComponent = ip->maximum_dsc_bits_per_component;
323 	mode_lib->vba.DSC422NativeSupport = ip->dsc422_native_support;
324 
325 	mode_lib->vba.PixelChunkSizeInKByte = ip->pixel_chunk_size_kbytes;
326 	mode_lib->vba.MetaChunkSize = ip->meta_chunk_size_kbytes;
327 	mode_lib->vba.MinMetaChunkSizeBytes = ip->min_meta_chunk_size_bytes;
328 	mode_lib->vba.WritebackChunkSize = ip->writeback_chunk_size_kbytes;
329 	mode_lib->vba.LineBufferSize = ip->line_buffer_size_bits;
330 	mode_lib->vba.MaxLineBufferLines = ip->max_line_buffer_lines;
331 	mode_lib->vba.PTEBufferSizeInRequestsLuma = ip->dpte_buffer_size_in_pte_reqs_luma;
332 	mode_lib->vba.PTEBufferSizeInRequestsChroma = ip->dpte_buffer_size_in_pte_reqs_chroma;
333 	mode_lib->vba.DPPOutputBufferPixels = ip->dpp_output_buffer_pixels;
334 	mode_lib->vba.OPPOutputBufferLines = ip->opp_output_buffer_lines;
335 	mode_lib->vba.MaxHSCLRatio = ip->max_hscl_ratio;
336 	mode_lib->vba.MaxVSCLRatio = ip->max_vscl_ratio;
337 	mode_lib->vba.WritebackInterfaceLumaBufferSize = ip->writeback_luma_buffer_size_kbytes * 1024;
338 	mode_lib->vba.WritebackInterfaceChromaBufferSize = ip->writeback_chroma_buffer_size_kbytes * 1024;
339 
340 	mode_lib->vba.WritebackInterfaceBufferSize = ip->writeback_interface_buffer_size_kbytes;
341 	mode_lib->vba.WritebackLineBufferSize = ip->writeback_line_buffer_buffer_size;
342 
343 	mode_lib->vba.WritebackChromaLineBufferWidth =
344 			ip->writeback_chroma_line_buffer_width_pixels;
345 	mode_lib->vba.WritebackLineBufferLumaBufferSize =
346 			ip->writeback_line_buffer_luma_buffer_size;
347 	mode_lib->vba.WritebackLineBufferChromaBufferSize =
348 			ip->writeback_line_buffer_chroma_buffer_size;
349 	mode_lib->vba.Writeback10bpc420Supported = ip->writeback_10bpc420_supported;
350 	mode_lib->vba.WritebackMaxHSCLRatio = ip->writeback_max_hscl_ratio;
351 	mode_lib->vba.WritebackMaxVSCLRatio = ip->writeback_max_vscl_ratio;
352 	mode_lib->vba.WritebackMinHSCLRatio = ip->writeback_min_hscl_ratio;
353 	mode_lib->vba.WritebackMinVSCLRatio = ip->writeback_min_vscl_ratio;
354 	mode_lib->vba.WritebackMaxHSCLTaps = ip->writeback_max_hscl_taps;
355 	mode_lib->vba.WritebackMaxVSCLTaps = ip->writeback_max_vscl_taps;
356 	mode_lib->vba.WritebackConfiguration = dm_normal;
357 	mode_lib->vba.GPUVMMaxPageTableLevels = ip->gpuvm_max_page_table_levels;
358 	mode_lib->vba.HostVMMaxNonCachedPageTableLevels = ip->hostvm_max_page_table_levels;
359 	mode_lib->vba.HostVMMaxPageTableLevels = ip->hostvm_max_page_table_levels;
360 	mode_lib->vba.HostVMCachedPageTableLevels = ip->hostvm_cached_page_table_levels;
361 	mode_lib->vba.MaxInterDCNTileRepeaters = ip->max_inter_dcn_tile_repeaters;
362 	mode_lib->vba.NumberOfDSC = ip->num_dsc;
363 	mode_lib->vba.ODMCapability = ip->odm_capable;
364 	mode_lib->vba.DISPCLKRampingMargin = ip->dispclk_ramp_margin_percent;
365 
366 	mode_lib->vba.XFCSupported = ip->xfc_supported;
367 	mode_lib->vba.XFCFillBWOverhead = ip->xfc_fill_bw_overhead_percent;
368 	mode_lib->vba.XFCFillConstant = ip->xfc_fill_constant_bytes;
369 	mode_lib->vba.DPPCLKDelaySubtotal = ip->dppclk_delay_subtotal;
370 	mode_lib->vba.DPPCLKDelaySCL = ip->dppclk_delay_scl;
371 	mode_lib->vba.DPPCLKDelaySCLLBOnly = ip->dppclk_delay_scl_lb_only;
372 	mode_lib->vba.DPPCLKDelayCNVCFormater = ip->dppclk_delay_cnvc_formatter;
373 	mode_lib->vba.DPPCLKDelayCNVCCursor = ip->dppclk_delay_cnvc_cursor;
374 	mode_lib->vba.DISPCLKDelaySubtotal = ip->dispclk_delay_subtotal;
375 	mode_lib->vba.DynamicMetadataVMEnabled = ip->dynamic_metadata_vm_enabled;
376 	mode_lib->vba.ODMCombine4To1Supported = ip->odm_combine_4to1_supported;
377 	mode_lib->vba.ProgressiveToInterlaceUnitInOPP = ip->ptoi_supported;
378 	mode_lib->vba.PDEProcessingBufIn64KBReqs = ip->pde_proc_buffer_size_64k_reqs;
379 	mode_lib->vba.PTEGroupSize = ip->pte_group_size_bytes;
380 	mode_lib->vba.SupportGFX7CompatibleTilingIn32bppAnd64bpp = ip->gfx7_compat_tiling_supported;
381 }
382 
383 static void fetch_pipe_params(struct display_mode_lib *mode_lib)
384 {
385 	display_e2e_pipe_params_st *pipes = mode_lib->vba.cache_pipes;
386 	ip_params_st *ip = &mode_lib->vba.ip;
387 
388 	unsigned int OTGInstPlane[DC__NUM_DPP__MAX];
389 	unsigned int j, k;
390 	bool PlaneVisited[DC__NUM_DPP__MAX];
391 	bool visited[DC__NUM_DPP__MAX];
392 
393 	// Convert Pipes to Planes
394 	for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k)
395 		visited[k] = false;
396 
397 	mode_lib->vba.NumberOfActivePlanes = 0;
398 	mode_lib->vba.ImmediateFlipSupport = false;
399 	mode_lib->vba.ImmediateFlipRequirement = dm_immediate_flip_not_required;
400 	for (j = 0; j < mode_lib->vba.cache_num_pipes; ++j) {
401 		display_pipe_source_params_st *src = &pipes[j].pipe.src;
402 		display_pipe_dest_params_st *dst = &pipes[j].pipe.dest;
403 		scaler_ratio_depth_st *scl = &pipes[j].pipe.scale_ratio_depth;
404 		scaler_taps_st *taps = &pipes[j].pipe.scale_taps;
405 		display_output_params_st *dout = &pipes[j].dout;
406 		display_clocks_and_cfg_st *clks = &pipes[j].clks_cfg;
407 
408 		if (visited[j])
409 			continue;
410 		visited[j] = true;
411 
412 		mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes;
413 		mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1;
414 		mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] =
415 				(enum scan_direction_class) (src->source_scan);
416 		mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] =
417 				src->viewport_width;
418 		mode_lib->vba.ViewportWidthChroma[mode_lib->vba.NumberOfActivePlanes] =
419 				src->viewport_width_c;
420 		mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] =
421 				src->viewport_height;
422 		mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] =
423 				src->viewport_height_c;
424 		mode_lib->vba.ViewportYStartY[mode_lib->vba.NumberOfActivePlanes] =
425 				src->viewport_y_y;
426 		mode_lib->vba.ViewportYStartC[mode_lib->vba.NumberOfActivePlanes] =
427 				src->viewport_y_c;
428 		mode_lib->vba.PitchY[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch;
429 		mode_lib->vba.SurfaceWidthY[mode_lib->vba.NumberOfActivePlanes] = src->surface_width_y;
430 		mode_lib->vba.SurfaceHeightY[mode_lib->vba.NumberOfActivePlanes] = src->surface_height_y;
431 		mode_lib->vba.PitchC[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch_c;
432 		mode_lib->vba.SurfaceHeightC[mode_lib->vba.NumberOfActivePlanes] = src->surface_height_c;
433 		mode_lib->vba.SurfaceWidthC[mode_lib->vba.NumberOfActivePlanes] = src->surface_width_c;
434 		mode_lib->vba.DCCMetaPitchY[mode_lib->vba.NumberOfActivePlanes] = src->meta_pitch;
435 		mode_lib->vba.DCCMetaPitchC[mode_lib->vba.NumberOfActivePlanes] = src->meta_pitch_c;
436 		mode_lib->vba.HRatio[mode_lib->vba.NumberOfActivePlanes] = scl->hscl_ratio;
437 		mode_lib->vba.HRatioChroma[mode_lib->vba.NumberOfActivePlanes] = scl->hscl_ratio_c;
438 		mode_lib->vba.VRatio[mode_lib->vba.NumberOfActivePlanes] = scl->vscl_ratio;
439 		mode_lib->vba.VRatioChroma[mode_lib->vba.NumberOfActivePlanes] = scl->vscl_ratio_c;
440 		mode_lib->vba.ScalerEnabled[mode_lib->vba.NumberOfActivePlanes] = scl->scl_enable;
441 		mode_lib->vba.Interlace[mode_lib->vba.NumberOfActivePlanes] = dst->interlaced;
442 		if (dst->interlaced && !ip->ptoi_supported) {
443 			mode_lib->vba.VRatio[mode_lib->vba.NumberOfActivePlanes] *= 2.0;
444 			mode_lib->vba.VRatioChroma[mode_lib->vba.NumberOfActivePlanes] *= 2.0;
445 		}
446 		mode_lib->vba.htaps[mode_lib->vba.NumberOfActivePlanes] = taps->htaps;
447 		mode_lib->vba.vtaps[mode_lib->vba.NumberOfActivePlanes] = taps->vtaps;
448 		mode_lib->vba.HTAPsChroma[mode_lib->vba.NumberOfActivePlanes] = taps->htaps_c;
449 		mode_lib->vba.VTAPsChroma[mode_lib->vba.NumberOfActivePlanes] = taps->vtaps_c;
450 		mode_lib->vba.HTotal[mode_lib->vba.NumberOfActivePlanes] = dst->htotal;
451 		mode_lib->vba.VTotal[mode_lib->vba.NumberOfActivePlanes] = dst->vtotal;
452 		mode_lib->vba.VFrontPorch[mode_lib->vba.NumberOfActivePlanes] = dst->vfront_porch;
453 		mode_lib->vba.DCCFractionOfZeroSizeRequestsLuma[mode_lib->vba.NumberOfActivePlanes] = src->dcc_fraction_of_zs_req_luma;
454 		mode_lib->vba.DCCFractionOfZeroSizeRequestsChroma[mode_lib->vba.NumberOfActivePlanes] = src->dcc_fraction_of_zs_req_chroma;
455 		mode_lib->vba.DCCEnable[mode_lib->vba.NumberOfActivePlanes] =
456 				src->dcc_use_global ?
457 						ip->dcc_supported : src->dcc && ip->dcc_supported;
458 		mode_lib->vba.DCCRate[mode_lib->vba.NumberOfActivePlanes] = src->dcc_rate;
459 		/* TODO: Needs to be set based on src->dcc_rate_luma/chroma */
460 		mode_lib->vba.DCCRateLuma[mode_lib->vba.NumberOfActivePlanes] = src->dcc_rate;
461 		mode_lib->vba.DCCRateChroma[mode_lib->vba.NumberOfActivePlanes] = src->dcc_rate_chroma;
462 		mode_lib->vba.SourcePixelFormat[mode_lib->vba.NumberOfActivePlanes] = (enum source_format_class) (src->source_format);
463 		mode_lib->vba.HActive[mode_lib->vba.NumberOfActivePlanes] = dst->hactive;
464 		mode_lib->vba.VActive[mode_lib->vba.NumberOfActivePlanes] = dst->vactive;
465 		mode_lib->vba.SurfaceTiling[mode_lib->vba.NumberOfActivePlanes] =
466 				(enum dm_swizzle_mode) (src->sw_mode);
467 		mode_lib->vba.ScalerRecoutWidth[mode_lib->vba.NumberOfActivePlanes] =
468 				dst->recout_width; // TODO: or should this be full_recout_width???...maybe only when in hsplit mode?
469 		mode_lib->vba.ODMCombineEnabled[mode_lib->vba.NumberOfActivePlanes] =
470 				dst->odm_combine;
471 		mode_lib->vba.OutputFormat[mode_lib->vba.NumberOfActivePlanes] =
472 				(enum output_format_class) (dout->output_format);
473 		mode_lib->vba.OutputBpp[mode_lib->vba.NumberOfActivePlanes] =
474 				dout->output_bpp;
475 		mode_lib->vba.Output[mode_lib->vba.NumberOfActivePlanes] =
476 				(enum output_encoder_class) (dout->output_type);
477 		mode_lib->vba.skip_dio_check[mode_lib->vba.NumberOfActivePlanes] =
478 				dout->is_virtual;
479 
480 		if (!dout->dsc_enable)
481 			mode_lib->vba.ForcedOutputLinkBPP[mode_lib->vba.NumberOfActivePlanes] = dout->output_bpp;
482 		else
483 			mode_lib->vba.ForcedOutputLinkBPP[mode_lib->vba.NumberOfActivePlanes] = 0.0;
484 
485 		mode_lib->vba.OutputLinkDPLanes[mode_lib->vba.NumberOfActivePlanes] =
486 				dout->dp_lanes;
487 		/* TODO: Needs to be set based on dout->audio.audio_sample_rate_khz/sample_layout */
488 		mode_lib->vba.AudioSampleRate[mode_lib->vba.NumberOfActivePlanes] =
489 			dout->max_audio_sample_rate;
490 		mode_lib->vba.AudioSampleLayout[mode_lib->vba.NumberOfActivePlanes] =
491 			1;
492 		mode_lib->vba.DRAMClockChangeLatencyOverride = 0.0;
493 		mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable;
494 		mode_lib->vba.DSCEnable[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable;
495 		mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] =
496 				dout->dsc_slices;
497 		if (!dout->dsc_input_bpc) {
498 			mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] =
499 				ip->maximum_dsc_bits_per_component;
500 		} else {
501 			mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] =
502 				dout->dsc_input_bpc;
503 		}
504 		mode_lib->vba.WritebackEnable[mode_lib->vba.NumberOfActivePlanes] = dout->wb_enable;
505 		mode_lib->vba.ActiveWritebacksPerPlane[mode_lib->vba.NumberOfActivePlanes] =
506 				dout->num_active_wb;
507 		mode_lib->vba.WritebackSourceHeight[mode_lib->vba.NumberOfActivePlanes] =
508 				dout->wb.wb_src_height;
509 		mode_lib->vba.WritebackSourceWidth[mode_lib->vba.NumberOfActivePlanes] =
510 				dout->wb.wb_src_width;
511 		mode_lib->vba.WritebackDestinationWidth[mode_lib->vba.NumberOfActivePlanes] =
512 				dout->wb.wb_dst_width;
513 		mode_lib->vba.WritebackDestinationHeight[mode_lib->vba.NumberOfActivePlanes] =
514 				dout->wb.wb_dst_height;
515 		mode_lib->vba.WritebackHRatio[mode_lib->vba.NumberOfActivePlanes] =
516 				dout->wb.wb_hratio;
517 		mode_lib->vba.WritebackVRatio[mode_lib->vba.NumberOfActivePlanes] =
518 				dout->wb.wb_vratio;
519 		mode_lib->vba.WritebackPixelFormat[mode_lib->vba.NumberOfActivePlanes] =
520 				(enum source_format_class) (dout->wb.wb_pixel_format);
521 		mode_lib->vba.WritebackHTaps[mode_lib->vba.NumberOfActivePlanes] =
522 				dout->wb.wb_htaps_luma;
523 		mode_lib->vba.WritebackVTaps[mode_lib->vba.NumberOfActivePlanes] =
524 				dout->wb.wb_vtaps_luma;
525 		mode_lib->vba.WritebackLumaHTaps[mode_lib->vba.NumberOfActivePlanes] =
526 				dout->wb.wb_htaps_luma;
527 		mode_lib->vba.WritebackLumaVTaps[mode_lib->vba.NumberOfActivePlanes] =
528 				dout->wb.wb_vtaps_luma;
529 		mode_lib->vba.WritebackChromaHTaps[mode_lib->vba.NumberOfActivePlanes] =
530 				dout->wb.wb_htaps_chroma;
531 		mode_lib->vba.WritebackChromaVTaps[mode_lib->vba.NumberOfActivePlanes] =
532 				dout->wb.wb_vtaps_chroma;
533 		mode_lib->vba.WritebackHRatio[mode_lib->vba.NumberOfActivePlanes] =
534 				dout->wb.wb_hratio;
535 		mode_lib->vba.WritebackVRatio[mode_lib->vba.NumberOfActivePlanes] =
536 				dout->wb.wb_vratio;
537 
538 		mode_lib->vba.DynamicMetadataEnable[mode_lib->vba.NumberOfActivePlanes] =
539 				src->dynamic_metadata_enable;
540 		mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[mode_lib->vba.NumberOfActivePlanes] =
541 				src->dynamic_metadata_lines_before_active;
542 		mode_lib->vba.DynamicMetadataTransmittedBytes[mode_lib->vba.NumberOfActivePlanes] =
543 				src->dynamic_metadata_xmit_bytes;
544 
545 		mode_lib->vba.XFCEnabled[mode_lib->vba.NumberOfActivePlanes] = src->xfc_enable
546 				&& ip->xfc_supported;
547 		mode_lib->vba.XFCSlvChunkSize = src->xfc_params.xfc_slv_chunk_size_bytes;
548 		mode_lib->vba.XFCTSlvVupdateOffset = src->xfc_params.xfc_tslv_vupdate_offset_us;
549 		mode_lib->vba.XFCTSlvVupdateWidth = src->xfc_params.xfc_tslv_vupdate_width_us;
550 		mode_lib->vba.XFCTSlvVreadyOffset = src->xfc_params.xfc_tslv_vready_offset_us;
551 		mode_lib->vba.PixelClock[mode_lib->vba.NumberOfActivePlanes] = dst->pixel_rate_mhz;
552 		mode_lib->vba.PixelClockBackEnd[mode_lib->vba.NumberOfActivePlanes] = dst->pixel_rate_mhz;
553 		mode_lib->vba.DPPCLK[mode_lib->vba.NumberOfActivePlanes] = clks->dppclk_mhz;
554 		if (ip->is_line_buffer_bpp_fixed)
555 			mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] =
556 					ip->line_buffer_fixed_bpp;
557 		else {
558 			unsigned int lb_depth;
559 
560 			switch (scl->lb_depth) {
561 			case dm_lb_6:
562 				lb_depth = 18;
563 				break;
564 			case dm_lb_8:
565 				lb_depth = 24;
566 				break;
567 			case dm_lb_10:
568 				lb_depth = 30;
569 				break;
570 			case dm_lb_12:
571 				lb_depth = 36;
572 				break;
573 			case dm_lb_16:
574 				lb_depth = 48;
575 				break;
576 			case dm_lb_19:
577 				lb_depth = 57;
578 				break;
579 			default:
580 				lb_depth = 36;
581 			}
582 			mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] = lb_depth;
583 		}
584 		mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes] = 0;
585 		// The DML spreadsheet assumes that the two cursors utilize the same amount of bandwidth. We'll
586 		// calculate things a little more accurately
587 		for (k = 0; k < DC__NUM_CURSOR__MAX; ++k) {
588 			switch (k) {
589 			case 0:
590 				mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][0] =
591 						CursorBppEnumToBits(
592 								(enum cursor_bpp) (src->cur0_bpp));
593 				mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][0] =
594 						src->cur0_src_width;
595 				if (src->cur0_src_width > 0)
596 					mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++;
597 				break;
598 			case 1:
599 				mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][1] =
600 						CursorBppEnumToBits(
601 								(enum cursor_bpp) (src->cur1_bpp));
602 				mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][1] =
603 						src->cur1_src_width;
604 				if (src->cur1_src_width > 0)
605 					mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++;
606 				break;
607 			default:
608 				dml_print(
609 						"ERROR: Number of cursors specified exceeds supported maximum\n")
610 				;
611 			}
612 		}
613 
614 		OTGInstPlane[mode_lib->vba.NumberOfActivePlanes] = dst->otg_inst;
615 
616 		if (j == 0)
617 			mode_lib->vba.UseMaximumVStartup = dst->use_maximum_vstartup;
618 		else
619 			mode_lib->vba.UseMaximumVStartup = mode_lib->vba.UseMaximumVStartup
620 									|| dst->use_maximum_vstartup;
621 
622 		if (dst->odm_combine && !src->is_hsplit)
623 			dml_print(
624 					"ERROR: ODM Combine is specified but is_hsplit has not be specified for pipe %i\n",
625 					j);
626 
627 		if (src->is_hsplit) {
628 			for (k = j + 1; k < mode_lib->vba.cache_num_pipes; ++k) {
629 				display_pipe_source_params_st *src_k = &pipes[k].pipe.src;
630 				display_pipe_dest_params_st *dst_k = &pipes[k].pipe.dest;
631 
632 				if (src_k->is_hsplit && !visited[k]
633 						&& src->hsplit_grp == src_k->hsplit_grp) {
634 					mode_lib->vba.pipe_plane[k] =
635 							mode_lib->vba.NumberOfActivePlanes;
636 					mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes]++;
637 					if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes]
638 							== dm_horz) {
639 						mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] +=
640 								src_k->viewport_width;
641 						mode_lib->vba.ViewportWidthChroma[mode_lib->vba.NumberOfActivePlanes] +=
642 								src_k->viewport_width_c;
643 						mode_lib->vba.ScalerRecoutWidth[mode_lib->vba.NumberOfActivePlanes] +=
644 								dst_k->recout_width;
645 					} else {
646 						mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] +=
647 								src_k->viewport_height;
648 						mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] +=
649 								src_k->viewport_height_c;
650 					}
651 
652 					visited[k] = true;
653 				}
654 			}
655 		}
656 		if (src->viewport_width_max) {
657 			int hdiv_c = src->source_format >= dm_420_8 && src->source_format <= dm_422_10 ? 2 : 1;
658 			int vdiv_c = src->source_format >= dm_420_8 && src->source_format <= dm_420_12 ? 2 : 1;
659 
660 			if (mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] > src->viewport_width_max)
661 				mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width_max;
662 			if (mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] > src->viewport_height_max)
663 				mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height_max;
664 			if (mode_lib->vba.ViewportWidthChroma[mode_lib->vba.NumberOfActivePlanes] > src->viewport_width_max / hdiv_c)
665 				mode_lib->vba.ViewportWidthChroma[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width_max / hdiv_c;
666 			if (mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] > src->viewport_height_max / vdiv_c)
667 				mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height_max / vdiv_c;
668 		}
669 
670 		if (pipes[k].pipe.src.immediate_flip) {
671 			mode_lib->vba.ImmediateFlipSupport = true;
672 			mode_lib->vba.ImmediateFlipRequirement = dm_immediate_flip_required;
673 		}
674 
675 		mode_lib->vba.NumberOfActivePlanes++;
676 	}
677 
678 	// handle overlays through BlendingAndTiming
679 	// BlendingAndTiming tells you which instance to look at to get timing, the so called 'master'
680 
681 	for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j)
682 		PlaneVisited[j] = false;
683 
684 	for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) {
685 		for (k = j + 1; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
686 			if (!PlaneVisited[k] && OTGInstPlane[j] == OTGInstPlane[k]) {
687 				// doesn't matter, so choose the smaller one
688 				mode_lib->vba.BlendingAndTiming[j] = j;
689 				PlaneVisited[j] = true;
690 				mode_lib->vba.BlendingAndTiming[k] = j;
691 				PlaneVisited[k] = true;
692 			}
693 		}
694 
695 		if (!PlaneVisited[j]) {
696 			mode_lib->vba.BlendingAndTiming[j] = j;
697 			PlaneVisited[j] = true;
698 		}
699 	}
700 
701 	mode_lib->vba.UseUnboundedRequesting = dm_unbounded_requesting;
702 	for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) {
703 		if (pipes[k].pipe.src.unbounded_req_mode == 0)
704 			mode_lib->vba.UseUnboundedRequesting = dm_unbounded_requesting_disable;
705 	}
706 	// TODO: ODMCombineEnabled => 2 * DPPPerPlane...actually maybe not since all pipes are specified
707 	// Do we want the dscclk to automatically be halved? Guess not since the value is specified
708 	mode_lib->vba.SynchronizedVBlank = pipes[0].pipe.dest.synchronized_vblank_all_planes;
709 	for (k = 1; k < mode_lib->vba.cache_num_pipes; ++k) {
710 		ASSERT(mode_lib->vba.SynchronizedVBlank == pipes[k].pipe.dest.synchronized_vblank_all_planes);
711 	}
712 
713 	mode_lib->vba.GPUVMEnable = false;
714 	mode_lib->vba.HostVMEnable = false;
715 	mode_lib->vba.OverrideGPUVMPageTableLevels = 0;
716 	mode_lib->vba.OverrideHostVMPageTableLevels = 0;
717 
718 	for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) {
719 		mode_lib->vba.GPUVMEnable = mode_lib->vba.GPUVMEnable || !!pipes[k].pipe.src.gpuvm || !!pipes[k].pipe.src.vm;
720 		mode_lib->vba.OverrideGPUVMPageTableLevels =
721 				(pipes[k].pipe.src.gpuvm_levels_force_en
722 						&& mode_lib->vba.OverrideGPUVMPageTableLevels
723 								< pipes[k].pipe.src.gpuvm_levels_force) ?
724 						pipes[k].pipe.src.gpuvm_levels_force :
725 						mode_lib->vba.OverrideGPUVMPageTableLevels;
726 
727 		mode_lib->vba.HostVMEnable = mode_lib->vba.HostVMEnable || !!pipes[k].pipe.src.hostvm || !!pipes[k].pipe.src.vm;
728 		mode_lib->vba.OverrideHostVMPageTableLevels =
729 				(pipes[k].pipe.src.hostvm_levels_force_en
730 						&& mode_lib->vba.OverrideHostVMPageTableLevels
731 								< pipes[k].pipe.src.hostvm_levels_force) ?
732 						pipes[k].pipe.src.hostvm_levels_force :
733 						mode_lib->vba.OverrideHostVMPageTableLevels;
734 	}
735 
736 	mode_lib->vba.AllowDRAMSelfRefreshOrDRAMClockChangeInVblank = dm_try_to_allow_self_refresh_and_mclk_switch;
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 		if (mode_lib->vba.Interlace[k] == 1
849 				&& mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true) {
850 			mode_lib->vba.PixelClock[k] = 2 * mode_lib->vba.PixelClockBackEnd[k];
851 		}
852 	}
853 }
854 
855 static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp)
856 {
857 	switch (ebpp) {
858 	case dm_cur_2bit:
859 		return 2;
860 	case dm_cur_32bit:
861 		return 32;
862 	case dm_cur_64bit:
863 		return 64;
864 	default:
865 		return 0;
866 	}
867 }
868 
869 void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib)
870 {
871 	soc_bounding_box_st *soc = &mode_lib->vba.soc;
872 	unsigned int k;
873 	unsigned int total_pipes = 0;
874 
875 	mode_lib->vba.VoltageLevel = mode_lib->vba.cache_pipes[0].clks_cfg.voltage;
876 	mode_lib->vba.ReturnBW = mode_lib->vba.ReturnBWPerState[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb];
877 	if (mode_lib->vba.ReturnBW == 0)
878 		mode_lib->vba.ReturnBW = mode_lib->vba.ReturnBWPerState[mode_lib->vba.VoltageLevel][0];
879 	mode_lib->vba.FabricAndDRAMBandwidth = mode_lib->vba.FabricAndDRAMBandwidthPerState[mode_lib->vba.VoltageLevel];
880 
881 	fetch_socbb_params(mode_lib);
882 	fetch_ip_params(mode_lib);
883 	fetch_pipe_params(mode_lib);
884 
885 	mode_lib->vba.DCFCLK = mode_lib->vba.cache_pipes[0].clks_cfg.dcfclk_mhz;
886 	mode_lib->vba.SOCCLK = mode_lib->vba.cache_pipes[0].clks_cfg.socclk_mhz;
887 	if (mode_lib->vba.cache_pipes[0].clks_cfg.dispclk_mhz > 0.0)
888 		mode_lib->vba.DISPCLK = mode_lib->vba.cache_pipes[0].clks_cfg.dispclk_mhz;
889 	else
890 		mode_lib->vba.DISPCLK = soc->clock_limits[mode_lib->vba.VoltageLevel].dispclk_mhz;
891 
892 	// Total Available Pipes Support Check
893 	for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k)
894 		total_pipes += mode_lib->vba.DPPPerPlane[k];
895 	ASSERT(total_pipes <= DC__NUM_DPP__MAX);
896 }
897 
898 double CalculateWriteBackDISPCLK(
899 		enum source_format_class WritebackPixelFormat,
900 		double PixelClock,
901 		double WritebackHRatio,
902 		double WritebackVRatio,
903 		unsigned int WritebackLumaHTaps,
904 		unsigned int WritebackLumaVTaps,
905 		unsigned int WritebackChromaHTaps,
906 		unsigned int WritebackChromaVTaps,
907 		double WritebackDestinationWidth,
908 		unsigned int HTotal,
909 		unsigned int WritebackChromaLineBufferWidth)
910 {
911 	double CalculateWriteBackDISPCLK = 1.01 * PixelClock * dml_max(
912 		dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio,
913 		dml_max((WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) * dml_ceil(WritebackDestinationWidth / 4.0, 1)
914 			+ dml_ceil(WritebackDestinationWidth / 4.0, 1)) / (double) HTotal + dml_ceil(1.0 / WritebackVRatio, 1)
915 			* (dml_ceil(WritebackLumaVTaps / 4.0, 1) + 4.0) / (double) HTotal,
916 			dml_ceil(1.0 / WritebackVRatio, 1) * WritebackDestinationWidth / (double) HTotal));
917 	if (WritebackPixelFormat != dm_444_32) {
918 		CalculateWriteBackDISPCLK = dml_max(CalculateWriteBackDISPCLK, 1.01 * PixelClock * dml_max(
919 			dml_ceil(WritebackChromaHTaps / 2.0, 1) / (2 * WritebackHRatio),
920 			dml_max((WritebackChromaVTaps * dml_ceil(1 / (2 * WritebackVRatio), 1) * dml_ceil(WritebackDestinationWidth / 2.0 / 2.0, 1)
921 				+ dml_ceil(WritebackDestinationWidth / 2.0 / WritebackChromaLineBufferWidth, 1)) / HTotal
922 				+ dml_ceil(1 / (2 * WritebackVRatio), 1) * (dml_ceil(WritebackChromaVTaps / 4.0, 1) + 4) / HTotal,
923 				dml_ceil(1.0 / (2 * WritebackVRatio), 1) * WritebackDestinationWidth / 2.0 / HTotal)));
924 	}
925 	return CalculateWriteBackDISPCLK;
926 }
927 
928