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 | |
85 | struct _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 | |
152 | struct _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 | |
221 | struct _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 | |
333 | struct _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 | |
444 | struct _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 | |
554 | struct _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 | |
625 | struct _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 | |
768 | struct 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 | |
805 | struct 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 | |
842 | struct 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 | |
879 | struct 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 | |
916 | struct 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 | |
953 | struct 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 | |
990 | void 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 | |
1030 | void 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(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1041 | wb_arb_params->pstate_watermark[k] = get_wm_writeback_dram_clock_change(mode_lib: &context->bw_ctx.dml, pipes, num_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 | |
1046 | static 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 | |
1058 | static 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 | |
1104 | static 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 | |
1137 | void 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(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt, which_pipe: pipe_idx); |
1182 | pipes[pipe_idx].pipe.dest.vupdate_offset = get_vupdate_offset(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt, which_pipe: pipe_idx); |
1183 | pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt, which_pipe: pipe_idx); |
1184 | pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt, which_pipe: pipe_idx); |
1185 | |
1186 | if (dc_state_get_pipe_subvp_type(state: context, pipe_ctx: &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 | dc_crtc_timing: &context->res_ctx.pipe_ctx[i].stream->timing, |
1204 | vstartup_start: &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 | |
1249 | static 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 | |
1311 | int 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 | stream1: res_ctx->pipe_ctx[pipe_cnt].stream, |
1337 | stream2: res_ctx->pipe_ctx[i].stream) && |
1338 | !resource_are_vblanks_synchronizable( |
1339 | stream1: res_ctx->pipe_ctx[pipe_cnt].stream, |
1340 | stream2: 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(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(pipe: &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(aud_modes: &res_ctx->pipe_ctx[i].stream->audio_info, aud_chk: &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(state: context, pipe_ctx: &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(sw_mode: pln->tiling_info.gfx9.swizzle); |
1682 | swizzle_to_dml_params(swizzle: pln->tiling_info.gfx9.swizzle, |
1683 | sw_mode: &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 | |
1725 | void 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(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1796 | context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1797 | context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1798 | context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1799 | context->bw_ctx.bw.dcn.watermarks.b.pte_meta_urgent_ns = get_wm_memory_trip(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1800 | context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1801 | context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1802 | context->bw_ctx.bw.dcn.watermarks.b.urgent_latency_ns = get_urgent_latency(mode_lib: &context->bw_ctx.dml, pipes, num_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(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1810 | context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1811 | context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1812 | context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1813 | context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1814 | context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1815 | context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(mode_lib: &context->bw_ctx.dml, pipes, num_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(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1823 | context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1824 | context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1825 | context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1826 | context->bw_ctx.bw.dcn.watermarks.d.pte_meta_urgent_ns = get_wm_memory_trip(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1827 | context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1828 | context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(mode_lib: &context->bw_ctx.dml, pipes, num_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(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1834 | context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1835 | context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1836 | context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1837 | context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1838 | context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1839 | context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(mode_lib: &context->bw_ctx.dml, pipes, num_pipes: pipe_cnt) * 1000; |
1840 | } |
1841 | |
1842 | void 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(dividend: ((unsigned long long)uclk_states[i]) * 1080, |
1877 | divisor: 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 | |
1908 | void 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 | |
1976 | void 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 | |
2023 | static 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_out: &pipe_cnt, pipe_split_from, vlevel_out: &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, out_pipe_cnt: &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 | |
2059 | validate_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 | |
2066 | validate_out: |
2067 | |
2068 | BW_VAL_TRACE_FINISH(); |
2069 | |
2070 | return out; |
2071 | } |
2072 | |
2073 | bool 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, fast_validate: true, pipes); |
2094 | } |
2095 | |
2096 | // Best case, we support full UCLK switch latency |
2097 | voltage_supported = dcn20_validate_bandwidth_internal(dc, context, fast_validate: 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, fast_validate: 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 | |
2121 | restore_dml_state: |
2122 | context->bw_ctx.dml.soc.dram_clock_change_latency_us = p_state_latency_us; |
2123 | return voltage_supported; |
2124 | } |
2125 | |
2126 | void 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 | |
2136 | void 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 | |
2150 | int 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 | |
2171 | static 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 | |
2201 | static 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(mode_lib: dml, pipes, num_pipes: pipe_cnt) * 1000; |
2221 | wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(mode_lib: dml, pipes, num_pipes: pipe_cnt) * 1000; |
2222 | wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(mode_lib: dml, pipes, num_pipes: pipe_cnt) * 1000; |
2223 | wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(mode_lib: dml, pipes, num_pipes: pipe_cnt) * 1000; |
2224 | wm_set->pte_meta_urgent_ns = get_wm_memory_trip(mode_lib: dml, pipes, num_pipes: pipe_cnt) * 1000; |
2225 | wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(mode_lib: dml, pipes, num_pipes: pipe_cnt) * 1000; |
2226 | wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(mode_lib: dml, pipes, num_pipes: pipe_cnt) * 1000; |
2227 | wm_set->urgent_latency_ns = get_urgent_latency(mode_lib: dml, pipes, num_pipes: pipe_cnt) * 1000; |
2228 | dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached; |
2229 | } |
2230 | |
2231 | static 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, bb: &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, wm_set: &context->bw_ctx.bw.dcn.watermarks.d, |
2296 | dml: &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, wm_set: &context->bw_ctx.bw.dcn.watermarks.c, |
2301 | dml: &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, wm_set: &context->bw_ctx.bw.dcn.watermarks.b, |
2306 | dml: &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, wm_set: &context->bw_ctx.bw.dcn.watermarks.a, |
2312 | dml: &context->bw_ctx.dml, pipes, pipe_cnt); |
2313 | } |
2314 | |
2315 | bool 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_out: &pipe_cnt, pipe_split_from, vlevel_out: &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, out_pipe_cnt: &pipe_cnt, pipe_split_from, vlevel_req: 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 | |
2356 | validate_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 | |
2363 | validate_out: |
2364 | |
2365 | BW_VAL_TRACE_FINISH(); |
2366 | |
2367 | return out; |
2368 | } |
2369 | |
2370 | static 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 | |
2397 | void 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, high_voltage_lvl: 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(lib: &dc->dml, soc_bb: &dcn2_1_soc, ip_params: &dcn2_1_ip, project: DML_PROJECT_DCN21); |
2458 | } |
2459 | |
2460 | void 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 | |
2470 | void 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 | WritebackPixelFormat: dout_wb.wb_pixel_format, |
2534 | PixelClock: pipes[pipe_cnt].pipe.dest.pixel_rate_mhz, |
2535 | WritebackHRatio: dout_wb.wb_hratio, |
2536 | WritebackVRatio: dout_wb.wb_vratio, |
2537 | WritebackLumaHTaps: dout_wb.wb_htaps_luma, |
2538 | WritebackLumaVTaps: dout_wb.wb_vtaps_luma, |
2539 | WritebackChromaHTaps: dout_wb.wb_htaps_chroma, |
2540 | WritebackChromaVTaps: dout_wb.wb_vtaps_chroma, |
2541 | WritebackDestinationWidth: dout_wb.wb_dst_width, |
2542 | HTotal: pipes[pipe_cnt].pipe.dest.htotal, |
2543 | WritebackChromaLineBufferWidth: 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 | |