1// SPDX-License-Identifier: MIT
2/*
3 * Copyright 2021 Advanced Micro Devices, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors: AMD
24 *
25 */
26
27#include "resource.h"
28#include "clk_mgr.h"
29#include "dchubbub.h"
30#include "dcn20/dcn20_resource.h"
31#include "dcn21/dcn21_resource.h"
32#include "clk_mgr/dcn21/rn_clk_mgr.h"
33
34#include "link.h"
35#include "dcn20_fpu.h"
36#include "dc_state_priv.h"
37
38#define DC_LOGGER \
39	dc->ctx->logger
40#define DC_LOGGER_INIT(logger)
41
42#ifndef MAX
43#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
44#endif
45#ifndef MIN
46#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
47#endif
48
49/* Constant */
50#define LPDDR_MEM_RETRAIN_LATENCY 4.977 /* Number obtained from LPDDR4 Training Counter Requirement doc */
51
52/**
53 * DOC: DCN2x FPU manipulation Overview
54 *
55 * The DCN architecture relies on FPU operations, which require special
56 * compilation flags and the use of kernel_fpu_begin/end functions; ideally, we
57 * want to avoid spreading FPU access across multiple files. With this idea in
58 * mind, this file aims to centralize all DCN20 and DCN2.1 (DCN2x) functions
59 * that require FPU access in a single place. Code in this file follows the
60 * following code pattern:
61 *
62 * 1. Functions that use FPU operations should be isolated in static functions.
63 * 2. The FPU functions should have the noinline attribute to ensure anything
64 *    that deals with FP register is contained within this call.
65 * 3. All function that needs to be accessed outside this file requires a
66 *    public interface that not uses any FPU reference.
67 * 4. Developers **must not** use DC_FP_START/END in this file, but they need
68 *    to ensure that the caller invokes it before access any function available
69 *    in this file. For this reason, public functions in this file must invoke
70 *    dc_assert_fp_enabled();
71 *
72 * Let's expand a little bit more the idea in the code pattern. To fully
73 * isolate FPU operations in a single place, we must avoid situations where
74 * compilers spill FP values to registers due to FP enable in a specific C
75 * file. Note that even if we isolate all FPU functions in a single file and
76 * call its interface from other files, the compiler might enable the use of
77 * FPU before we call DC_FP_START. Nevertheless, it is the programmer's
78 * responsibility to invoke DC_FP_START/END in the correct place. To highlight
79 * situations where developers forgot to use the FP protection before calling
80 * the DC FPU interface functions, we introduce a helper that checks if the
81 * function is invoked under FP protection. If not, it will trigger a kernel
82 * warning.
83 */
84
85struct _vcs_dpi_ip_params_st dcn2_0_ip = {
86	.odm_capable = 1,
87	.gpuvm_enable = 0,
88	.hostvm_enable = 0,
89	.gpuvm_max_page_table_levels = 4,
90	.hostvm_max_page_table_levels = 4,
91	.hostvm_cached_page_table_levels = 0,
92	.pte_group_size_bytes = 2048,
93	.num_dsc = 6,
94	.rob_buffer_size_kbytes = 168,
95	.det_buffer_size_kbytes = 164,
96	.dpte_buffer_size_in_pte_reqs_luma = 84,
97	.pde_proc_buffer_size_64k_reqs = 48,
98	.dpp_output_buffer_pixels = 2560,
99	.opp_output_buffer_lines = 1,
100	.pixel_chunk_size_kbytes = 8,
101	.pte_chunk_size_kbytes = 2,
102	.meta_chunk_size_kbytes = 2,
103	.writeback_chunk_size_kbytes = 2,
104	.line_buffer_size_bits = 789504,
105	.is_line_buffer_bpp_fixed = 0,
106	.line_buffer_fixed_bpp = 0,
107	.dcc_supported = true,
108	.max_line_buffer_lines = 12,
109	.writeback_luma_buffer_size_kbytes = 12,
110	.writeback_chroma_buffer_size_kbytes = 8,
111	.writeback_chroma_line_buffer_width_pixels = 4,
112	.writeback_max_hscl_ratio = 1,
113	.writeback_max_vscl_ratio = 1,
114	.writeback_min_hscl_ratio = 1,
115	.writeback_min_vscl_ratio = 1,
116	.writeback_max_hscl_taps = 12,
117	.writeback_max_vscl_taps = 12,
118	.writeback_line_buffer_luma_buffer_size = 0,
119	.writeback_line_buffer_chroma_buffer_size = 14643,
120	.cursor_buffer_size = 8,
121	.cursor_chunk_size = 2,
122	.max_num_otg = 6,
123	.max_num_dpp = 6,
124	.max_num_wb = 1,
125	.max_dchub_pscl_bw_pix_per_clk = 4,
126	.max_pscl_lb_bw_pix_per_clk = 2,
127	.max_lb_vscl_bw_pix_per_clk = 4,
128	.max_vscl_hscl_bw_pix_per_clk = 4,
129	.max_hscl_ratio = 8,
130	.max_vscl_ratio = 8,
131	.hscl_mults = 4,
132	.vscl_mults = 4,
133	.max_hscl_taps = 8,
134	.max_vscl_taps = 8,
135	.dispclk_ramp_margin_percent = 1,
136	.underscan_factor = 1.10,
137	.min_vblank_lines = 32, //
138	.dppclk_delay_subtotal = 77, //
139	.dppclk_delay_scl_lb_only = 16,
140	.dppclk_delay_scl = 50,
141	.dppclk_delay_cnvc_formatter = 8,
142	.dppclk_delay_cnvc_cursor = 6,
143	.dispclk_delay_subtotal = 87, //
144	.dcfclk_cstate_latency = 10, // SRExitTime
145	.max_inter_dcn_tile_repeaters = 8,
146	.xfc_supported = true,
147	.xfc_fill_bw_overhead_percent = 10.0,
148	.xfc_fill_constant_bytes = 0,
149	.number_of_cursors = 1,
150};
151
152struct _vcs_dpi_ip_params_st dcn2_0_nv14_ip = {
153	.odm_capable = 1,
154	.gpuvm_enable = 0,
155	.hostvm_enable = 0,
156	.gpuvm_max_page_table_levels = 4,
157	.hostvm_max_page_table_levels = 4,
158	.hostvm_cached_page_table_levels = 0,
159	.num_dsc = 5,
160	.rob_buffer_size_kbytes = 168,
161	.det_buffer_size_kbytes = 164,
162	.dpte_buffer_size_in_pte_reqs_luma = 84,
163	.dpte_buffer_size_in_pte_reqs_chroma = 42,//todo
164	.dpp_output_buffer_pixels = 2560,
165	.opp_output_buffer_lines = 1,
166	.pixel_chunk_size_kbytes = 8,
167	.pte_enable = 1,
168	.max_page_table_levels = 4,
169	.pte_chunk_size_kbytes = 2,
170	.meta_chunk_size_kbytes = 2,
171	.writeback_chunk_size_kbytes = 2,
172	.line_buffer_size_bits = 789504,
173	.is_line_buffer_bpp_fixed = 0,
174	.line_buffer_fixed_bpp = 0,
175	.dcc_supported = true,
176	.max_line_buffer_lines = 12,
177	.writeback_luma_buffer_size_kbytes = 12,
178	.writeback_chroma_buffer_size_kbytes = 8,
179	.writeback_chroma_line_buffer_width_pixels = 4,
180	.writeback_max_hscl_ratio = 1,
181	.writeback_max_vscl_ratio = 1,
182	.writeback_min_hscl_ratio = 1,
183	.writeback_min_vscl_ratio = 1,
184	.writeback_max_hscl_taps = 12,
185	.writeback_max_vscl_taps = 12,
186	.writeback_line_buffer_luma_buffer_size = 0,
187	.writeback_line_buffer_chroma_buffer_size = 14643,
188	.cursor_buffer_size = 8,
189	.cursor_chunk_size = 2,
190	.max_num_otg = 5,
191	.max_num_dpp = 5,
192	.max_num_wb = 1,
193	.max_dchub_pscl_bw_pix_per_clk = 4,
194	.max_pscl_lb_bw_pix_per_clk = 2,
195	.max_lb_vscl_bw_pix_per_clk = 4,
196	.max_vscl_hscl_bw_pix_per_clk = 4,
197	.max_hscl_ratio = 8,
198	.max_vscl_ratio = 8,
199	.hscl_mults = 4,
200	.vscl_mults = 4,
201	.max_hscl_taps = 8,
202	.max_vscl_taps = 8,
203	.dispclk_ramp_margin_percent = 1,
204	.underscan_factor = 1.10,
205	.min_vblank_lines = 32, //
206	.dppclk_delay_subtotal = 77, //
207	.dppclk_delay_scl_lb_only = 16,
208	.dppclk_delay_scl = 50,
209	.dppclk_delay_cnvc_formatter = 8,
210	.dppclk_delay_cnvc_cursor = 6,
211	.dispclk_delay_subtotal = 87, //
212	.dcfclk_cstate_latency = 10, // SRExitTime
213	.max_inter_dcn_tile_repeaters = 8,
214	.xfc_supported = true,
215	.xfc_fill_bw_overhead_percent = 10.0,
216	.xfc_fill_constant_bytes = 0,
217	.ptoi_supported = 0,
218	.number_of_cursors = 1,
219};
220
221struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc = {
222	/* Defaults that get patched on driver load from firmware. */
223	.clock_limits = {
224			{
225				.state = 0,
226				.dcfclk_mhz = 560.0,
227				.fabricclk_mhz = 560.0,
228				.dispclk_mhz = 513.0,
229				.dppclk_mhz = 513.0,
230				.phyclk_mhz = 540.0,
231				.socclk_mhz = 560.0,
232				.dscclk_mhz = 171.0,
233				.dram_speed_mts = 8960.0,
234			},
235			{
236				.state = 1,
237				.dcfclk_mhz = 694.0,
238				.fabricclk_mhz = 694.0,
239				.dispclk_mhz = 642.0,
240				.dppclk_mhz = 642.0,
241				.phyclk_mhz = 600.0,
242				.socclk_mhz = 694.0,
243				.dscclk_mhz = 214.0,
244				.dram_speed_mts = 11104.0,
245			},
246			{
247				.state = 2,
248				.dcfclk_mhz = 875.0,
249				.fabricclk_mhz = 875.0,
250				.dispclk_mhz = 734.0,
251				.dppclk_mhz = 734.0,
252				.phyclk_mhz = 810.0,
253				.socclk_mhz = 875.0,
254				.dscclk_mhz = 245.0,
255				.dram_speed_mts = 14000.0,
256			},
257			{
258				.state = 3,
259				.dcfclk_mhz = 1000.0,
260				.fabricclk_mhz = 1000.0,
261				.dispclk_mhz = 1100.0,
262				.dppclk_mhz = 1100.0,
263				.phyclk_mhz = 810.0,
264				.socclk_mhz = 1000.0,
265				.dscclk_mhz = 367.0,
266				.dram_speed_mts = 16000.0,
267			},
268			{
269				.state = 4,
270				.dcfclk_mhz = 1200.0,
271				.fabricclk_mhz = 1200.0,
272				.dispclk_mhz = 1284.0,
273				.dppclk_mhz = 1284.0,
274				.phyclk_mhz = 810.0,
275				.socclk_mhz = 1200.0,
276				.dscclk_mhz = 428.0,
277				.dram_speed_mts = 16000.0,
278			},
279			/*Extra state, no dispclk ramping*/
280			{
281				.state = 5,
282				.dcfclk_mhz = 1200.0,
283				.fabricclk_mhz = 1200.0,
284				.dispclk_mhz = 1284.0,
285				.dppclk_mhz = 1284.0,
286				.phyclk_mhz = 810.0,
287				.socclk_mhz = 1200.0,
288				.dscclk_mhz = 428.0,
289				.dram_speed_mts = 16000.0,
290			},
291		},
292	.num_states = 5,
293	.sr_exit_time_us = 8.6,
294	.sr_enter_plus_exit_time_us = 10.9,
295	.urgent_latency_us = 4.0,
296	.urgent_latency_pixel_data_only_us = 4.0,
297	.urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
298	.urgent_latency_vm_data_only_us = 4.0,
299	.urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
300	.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
301	.urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
302	.pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 40.0,
303	.pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0,
304	.pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
305	.max_avg_sdp_bw_use_normal_percent = 40.0,
306	.max_avg_dram_bw_use_normal_percent = 40.0,
307	.writeback_latency_us = 12.0,
308	.ideal_dram_bw_after_urgent_percent = 40.0,
309	.max_request_size_bytes = 256,
310	.dram_channel_width_bytes = 2,
311	.fabric_datapath_to_dcn_data_return_bytes = 64,
312	.dcn_downspread_percent = 0.5,
313	.downspread_percent = 0.38,
314	.dram_page_open_time_ns = 50.0,
315	.dram_rw_turnaround_time_ns = 17.5,
316	.dram_return_buffer_per_channel_bytes = 8192,
317	.round_trip_ping_latency_dcfclk_cycles = 131,
318	.urgent_out_of_order_return_per_channel_bytes = 256,
319	.channel_interleave_bytes = 256,
320	.num_banks = 8,
321	.num_chans = 16,
322	.vmm_page_size_bytes = 4096,
323	.dram_clock_change_latency_us = 404.0,
324	.dummy_pstate_latency_us = 5.0,
325	.writeback_dram_clock_change_latency_us = 23.0,
326	.return_bus_width_bytes = 64,
327	.dispclk_dppclk_vco_speed_mhz = 3850,
328	.xfc_bus_transport_time_us = 20,
329	.xfc_xbuf_latency_tolerance_us = 4,
330	.use_urgent_burst_bw = 0
331};
332
333struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = {
334	.clock_limits = {
335			{
336				.state = 0,
337				.dcfclk_mhz = 560.0,
338				.fabricclk_mhz = 560.0,
339				.dispclk_mhz = 513.0,
340				.dppclk_mhz = 513.0,
341				.phyclk_mhz = 540.0,
342				.socclk_mhz = 560.0,
343				.dscclk_mhz = 171.0,
344				.dram_speed_mts = 8960.0,
345			},
346			{
347				.state = 1,
348				.dcfclk_mhz = 694.0,
349				.fabricclk_mhz = 694.0,
350				.dispclk_mhz = 642.0,
351				.dppclk_mhz = 642.0,
352				.phyclk_mhz = 600.0,
353				.socclk_mhz = 694.0,
354				.dscclk_mhz = 214.0,
355				.dram_speed_mts = 11104.0,
356			},
357			{
358				.state = 2,
359				.dcfclk_mhz = 875.0,
360				.fabricclk_mhz = 875.0,
361				.dispclk_mhz = 734.0,
362				.dppclk_mhz = 734.0,
363				.phyclk_mhz = 810.0,
364				.socclk_mhz = 875.0,
365				.dscclk_mhz = 245.0,
366				.dram_speed_mts = 14000.0,
367			},
368			{
369				.state = 3,
370				.dcfclk_mhz = 1000.0,
371				.fabricclk_mhz = 1000.0,
372				.dispclk_mhz = 1100.0,
373				.dppclk_mhz = 1100.0,
374				.phyclk_mhz = 810.0,
375				.socclk_mhz = 1000.0,
376				.dscclk_mhz = 367.0,
377				.dram_speed_mts = 16000.0,
378			},
379			{
380				.state = 4,
381				.dcfclk_mhz = 1200.0,
382				.fabricclk_mhz = 1200.0,
383				.dispclk_mhz = 1284.0,
384				.dppclk_mhz = 1284.0,
385				.phyclk_mhz = 810.0,
386				.socclk_mhz = 1200.0,
387				.dscclk_mhz = 428.0,
388				.dram_speed_mts = 16000.0,
389			},
390			/*Extra state, no dispclk ramping*/
391			{
392				.state = 5,
393				.dcfclk_mhz = 1200.0,
394				.fabricclk_mhz = 1200.0,
395				.dispclk_mhz = 1284.0,
396				.dppclk_mhz = 1284.0,
397				.phyclk_mhz = 810.0,
398				.socclk_mhz = 1200.0,
399				.dscclk_mhz = 428.0,
400				.dram_speed_mts = 16000.0,
401			},
402		},
403	.num_states = 5,
404	.sr_exit_time_us = 11.6,
405	.sr_enter_plus_exit_time_us = 13.9,
406	.urgent_latency_us = 4.0,
407	.urgent_latency_pixel_data_only_us = 4.0,
408	.urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
409	.urgent_latency_vm_data_only_us = 4.0,
410	.urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
411	.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
412	.urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
413	.pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 40.0,
414	.pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0,
415	.pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
416	.max_avg_sdp_bw_use_normal_percent = 40.0,
417	.max_avg_dram_bw_use_normal_percent = 40.0,
418	.writeback_latency_us = 12.0,
419	.ideal_dram_bw_after_urgent_percent = 40.0,
420	.max_request_size_bytes = 256,
421	.dram_channel_width_bytes = 2,
422	.fabric_datapath_to_dcn_data_return_bytes = 64,
423	.dcn_downspread_percent = 0.5,
424	.downspread_percent = 0.38,
425	.dram_page_open_time_ns = 50.0,
426	.dram_rw_turnaround_time_ns = 17.5,
427	.dram_return_buffer_per_channel_bytes = 8192,
428	.round_trip_ping_latency_dcfclk_cycles = 131,
429	.urgent_out_of_order_return_per_channel_bytes = 256,
430	.channel_interleave_bytes = 256,
431	.num_banks = 8,
432	.num_chans = 8,
433	.vmm_page_size_bytes = 4096,
434	.dram_clock_change_latency_us = 404.0,
435	.dummy_pstate_latency_us = 5.0,
436	.writeback_dram_clock_change_latency_us = 23.0,
437	.return_bus_width_bytes = 64,
438	.dispclk_dppclk_vco_speed_mhz = 3850,
439	.xfc_bus_transport_time_us = 20,
440	.xfc_xbuf_latency_tolerance_us = 4,
441	.use_urgent_burst_bw = 0
442};
443
444struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = {
445	.clock_limits = {
446		{
447			.state = 0,
448			.dcfclk_mhz = 560.0,
449			.fabricclk_mhz = 560.0,
450			.dispclk_mhz = 513.0,
451			.dppclk_mhz = 513.0,
452			.phyclk_mhz = 540.0,
453			.socclk_mhz = 560.0,
454			.dscclk_mhz = 171.0,
455			.dram_speed_mts = 1069.0,
456		},
457		{
458			.state = 1,
459			.dcfclk_mhz = 694.0,
460			.fabricclk_mhz = 694.0,
461			.dispclk_mhz = 642.0,
462			.dppclk_mhz = 642.0,
463			.phyclk_mhz = 600.0,
464			.socclk_mhz = 694.0,
465			.dscclk_mhz = 214.0,
466			.dram_speed_mts = 1324.0,
467		},
468		{
469			.state = 2,
470			.dcfclk_mhz = 875.0,
471			.fabricclk_mhz = 875.0,
472			.dispclk_mhz = 734.0,
473			.dppclk_mhz = 734.0,
474			.phyclk_mhz = 810.0,
475			.socclk_mhz = 875.0,
476			.dscclk_mhz = 245.0,
477			.dram_speed_mts = 1670.0,
478		},
479		{
480			.state = 3,
481			.dcfclk_mhz = 1000.0,
482			.fabricclk_mhz = 1000.0,
483			.dispclk_mhz = 1100.0,
484			.dppclk_mhz = 1100.0,
485			.phyclk_mhz = 810.0,
486			.socclk_mhz = 1000.0,
487			.dscclk_mhz = 367.0,
488			.dram_speed_mts = 2000.0,
489		},
490		{
491			.state = 4,
492			.dcfclk_mhz = 1200.0,
493			.fabricclk_mhz = 1200.0,
494			.dispclk_mhz = 1284.0,
495			.dppclk_mhz = 1284.0,
496			.phyclk_mhz = 810.0,
497			.socclk_mhz = 1200.0,
498			.dscclk_mhz = 428.0,
499			.dram_speed_mts = 2000.0,
500		},
501		{
502			.state = 5,
503			.dcfclk_mhz = 1200.0,
504			.fabricclk_mhz = 1200.0,
505			.dispclk_mhz = 1284.0,
506			.dppclk_mhz = 1284.0,
507			.phyclk_mhz = 810.0,
508			.socclk_mhz = 1200.0,
509			.dscclk_mhz = 428.0,
510			.dram_speed_mts = 2000.0,
511		},
512	},
513
514	.num_states = 5,
515	.sr_exit_time_us = 1.9,
516	.sr_enter_plus_exit_time_us = 4.4,
517	.urgent_latency_us = 3.0,
518	.urgent_latency_pixel_data_only_us = 4.0,
519	.urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
520	.urgent_latency_vm_data_only_us = 4.0,
521	.urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
522	.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
523	.urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
524	.pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 40.0,
525	.pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0,
526	.pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
527	.max_avg_sdp_bw_use_normal_percent = 40.0,
528	.max_avg_dram_bw_use_normal_percent = 40.0,
529	.writeback_latency_us = 12.0,
530	.ideal_dram_bw_after_urgent_percent = 40.0,
531	.max_request_size_bytes = 256,
532	.dram_channel_width_bytes = 16,
533	.fabric_datapath_to_dcn_data_return_bytes = 64,
534	.dcn_downspread_percent = 0.5,
535	.downspread_percent = 0.5,
536	.dram_page_open_time_ns = 50.0,
537	.dram_rw_turnaround_time_ns = 17.5,
538	.dram_return_buffer_per_channel_bytes = 8192,
539	.round_trip_ping_latency_dcfclk_cycles = 131,
540	.urgent_out_of_order_return_per_channel_bytes = 4096,
541	.channel_interleave_bytes = 256,
542	.num_banks = 8,
543	.num_chans = 16,
544	.vmm_page_size_bytes = 4096,
545	.dram_clock_change_latency_us = 45.0,
546	.writeback_dram_clock_change_latency_us = 23.0,
547	.return_bus_width_bytes = 64,
548	.dispclk_dppclk_vco_speed_mhz = 3850,
549	.xfc_bus_transport_time_us = 20,
550	.xfc_xbuf_latency_tolerance_us = 50,
551	.use_urgent_burst_bw = 0,
552};
553
554struct _vcs_dpi_ip_params_st dcn2_1_ip = {
555	.odm_capable = 1,
556	.gpuvm_enable = 1,
557	.hostvm_enable = 1,
558	.gpuvm_max_page_table_levels = 1,
559	.hostvm_max_page_table_levels = 4,
560	.hostvm_cached_page_table_levels = 2,
561	.num_dsc = 3,
562	.rob_buffer_size_kbytes = 168,
563	.det_buffer_size_kbytes = 164,
564	.dpte_buffer_size_in_pte_reqs_luma = 44,
565	.dpte_buffer_size_in_pte_reqs_chroma = 42,//todo
566	.dpp_output_buffer_pixels = 2560,
567	.opp_output_buffer_lines = 1,
568	.pixel_chunk_size_kbytes = 8,
569	.pte_enable = 1,
570	.max_page_table_levels = 4,
571	.pte_chunk_size_kbytes = 2,
572	.meta_chunk_size_kbytes = 2,
573	.min_meta_chunk_size_bytes = 256,
574	.writeback_chunk_size_kbytes = 2,
575	.line_buffer_size_bits = 789504,
576	.is_line_buffer_bpp_fixed = 0,
577	.line_buffer_fixed_bpp = 0,
578	.dcc_supported = true,
579	.max_line_buffer_lines = 12,
580	.writeback_luma_buffer_size_kbytes = 12,
581	.writeback_chroma_buffer_size_kbytes = 8,
582	.writeback_chroma_line_buffer_width_pixels = 4,
583	.writeback_max_hscl_ratio = 1,
584	.writeback_max_vscl_ratio = 1,
585	.writeback_min_hscl_ratio = 1,
586	.writeback_min_vscl_ratio = 1,
587	.writeback_max_hscl_taps = 12,
588	.writeback_max_vscl_taps = 12,
589	.writeback_line_buffer_luma_buffer_size = 0,
590	.writeback_line_buffer_chroma_buffer_size = 14643,
591	.cursor_buffer_size = 8,
592	.cursor_chunk_size = 2,
593	.max_num_otg = 4,
594	.max_num_dpp = 4,
595	.max_num_wb = 1,
596	.max_dchub_pscl_bw_pix_per_clk = 4,
597	.max_pscl_lb_bw_pix_per_clk = 2,
598	.max_lb_vscl_bw_pix_per_clk = 4,
599	.max_vscl_hscl_bw_pix_per_clk = 4,
600	.max_hscl_ratio = 4,
601	.max_vscl_ratio = 4,
602	.hscl_mults = 4,
603	.vscl_mults = 4,
604	.max_hscl_taps = 8,
605	.max_vscl_taps = 8,
606	.dispclk_ramp_margin_percent = 1,
607	.underscan_factor = 1.10,
608	.min_vblank_lines = 32, //
609	.dppclk_delay_subtotal = 77, //
610	.dppclk_delay_scl_lb_only = 16,
611	.dppclk_delay_scl = 50,
612	.dppclk_delay_cnvc_formatter = 8,
613	.dppclk_delay_cnvc_cursor = 6,
614	.dispclk_delay_subtotal = 87, //
615	.dcfclk_cstate_latency = 10, // SRExitTime
616	.max_inter_dcn_tile_repeaters = 8,
617
618	.xfc_supported = false,
619	.xfc_fill_bw_overhead_percent = 10.0,
620	.xfc_fill_constant_bytes = 0,
621	.ptoi_supported = 0,
622	.number_of_cursors = 1,
623};
624
625struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
626	.clock_limits = {
627			{
628				.state = 0,
629				.dcfclk_mhz = 400.0,
630				.fabricclk_mhz = 400.0,
631				.dispclk_mhz = 600.0,
632				.dppclk_mhz = 400.00,
633				.phyclk_mhz = 600.0,
634				.socclk_mhz = 278.0,
635				.dscclk_mhz = 205.67,
636				.dram_speed_mts = 1600.0,
637			},
638			{
639				.state = 1,
640				.dcfclk_mhz = 464.52,
641				.fabricclk_mhz = 800.0,
642				.dispclk_mhz = 654.55,
643				.dppclk_mhz = 626.09,
644				.phyclk_mhz = 600.0,
645				.socclk_mhz = 278.0,
646				.dscclk_mhz = 205.67,
647				.dram_speed_mts = 1600.0,
648			},
649			{
650				.state = 2,
651				.dcfclk_mhz = 514.29,
652				.fabricclk_mhz = 933.0,
653				.dispclk_mhz = 757.89,
654				.dppclk_mhz = 685.71,
655				.phyclk_mhz = 600.0,
656				.socclk_mhz = 278.0,
657				.dscclk_mhz = 287.67,
658				.dram_speed_mts = 1866.0,
659			},
660			{
661				.state = 3,
662				.dcfclk_mhz = 576.00,
663				.fabricclk_mhz = 1067.0,
664				.dispclk_mhz = 847.06,
665				.dppclk_mhz = 757.89,
666				.phyclk_mhz = 600.0,
667				.socclk_mhz = 715.0,
668				.dscclk_mhz = 318.334,
669				.dram_speed_mts = 2134.0,
670			},
671			{
672				.state = 4,
673				.dcfclk_mhz = 626.09,
674				.fabricclk_mhz = 1200.0,
675				.dispclk_mhz = 900.00,
676				.dppclk_mhz = 847.06,
677				.phyclk_mhz = 810.0,
678				.socclk_mhz = 953.0,
679				.dscclk_mhz = 300.0,
680				.dram_speed_mts = 2400.0,
681			},
682			{
683				.state = 5,
684				.dcfclk_mhz = 685.71,
685				.fabricclk_mhz = 1333.0,
686				.dispclk_mhz = 1028.57,
687				.dppclk_mhz = 960.00,
688				.phyclk_mhz = 810.0,
689				.socclk_mhz = 278.0,
690				.dscclk_mhz = 342.86,
691				.dram_speed_mts = 2666.0,
692			},
693			{
694				.state = 6,
695				.dcfclk_mhz = 757.89,
696				.fabricclk_mhz = 1467.0,
697				.dispclk_mhz = 1107.69,
698				.dppclk_mhz = 1028.57,
699				.phyclk_mhz = 810.0,
700				.socclk_mhz = 715.0,
701				.dscclk_mhz = 369.23,
702				.dram_speed_mts = 3200.0,
703			},
704			{
705				.state = 7,
706				.dcfclk_mhz = 847.06,
707				.fabricclk_mhz = 1600.0,
708				.dispclk_mhz = 1395.0,
709				.dppclk_mhz = 1285.00,
710				.phyclk_mhz = 1325.0,
711				.socclk_mhz = 953.0,
712				.dscclk_mhz = 489.0,
713				.dram_speed_mts = 4266.0,
714			},
715			/*Extra state, no dispclk ramping*/
716			{
717				.state = 8,
718				.dcfclk_mhz = 847.06,
719				.fabricclk_mhz = 1600.0,
720				.dispclk_mhz = 1395.0,
721				.dppclk_mhz = 1285.0,
722				.phyclk_mhz = 1325.0,
723				.socclk_mhz = 953.0,
724				.dscclk_mhz = 489.0,
725				.dram_speed_mts = 4266.0,
726			},
727
728		},
729
730	.sr_exit_time_us = 12.5,
731	.sr_enter_plus_exit_time_us = 17.0,
732	.urgent_latency_us = 4.0,
733	.urgent_latency_pixel_data_only_us = 4.0,
734	.urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
735	.urgent_latency_vm_data_only_us = 4.0,
736	.urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
737	.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
738	.urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
739	.pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0,
740	.pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 75.0,
741	.pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
742	.max_avg_sdp_bw_use_normal_percent = 60.0,
743	.max_avg_dram_bw_use_normal_percent = 100.0,
744	.writeback_latency_us = 12.0,
745	.max_request_size_bytes = 256,
746	.dram_channel_width_bytes = 4,
747	.fabric_datapath_to_dcn_data_return_bytes = 32,
748	.dcn_downspread_percent = 0.5,
749	.downspread_percent = 0.38,
750	.dram_page_open_time_ns = 50.0,
751	.dram_rw_turnaround_time_ns = 17.5,
752	.dram_return_buffer_per_channel_bytes = 8192,
753	.round_trip_ping_latency_dcfclk_cycles = 128,
754	.urgent_out_of_order_return_per_channel_bytes = 4096,
755	.channel_interleave_bytes = 256,
756	.num_banks = 8,
757	.num_chans = 4,
758	.vmm_page_size_bytes = 4096,
759	.dram_clock_change_latency_us = 23.84,
760	.return_bus_width_bytes = 64,
761	.dispclk_dppclk_vco_speed_mhz = 3600,
762	.xfc_bus_transport_time_us = 4,
763	.xfc_xbuf_latency_tolerance_us = 4,
764	.use_urgent_burst_bw = 1,
765	.num_states = 8
766};
767
768struct wm_table ddr4_wm_table_gs = {
769	.entries = {
770		{
771			.wm_inst = WM_A,
772			.wm_type = WM_TYPE_PSTATE_CHG,
773			.pstate_latency_us = 11.72,
774			.sr_exit_time_us = 7.09,
775			.sr_enter_plus_exit_time_us = 8.14,
776			.valid = true,
777		},
778		{
779			.wm_inst = WM_B,
780			.wm_type = WM_TYPE_PSTATE_CHG,
781			.pstate_latency_us = 11.72,
782			.sr_exit_time_us = 10.12,
783			.sr_enter_plus_exit_time_us = 11.48,
784			.valid = true,
785		},
786		{
787			.wm_inst = WM_C,
788			.wm_type = WM_TYPE_PSTATE_CHG,
789			.pstate_latency_us = 11.72,
790			.sr_exit_time_us = 10.12,
791			.sr_enter_plus_exit_time_us = 11.48,
792			.valid = true,
793		},
794		{
795			.wm_inst = WM_D,
796			.wm_type = WM_TYPE_PSTATE_CHG,
797			.pstate_latency_us = 11.72,
798			.sr_exit_time_us = 10.12,
799			.sr_enter_plus_exit_time_us = 11.48,
800			.valid = true,
801		},
802	}
803};
804
805struct wm_table lpddr4_wm_table_gs = {
806	.entries = {
807		{
808			.wm_inst = WM_A,
809			.wm_type = WM_TYPE_PSTATE_CHG,
810			.pstate_latency_us = 11.65333,
811			.sr_exit_time_us = 5.32,
812			.sr_enter_plus_exit_time_us = 6.38,
813			.valid = true,
814		},
815		{
816			.wm_inst = WM_B,
817			.wm_type = WM_TYPE_PSTATE_CHG,
818			.pstate_latency_us = 11.65333,
819			.sr_exit_time_us = 9.82,
820			.sr_enter_plus_exit_time_us = 11.196,
821			.valid = true,
822		},
823		{
824			.wm_inst = WM_C,
825			.wm_type = WM_TYPE_PSTATE_CHG,
826			.pstate_latency_us = 11.65333,
827			.sr_exit_time_us = 9.89,
828			.sr_enter_plus_exit_time_us = 11.24,
829			.valid = true,
830		},
831		{
832			.wm_inst = WM_D,
833			.wm_type = WM_TYPE_PSTATE_CHG,
834			.pstate_latency_us = 11.65333,
835			.sr_exit_time_us = 9.748,
836			.sr_enter_plus_exit_time_us = 11.102,
837			.valid = true,
838		},
839	}
840};
841
842struct wm_table lpddr4_wm_table_with_disabled_ppt = {
843	.entries = {
844		{
845			.wm_inst = WM_A,
846			.wm_type = WM_TYPE_PSTATE_CHG,
847			.pstate_latency_us = 11.65333,
848			.sr_exit_time_us = 8.32,
849			.sr_enter_plus_exit_time_us = 9.38,
850			.valid = true,
851		},
852		{
853			.wm_inst = WM_B,
854			.wm_type = WM_TYPE_PSTATE_CHG,
855			.pstate_latency_us = 11.65333,
856			.sr_exit_time_us = 9.82,
857			.sr_enter_plus_exit_time_us = 11.196,
858			.valid = true,
859		},
860		{
861			.wm_inst = WM_C,
862			.wm_type = WM_TYPE_PSTATE_CHG,
863			.pstate_latency_us = 11.65333,
864			.sr_exit_time_us = 9.89,
865			.sr_enter_plus_exit_time_us = 11.24,
866			.valid = true,
867		},
868		{
869			.wm_inst = WM_D,
870			.wm_type = WM_TYPE_PSTATE_CHG,
871			.pstate_latency_us = 11.65333,
872			.sr_exit_time_us = 9.748,
873			.sr_enter_plus_exit_time_us = 11.102,
874			.valid = true,
875		},
876	}
877};
878
879struct wm_table ddr4_wm_table_rn = {
880	.entries = {
881		{
882			.wm_inst = WM_A,
883			.wm_type = WM_TYPE_PSTATE_CHG,
884			.pstate_latency_us = 11.72,
885			.sr_exit_time_us = 11.90,
886			.sr_enter_plus_exit_time_us = 12.80,
887			.valid = true,
888		},
889		{
890			.wm_inst = WM_B,
891			.wm_type = WM_TYPE_PSTATE_CHG,
892			.pstate_latency_us = 11.72,
893			.sr_exit_time_us = 13.18,
894			.sr_enter_plus_exit_time_us = 14.30,
895			.valid = true,
896		},
897		{
898			.wm_inst = WM_C,
899			.wm_type = WM_TYPE_PSTATE_CHG,
900			.pstate_latency_us = 11.72,
901			.sr_exit_time_us = 13.18,
902			.sr_enter_plus_exit_time_us = 14.30,
903			.valid = true,
904		},
905		{
906			.wm_inst = WM_D,
907			.wm_type = WM_TYPE_PSTATE_CHG,
908			.pstate_latency_us = 11.72,
909			.sr_exit_time_us = 13.18,
910			.sr_enter_plus_exit_time_us = 14.30,
911			.valid = true,
912		},
913	}
914};
915
916struct wm_table ddr4_1R_wm_table_rn = {
917	.entries = {
918		{
919			.wm_inst = WM_A,
920			.wm_type = WM_TYPE_PSTATE_CHG,
921			.pstate_latency_us = 11.72,
922			.sr_exit_time_us = 13.90,
923			.sr_enter_plus_exit_time_us = 14.80,
924			.valid = true,
925		},
926		{
927			.wm_inst = WM_B,
928			.wm_type = WM_TYPE_PSTATE_CHG,
929			.pstate_latency_us = 11.72,
930			.sr_exit_time_us = 13.90,
931			.sr_enter_plus_exit_time_us = 14.80,
932			.valid = true,
933		},
934		{
935			.wm_inst = WM_C,
936			.wm_type = WM_TYPE_PSTATE_CHG,
937			.pstate_latency_us = 11.72,
938			.sr_exit_time_us = 13.90,
939			.sr_enter_plus_exit_time_us = 14.80,
940			.valid = true,
941		},
942		{
943			.wm_inst = WM_D,
944			.wm_type = WM_TYPE_PSTATE_CHG,
945			.pstate_latency_us = 11.72,
946			.sr_exit_time_us = 13.90,
947			.sr_enter_plus_exit_time_us = 14.80,
948			.valid = true,
949		},
950	}
951};
952
953struct wm_table lpddr4_wm_table_rn = {
954	.entries = {
955		{
956			.wm_inst = WM_A,
957			.wm_type = WM_TYPE_PSTATE_CHG,
958			.pstate_latency_us = 11.65333,
959			.sr_exit_time_us = 7.32,
960			.sr_enter_plus_exit_time_us = 8.38,
961			.valid = true,
962		},
963		{
964			.wm_inst = WM_B,
965			.wm_type = WM_TYPE_PSTATE_CHG,
966			.pstate_latency_us = 11.65333,
967			.sr_exit_time_us = 9.82,
968			.sr_enter_plus_exit_time_us = 11.196,
969			.valid = true,
970		},
971		{
972			.wm_inst = WM_C,
973			.wm_type = WM_TYPE_PSTATE_CHG,
974			.pstate_latency_us = 11.65333,
975			.sr_exit_time_us = 9.89,
976			.sr_enter_plus_exit_time_us = 11.24,
977			.valid = true,
978		},
979		{
980			.wm_inst = WM_D,
981			.wm_type = WM_TYPE_PSTATE_CHG,
982			.pstate_latency_us = 11.65333,
983			.sr_exit_time_us = 9.748,
984			.sr_enter_plus_exit_time_us = 11.102,
985			.valid = true,
986		},
987	}
988};
989
990void dcn20_populate_dml_writeback_from_context(struct dc *dc,
991					       struct resource_context *res_ctx,
992					       display_e2e_pipe_params_st *pipes)
993{
994	int pipe_cnt, i;
995
996	dc_assert_fp_enabled();
997
998	for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
999		struct dc_writeback_info *wb_info = &res_ctx->pipe_ctx[i].stream->writeback_info[0];
1000
1001		if (!res_ctx->pipe_ctx[i].stream)
1002			continue;
1003
1004		/* Set writeback information */
1005		pipes[pipe_cnt].dout.wb_enable = (wb_info->wb_enabled == true) ? 1 : 0;
1006		pipes[pipe_cnt].dout.num_active_wb++;
1007		pipes[pipe_cnt].dout.wb.wb_src_height = wb_info->dwb_params.cnv_params.crop_height;
1008		pipes[pipe_cnt].dout.wb.wb_src_width = wb_info->dwb_params.cnv_params.crop_width;
1009		pipes[pipe_cnt].dout.wb.wb_dst_width = wb_info->dwb_params.dest_width;
1010		pipes[pipe_cnt].dout.wb.wb_dst_height = wb_info->dwb_params.dest_height;
1011		pipes[pipe_cnt].dout.wb.wb_htaps_luma = 1;
1012		pipes[pipe_cnt].dout.wb.wb_vtaps_luma = 1;
1013		pipes[pipe_cnt].dout.wb.wb_htaps_chroma = wb_info->dwb_params.scaler_taps.h_taps_c;
1014		pipes[pipe_cnt].dout.wb.wb_vtaps_chroma = wb_info->dwb_params.scaler_taps.v_taps_c;
1015		pipes[pipe_cnt].dout.wb.wb_hratio = 1.0;
1016		pipes[pipe_cnt].dout.wb.wb_vratio = 1.0;
1017		if (wb_info->dwb_params.out_format == dwb_scaler_mode_yuv420) {
1018			if (wb_info->dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC)
1019				pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_420_8;
1020			else
1021				pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_420_10;
1022		} else {
1023			pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_444_32;
1024		}
1025
1026		pipe_cnt++;
1027	}
1028}
1029
1030void dcn20_fpu_set_wb_arb_params(struct mcif_arb_params *wb_arb_params,
1031				 struct dc_state *context,
1032				 display_e2e_pipe_params_st *pipes,
1033				 int pipe_cnt, int i)
1034{
1035	int k;
1036
1037	dc_assert_fp_enabled();
1038
1039	for (k = 0; k < sizeof(wb_arb_params->cli_watermark)/sizeof(wb_arb_params->cli_watermark[0]); k++) {
1040		wb_arb_params->cli_watermark[k] = get_wm_writeback_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1041		wb_arb_params->pstate_watermark[k] = get_wm_writeback_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1042	}
1043	wb_arb_params->time_per_pixel = 16.0 * 1000 / (context->res_ctx.pipe_ctx[i].stream->phy_pix_clk / 1000); /* 4 bit fraction, ms */
1044}
1045
1046static bool is_dtbclk_required(struct dc *dc, struct dc_state *context)
1047{
1048	int i;
1049	for (i = 0; i < dc->res_pool->pipe_count; i++) {
1050		if (!context->res_ctx.pipe_ctx[i].stream)
1051			continue;
1052		if (dc->link_srv->dp_is_128b_132b_signal(&context->res_ctx.pipe_ctx[i]))
1053			return true;
1054	}
1055	return false;
1056}
1057
1058static enum dcn_zstate_support_state  decide_zstate_support(struct dc *dc, struct dc_state *context)
1059{
1060	int plane_count;
1061	int i;
1062
1063	plane_count = 0;
1064	for (i = 0; i < dc->res_pool->pipe_count; i++) {
1065		if (context->res_ctx.pipe_ctx[i].plane_state)
1066			plane_count++;
1067	}
1068
1069	/*
1070	 * Z9 and Z10 allowed cases:
1071	 * 	1. 0 Planes enabled
1072	 * 	2. single eDP, on link 0, 1 plane and stutter period > 5ms
1073	 * Z10 only cases:
1074	 * 	1. single eDP, on link 0, 1 plane and stutter period >= 5ms
1075	 * Z8 cases:
1076	 * 	1. stutter period sufficient
1077	 * Zstate not allowed cases:
1078	 * 	1. Everything else
1079	 */
1080	if (plane_count == 0)
1081		return DCN_ZSTATE_SUPPORT_ALLOW;
1082	else if (context->stream_count == 1 &&  context->streams[0]->signal == SIGNAL_TYPE_EDP) {
1083		struct dc_link *link = context->streams[0]->sink->link;
1084		struct dc_stream_status *stream_status = &context->stream_status[0];
1085		int minmum_z8_residency = dc->debug.minimum_z8_residency_time > 0 ? dc->debug.minimum_z8_residency_time : 1000;
1086		bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z8_residency;
1087		bool is_pwrseq0 = link->link_index == 0;
1088
1089		/* Don't support multi-plane configurations */
1090		if (stream_status->plane_count > 1)
1091			return DCN_ZSTATE_SUPPORT_DISALLOW;
1092
1093		if (is_pwrseq0 && context->bw_ctx.dml.vba.StutterPeriod > 5000.0)
1094			return DCN_ZSTATE_SUPPORT_ALLOW;
1095		else if (is_pwrseq0 && link->psr_settings.psr_version == DC_PSR_VERSION_1 && !link->panel_config.psr.disable_psr)
1096			return allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY : DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY;
1097		else
1098			return allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY : DCN_ZSTATE_SUPPORT_DISALLOW;
1099	} else {
1100		return DCN_ZSTATE_SUPPORT_DISALLOW;
1101	}
1102}
1103
1104static void dcn20_adjust_freesync_v_startup(
1105		const struct dc_crtc_timing *dc_crtc_timing, int *vstartup_start)
1106{
1107	struct dc_crtc_timing patched_crtc_timing;
1108	uint32_t asic_blank_end   = 0;
1109	uint32_t asic_blank_start = 0;
1110	uint32_t newVstartup	  = 0;
1111
1112	patched_crtc_timing = *dc_crtc_timing;
1113
1114	if (patched_crtc_timing.flags.INTERLACE == 1) {
1115		if (patched_crtc_timing.v_front_porch < 2)
1116			patched_crtc_timing.v_front_porch = 2;
1117	} else {
1118		if (patched_crtc_timing.v_front_porch < 1)
1119			patched_crtc_timing.v_front_porch = 1;
1120	}
1121
1122	/* blank_start = frame end - front porch */
1123	asic_blank_start = patched_crtc_timing.v_total -
1124					patched_crtc_timing.v_front_porch;
1125
1126	/* blank_end = blank_start - active */
1127	asic_blank_end = asic_blank_start -
1128					patched_crtc_timing.v_border_bottom -
1129					patched_crtc_timing.v_addressable -
1130					patched_crtc_timing.v_border_top;
1131
1132	newVstartup = asic_blank_end + (patched_crtc_timing.v_total - asic_blank_start);
1133
1134	*vstartup_start = ((newVstartup > *vstartup_start) ? newVstartup : *vstartup_start);
1135}
1136
1137void dcn20_calculate_dlg_params(struct dc *dc,
1138				struct dc_state *context,
1139				display_e2e_pipe_params_st *pipes,
1140				int pipe_cnt,
1141				int vlevel)
1142{
1143	int i, pipe_idx, active_hubp_count = 0;
1144
1145	dc_assert_fp_enabled();
1146
1147	/* Writeback MCIF_WB arbitration parameters */
1148	dc->res_pool->funcs->set_mcif_arb_params(dc, context, pipes, pipe_cnt);
1149
1150	context->bw_ctx.bw.dcn.clk.dispclk_khz = context->bw_ctx.dml.vba.DISPCLK * 1000;
1151	context->bw_ctx.bw.dcn.clk.dcfclk_khz = context->bw_ctx.dml.vba.DCFCLK * 1000;
1152	context->bw_ctx.bw.dcn.clk.socclk_khz = context->bw_ctx.dml.vba.SOCCLK * 1000;
1153	context->bw_ctx.bw.dcn.clk.dramclk_khz = context->bw_ctx.dml.vba.DRAMSpeed * 1000 / 16;
1154
1155	if (dc->debug.min_dram_clk_khz > context->bw_ctx.bw.dcn.clk.dramclk_khz)
1156		context->bw_ctx.bw.dcn.clk.dramclk_khz = dc->debug.min_dram_clk_khz;
1157
1158	context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = context->bw_ctx.dml.vba.DCFCLKDeepSleep * 1000;
1159	context->bw_ctx.bw.dcn.clk.fclk_khz = context->bw_ctx.dml.vba.FabricClock * 1000;
1160	context->bw_ctx.bw.dcn.clk.p_state_change_support =
1161		context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb]
1162							!= dm_dram_clock_change_unsupported;
1163
1164	/* Pstate change might not be supported by hardware, but it might be
1165	 * possible with firmware driven vertical blank stretching.
1166	 */
1167	context->bw_ctx.bw.dcn.clk.p_state_change_support |= context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching;
1168
1169	context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
1170
1171	context->bw_ctx.bw.dcn.clk.dtbclk_en = is_dtbclk_required(dc, context);
1172
1173	if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz)
1174		context->bw_ctx.bw.dcn.clk.dispclk_khz = dc->debug.min_disp_clk_khz;
1175
1176	for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
1177		if (!context->res_ctx.pipe_ctx[i].stream)
1178			continue;
1179		if (context->res_ctx.pipe_ctx[i].plane_state)
1180			active_hubp_count++;
1181		pipes[pipe_idx].pipe.dest.vstartup_start = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
1182		pipes[pipe_idx].pipe.dest.vupdate_offset = get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
1183		pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
1184		pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
1185
1186		if (dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM) {
1187			// Phantom pipe requires that DET_SIZE = 0 and no unbounded requests
1188			context->res_ctx.pipe_ctx[i].det_buffer_size_kb = 0;
1189			context->res_ctx.pipe_ctx[i].unbounded_req = false;
1190		} else {
1191			context->res_ctx.pipe_ctx[i].det_buffer_size_kb = context->bw_ctx.dml.ip.det_buffer_size_kbytes;
1192			context->res_ctx.pipe_ctx[i].unbounded_req = pipes[pipe_idx].pipe.src.unbounded_req_mode;
1193		}
1194
1195		if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
1196			context->bw_ctx.bw.dcn.clk.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
1197		context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz =
1198						pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
1199		context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest;
1200		if (dc->ctx->dce_version < DCN_VERSION_3_1 &&
1201		    context->res_ctx.pipe_ctx[i].stream->adaptive_sync_infopacket.valid)
1202			dcn20_adjust_freesync_v_startup(
1203				&context->res_ctx.pipe_ctx[i].stream->timing,
1204				&context->res_ctx.pipe_ctx[i].pipe_dlg_param.vstartup_start);
1205
1206		pipe_idx++;
1207	}
1208	/* If DCN isn't making memory requests we can allow pstate change */
1209	if (!active_hubp_count) {
1210		context->bw_ctx.bw.dcn.clk.p_state_change_support = true;
1211	}
1212	/*save a original dppclock copy*/
1213	context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
1214	context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
1215	context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dppclk_mhz * 1000;
1216	context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dispclk_mhz * 1000;
1217
1218	context->bw_ctx.bw.dcn.compbuf_size_kb = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes
1219						- context->bw_ctx.dml.ip.det_buffer_size_kbytes * pipe_idx;
1220
1221	for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
1222		bool cstate_en = context->bw_ctx.dml.vba.PrefetchMode[vlevel][context->bw_ctx.dml.vba.maxMpcComb] != 2;
1223
1224		if (!context->res_ctx.pipe_ctx[i].stream)
1225			continue;
1226
1227		/* cstate disabled on 201 */
1228		if (dc->ctx->dce_version == DCN_VERSION_2_01)
1229			cstate_en = false;
1230
1231		context->bw_ctx.dml.funcs.rq_dlg_get_dlg_reg(&context->bw_ctx.dml,
1232				&context->res_ctx.pipe_ctx[i].dlg_regs,
1233				&context->res_ctx.pipe_ctx[i].ttu_regs,
1234				pipes,
1235				pipe_cnt,
1236				pipe_idx,
1237				cstate_en,
1238				context->bw_ctx.bw.dcn.clk.p_state_change_support,
1239				false, false, true);
1240
1241		context->bw_ctx.dml.funcs.rq_dlg_get_rq_reg(&context->bw_ctx.dml,
1242				&context->res_ctx.pipe_ctx[i].rq_regs,
1243				&pipes[pipe_idx].pipe);
1244		pipe_idx++;
1245	}
1246	context->bw_ctx.bw.dcn.clk.zstate_support = decide_zstate_support(dc, context);
1247}
1248
1249static void swizzle_to_dml_params(
1250		enum swizzle_mode_values swizzle,
1251		unsigned int *sw_mode)
1252{
1253	switch (swizzle) {
1254	case DC_SW_LINEAR:
1255		*sw_mode = dm_sw_linear;
1256		break;
1257	case DC_SW_4KB_S:
1258		*sw_mode = dm_sw_4kb_s;
1259		break;
1260	case DC_SW_4KB_S_X:
1261		*sw_mode = dm_sw_4kb_s_x;
1262		break;
1263	case DC_SW_4KB_D:
1264		*sw_mode = dm_sw_4kb_d;
1265		break;
1266	case DC_SW_4KB_D_X:
1267		*sw_mode = dm_sw_4kb_d_x;
1268		break;
1269	case DC_SW_64KB_S:
1270		*sw_mode = dm_sw_64kb_s;
1271		break;
1272	case DC_SW_64KB_S_X:
1273		*sw_mode = dm_sw_64kb_s_x;
1274		break;
1275	case DC_SW_64KB_S_T:
1276		*sw_mode = dm_sw_64kb_s_t;
1277		break;
1278	case DC_SW_64KB_D:
1279		*sw_mode = dm_sw_64kb_d;
1280		break;
1281	case DC_SW_64KB_D_X:
1282		*sw_mode = dm_sw_64kb_d_x;
1283		break;
1284	case DC_SW_64KB_D_T:
1285		*sw_mode = dm_sw_64kb_d_t;
1286		break;
1287	case DC_SW_64KB_R_X:
1288		*sw_mode = dm_sw_64kb_r_x;
1289		break;
1290	case DC_SW_VAR_S:
1291		*sw_mode = dm_sw_var_s;
1292		break;
1293	case DC_SW_VAR_S_X:
1294		*sw_mode = dm_sw_var_s_x;
1295		break;
1296	case DC_SW_VAR_D:
1297		*sw_mode = dm_sw_var_d;
1298		break;
1299	case DC_SW_VAR_D_X:
1300		*sw_mode = dm_sw_var_d_x;
1301		break;
1302	case DC_SW_VAR_R_X:
1303		*sw_mode = dm_sw_var_r_x;
1304		break;
1305	default:
1306		ASSERT(0); /* Not supported */
1307		break;
1308	}
1309}
1310
1311int dcn20_populate_dml_pipes_from_context(struct dc *dc,
1312					  struct dc_state *context,
1313					  display_e2e_pipe_params_st *pipes,
1314					  bool fast_validate)
1315{
1316	int pipe_cnt, i;
1317	bool synchronized_vblank = true;
1318	struct resource_context *res_ctx = &context->res_ctx;
1319
1320	dc_assert_fp_enabled();
1321
1322	for (i = 0, pipe_cnt = -1; i < dc->res_pool->pipe_count; i++) {
1323		if (!res_ctx->pipe_ctx[i].stream)
1324			continue;
1325
1326		if (pipe_cnt < 0) {
1327			pipe_cnt = i;
1328			continue;
1329		}
1330
1331		if (res_ctx->pipe_ctx[pipe_cnt].stream == res_ctx->pipe_ctx[i].stream)
1332			continue;
1333
1334		if (dc->debug.disable_timing_sync ||
1335			(!resource_are_streams_timing_synchronizable(
1336				res_ctx->pipe_ctx[pipe_cnt].stream,
1337				res_ctx->pipe_ctx[i].stream) &&
1338			!resource_are_vblanks_synchronizable(
1339				res_ctx->pipe_ctx[pipe_cnt].stream,
1340				res_ctx->pipe_ctx[i].stream))) {
1341			synchronized_vblank = false;
1342			break;
1343		}
1344	}
1345
1346	for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
1347		struct dc_crtc_timing *timing = &res_ctx->pipe_ctx[i].stream->timing;
1348		unsigned int v_total;
1349		unsigned int front_porch;
1350		int output_bpc;
1351		struct audio_check aud_check = {0};
1352
1353		if (!res_ctx->pipe_ctx[i].stream)
1354			continue;
1355
1356		v_total = timing->v_total;
1357		front_porch = timing->v_front_porch;
1358
1359		/* todo:
1360		pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = 0;
1361		pipes[pipe_cnt].pipe.src.dcc = 0;
1362		pipes[pipe_cnt].pipe.src.vm = 0;*/
1363
1364		pipes[pipe_cnt].clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0;
1365
1366		pipes[pipe_cnt].pipe.dest.use_maximum_vstartup = dc->ctx->dce_version == DCN_VERSION_2_01;
1367
1368		pipes[pipe_cnt].dout.dsc_enable = res_ctx->pipe_ctx[i].stream->timing.flags.DSC;
1369		/* todo: rotation?*/
1370		pipes[pipe_cnt].dout.dsc_slices = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.num_slices_h;
1371		if (res_ctx->pipe_ctx[i].stream->use_dynamic_meta) {
1372			pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = true;
1373			/* 1/2 vblank */
1374			pipes[pipe_cnt].pipe.src.dynamic_metadata_lines_before_active =
1375				(v_total - timing->v_addressable
1376					- timing->v_border_top - timing->v_border_bottom) / 2;
1377			/* 36 bytes dp, 32 hdmi */
1378			pipes[pipe_cnt].pipe.src.dynamic_metadata_xmit_bytes =
1379				dc_is_dp_signal(res_ctx->pipe_ctx[i].stream->signal) ? 36 : 32;
1380		}
1381		pipes[pipe_cnt].pipe.src.dcc = false;
1382		pipes[pipe_cnt].pipe.src.dcc_rate = 1;
1383		pipes[pipe_cnt].pipe.dest.synchronized_vblank_all_planes = synchronized_vblank;
1384		pipes[pipe_cnt].pipe.dest.synchronize_timings = synchronized_vblank;
1385		pipes[pipe_cnt].pipe.dest.hblank_start = timing->h_total - timing->h_front_porch;
1386		pipes[pipe_cnt].pipe.dest.hblank_end = pipes[pipe_cnt].pipe.dest.hblank_start
1387				- timing->h_addressable
1388				- timing->h_border_left
1389				- timing->h_border_right;
1390		pipes[pipe_cnt].pipe.dest.vblank_start = v_total - front_porch;
1391		pipes[pipe_cnt].pipe.dest.vblank_end = pipes[pipe_cnt].pipe.dest.vblank_start
1392				- timing->v_addressable
1393				- timing->v_border_top
1394				- timing->v_border_bottom;
1395		pipes[pipe_cnt].pipe.dest.htotal = timing->h_total;
1396		pipes[pipe_cnt].pipe.dest.vtotal = v_total;
1397		pipes[pipe_cnt].pipe.dest.hactive =
1398			timing->h_addressable + timing->h_border_left + timing->h_border_right;
1399		pipes[pipe_cnt].pipe.dest.vactive =
1400			timing->v_addressable + timing->v_border_top + timing->v_border_bottom;
1401		pipes[pipe_cnt].pipe.dest.interlaced = timing->flags.INTERLACE;
1402		pipes[pipe_cnt].pipe.dest.pixel_rate_mhz = timing->pix_clk_100hz/10000.0;
1403		if (timing->timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
1404			pipes[pipe_cnt].pipe.dest.pixel_rate_mhz *= 2;
1405		pipes[pipe_cnt].pipe.dest.otg_inst = res_ctx->pipe_ctx[i].stream_res.tg->inst;
1406		pipes[pipe_cnt].dout.dp_lanes = 4;
1407		pipes[pipe_cnt].dout.dp_rate = dm_dp_rate_na;
1408		pipes[pipe_cnt].dout.is_virtual = 0;
1409		pipes[pipe_cnt].pipe.dest.vtotal_min = res_ctx->pipe_ctx[i].stream->adjust.v_total_min;
1410		pipes[pipe_cnt].pipe.dest.vtotal_max = res_ctx->pipe_ctx[i].stream->adjust.v_total_max;
1411		switch (resource_get_odm_slice_count(&res_ctx->pipe_ctx[i])) {
1412		case 2:
1413			pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_2to1;
1414			break;
1415		case 4:
1416			pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_4to1;
1417			break;
1418		default:
1419			pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_disabled;
1420		}
1421		pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].pipe_idx;
1422		if (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state
1423				== res_ctx->pipe_ctx[i].plane_state) {
1424			struct pipe_ctx *first_pipe = res_ctx->pipe_ctx[i].top_pipe;
1425			int split_idx = 0;
1426
1427			while (first_pipe->top_pipe && first_pipe->top_pipe->plane_state
1428					== res_ctx->pipe_ctx[i].plane_state) {
1429				first_pipe = first_pipe->top_pipe;
1430				split_idx++;
1431			}
1432			/* Treat 4to1 mpc combine as an mpo of 2 2-to-1 combines */
1433			if (split_idx == 0)
1434				pipes[pipe_cnt].pipe.src.hsplit_grp = first_pipe->pipe_idx;
1435			else if (split_idx == 1)
1436				pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].pipe_idx;
1437			else if (split_idx == 2)
1438				pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].top_pipe->pipe_idx;
1439		} else if (res_ctx->pipe_ctx[i].prev_odm_pipe) {
1440			struct pipe_ctx *first_pipe = res_ctx->pipe_ctx[i].prev_odm_pipe;
1441
1442			while (first_pipe->prev_odm_pipe)
1443				first_pipe = first_pipe->prev_odm_pipe;
1444			pipes[pipe_cnt].pipe.src.hsplit_grp = first_pipe->pipe_idx;
1445		}
1446
1447		switch (res_ctx->pipe_ctx[i].stream->signal) {
1448		case SIGNAL_TYPE_DISPLAY_PORT_MST:
1449		case SIGNAL_TYPE_DISPLAY_PORT:
1450			pipes[pipe_cnt].dout.output_type = dm_dp;
1451			if (dc->link_srv->dp_is_128b_132b_signal(&res_ctx->pipe_ctx[i]))
1452				pipes[pipe_cnt].dout.output_type = dm_dp2p0;
1453			break;
1454		case SIGNAL_TYPE_EDP:
1455			pipes[pipe_cnt].dout.output_type = dm_edp;
1456			break;
1457		case SIGNAL_TYPE_HDMI_TYPE_A:
1458		case SIGNAL_TYPE_DVI_SINGLE_LINK:
1459		case SIGNAL_TYPE_DVI_DUAL_LINK:
1460			pipes[pipe_cnt].dout.output_type = dm_hdmi;
1461			break;
1462		default:
1463			/* In case there is no signal, set dp with 4 lanes to allow max config */
1464			pipes[pipe_cnt].dout.is_virtual = 1;
1465			pipes[pipe_cnt].dout.output_type = dm_dp;
1466			pipes[pipe_cnt].dout.dp_lanes = 4;
1467		}
1468
1469		switch (res_ctx->pipe_ctx[i].stream->timing.display_color_depth) {
1470		case COLOR_DEPTH_666:
1471			output_bpc = 6;
1472			break;
1473		case COLOR_DEPTH_888:
1474			output_bpc = 8;
1475			break;
1476		case COLOR_DEPTH_101010:
1477			output_bpc = 10;
1478			break;
1479		case COLOR_DEPTH_121212:
1480			output_bpc = 12;
1481			break;
1482		case COLOR_DEPTH_141414:
1483			output_bpc = 14;
1484			break;
1485		case COLOR_DEPTH_161616:
1486			output_bpc = 16;
1487			break;
1488		case COLOR_DEPTH_999:
1489			output_bpc = 9;
1490			break;
1491		case COLOR_DEPTH_111111:
1492			output_bpc = 11;
1493			break;
1494		default:
1495			output_bpc = 8;
1496			break;
1497		}
1498
1499		switch (res_ctx->pipe_ctx[i].stream->timing.pixel_encoding) {
1500		case PIXEL_ENCODING_RGB:
1501		case PIXEL_ENCODING_YCBCR444:
1502			pipes[pipe_cnt].dout.output_format = dm_444;
1503			pipes[pipe_cnt].dout.output_bpp = output_bpc * 3;
1504			break;
1505		case PIXEL_ENCODING_YCBCR420:
1506			pipes[pipe_cnt].dout.output_format = dm_420;
1507			pipes[pipe_cnt].dout.output_bpp = (output_bpc * 3.0) / 2;
1508			break;
1509		case PIXEL_ENCODING_YCBCR422:
1510			if (res_ctx->pipe_ctx[i].stream->timing.flags.DSC &&
1511			    !res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.ycbcr422_simple)
1512				pipes[pipe_cnt].dout.output_format = dm_n422;
1513			else
1514				pipes[pipe_cnt].dout.output_format = dm_s422;
1515			pipes[pipe_cnt].dout.output_bpp = output_bpc * 2;
1516			break;
1517		default:
1518			pipes[pipe_cnt].dout.output_format = dm_444;
1519			pipes[pipe_cnt].dout.output_bpp = output_bpc * 3;
1520		}
1521
1522		if (res_ctx->pipe_ctx[i].stream->timing.flags.DSC)
1523			pipes[pipe_cnt].dout.output_bpp = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.bits_per_pixel / 16.0;
1524
1525		/* todo: default max for now, until there is logic reflecting this in dc*/
1526		pipes[pipe_cnt].dout.dsc_input_bpc = 12;
1527		/*fill up the audio sample rate (unit in kHz)*/
1528		get_audio_check(&res_ctx->pipe_ctx[i].stream->audio_info, &aud_check);
1529		pipes[pipe_cnt].dout.max_audio_sample_rate = aud_check.max_audiosample_rate / 1000;
1530		/*
1531		 * For graphic plane, cursor number is 1, nv12 is 0
1532		 * bw calculations due to cursor on/off
1533		 */
1534		if (res_ctx->pipe_ctx[i].plane_state &&
1535				(res_ctx->pipe_ctx[i].plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE ||
1536				dc_state_get_pipe_subvp_type(context, &res_ctx->pipe_ctx[i]) == SUBVP_PHANTOM))
1537			pipes[pipe_cnt].pipe.src.num_cursors = 0;
1538		else
1539			pipes[pipe_cnt].pipe.src.num_cursors = dc->dml.ip.number_of_cursors;
1540
1541		pipes[pipe_cnt].pipe.src.cur0_src_width = 256;
1542		pipes[pipe_cnt].pipe.src.cur0_bpp = dm_cur_32bit;
1543
1544		if (!res_ctx->pipe_ctx[i].plane_state) {
1545			pipes[pipe_cnt].pipe.src.is_hsplit = pipes[pipe_cnt].pipe.dest.odm_combine != dm_odm_combine_mode_disabled;
1546			pipes[pipe_cnt].pipe.src.source_scan = dm_horz;
1547			pipes[pipe_cnt].pipe.src.source_rotation = dm_rotation_0;
1548			pipes[pipe_cnt].pipe.src.sw_mode = dm_sw_4kb_s;
1549			pipes[pipe_cnt].pipe.src.macro_tile_size = dm_64k_tile;
1550			pipes[pipe_cnt].pipe.src.viewport_width = timing->h_addressable;
1551			if (pipes[pipe_cnt].pipe.src.viewport_width > 1920)
1552				pipes[pipe_cnt].pipe.src.viewport_width = 1920;
1553			pipes[pipe_cnt].pipe.src.viewport_height = timing->v_addressable;
1554			if (pipes[pipe_cnt].pipe.src.viewport_height > 1080)
1555				pipes[pipe_cnt].pipe.src.viewport_height = 1080;
1556			pipes[pipe_cnt].pipe.src.surface_height_y = pipes[pipe_cnt].pipe.src.viewport_height;
1557			pipes[pipe_cnt].pipe.src.surface_width_y = pipes[pipe_cnt].pipe.src.viewport_width;
1558			pipes[pipe_cnt].pipe.src.surface_height_c = pipes[pipe_cnt].pipe.src.viewport_height;
1559			pipes[pipe_cnt].pipe.src.surface_width_c = pipes[pipe_cnt].pipe.src.viewport_width;
1560			pipes[pipe_cnt].pipe.src.data_pitch = ((pipes[pipe_cnt].pipe.src.viewport_width + 255) / 256) * 256;
1561			pipes[pipe_cnt].pipe.src.source_format = dm_444_32;
1562			pipes[pipe_cnt].pipe.dest.recout_width = pipes[pipe_cnt].pipe.src.viewport_width; /*vp_width/hratio*/
1563			pipes[pipe_cnt].pipe.dest.recout_height = pipes[pipe_cnt].pipe.src.viewport_height; /*vp_height/vratio*/
1564			pipes[pipe_cnt].pipe.dest.full_recout_width = pipes[pipe_cnt].pipe.dest.recout_width;  /*when is_hsplit != 1*/
1565			pipes[pipe_cnt].pipe.dest.full_recout_height = pipes[pipe_cnt].pipe.dest.recout_height; /*when is_hsplit != 1*/
1566			pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_16;
1567			pipes[pipe_cnt].pipe.scale_ratio_depth.hscl_ratio = 1.0;
1568			pipes[pipe_cnt].pipe.scale_ratio_depth.vscl_ratio = 1.0;
1569			pipes[pipe_cnt].pipe.scale_ratio_depth.scl_enable = 0; /*Lb only or Full scl*/
1570			pipes[pipe_cnt].pipe.scale_taps.htaps = 1;
1571			pipes[pipe_cnt].pipe.scale_taps.vtaps = 1;
1572			pipes[pipe_cnt].pipe.dest.vtotal_min = v_total;
1573			pipes[pipe_cnt].pipe.dest.vtotal_max = v_total;
1574
1575			if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_2to1) {
1576				pipes[pipe_cnt].pipe.src.viewport_width /= 2;
1577				pipes[pipe_cnt].pipe.dest.recout_width /= 2;
1578			} else if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_4to1) {
1579				pipes[pipe_cnt].pipe.src.viewport_width /= 4;
1580				pipes[pipe_cnt].pipe.dest.recout_width /= 4;
1581			}
1582		} else {
1583			struct dc_plane_state *pln = res_ctx->pipe_ctx[i].plane_state;
1584			struct scaler_data *scl = &res_ctx->pipe_ctx[i].plane_res.scl_data;
1585
1586			pipes[pipe_cnt].pipe.src.immediate_flip = pln->flip_immediate;
1587			pipes[pipe_cnt].pipe.src.is_hsplit = (res_ctx->pipe_ctx[i].bottom_pipe && res_ctx->pipe_ctx[i].bottom_pipe->plane_state == pln)
1588					|| (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state == pln)
1589					|| pipes[pipe_cnt].pipe.dest.odm_combine != dm_odm_combine_mode_disabled;
1590
1591			/* stereo is not split */
1592			if (pln->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE ||
1593			    pln->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM) {
1594				pipes[pipe_cnt].pipe.src.is_hsplit = false;
1595				pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].pipe_idx;
1596			}
1597
1598			pipes[pipe_cnt].pipe.src.source_scan = pln->rotation == ROTATION_ANGLE_90
1599					|| pln->rotation == ROTATION_ANGLE_270 ? dm_vert : dm_horz;
1600			switch (pln->rotation) {
1601			case ROTATION_ANGLE_0:
1602				pipes[pipe_cnt].pipe.src.source_rotation = dm_rotation_0;
1603				break;
1604			case ROTATION_ANGLE_90:
1605				pipes[pipe_cnt].pipe.src.source_rotation = dm_rotation_90;
1606				break;
1607			case ROTATION_ANGLE_180:
1608				pipes[pipe_cnt].pipe.src.source_rotation = dm_rotation_180;
1609				break;
1610			case ROTATION_ANGLE_270:
1611				pipes[pipe_cnt].pipe.src.source_rotation = dm_rotation_270;
1612				break;
1613			default:
1614				break;
1615			}
1616
1617			pipes[pipe_cnt].pipe.src.viewport_y_y = scl->viewport.y;
1618			pipes[pipe_cnt].pipe.src.viewport_y_c = scl->viewport_c.y;
1619			pipes[pipe_cnt].pipe.src.viewport_x_y = scl->viewport.x;
1620			pipes[pipe_cnt].pipe.src.viewport_x_c = scl->viewport_c.x;
1621			pipes[pipe_cnt].pipe.src.viewport_width = scl->viewport.width;
1622			pipes[pipe_cnt].pipe.src.viewport_width_c = scl->viewport_c.width;
1623			pipes[pipe_cnt].pipe.src.viewport_height = scl->viewport.height;
1624			pipes[pipe_cnt].pipe.src.viewport_height_c = scl->viewport_c.height;
1625			pipes[pipe_cnt].pipe.src.viewport_width_max = pln->src_rect.width;
1626			pipes[pipe_cnt].pipe.src.viewport_height_max = pln->src_rect.height;
1627			pipes[pipe_cnt].pipe.src.surface_width_y = pln->plane_size.surface_size.width;
1628			pipes[pipe_cnt].pipe.src.surface_height_y = pln->plane_size.surface_size.height;
1629			pipes[pipe_cnt].pipe.src.surface_width_c = pln->plane_size.chroma_size.width;
1630			pipes[pipe_cnt].pipe.src.surface_height_c = pln->plane_size.chroma_size.height;
1631			if (pln->format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA
1632					|| pln->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
1633				pipes[pipe_cnt].pipe.src.data_pitch = pln->plane_size.surface_pitch;
1634				pipes[pipe_cnt].pipe.src.data_pitch_c = pln->plane_size.chroma_pitch;
1635				pipes[pipe_cnt].pipe.src.meta_pitch = pln->dcc.meta_pitch;
1636				pipes[pipe_cnt].pipe.src.meta_pitch_c = pln->dcc.meta_pitch_c;
1637			} else {
1638				pipes[pipe_cnt].pipe.src.data_pitch = pln->plane_size.surface_pitch;
1639				pipes[pipe_cnt].pipe.src.meta_pitch = pln->dcc.meta_pitch;
1640			}
1641			pipes[pipe_cnt].pipe.src.dcc = pln->dcc.enable;
1642			pipes[pipe_cnt].pipe.dest.recout_width = scl->recout.width;
1643			pipes[pipe_cnt].pipe.dest.recout_height = scl->recout.height;
1644			pipes[pipe_cnt].pipe.dest.full_recout_height = scl->recout.height;
1645			pipes[pipe_cnt].pipe.dest.full_recout_width = scl->recout.width;
1646			if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_2to1)
1647				pipes[pipe_cnt].pipe.dest.full_recout_width *= 2;
1648			else if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_4to1)
1649				pipes[pipe_cnt].pipe.dest.full_recout_width *= 4;
1650			else {
1651				struct pipe_ctx *split_pipe = res_ctx->pipe_ctx[i].bottom_pipe;
1652
1653				while (split_pipe && split_pipe->plane_state == pln) {
1654					pipes[pipe_cnt].pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width;
1655					split_pipe = split_pipe->bottom_pipe;
1656				}
1657				split_pipe = res_ctx->pipe_ctx[i].top_pipe;
1658				while (split_pipe && split_pipe->plane_state == pln) {
1659					pipes[pipe_cnt].pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width;
1660					split_pipe = split_pipe->top_pipe;
1661				}
1662			}
1663
1664			pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_16;
1665			pipes[pipe_cnt].pipe.scale_ratio_depth.hscl_ratio = (double) scl->ratios.horz.value / (1ULL<<32);
1666			pipes[pipe_cnt].pipe.scale_ratio_depth.hscl_ratio_c = (double) scl->ratios.horz_c.value / (1ULL<<32);
1667			pipes[pipe_cnt].pipe.scale_ratio_depth.vscl_ratio = (double) scl->ratios.vert.value / (1ULL<<32);
1668			pipes[pipe_cnt].pipe.scale_ratio_depth.vscl_ratio_c = (double) scl->ratios.vert_c.value / (1ULL<<32);
1669			pipes[pipe_cnt].pipe.scale_ratio_depth.scl_enable =
1670					scl->ratios.vert.value != dc_fixpt_one.value
1671					|| scl->ratios.horz.value != dc_fixpt_one.value
1672					|| scl->ratios.vert_c.value != dc_fixpt_one.value
1673					|| scl->ratios.horz_c.value != dc_fixpt_one.value /*Lb only or Full scl*/
1674					|| dc->debug.always_scale; /*support always scale*/
1675			pipes[pipe_cnt].pipe.scale_taps.htaps = scl->taps.h_taps;
1676			pipes[pipe_cnt].pipe.scale_taps.htaps_c = scl->taps.h_taps_c;
1677			pipes[pipe_cnt].pipe.scale_taps.vtaps = scl->taps.v_taps;
1678			pipes[pipe_cnt].pipe.scale_taps.vtaps_c = scl->taps.v_taps_c;
1679
1680			pipes[pipe_cnt].pipe.src.macro_tile_size =
1681					swizzle_mode_to_macro_tile_size(pln->tiling_info.gfx9.swizzle);
1682			swizzle_to_dml_params(pln->tiling_info.gfx9.swizzle,
1683					&pipes[pipe_cnt].pipe.src.sw_mode);
1684
1685			switch (pln->format) {
1686			case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
1687			case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
1688				pipes[pipe_cnt].pipe.src.source_format = dm_420_8;
1689				break;
1690			case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
1691			case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
1692				pipes[pipe_cnt].pipe.src.source_format = dm_420_10;
1693				break;
1694			case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
1695			case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
1696			case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
1697			case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
1698				pipes[pipe_cnt].pipe.src.source_format = dm_444_64;
1699				break;
1700			case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
1701			case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
1702				pipes[pipe_cnt].pipe.src.source_format = dm_444_16;
1703				break;
1704			case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
1705				pipes[pipe_cnt].pipe.src.source_format = dm_444_8;
1706				break;
1707			case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
1708				pipes[pipe_cnt].pipe.src.source_format = dm_rgbe_alpha;
1709				break;
1710			default:
1711				pipes[pipe_cnt].pipe.src.source_format = dm_444_32;
1712				break;
1713			}
1714		}
1715
1716		pipe_cnt++;
1717	}
1718
1719	/* populate writeback information */
1720	dc->res_pool->funcs->populate_dml_writeback_from_context(dc, res_ctx, pipes);
1721
1722	return pipe_cnt;
1723}
1724
1725void dcn20_calculate_wm(struct dc *dc, struct dc_state *context,
1726			display_e2e_pipe_params_st *pipes,
1727			int *out_pipe_cnt,
1728			int *pipe_split_from,
1729			int vlevel,
1730			bool fast_validate)
1731{
1732	int pipe_cnt, i, pipe_idx;
1733
1734	dc_assert_fp_enabled();
1735
1736	for (i = 0, pipe_idx = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
1737		if (!context->res_ctx.pipe_ctx[i].stream)
1738			continue;
1739
1740		pipes[pipe_cnt].clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0;
1741		pipes[pipe_cnt].clks_cfg.dispclk_mhz = context->bw_ctx.dml.vba.RequiredDISPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
1742
1743		if (pipe_split_from[i] < 0) {
1744			pipes[pipe_cnt].clks_cfg.dppclk_mhz =
1745					context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx];
1746			if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_idx] == pipe_idx)
1747				pipes[pipe_cnt].pipe.dest.odm_combine =
1748						context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx];
1749			else
1750				pipes[pipe_cnt].pipe.dest.odm_combine = 0;
1751			pipe_idx++;
1752		} else {
1753			pipes[pipe_cnt].clks_cfg.dppclk_mhz =
1754					context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_split_from[i]];
1755			if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_split_from[i]] == pipe_split_from[i])
1756				pipes[pipe_cnt].pipe.dest.odm_combine =
1757						context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_split_from[i]];
1758			else
1759				pipes[pipe_cnt].pipe.dest.odm_combine = 0;
1760		}
1761
1762		if (dc->config.forced_clocks) {
1763			pipes[pipe_cnt].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
1764			pipes[pipe_cnt].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
1765		}
1766		if (dc->debug.min_disp_clk_khz > pipes[pipe_cnt].clks_cfg.dispclk_mhz * 1000)
1767			pipes[pipe_cnt].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
1768		if (dc->debug.min_dpp_clk_khz > pipes[pipe_cnt].clks_cfg.dppclk_mhz * 1000)
1769			pipes[pipe_cnt].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
1770
1771		pipe_cnt++;
1772	}
1773
1774	if (pipe_cnt != pipe_idx) {
1775		if (dc->res_pool->funcs->populate_dml_pipes)
1776			pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc,
1777				context, pipes, fast_validate);
1778		else
1779			pipe_cnt = dcn20_populate_dml_pipes_from_context(dc,
1780				context, pipes, fast_validate);
1781	}
1782
1783	*out_pipe_cnt = pipe_cnt;
1784
1785	pipes[0].clks_cfg.voltage = vlevel;
1786	pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].dcfclk_mhz;
1787	pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz;
1788
1789	/* only pipe 0 is read for voltage and dcf/soc clocks */
1790	if (vlevel < 1) {
1791		pipes[0].clks_cfg.voltage = 1;
1792		pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[1].dcfclk_mhz;
1793		pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[1].socclk_mhz;
1794	}
1795	context->bw_ctx.bw.dcn.watermarks.b.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1796	context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1797	context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1798	context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1799	context->bw_ctx.bw.dcn.watermarks.b.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1800	context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1801	context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1802	context->bw_ctx.bw.dcn.watermarks.b.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1803
1804	if (vlevel < 2) {
1805		pipes[0].clks_cfg.voltage = 2;
1806		pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].dcfclk_mhz;
1807		pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].socclk_mhz;
1808	}
1809	context->bw_ctx.bw.dcn.watermarks.c.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1810	context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1811	context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1812	context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1813	context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1814	context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1815	context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1816
1817	if (vlevel < 3) {
1818		pipes[0].clks_cfg.voltage = 3;
1819		pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].dcfclk_mhz;
1820		pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].socclk_mhz;
1821	}
1822	context->bw_ctx.bw.dcn.watermarks.d.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1823	context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1824	context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1825	context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1826	context->bw_ctx.bw.dcn.watermarks.d.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1827	context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1828	context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1829
1830	pipes[0].clks_cfg.voltage = vlevel;
1831	pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].dcfclk_mhz;
1832	pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz;
1833	context->bw_ctx.bw.dcn.watermarks.a.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1834	context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1835	context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1836	context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1837	context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1838	context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1839	context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
1840}
1841
1842void dcn20_update_bounding_box(struct dc *dc,
1843			       struct _vcs_dpi_soc_bounding_box_st *bb,
1844			       struct pp_smu_nv_clock_table *max_clocks,
1845			       unsigned int *uclk_states,
1846			       unsigned int num_states)
1847{
1848	int num_calculated_states = 0;
1849	int min_dcfclk = 0;
1850	int i;
1851
1852	dc_assert_fp_enabled();
1853
1854	if (num_states == 0)
1855		return;
1856
1857	memset(bb->clock_limits, 0, sizeof(bb->clock_limits));
1858
1859	if (dc->bb_overrides.min_dcfclk_mhz > 0) {
1860		min_dcfclk = dc->bb_overrides.min_dcfclk_mhz;
1861	} else {
1862		if (ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev))
1863			min_dcfclk = 310;
1864		else
1865			// Accounting for SOC/DCF relationship, we can go as high as
1866			// 506Mhz in Vmin.
1867			min_dcfclk = 506;
1868	}
1869
1870	for (i = 0; i < num_states; i++) {
1871		int min_fclk_required_by_uclk;
1872		bb->clock_limits[i].state = i;
1873		bb->clock_limits[i].dram_speed_mts = uclk_states[i] * 16 / 1000;
1874
1875		// FCLK:UCLK ratio is 1.08
1876		min_fclk_required_by_uclk = div_u64(((unsigned long long)uclk_states[i]) * 1080,
1877			1000000);
1878
1879		bb->clock_limits[i].fabricclk_mhz = (min_fclk_required_by_uclk < min_dcfclk) ?
1880				min_dcfclk : min_fclk_required_by_uclk;
1881
1882		bb->clock_limits[i].socclk_mhz = (bb->clock_limits[i].fabricclk_mhz > max_clocks->socClockInKhz / 1000) ?
1883				max_clocks->socClockInKhz / 1000 : bb->clock_limits[i].fabricclk_mhz;
1884
1885		bb->clock_limits[i].dcfclk_mhz = (bb->clock_limits[i].fabricclk_mhz > max_clocks->dcfClockInKhz / 1000) ?
1886				max_clocks->dcfClockInKhz / 1000 : bb->clock_limits[i].fabricclk_mhz;
1887
1888		bb->clock_limits[i].dispclk_mhz = max_clocks->displayClockInKhz / 1000;
1889		bb->clock_limits[i].dppclk_mhz = max_clocks->displayClockInKhz / 1000;
1890		bb->clock_limits[i].dscclk_mhz = max_clocks->displayClockInKhz / (1000 * 3);
1891
1892		bb->clock_limits[i].phyclk_mhz = max_clocks->phyClockInKhz / 1000;
1893
1894		num_calculated_states++;
1895	}
1896
1897	bb->clock_limits[num_calculated_states - 1].socclk_mhz = max_clocks->socClockInKhz / 1000;
1898	bb->clock_limits[num_calculated_states - 1].fabricclk_mhz = max_clocks->socClockInKhz / 1000;
1899	bb->clock_limits[num_calculated_states - 1].dcfclk_mhz = max_clocks->dcfClockInKhz / 1000;
1900
1901	bb->num_states = num_calculated_states;
1902
1903	// Duplicate the last state, DML always an extra state identical to max state to work
1904	memcpy(&bb->clock_limits[num_calculated_states], &bb->clock_limits[num_calculated_states - 1], sizeof(struct _vcs_dpi_voltage_scaling_st));
1905	bb->clock_limits[num_calculated_states].state = bb->num_states;
1906}
1907
1908void dcn20_cap_soc_clocks(struct _vcs_dpi_soc_bounding_box_st *bb,
1909			  struct pp_smu_nv_clock_table max_clocks)
1910{
1911	int i;
1912
1913	dc_assert_fp_enabled();
1914
1915	// First pass - cap all clocks higher than the reported max
1916	for (i = 0; i < bb->num_states; i++) {
1917		if ((bb->clock_limits[i].dcfclk_mhz > (max_clocks.dcfClockInKhz / 1000))
1918				&& max_clocks.dcfClockInKhz != 0)
1919			bb->clock_limits[i].dcfclk_mhz = (max_clocks.dcfClockInKhz / 1000);
1920
1921		if ((bb->clock_limits[i].dram_speed_mts > (max_clocks.uClockInKhz / 1000) * 16)
1922						&& max_clocks.uClockInKhz != 0)
1923			bb->clock_limits[i].dram_speed_mts = (max_clocks.uClockInKhz / 1000) * 16;
1924
1925		if ((bb->clock_limits[i].fabricclk_mhz > (max_clocks.fabricClockInKhz / 1000))
1926						&& max_clocks.fabricClockInKhz != 0)
1927			bb->clock_limits[i].fabricclk_mhz = (max_clocks.fabricClockInKhz / 1000);
1928
1929		if ((bb->clock_limits[i].dispclk_mhz > (max_clocks.displayClockInKhz / 1000))
1930						&& max_clocks.displayClockInKhz != 0)
1931			bb->clock_limits[i].dispclk_mhz = (max_clocks.displayClockInKhz / 1000);
1932
1933		if ((bb->clock_limits[i].dppclk_mhz > (max_clocks.dppClockInKhz / 1000))
1934						&& max_clocks.dppClockInKhz != 0)
1935			bb->clock_limits[i].dppclk_mhz = (max_clocks.dppClockInKhz / 1000);
1936
1937		if ((bb->clock_limits[i].phyclk_mhz > (max_clocks.phyClockInKhz / 1000))
1938						&& max_clocks.phyClockInKhz != 0)
1939			bb->clock_limits[i].phyclk_mhz = (max_clocks.phyClockInKhz / 1000);
1940
1941		if ((bb->clock_limits[i].socclk_mhz > (max_clocks.socClockInKhz / 1000))
1942						&& max_clocks.socClockInKhz != 0)
1943			bb->clock_limits[i].socclk_mhz = (max_clocks.socClockInKhz / 1000);
1944
1945		if ((bb->clock_limits[i].dscclk_mhz > (max_clocks.dscClockInKhz / 1000))
1946						&& max_clocks.dscClockInKhz != 0)
1947			bb->clock_limits[i].dscclk_mhz = (max_clocks.dscClockInKhz / 1000);
1948	}
1949
1950	// Second pass - remove all duplicate clock states
1951	for (i = bb->num_states - 1; i > 1; i--) {
1952		bool duplicate = true;
1953
1954		if (bb->clock_limits[i-1].dcfclk_mhz != bb->clock_limits[i].dcfclk_mhz)
1955			duplicate = false;
1956		if (bb->clock_limits[i-1].dispclk_mhz != bb->clock_limits[i].dispclk_mhz)
1957			duplicate = false;
1958		if (bb->clock_limits[i-1].dppclk_mhz != bb->clock_limits[i].dppclk_mhz)
1959			duplicate = false;
1960		if (bb->clock_limits[i-1].dram_speed_mts != bb->clock_limits[i].dram_speed_mts)
1961			duplicate = false;
1962		if (bb->clock_limits[i-1].dscclk_mhz != bb->clock_limits[i].dscclk_mhz)
1963			duplicate = false;
1964		if (bb->clock_limits[i-1].fabricclk_mhz != bb->clock_limits[i].fabricclk_mhz)
1965			duplicate = false;
1966		if (bb->clock_limits[i-1].phyclk_mhz != bb->clock_limits[i].phyclk_mhz)
1967			duplicate = false;
1968		if (bb->clock_limits[i-1].socclk_mhz != bb->clock_limits[i].socclk_mhz)
1969			duplicate = false;
1970
1971		if (duplicate)
1972			bb->num_states--;
1973	}
1974}
1975
1976void dcn20_patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb)
1977{
1978	dc_assert_fp_enabled();
1979
1980	if ((int)(bb->sr_exit_time_us * 1000) != dc->bb_overrides.sr_exit_time_ns
1981			&& dc->bb_overrides.sr_exit_time_ns) {
1982		bb->sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
1983	}
1984
1985	if ((int)(bb->sr_enter_plus_exit_time_us * 1000)
1986				!= dc->bb_overrides.sr_enter_plus_exit_time_ns
1987			&& dc->bb_overrides.sr_enter_plus_exit_time_ns) {
1988		bb->sr_enter_plus_exit_time_us =
1989				dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
1990	}
1991
1992	if ((int)(bb->sr_exit_z8_time_us * 1000)
1993				!= dc->bb_overrides.sr_exit_z8_time_ns
1994			&& dc->bb_overrides.sr_exit_z8_time_ns) {
1995		bb->sr_exit_z8_time_us = dc->bb_overrides.sr_exit_z8_time_ns / 1000.0;
1996	}
1997
1998	if ((int)(bb->sr_enter_plus_exit_z8_time_us * 1000)
1999				!= dc->bb_overrides.sr_enter_plus_exit_z8_time_ns
2000			&& dc->bb_overrides.sr_enter_plus_exit_z8_time_ns) {
2001		bb->sr_enter_plus_exit_z8_time_us = dc->bb_overrides.sr_enter_plus_exit_z8_time_ns / 1000.0;
2002	}
2003	if ((int)(bb->urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns
2004			&& dc->bb_overrides.urgent_latency_ns) {
2005		bb->urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
2006	}
2007
2008	if ((int)(bb->dram_clock_change_latency_us * 1000)
2009				!= dc->bb_overrides.dram_clock_change_latency_ns
2010			&& dc->bb_overrides.dram_clock_change_latency_ns) {
2011		bb->dram_clock_change_latency_us =
2012				dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
2013	}
2014
2015	if ((int)(bb->dummy_pstate_latency_us * 1000)
2016				!= dc->bb_overrides.dummy_clock_change_latency_ns
2017			&& dc->bb_overrides.dummy_clock_change_latency_ns) {
2018		bb->dummy_pstate_latency_us =
2019				dc->bb_overrides.dummy_clock_change_latency_ns / 1000.0;
2020	}
2021}
2022
2023static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *context,
2024		bool fast_validate, display_e2e_pipe_params_st *pipes)
2025{
2026	bool out = false;
2027
2028	BW_VAL_TRACE_SETUP();
2029
2030	int vlevel = 0;
2031	int pipe_split_from[MAX_PIPES];
2032	int pipe_cnt = 0;
2033	DC_LOGGER_INIT(dc->ctx->logger);
2034
2035	BW_VAL_TRACE_COUNT();
2036
2037	out = dcn20_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, fast_validate);
2038
2039	if (pipe_cnt == 0)
2040		goto validate_out;
2041
2042	if (!out)
2043		goto validate_fail;
2044
2045	BW_VAL_TRACE_END_VOLTAGE_LEVEL();
2046
2047	if (fast_validate) {
2048		BW_VAL_TRACE_SKIP(fast);
2049		goto validate_out;
2050	}
2051
2052	dcn20_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate);
2053	dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
2054
2055	BW_VAL_TRACE_END_WATERMARKS();
2056
2057	goto validate_out;
2058
2059validate_fail:
2060	DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n",
2061		dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states]));
2062
2063	BW_VAL_TRACE_SKIP(fail);
2064	out = false;
2065
2066validate_out:
2067
2068	BW_VAL_TRACE_FINISH();
2069
2070	return out;
2071}
2072
2073bool dcn20_validate_bandwidth_fp(struct dc *dc, struct dc_state *context,
2074				 bool fast_validate, display_e2e_pipe_params_st *pipes)
2075{
2076	bool voltage_supported = false;
2077	bool full_pstate_supported = false;
2078	bool dummy_pstate_supported = false;
2079	double p_state_latency_us;
2080
2081	dc_assert_fp_enabled();
2082
2083	p_state_latency_us = context->bw_ctx.dml.soc.dram_clock_change_latency_us;
2084	context->bw_ctx.dml.soc.disable_dram_clock_change_vactive_support =
2085		dc->debug.disable_dram_clock_change_vactive_support;
2086	context->bw_ctx.dml.soc.allow_dram_clock_one_display_vactive =
2087		dc->debug.enable_dram_clock_change_one_display_vactive;
2088
2089	/*Unsafe due to current pipe merge and split logic*/
2090	ASSERT(context != dc->current_state);
2091
2092	if (fast_validate) {
2093		return dcn20_validate_bandwidth_internal(dc, context, true, pipes);
2094	}
2095
2096	// Best case, we support full UCLK switch latency
2097	voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false, pipes);
2098	full_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;
2099
2100	if (context->bw_ctx.dml.soc.dummy_pstate_latency_us == 0 ||
2101		(voltage_supported && full_pstate_supported)) {
2102		context->bw_ctx.bw.dcn.clk.p_state_change_support = full_pstate_supported;
2103		goto restore_dml_state;
2104	}
2105
2106	// Fallback: Try to only support G6 temperature read latency
2107	context->bw_ctx.dml.soc.dram_clock_change_latency_us = context->bw_ctx.dml.soc.dummy_pstate_latency_us;
2108
2109	memset(pipes, 0, dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st));
2110	voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false, pipes);
2111	dummy_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;
2112
2113	if (voltage_supported && (dummy_pstate_supported || !(context->stream_count))) {
2114		context->bw_ctx.bw.dcn.clk.p_state_change_support = false;
2115		goto restore_dml_state;
2116	}
2117
2118	// ERROR: fallback is supposed to always work.
2119	ASSERT(false);
2120
2121restore_dml_state:
2122	context->bw_ctx.dml.soc.dram_clock_change_latency_us = p_state_latency_us;
2123	return voltage_supported;
2124}
2125
2126void dcn20_fpu_set_wm_ranges(int i,
2127			     struct pp_smu_wm_range_sets *ranges,
2128			     struct _vcs_dpi_soc_bounding_box_st *loaded_bb)
2129{
2130	dc_assert_fp_enabled();
2131
2132	ranges->reader_wm_sets[i].min_fill_clk_mhz = (i > 0) ? (loaded_bb->clock_limits[i - 1].dram_speed_mts / 16) + 1 : 0;
2133	ranges->reader_wm_sets[i].max_fill_clk_mhz = loaded_bb->clock_limits[i].dram_speed_mts / 16;
2134}
2135
2136void dcn20_fpu_adjust_dppclk(struct vba_vars_st *v,
2137			     int vlevel,
2138			     int max_mpc_comb,
2139			     int pipe_idx,
2140			     bool is_validating_bw)
2141{
2142	dc_assert_fp_enabled();
2143
2144	if (is_validating_bw)
2145		v->RequiredDPPCLK[vlevel][max_mpc_comb][pipe_idx] *= 2;
2146	else
2147		v->RequiredDPPCLK[vlevel][max_mpc_comb][pipe_idx] /= 2;
2148}
2149
2150int dcn21_populate_dml_pipes_from_context(struct dc *dc,
2151					  struct dc_state *context,
2152					  display_e2e_pipe_params_st *pipes,
2153					  bool fast_validate)
2154{
2155	uint32_t pipe_cnt;
2156	int i;
2157
2158	dc_assert_fp_enabled();
2159
2160	pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
2161
2162	for (i = 0; i < pipe_cnt; i++) {
2163
2164		pipes[i].pipe.src.hostvm = dc->res_pool->hubbub->riommu_active;
2165		pipes[i].pipe.src.gpuvm = 1;
2166	}
2167
2168	return pipe_cnt;
2169}
2170
2171static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb)
2172{
2173	int i;
2174
2175	if (dc->bb_overrides.sr_exit_time_ns) {
2176		for (i = 0; i < WM_SET_COUNT; i++) {
2177			  dc->clk_mgr->bw_params->wm_table.entries[i].sr_exit_time_us =
2178					  dc->bb_overrides.sr_exit_time_ns / 1000.0;
2179		}
2180	}
2181
2182	if (dc->bb_overrides.sr_enter_plus_exit_time_ns) {
2183		for (i = 0; i < WM_SET_COUNT; i++) {
2184			  dc->clk_mgr->bw_params->wm_table.entries[i].sr_enter_plus_exit_time_us =
2185					  dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
2186		}
2187	}
2188
2189	if (dc->bb_overrides.urgent_latency_ns) {
2190		bb->urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
2191	}
2192
2193	if (dc->bb_overrides.dram_clock_change_latency_ns) {
2194		for (i = 0; i < WM_SET_COUNT; i++) {
2195			dc->clk_mgr->bw_params->wm_table.entries[i].pstate_latency_us =
2196				dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
2197		}
2198	}
2199}
2200
2201static void calculate_wm_set_for_vlevel(int vlevel,
2202					struct wm_range_table_entry *table_entry,
2203					struct dcn_watermarks *wm_set,
2204					struct display_mode_lib *dml,
2205					display_e2e_pipe_params_st *pipes,
2206					int pipe_cnt)
2207{
2208	double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us;
2209
2210	ASSERT(vlevel < dml->soc.num_states);
2211	/* only pipe 0 is read for voltage and dcf/soc clocks */
2212	pipes[0].clks_cfg.voltage = vlevel;
2213	pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz;
2214	pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
2215
2216	dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
2217	dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us;
2218	dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us;
2219
2220	wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
2221	wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
2222	wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000;
2223	wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000;
2224	wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000;
2225	wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000;
2226	wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000;
2227	wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000;
2228	dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached;
2229}
2230
2231static void dcn21_calculate_wm(struct dc *dc, struct dc_state *context,
2232			display_e2e_pipe_params_st *pipes,
2233			int *out_pipe_cnt,
2234			int *pipe_split_from,
2235			int vlevel_req,
2236			bool fast_validate)
2237{
2238	int pipe_cnt, i, pipe_idx;
2239	int vlevel, vlevel_max;
2240	struct wm_range_table_entry *table_entry;
2241	struct clk_bw_params *bw_params = dc->clk_mgr->bw_params;
2242
2243	ASSERT(bw_params);
2244
2245	patch_bounding_box(dc, &context->bw_ctx.dml.soc);
2246
2247	for (i = 0, pipe_idx = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
2248			if (!context->res_ctx.pipe_ctx[i].stream)
2249				continue;
2250
2251			pipes[pipe_cnt].clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0;
2252			pipes[pipe_cnt].clks_cfg.dispclk_mhz = context->bw_ctx.dml.vba.RequiredDISPCLK[vlevel_req][context->bw_ctx.dml.vba.maxMpcComb];
2253
2254			if (pipe_split_from[i] < 0) {
2255				pipes[pipe_cnt].clks_cfg.dppclk_mhz =
2256						context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel_req][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx];
2257				if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_idx] == pipe_idx)
2258					pipes[pipe_cnt].pipe.dest.odm_combine =
2259							context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel_req][pipe_idx];
2260				else
2261					pipes[pipe_cnt].pipe.dest.odm_combine = 0;
2262				pipe_idx++;
2263			} else {
2264				pipes[pipe_cnt].clks_cfg.dppclk_mhz =
2265						context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel_req][context->bw_ctx.dml.vba.maxMpcComb][pipe_split_from[i]];
2266				if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_split_from[i]] == pipe_split_from[i])
2267					pipes[pipe_cnt].pipe.dest.odm_combine =
2268							context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel_req][pipe_split_from[i]];
2269				else
2270					pipes[pipe_cnt].pipe.dest.odm_combine = 0;
2271			}
2272			pipe_cnt++;
2273	}
2274
2275	if (pipe_cnt != pipe_idx) {
2276		if (dc->res_pool->funcs->populate_dml_pipes)
2277			pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc,
2278				context, pipes, fast_validate);
2279		else
2280			pipe_cnt = dcn21_populate_dml_pipes_from_context(dc,
2281				context, pipes, fast_validate);
2282	}
2283
2284	*out_pipe_cnt = pipe_cnt;
2285
2286	vlevel_max = bw_params->clk_table.num_entries - 1;
2287
2288
2289	/* WM Set D */
2290	table_entry = &bw_params->wm_table.entries[WM_D];
2291	if (table_entry->wm_type == WM_TYPE_RETRAINING)
2292		vlevel = 0;
2293	else
2294		vlevel = vlevel_max;
2295	calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d,
2296						&context->bw_ctx.dml, pipes, pipe_cnt);
2297	/* WM Set C */
2298	table_entry = &bw_params->wm_table.entries[WM_C];
2299	vlevel = MIN(MAX(vlevel_req, 3), vlevel_max);
2300	calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c,
2301						&context->bw_ctx.dml, pipes, pipe_cnt);
2302	/* WM Set B */
2303	table_entry = &bw_params->wm_table.entries[WM_B];
2304	vlevel = MIN(MAX(vlevel_req, 2), vlevel_max);
2305	calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b,
2306						&context->bw_ctx.dml, pipes, pipe_cnt);
2307
2308	/* WM Set A */
2309	table_entry = &bw_params->wm_table.entries[WM_A];
2310	vlevel = MIN(vlevel_req, vlevel_max);
2311	calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a,
2312						&context->bw_ctx.dml, pipes, pipe_cnt);
2313}
2314
2315bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context,
2316				 bool fast_validate, display_e2e_pipe_params_st *pipes)
2317{
2318	bool out = false;
2319
2320	BW_VAL_TRACE_SETUP();
2321
2322	int vlevel = 0;
2323	int pipe_split_from[MAX_PIPES];
2324	int pipe_cnt = 0;
2325	DC_LOGGER_INIT(dc->ctx->logger);
2326
2327	BW_VAL_TRACE_COUNT();
2328
2329	dc_assert_fp_enabled();
2330
2331	/*Unsafe due to current pipe merge and split logic*/
2332	ASSERT(context != dc->current_state);
2333
2334	out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, fast_validate);
2335
2336	if (pipe_cnt == 0)
2337		goto validate_out;
2338
2339	if (!out)
2340		goto validate_fail;
2341
2342	BW_VAL_TRACE_END_VOLTAGE_LEVEL();
2343
2344	if (fast_validate) {
2345		BW_VAL_TRACE_SKIP(fast);
2346		goto validate_out;
2347	}
2348
2349	dcn21_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel, fast_validate);
2350	dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
2351
2352	BW_VAL_TRACE_END_WATERMARKS();
2353
2354	goto validate_out;
2355
2356validate_fail:
2357	DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n",
2358			dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states]));
2359
2360	BW_VAL_TRACE_SKIP(fail);
2361	out = false;
2362
2363validate_out:
2364
2365	BW_VAL_TRACE_FINISH();
2366
2367	return out;
2368}
2369
2370static struct _vcs_dpi_voltage_scaling_st construct_low_pstate_lvl(struct clk_limit_table *clk_table, unsigned int high_voltage_lvl)
2371{
2372	struct _vcs_dpi_voltage_scaling_st low_pstate_lvl;
2373	int i;
2374
2375	low_pstate_lvl.state = 1;
2376	low_pstate_lvl.dcfclk_mhz = clk_table->entries[0].dcfclk_mhz;
2377	low_pstate_lvl.fabricclk_mhz = clk_table->entries[0].fclk_mhz;
2378	low_pstate_lvl.socclk_mhz = clk_table->entries[0].socclk_mhz;
2379	low_pstate_lvl.dram_speed_mts = clk_table->entries[0].memclk_mhz * 2;
2380
2381	low_pstate_lvl.dispclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].dispclk_mhz;
2382	low_pstate_lvl.dppclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].dppclk_mhz;
2383	low_pstate_lvl.dram_bw_per_chan_gbps = dcn2_1_soc.clock_limits[high_voltage_lvl].dram_bw_per_chan_gbps;
2384	low_pstate_lvl.dscclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].dscclk_mhz;
2385	low_pstate_lvl.dtbclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].dtbclk_mhz;
2386	low_pstate_lvl.phyclk_d18_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_d18_mhz;
2387	low_pstate_lvl.phyclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_mhz;
2388
2389	for (i = clk_table->num_entries; i > 1; i--)
2390		clk_table->entries[i] = clk_table->entries[i-1];
2391	clk_table->entries[1] = clk_table->entries[0];
2392	clk_table->num_entries++;
2393
2394	return low_pstate_lvl;
2395}
2396
2397void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
2398{
2399	struct _vcs_dpi_voltage_scaling_st *s = dc->scratch.update_bw_bounding_box.clock_limits;
2400	struct dcn21_resource_pool *pool = TO_DCN21_RES_POOL(dc->res_pool);
2401	struct clk_limit_table *clk_table = &bw_params->clk_table;
2402	unsigned int i, closest_clk_lvl = 0, k = 0;
2403	int j;
2404
2405	dc_assert_fp_enabled();
2406
2407	dcn2_1_ip.max_num_otg = pool->base.res_cap->num_timing_generator;
2408	dcn2_1_ip.max_num_dpp = pool->base.pipe_count;
2409	dcn2_1_soc.num_chans = bw_params->num_channels;
2410
2411	ASSERT(clk_table->num_entries);
2412	/* Copy dcn2_1_soc.clock_limits to clock_limits to avoid copying over null states later */
2413	memcpy(s, dcn2_1_soc.clock_limits, sizeof(dcn2_1_soc.clock_limits));
2414
2415	for (i = 0; i < clk_table->num_entries; i++) {
2416		/* loop backwards*/
2417		for (closest_clk_lvl = 0, j = dcn2_1_soc.num_states - 1; j >= 0; j--) {
2418			if ((unsigned int) dcn2_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
2419				closest_clk_lvl = j;
2420				break;
2421			}
2422		}
2423
2424		/* clk_table[1] is reserved for min DF PState.  skip here to fill in later. */
2425		if (i == 1)
2426			k++;
2427
2428		s[k].state = k;
2429		s[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
2430		s[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
2431		s[k].socclk_mhz = clk_table->entries[i].socclk_mhz;
2432		s[k].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2;
2433
2434		s[k].dispclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
2435		s[k].dppclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
2436		s[k].dram_bw_per_chan_gbps =
2437			dcn2_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
2438		s[k].dscclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
2439		s[k].dtbclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
2440		s[k].phyclk_d18_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
2441		s[k].phyclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
2442
2443		k++;
2444	}
2445
2446	memcpy(&dcn2_1_soc.clock_limits, s, sizeof(dcn2_1_soc.clock_limits));
2447
2448	if (clk_table->num_entries) {
2449		dcn2_1_soc.num_states = clk_table->num_entries + 1;
2450		/* fill in min DF PState */
2451		dcn2_1_soc.clock_limits[1] = construct_low_pstate_lvl(clk_table, closest_clk_lvl);
2452		/* duplicate last level */
2453		dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1];
2454		dcn2_1_soc.clock_limits[dcn2_1_soc.num_states].state = dcn2_1_soc.num_states;
2455	}
2456
2457	dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21);
2458}
2459
2460void dcn21_clk_mgr_set_bw_params_wm_table(struct clk_bw_params *bw_params)
2461{
2462	dc_assert_fp_enabled();
2463
2464	bw_params->wm_table.entries[WM_D].pstate_latency_us = LPDDR_MEM_RETRAIN_LATENCY;
2465	bw_params->wm_table.entries[WM_D].wm_inst = WM_D;
2466	bw_params->wm_table.entries[WM_D].wm_type = WM_TYPE_RETRAINING;
2467	bw_params->wm_table.entries[WM_D].valid = true;
2468}
2469
2470void dcn201_populate_dml_writeback_from_context_fpu(struct dc *dc,
2471						    struct resource_context *res_ctx,
2472						    display_e2e_pipe_params_st *pipes)
2473{
2474	int pipe_cnt, i, j;
2475	double max_calc_writeback_dispclk;
2476	double writeback_dispclk;
2477	struct writeback_st dout_wb;
2478
2479	dc_assert_fp_enabled();
2480
2481	for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
2482		struct dc_stream_state *stream = res_ctx->pipe_ctx[i].stream;
2483
2484		if (!stream)
2485			continue;
2486		max_calc_writeback_dispclk = 0;
2487
2488		/* Set writeback information */
2489		pipes[pipe_cnt].dout.wb_enable = 0;
2490		pipes[pipe_cnt].dout.num_active_wb = 0;
2491		for (j = 0; j < stream->num_wb_info; j++) {
2492			struct dc_writeback_info *wb_info = &stream->writeback_info[j];
2493
2494			if (wb_info->wb_enabled && wb_info->writeback_source_plane &&
2495					(wb_info->writeback_source_plane == res_ctx->pipe_ctx[i].plane_state)) {
2496				pipes[pipe_cnt].dout.wb_enable = 1;
2497				pipes[pipe_cnt].dout.num_active_wb++;
2498				dout_wb.wb_src_height = wb_info->dwb_params.cnv_params.crop_en ?
2499					wb_info->dwb_params.cnv_params.crop_height :
2500					wb_info->dwb_params.cnv_params.src_height;
2501				dout_wb.wb_src_width = wb_info->dwb_params.cnv_params.crop_en ?
2502					wb_info->dwb_params.cnv_params.crop_width :
2503					wb_info->dwb_params.cnv_params.src_width;
2504				dout_wb.wb_dst_width = wb_info->dwb_params.dest_width;
2505				dout_wb.wb_dst_height = wb_info->dwb_params.dest_height;
2506				dout_wb.wb_htaps_luma = wb_info->dwb_params.scaler_taps.h_taps;
2507				dout_wb.wb_vtaps_luma = wb_info->dwb_params.scaler_taps.v_taps;
2508				dout_wb.wb_htaps_chroma = wb_info->dwb_params.scaler_taps.h_taps_c;
2509				dout_wb.wb_vtaps_chroma = wb_info->dwb_params.scaler_taps.v_taps_c;
2510				dout_wb.wb_hratio = wb_info->dwb_params.cnv_params.crop_en ?
2511					(double)wb_info->dwb_params.cnv_params.crop_width /
2512						(double)wb_info->dwb_params.dest_width :
2513					(double)wb_info->dwb_params.cnv_params.src_width /
2514						(double)wb_info->dwb_params.dest_width;
2515				dout_wb.wb_vratio = wb_info->dwb_params.cnv_params.crop_en ?
2516					(double)wb_info->dwb_params.cnv_params.crop_height /
2517						(double)wb_info->dwb_params.dest_height :
2518					(double)wb_info->dwb_params.cnv_params.src_height /
2519						(double)wb_info->dwb_params.dest_height;
2520				if (wb_info->dwb_params.out_format == dwb_scaler_mode_yuv420) {
2521					if (wb_info->dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC)
2522						dout_wb.wb_pixel_format = dm_420_8;
2523					else
2524						dout_wb.wb_pixel_format = dm_420_10;
2525				} else
2526					dout_wb.wb_pixel_format = dm_444_32;
2527
2528				/* Workaround for cases where multiple writebacks are connected to same plane
2529				 * In which case, need to compute worst case and set the associated writeback parameters
2530				 * This workaround is necessary due to DML computation assuming only 1 set of writeback
2531				 * parameters per pipe */
2532				writeback_dispclk = CalculateWriteBackDISPCLK(
2533						dout_wb.wb_pixel_format,
2534						pipes[pipe_cnt].pipe.dest.pixel_rate_mhz,
2535						dout_wb.wb_hratio,
2536						dout_wb.wb_vratio,
2537						dout_wb.wb_htaps_luma,
2538						dout_wb.wb_vtaps_luma,
2539						dout_wb.wb_htaps_chroma,
2540						dout_wb.wb_vtaps_chroma,
2541						dout_wb.wb_dst_width,
2542						pipes[pipe_cnt].pipe.dest.htotal,
2543						2);
2544
2545				if (writeback_dispclk > max_calc_writeback_dispclk) {
2546					max_calc_writeback_dispclk = writeback_dispclk;
2547					pipes[pipe_cnt].dout.wb = dout_wb;
2548				}
2549			}
2550		}
2551
2552		pipe_cnt++;
2553	}
2554
2555}
2556