1 // SPDX-License-Identifier: MIT
3 * Copyright 2021 Advanced Micro Devices, Inc.
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
30 #include "dcn20/dcn20_resource.h"
31 #include "dcn21/dcn21_resource.h"
32 #include "clk_mgr/dcn21/rn_clk_mgr.h"
35 #include "dcn20_fpu.h"
39 #define DC_LOGGER_INIT(logger)
42 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
45 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
49 #define LPDDR_MEM_RETRAIN_LATENCY 4.977 /* Number obtained from LPDDR4 Training Counter Requirement doc */
52 * DOC: DCN2x FPU manipulation Overview
54 * The DCN architecture relies on FPU operations, which require special
55 * compilation flags and the use of kernel_fpu_begin/end functions; ideally, we
56 * want to avoid spreading FPU access across multiple files. With this idea in
57 * mind, this file aims to centralize all DCN20 and DCN2.1 (DCN2x) functions
58 * that require FPU access in a single place. Code in this file follows the
59 * following code pattern:
61 * 1. Functions that use FPU operations should be isolated in static functions.
62 * 2. The FPU functions should have the noinline attribute to ensure anything
63 * that deals with FP register is contained within this call.
64 * 3. All function that needs to be accessed outside this file requires a
65 * public interface that not uses any FPU reference.
66 * 4. Developers **must not** use DC_FP_START/END in this file, but they need
67 * to ensure that the caller invokes it before access any function available
68 * in this file. For this reason, public functions in this file must invoke
69 * dc_assert_fp_enabled();
71 * Let's expand a little bit more the idea in the code pattern. To fully
72 * isolate FPU operations in a single place, we must avoid situations where
73 * compilers spill FP values to registers due to FP enable in a specific C
74 * file. Note that even if we isolate all FPU functions in a single file and
75 * call its interface from other files, the compiler might enable the use of
76 * FPU before we call DC_FP_START. Nevertheless, it is the programmer's
77 * responsibility to invoke DC_FP_START/END in the correct place. To highlight
78 * situations where developers forgot to use the FP protection before calling
79 * the DC FPU interface functions, we introduce a helper that checks if the
80 * function is invoked under FP protection. If not, it will trigger a kernel
84 struct _vcs_dpi_ip_params_st dcn2_0_ip
= {
88 .gpuvm_max_page_table_levels
= 4,
89 .hostvm_max_page_table_levels
= 4,
90 .hostvm_cached_page_table_levels
= 0,
91 .pte_group_size_bytes
= 2048,
93 .rob_buffer_size_kbytes
= 168,
94 .det_buffer_size_kbytes
= 164,
95 .dpte_buffer_size_in_pte_reqs_luma
= 84,
96 .pde_proc_buffer_size_64k_reqs
= 48,
97 .dpp_output_buffer_pixels
= 2560,
98 .opp_output_buffer_lines
= 1,
99 .pixel_chunk_size_kbytes
= 8,
100 .pte_chunk_size_kbytes
= 2,
101 .meta_chunk_size_kbytes
= 2,
102 .writeback_chunk_size_kbytes
= 2,
103 .line_buffer_size_bits
= 789504,
104 .is_line_buffer_bpp_fixed
= 0,
105 .line_buffer_fixed_bpp
= 0,
106 .dcc_supported
= true,
107 .max_line_buffer_lines
= 12,
108 .writeback_luma_buffer_size_kbytes
= 12,
109 .writeback_chroma_buffer_size_kbytes
= 8,
110 .writeback_chroma_line_buffer_width_pixels
= 4,
111 .writeback_max_hscl_ratio
= 1,
112 .writeback_max_vscl_ratio
= 1,
113 .writeback_min_hscl_ratio
= 1,
114 .writeback_min_vscl_ratio
= 1,
115 .writeback_max_hscl_taps
= 12,
116 .writeback_max_vscl_taps
= 12,
117 .writeback_line_buffer_luma_buffer_size
= 0,
118 .writeback_line_buffer_chroma_buffer_size
= 14643,
119 .cursor_buffer_size
= 8,
120 .cursor_chunk_size
= 2,
124 .max_dchub_pscl_bw_pix_per_clk
= 4,
125 .max_pscl_lb_bw_pix_per_clk
= 2,
126 .max_lb_vscl_bw_pix_per_clk
= 4,
127 .max_vscl_hscl_bw_pix_per_clk
= 4,
134 .dispclk_ramp_margin_percent
= 1,
135 .underscan_factor
= 1.10,
136 .min_vblank_lines
= 32, //
137 .dppclk_delay_subtotal
= 77, //
138 .dppclk_delay_scl_lb_only
= 16,
139 .dppclk_delay_scl
= 50,
140 .dppclk_delay_cnvc_formatter
= 8,
141 .dppclk_delay_cnvc_cursor
= 6,
142 .dispclk_delay_subtotal
= 87, //
143 .dcfclk_cstate_latency
= 10, // SRExitTime
144 .max_inter_dcn_tile_repeaters
= 8,
145 .xfc_supported
= true,
146 .xfc_fill_bw_overhead_percent
= 10.0,
147 .xfc_fill_constant_bytes
= 0,
148 .number_of_cursors
= 1,
151 struct _vcs_dpi_ip_params_st dcn2_0_nv14_ip
= {
155 .gpuvm_max_page_table_levels
= 4,
156 .hostvm_max_page_table_levels
= 4,
157 .hostvm_cached_page_table_levels
= 0,
159 .rob_buffer_size_kbytes
= 168,
160 .det_buffer_size_kbytes
= 164,
161 .dpte_buffer_size_in_pte_reqs_luma
= 84,
162 .dpte_buffer_size_in_pte_reqs_chroma
= 42,//todo
163 .dpp_output_buffer_pixels
= 2560,
164 .opp_output_buffer_lines
= 1,
165 .pixel_chunk_size_kbytes
= 8,
167 .max_page_table_levels
= 4,
168 .pte_chunk_size_kbytes
= 2,
169 .meta_chunk_size_kbytes
= 2,
170 .writeback_chunk_size_kbytes
= 2,
171 .line_buffer_size_bits
= 789504,
172 .is_line_buffer_bpp_fixed
= 0,
173 .line_buffer_fixed_bpp
= 0,
174 .dcc_supported
= true,
175 .max_line_buffer_lines
= 12,
176 .writeback_luma_buffer_size_kbytes
= 12,
177 .writeback_chroma_buffer_size_kbytes
= 8,
178 .writeback_chroma_line_buffer_width_pixels
= 4,
179 .writeback_max_hscl_ratio
= 1,
180 .writeback_max_vscl_ratio
= 1,
181 .writeback_min_hscl_ratio
= 1,
182 .writeback_min_vscl_ratio
= 1,
183 .writeback_max_hscl_taps
= 12,
184 .writeback_max_vscl_taps
= 12,
185 .writeback_line_buffer_luma_buffer_size
= 0,
186 .writeback_line_buffer_chroma_buffer_size
= 14643,
187 .cursor_buffer_size
= 8,
188 .cursor_chunk_size
= 2,
192 .max_dchub_pscl_bw_pix_per_clk
= 4,
193 .max_pscl_lb_bw_pix_per_clk
= 2,
194 .max_lb_vscl_bw_pix_per_clk
= 4,
195 .max_vscl_hscl_bw_pix_per_clk
= 4,
202 .dispclk_ramp_margin_percent
= 1,
203 .underscan_factor
= 1.10,
204 .min_vblank_lines
= 32, //
205 .dppclk_delay_subtotal
= 77, //
206 .dppclk_delay_scl_lb_only
= 16,
207 .dppclk_delay_scl
= 50,
208 .dppclk_delay_cnvc_formatter
= 8,
209 .dppclk_delay_cnvc_cursor
= 6,
210 .dispclk_delay_subtotal
= 87, //
211 .dcfclk_cstate_latency
= 10, // SRExitTime
212 .max_inter_dcn_tile_repeaters
= 8,
213 .xfc_supported
= true,
214 .xfc_fill_bw_overhead_percent
= 10.0,
215 .xfc_fill_constant_bytes
= 0,
217 .number_of_cursors
= 1,
220 struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc
= {
221 /* Defaults that get patched on driver load from firmware. */
226 .fabricclk_mhz
= 560.0,
227 .dispclk_mhz
= 513.0,
232 .dram_speed_mts
= 8960.0,
237 .fabricclk_mhz
= 694.0,
238 .dispclk_mhz
= 642.0,
243 .dram_speed_mts
= 11104.0,
248 .fabricclk_mhz
= 875.0,
249 .dispclk_mhz
= 734.0,
254 .dram_speed_mts
= 14000.0,
258 .dcfclk_mhz
= 1000.0,
259 .fabricclk_mhz
= 1000.0,
260 .dispclk_mhz
= 1100.0,
261 .dppclk_mhz
= 1100.0,
263 .socclk_mhz
= 1000.0,
265 .dram_speed_mts
= 16000.0,
269 .dcfclk_mhz
= 1200.0,
270 .fabricclk_mhz
= 1200.0,
271 .dispclk_mhz
= 1284.0,
272 .dppclk_mhz
= 1284.0,
274 .socclk_mhz
= 1200.0,
276 .dram_speed_mts
= 16000.0,
278 /*Extra state, no dispclk ramping*/
281 .dcfclk_mhz
= 1200.0,
282 .fabricclk_mhz
= 1200.0,
283 .dispclk_mhz
= 1284.0,
284 .dppclk_mhz
= 1284.0,
286 .socclk_mhz
= 1200.0,
288 .dram_speed_mts
= 16000.0,
292 .sr_exit_time_us
= 8.6,
293 .sr_enter_plus_exit_time_us
= 10.9,
294 .urgent_latency_us
= 4.0,
295 .urgent_latency_pixel_data_only_us
= 4.0,
296 .urgent_latency_pixel_mixed_with_vm_data_us
= 4.0,
297 .urgent_latency_vm_data_only_us
= 4.0,
298 .urgent_out_of_order_return_per_channel_pixel_only_bytes
= 4096,
299 .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes
= 4096,
300 .urgent_out_of_order_return_per_channel_vm_only_bytes
= 4096,
301 .pct_ideal_dram_sdp_bw_after_urgent_pixel_only
= 40.0,
302 .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm
= 40.0,
303 .pct_ideal_dram_sdp_bw_after_urgent_vm_only
= 40.0,
304 .max_avg_sdp_bw_use_normal_percent
= 40.0,
305 .max_avg_dram_bw_use_normal_percent
= 40.0,
306 .writeback_latency_us
= 12.0,
307 .ideal_dram_bw_after_urgent_percent
= 40.0,
308 .max_request_size_bytes
= 256,
309 .dram_channel_width_bytes
= 2,
310 .fabric_datapath_to_dcn_data_return_bytes
= 64,
311 .dcn_downspread_percent
= 0.5,
312 .downspread_percent
= 0.38,
313 .dram_page_open_time_ns
= 50.0,
314 .dram_rw_turnaround_time_ns
= 17.5,
315 .dram_return_buffer_per_channel_bytes
= 8192,
316 .round_trip_ping_latency_dcfclk_cycles
= 131,
317 .urgent_out_of_order_return_per_channel_bytes
= 256,
318 .channel_interleave_bytes
= 256,
321 .vmm_page_size_bytes
= 4096,
322 .dram_clock_change_latency_us
= 404.0,
323 .dummy_pstate_latency_us
= 5.0,
324 .writeback_dram_clock_change_latency_us
= 23.0,
325 .return_bus_width_bytes
= 64,
326 .dispclk_dppclk_vco_speed_mhz
= 3850,
327 .xfc_bus_transport_time_us
= 20,
328 .xfc_xbuf_latency_tolerance_us
= 4,
329 .use_urgent_burst_bw
= 0
332 struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc
= {
337 .fabricclk_mhz
= 560.0,
338 .dispclk_mhz
= 513.0,
343 .dram_speed_mts
= 8960.0,
348 .fabricclk_mhz
= 694.0,
349 .dispclk_mhz
= 642.0,
354 .dram_speed_mts
= 11104.0,
359 .fabricclk_mhz
= 875.0,
360 .dispclk_mhz
= 734.0,
365 .dram_speed_mts
= 14000.0,
369 .dcfclk_mhz
= 1000.0,
370 .fabricclk_mhz
= 1000.0,
371 .dispclk_mhz
= 1100.0,
372 .dppclk_mhz
= 1100.0,
374 .socclk_mhz
= 1000.0,
376 .dram_speed_mts
= 16000.0,
380 .dcfclk_mhz
= 1200.0,
381 .fabricclk_mhz
= 1200.0,
382 .dispclk_mhz
= 1284.0,
383 .dppclk_mhz
= 1284.0,
385 .socclk_mhz
= 1200.0,
387 .dram_speed_mts
= 16000.0,
389 /*Extra state, no dispclk ramping*/
392 .dcfclk_mhz
= 1200.0,
393 .fabricclk_mhz
= 1200.0,
394 .dispclk_mhz
= 1284.0,
395 .dppclk_mhz
= 1284.0,
397 .socclk_mhz
= 1200.0,
399 .dram_speed_mts
= 16000.0,
403 .sr_exit_time_us
= 11.6,
404 .sr_enter_plus_exit_time_us
= 13.9,
405 .urgent_latency_us
= 4.0,
406 .urgent_latency_pixel_data_only_us
= 4.0,
407 .urgent_latency_pixel_mixed_with_vm_data_us
= 4.0,
408 .urgent_latency_vm_data_only_us
= 4.0,
409 .urgent_out_of_order_return_per_channel_pixel_only_bytes
= 4096,
410 .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes
= 4096,
411 .urgent_out_of_order_return_per_channel_vm_only_bytes
= 4096,
412 .pct_ideal_dram_sdp_bw_after_urgent_pixel_only
= 40.0,
413 .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm
= 40.0,
414 .pct_ideal_dram_sdp_bw_after_urgent_vm_only
= 40.0,
415 .max_avg_sdp_bw_use_normal_percent
= 40.0,
416 .max_avg_dram_bw_use_normal_percent
= 40.0,
417 .writeback_latency_us
= 12.0,
418 .ideal_dram_bw_after_urgent_percent
= 40.0,
419 .max_request_size_bytes
= 256,
420 .dram_channel_width_bytes
= 2,
421 .fabric_datapath_to_dcn_data_return_bytes
= 64,
422 .dcn_downspread_percent
= 0.5,
423 .downspread_percent
= 0.38,
424 .dram_page_open_time_ns
= 50.0,
425 .dram_rw_turnaround_time_ns
= 17.5,
426 .dram_return_buffer_per_channel_bytes
= 8192,
427 .round_trip_ping_latency_dcfclk_cycles
= 131,
428 .urgent_out_of_order_return_per_channel_bytes
= 256,
429 .channel_interleave_bytes
= 256,
432 .vmm_page_size_bytes
= 4096,
433 .dram_clock_change_latency_us
= 404.0,
434 .dummy_pstate_latency_us
= 5.0,
435 .writeback_dram_clock_change_latency_us
= 23.0,
436 .return_bus_width_bytes
= 64,
437 .dispclk_dppclk_vco_speed_mhz
= 3850,
438 .xfc_bus_transport_time_us
= 20,
439 .xfc_xbuf_latency_tolerance_us
= 4,
440 .use_urgent_burst_bw
= 0
443 struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc
= { 0 };
445 struct _vcs_dpi_ip_params_st dcn2_1_ip
= {
449 .gpuvm_max_page_table_levels
= 1,
450 .hostvm_max_page_table_levels
= 4,
451 .hostvm_cached_page_table_levels
= 2,
453 .rob_buffer_size_kbytes
= 168,
454 .det_buffer_size_kbytes
= 164,
455 .dpte_buffer_size_in_pte_reqs_luma
= 44,
456 .dpte_buffer_size_in_pte_reqs_chroma
= 42,//todo
457 .dpp_output_buffer_pixels
= 2560,
458 .opp_output_buffer_lines
= 1,
459 .pixel_chunk_size_kbytes
= 8,
461 .max_page_table_levels
= 4,
462 .pte_chunk_size_kbytes
= 2,
463 .meta_chunk_size_kbytes
= 2,
464 .min_meta_chunk_size_bytes
= 256,
465 .writeback_chunk_size_kbytes
= 2,
466 .line_buffer_size_bits
= 789504,
467 .is_line_buffer_bpp_fixed
= 0,
468 .line_buffer_fixed_bpp
= 0,
469 .dcc_supported
= true,
470 .max_line_buffer_lines
= 12,
471 .writeback_luma_buffer_size_kbytes
= 12,
472 .writeback_chroma_buffer_size_kbytes
= 8,
473 .writeback_chroma_line_buffer_width_pixels
= 4,
474 .writeback_max_hscl_ratio
= 1,
475 .writeback_max_vscl_ratio
= 1,
476 .writeback_min_hscl_ratio
= 1,
477 .writeback_min_vscl_ratio
= 1,
478 .writeback_max_hscl_taps
= 12,
479 .writeback_max_vscl_taps
= 12,
480 .writeback_line_buffer_luma_buffer_size
= 0,
481 .writeback_line_buffer_chroma_buffer_size
= 14643,
482 .cursor_buffer_size
= 8,
483 .cursor_chunk_size
= 2,
487 .max_dchub_pscl_bw_pix_per_clk
= 4,
488 .max_pscl_lb_bw_pix_per_clk
= 2,
489 .max_lb_vscl_bw_pix_per_clk
= 4,
490 .max_vscl_hscl_bw_pix_per_clk
= 4,
497 .dispclk_ramp_margin_percent
= 1,
498 .underscan_factor
= 1.10,
499 .min_vblank_lines
= 32, //
500 .dppclk_delay_subtotal
= 77, //
501 .dppclk_delay_scl_lb_only
= 16,
502 .dppclk_delay_scl
= 50,
503 .dppclk_delay_cnvc_formatter
= 8,
504 .dppclk_delay_cnvc_cursor
= 6,
505 .dispclk_delay_subtotal
= 87, //
506 .dcfclk_cstate_latency
= 10, // SRExitTime
507 .max_inter_dcn_tile_repeaters
= 8,
509 .xfc_supported
= false,
510 .xfc_fill_bw_overhead_percent
= 10.0,
511 .xfc_fill_constant_bytes
= 0,
513 .number_of_cursors
= 1,
516 struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc
= {
521 .fabricclk_mhz
= 400.0,
522 .dispclk_mhz
= 600.0,
523 .dppclk_mhz
= 400.00,
526 .dscclk_mhz
= 205.67,
527 .dram_speed_mts
= 1600.0,
531 .dcfclk_mhz
= 464.52,
532 .fabricclk_mhz
= 800.0,
533 .dispclk_mhz
= 654.55,
534 .dppclk_mhz
= 626.09,
537 .dscclk_mhz
= 205.67,
538 .dram_speed_mts
= 1600.0,
542 .dcfclk_mhz
= 514.29,
543 .fabricclk_mhz
= 933.0,
544 .dispclk_mhz
= 757.89,
545 .dppclk_mhz
= 685.71,
548 .dscclk_mhz
= 287.67,
549 .dram_speed_mts
= 1866.0,
553 .dcfclk_mhz
= 576.00,
554 .fabricclk_mhz
= 1067.0,
555 .dispclk_mhz
= 847.06,
556 .dppclk_mhz
= 757.89,
559 .dscclk_mhz
= 318.334,
560 .dram_speed_mts
= 2134.0,
564 .dcfclk_mhz
= 626.09,
565 .fabricclk_mhz
= 1200.0,
566 .dispclk_mhz
= 900.00,
567 .dppclk_mhz
= 847.06,
571 .dram_speed_mts
= 2400.0,
575 .dcfclk_mhz
= 685.71,
576 .fabricclk_mhz
= 1333.0,
577 .dispclk_mhz
= 1028.57,
578 .dppclk_mhz
= 960.00,
581 .dscclk_mhz
= 342.86,
582 .dram_speed_mts
= 2666.0,
586 .dcfclk_mhz
= 757.89,
587 .fabricclk_mhz
= 1467.0,
588 .dispclk_mhz
= 1107.69,
589 .dppclk_mhz
= 1028.57,
592 .dscclk_mhz
= 369.23,
593 .dram_speed_mts
= 3200.0,
597 .dcfclk_mhz
= 847.06,
598 .fabricclk_mhz
= 1600.0,
599 .dispclk_mhz
= 1395.0,
600 .dppclk_mhz
= 1285.00,
601 .phyclk_mhz
= 1325.0,
604 .dram_speed_mts
= 4266.0,
606 /*Extra state, no dispclk ramping*/
609 .dcfclk_mhz
= 847.06,
610 .fabricclk_mhz
= 1600.0,
611 .dispclk_mhz
= 1395.0,
612 .dppclk_mhz
= 1285.0,
613 .phyclk_mhz
= 1325.0,
616 .dram_speed_mts
= 4266.0,
621 .sr_exit_time_us
= 12.5,
622 .sr_enter_plus_exit_time_us
= 17.0,
623 .urgent_latency_us
= 4.0,
624 .urgent_latency_pixel_data_only_us
= 4.0,
625 .urgent_latency_pixel_mixed_with_vm_data_us
= 4.0,
626 .urgent_latency_vm_data_only_us
= 4.0,
627 .urgent_out_of_order_return_per_channel_pixel_only_bytes
= 4096,
628 .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes
= 4096,
629 .urgent_out_of_order_return_per_channel_vm_only_bytes
= 4096,
630 .pct_ideal_dram_sdp_bw_after_urgent_pixel_only
= 80.0,
631 .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm
= 75.0,
632 .pct_ideal_dram_sdp_bw_after_urgent_vm_only
= 40.0,
633 .max_avg_sdp_bw_use_normal_percent
= 60.0,
634 .max_avg_dram_bw_use_normal_percent
= 100.0,
635 .writeback_latency_us
= 12.0,
636 .max_request_size_bytes
= 256,
637 .dram_channel_width_bytes
= 4,
638 .fabric_datapath_to_dcn_data_return_bytes
= 32,
639 .dcn_downspread_percent
= 0.5,
640 .downspread_percent
= 0.38,
641 .dram_page_open_time_ns
= 50.0,
642 .dram_rw_turnaround_time_ns
= 17.5,
643 .dram_return_buffer_per_channel_bytes
= 8192,
644 .round_trip_ping_latency_dcfclk_cycles
= 128,
645 .urgent_out_of_order_return_per_channel_bytes
= 4096,
646 .channel_interleave_bytes
= 256,
649 .vmm_page_size_bytes
= 4096,
650 .dram_clock_change_latency_us
= 23.84,
651 .return_bus_width_bytes
= 64,
652 .dispclk_dppclk_vco_speed_mhz
= 3600,
653 .xfc_bus_transport_time_us
= 4,
654 .xfc_xbuf_latency_tolerance_us
= 4,
655 .use_urgent_burst_bw
= 1,
659 struct wm_table ddr4_wm_table_gs
= {
663 .wm_type
= WM_TYPE_PSTATE_CHG
,
664 .pstate_latency_us
= 11.72,
665 .sr_exit_time_us
= 7.09,
666 .sr_enter_plus_exit_time_us
= 8.14,
671 .wm_type
= WM_TYPE_PSTATE_CHG
,
672 .pstate_latency_us
= 11.72,
673 .sr_exit_time_us
= 10.12,
674 .sr_enter_plus_exit_time_us
= 11.48,
679 .wm_type
= WM_TYPE_PSTATE_CHG
,
680 .pstate_latency_us
= 11.72,
681 .sr_exit_time_us
= 10.12,
682 .sr_enter_plus_exit_time_us
= 11.48,
687 .wm_type
= WM_TYPE_PSTATE_CHG
,
688 .pstate_latency_us
= 11.72,
689 .sr_exit_time_us
= 10.12,
690 .sr_enter_plus_exit_time_us
= 11.48,
696 struct wm_table lpddr4_wm_table_gs
= {
700 .wm_type
= WM_TYPE_PSTATE_CHG
,
701 .pstate_latency_us
= 11.65333,
702 .sr_exit_time_us
= 5.32,
703 .sr_enter_plus_exit_time_us
= 6.38,
708 .wm_type
= WM_TYPE_PSTATE_CHG
,
709 .pstate_latency_us
= 11.65333,
710 .sr_exit_time_us
= 9.82,
711 .sr_enter_plus_exit_time_us
= 11.196,
716 .wm_type
= WM_TYPE_PSTATE_CHG
,
717 .pstate_latency_us
= 11.65333,
718 .sr_exit_time_us
= 9.89,
719 .sr_enter_plus_exit_time_us
= 11.24,
724 .wm_type
= WM_TYPE_PSTATE_CHG
,
725 .pstate_latency_us
= 11.65333,
726 .sr_exit_time_us
= 9.748,
727 .sr_enter_plus_exit_time_us
= 11.102,
733 struct wm_table lpddr4_wm_table_with_disabled_ppt
= {
737 .wm_type
= WM_TYPE_PSTATE_CHG
,
738 .pstate_latency_us
= 11.65333,
739 .sr_exit_time_us
= 8.32,
740 .sr_enter_plus_exit_time_us
= 9.38,
745 .wm_type
= WM_TYPE_PSTATE_CHG
,
746 .pstate_latency_us
= 11.65333,
747 .sr_exit_time_us
= 9.82,
748 .sr_enter_plus_exit_time_us
= 11.196,
753 .wm_type
= WM_TYPE_PSTATE_CHG
,
754 .pstate_latency_us
= 11.65333,
755 .sr_exit_time_us
= 9.89,
756 .sr_enter_plus_exit_time_us
= 11.24,
761 .wm_type
= WM_TYPE_PSTATE_CHG
,
762 .pstate_latency_us
= 11.65333,
763 .sr_exit_time_us
= 9.748,
764 .sr_enter_plus_exit_time_us
= 11.102,
770 struct wm_table ddr4_wm_table_rn
= {
774 .wm_type
= WM_TYPE_PSTATE_CHG
,
775 .pstate_latency_us
= 11.72,
776 .sr_exit_time_us
= 11.90,
777 .sr_enter_plus_exit_time_us
= 12.80,
782 .wm_type
= WM_TYPE_PSTATE_CHG
,
783 .pstate_latency_us
= 11.72,
784 .sr_exit_time_us
= 13.18,
785 .sr_enter_plus_exit_time_us
= 14.30,
790 .wm_type
= WM_TYPE_PSTATE_CHG
,
791 .pstate_latency_us
= 11.72,
792 .sr_exit_time_us
= 13.18,
793 .sr_enter_plus_exit_time_us
= 14.30,
798 .wm_type
= WM_TYPE_PSTATE_CHG
,
799 .pstate_latency_us
= 11.72,
800 .sr_exit_time_us
= 13.18,
801 .sr_enter_plus_exit_time_us
= 14.30,
807 struct wm_table ddr4_1R_wm_table_rn
= {
811 .wm_type
= WM_TYPE_PSTATE_CHG
,
812 .pstate_latency_us
= 11.72,
813 .sr_exit_time_us
= 13.90,
814 .sr_enter_plus_exit_time_us
= 14.80,
819 .wm_type
= WM_TYPE_PSTATE_CHG
,
820 .pstate_latency_us
= 11.72,
821 .sr_exit_time_us
= 13.90,
822 .sr_enter_plus_exit_time_us
= 14.80,
827 .wm_type
= WM_TYPE_PSTATE_CHG
,
828 .pstate_latency_us
= 11.72,
829 .sr_exit_time_us
= 13.90,
830 .sr_enter_plus_exit_time_us
= 14.80,
835 .wm_type
= WM_TYPE_PSTATE_CHG
,
836 .pstate_latency_us
= 11.72,
837 .sr_exit_time_us
= 13.90,
838 .sr_enter_plus_exit_time_us
= 14.80,
844 struct wm_table lpddr4_wm_table_rn
= {
848 .wm_type
= WM_TYPE_PSTATE_CHG
,
849 .pstate_latency_us
= 11.65333,
850 .sr_exit_time_us
= 7.32,
851 .sr_enter_plus_exit_time_us
= 8.38,
856 .wm_type
= WM_TYPE_PSTATE_CHG
,
857 .pstate_latency_us
= 11.65333,
858 .sr_exit_time_us
= 9.82,
859 .sr_enter_plus_exit_time_us
= 11.196,
864 .wm_type
= WM_TYPE_PSTATE_CHG
,
865 .pstate_latency_us
= 11.65333,
866 .sr_exit_time_us
= 9.89,
867 .sr_enter_plus_exit_time_us
= 11.24,
872 .wm_type
= WM_TYPE_PSTATE_CHG
,
873 .pstate_latency_us
= 11.65333,
874 .sr_exit_time_us
= 9.748,
875 .sr_enter_plus_exit_time_us
= 11.102,
881 void dcn20_populate_dml_writeback_from_context(struct dc
*dc
,
882 struct resource_context
*res_ctx
,
883 display_e2e_pipe_params_st
*pipes
)
887 dc_assert_fp_enabled();
889 for (i
= 0, pipe_cnt
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
890 struct dc_writeback_info
*wb_info
= &res_ctx
->pipe_ctx
[i
].stream
->writeback_info
[0];
892 if (!res_ctx
->pipe_ctx
[i
].stream
)
895 /* Set writeback information */
896 pipes
[pipe_cnt
].dout
.wb_enable
= (wb_info
->wb_enabled
== true) ? 1 : 0;
897 pipes
[pipe_cnt
].dout
.num_active_wb
++;
898 pipes
[pipe_cnt
].dout
.wb
.wb_src_height
= wb_info
->dwb_params
.cnv_params
.crop_height
;
899 pipes
[pipe_cnt
].dout
.wb
.wb_src_width
= wb_info
->dwb_params
.cnv_params
.crop_width
;
900 pipes
[pipe_cnt
].dout
.wb
.wb_dst_width
= wb_info
->dwb_params
.dest_width
;
901 pipes
[pipe_cnt
].dout
.wb
.wb_dst_height
= wb_info
->dwb_params
.dest_height
;
902 pipes
[pipe_cnt
].dout
.wb
.wb_htaps_luma
= 1;
903 pipes
[pipe_cnt
].dout
.wb
.wb_vtaps_luma
= 1;
904 pipes
[pipe_cnt
].dout
.wb
.wb_htaps_chroma
= wb_info
->dwb_params
.scaler_taps
.h_taps_c
;
905 pipes
[pipe_cnt
].dout
.wb
.wb_vtaps_chroma
= wb_info
->dwb_params
.scaler_taps
.v_taps_c
;
906 pipes
[pipe_cnt
].dout
.wb
.wb_hratio
= 1.0;
907 pipes
[pipe_cnt
].dout
.wb
.wb_vratio
= 1.0;
908 if (wb_info
->dwb_params
.out_format
== dwb_scaler_mode_yuv420
) {
909 if (wb_info
->dwb_params
.output_depth
== DWB_OUTPUT_PIXEL_DEPTH_8BPC
)
910 pipes
[pipe_cnt
].dout
.wb
.wb_pixel_format
= dm_420_8
;
912 pipes
[pipe_cnt
].dout
.wb
.wb_pixel_format
= dm_420_10
;
914 pipes
[pipe_cnt
].dout
.wb
.wb_pixel_format
= dm_444_32
;
921 void dcn20_fpu_set_wb_arb_params(struct mcif_arb_params
*wb_arb_params
,
922 struct dc_state
*context
,
923 display_e2e_pipe_params_st
*pipes
,
928 dc_assert_fp_enabled();
930 for (k
= 0; k
< sizeof(wb_arb_params
->cli_watermark
)/sizeof(wb_arb_params
->cli_watermark
[0]); k
++) {
931 wb_arb_params
->cli_watermark
[k
] = get_wm_writeback_urgent(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
932 wb_arb_params
->pstate_watermark
[k
] = get_wm_writeback_dram_clock_change(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
934 wb_arb_params
->time_per_pixel
= 16.0 * 1000 / (context
->res_ctx
.pipe_ctx
[i
].stream
->phy_pix_clk
/ 1000); /* 4 bit fraction, ms */
937 static bool is_dtbclk_required(struct dc
*dc
, struct dc_state
*context
)
940 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
941 if (!context
->res_ctx
.pipe_ctx
[i
].stream
)
943 if (dc
->link_srv
->dp_is_128b_132b_signal(&context
->res_ctx
.pipe_ctx
[i
]))
949 static enum dcn_zstate_support_state
decide_zstate_support(struct dc
*dc
, struct dc_state
*context
)
955 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
956 if (context
->res_ctx
.pipe_ctx
[i
].plane_state
)
961 * Z9 and Z10 allowed cases:
962 * 1. 0 Planes enabled
963 * 2. single eDP, on link 0, 1 plane and stutter period > 5ms
965 * 1. single eDP, on link 0, 1 plane and stutter period >= 5ms
967 * 1. stutter period sufficient
968 * Zstate not allowed cases:
971 if (plane_count
== 0)
972 return DCN_ZSTATE_SUPPORT_ALLOW
;
973 else if (context
->stream_count
== 1 && context
->streams
[0]->signal
== SIGNAL_TYPE_EDP
) {
974 struct dc_link
*link
= context
->streams
[0]->sink
->link
;
975 struct dc_stream_status
*stream_status
= &context
->stream_status
[0];
976 int minmum_z8_residency
= dc
->debug
.minimum_z8_residency_time
> 0 ? dc
->debug
.minimum_z8_residency_time
: 1000;
977 bool allow_z8
= context
->bw_ctx
.dml
.vba
.StutterPeriod
> (double)minmum_z8_residency
;
978 bool is_pwrseq0
= link
->link_index
== 0;
980 /* Don't support multi-plane configurations */
981 if (stream_status
->plane_count
> 1)
982 return DCN_ZSTATE_SUPPORT_DISALLOW
;
984 if (is_pwrseq0
&& context
->bw_ctx
.dml
.vba
.StutterPeriod
> 5000.0)
985 return DCN_ZSTATE_SUPPORT_ALLOW
;
986 else if (is_pwrseq0
&& link
->psr_settings
.psr_version
== DC_PSR_VERSION_1
&& !link
->panel_config
.psr
.disable_psr
)
987 return allow_z8
? DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY
: DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY
;
989 return allow_z8
? DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY
: DCN_ZSTATE_SUPPORT_DISALLOW
;
991 return DCN_ZSTATE_SUPPORT_DISALLOW
;
995 static void dcn20_adjust_freesync_v_startup(
996 const struct dc_crtc_timing
*dc_crtc_timing
, int *vstartup_start
)
998 struct dc_crtc_timing patched_crtc_timing
;
999 uint32_t asic_blank_end
= 0;
1000 uint32_t asic_blank_start
= 0;
1001 uint32_t newVstartup
= 0;
1003 patched_crtc_timing
= *dc_crtc_timing
;
1005 if (patched_crtc_timing
.flags
.INTERLACE
== 1) {
1006 if (patched_crtc_timing
.v_front_porch
< 2)
1007 patched_crtc_timing
.v_front_porch
= 2;
1009 if (patched_crtc_timing
.v_front_porch
< 1)
1010 patched_crtc_timing
.v_front_porch
= 1;
1013 /* blank_start = frame end - front porch */
1014 asic_blank_start
= patched_crtc_timing
.v_total
-
1015 patched_crtc_timing
.v_front_porch
;
1017 /* blank_end = blank_start - active */
1018 asic_blank_end
= asic_blank_start
-
1019 patched_crtc_timing
.v_border_bottom
-
1020 patched_crtc_timing
.v_addressable
-
1021 patched_crtc_timing
.v_border_top
;
1023 newVstartup
= asic_blank_end
+ (patched_crtc_timing
.v_total
- asic_blank_start
);
1025 *vstartup_start
= ((newVstartup
> *vstartup_start
) ? newVstartup
: *vstartup_start
);
1028 void dcn20_calculate_dlg_params(struct dc
*dc
,
1029 struct dc_state
*context
,
1030 display_e2e_pipe_params_st
*pipes
,
1034 int i
, pipe_idx
, active_hubp_count
= 0;
1036 dc_assert_fp_enabled();
1038 /* Writeback MCIF_WB arbitration parameters */
1039 dc
->res_pool
->funcs
->set_mcif_arb_params(dc
, context
, pipes
, pipe_cnt
);
1041 context
->bw_ctx
.bw
.dcn
.clk
.dispclk_khz
= context
->bw_ctx
.dml
.vba
.DISPCLK
* 1000;
1042 context
->bw_ctx
.bw
.dcn
.clk
.dcfclk_khz
= context
->bw_ctx
.dml
.vba
.DCFCLK
* 1000;
1043 context
->bw_ctx
.bw
.dcn
.clk
.socclk_khz
= context
->bw_ctx
.dml
.vba
.SOCCLK
* 1000;
1044 context
->bw_ctx
.bw
.dcn
.clk
.dramclk_khz
= context
->bw_ctx
.dml
.vba
.DRAMSpeed
* 1000 / 16;
1046 if (dc
->debug
.min_dram_clk_khz
> context
->bw_ctx
.bw
.dcn
.clk
.dramclk_khz
)
1047 context
->bw_ctx
.bw
.dcn
.clk
.dramclk_khz
= dc
->debug
.min_dram_clk_khz
;
1049 context
->bw_ctx
.bw
.dcn
.clk
.dcfclk_deep_sleep_khz
= context
->bw_ctx
.dml
.vba
.DCFCLKDeepSleep
* 1000;
1050 context
->bw_ctx
.bw
.dcn
.clk
.fclk_khz
= context
->bw_ctx
.dml
.vba
.FabricClock
* 1000;
1051 context
->bw_ctx
.bw
.dcn
.clk
.p_state_change_support
=
1052 context
->bw_ctx
.dml
.vba
.DRAMClockChangeSupport
[vlevel
][context
->bw_ctx
.dml
.vba
.maxMpcComb
]
1053 != dm_dram_clock_change_unsupported
;
1055 /* Pstate change might not be supported by hardware, but it might be
1056 * possible with firmware driven vertical blank stretching.
1058 context
->bw_ctx
.bw
.dcn
.clk
.p_state_change_support
|= context
->bw_ctx
.bw
.dcn
.clk
.fw_based_mclk_switching
;
1060 context
->bw_ctx
.bw
.dcn
.clk
.dppclk_khz
= 0;
1062 context
->bw_ctx
.bw
.dcn
.clk
.dtbclk_en
= is_dtbclk_required(dc
, context
);
1064 if (context
->bw_ctx
.bw
.dcn
.clk
.dispclk_khz
< dc
->debug
.min_disp_clk_khz
)
1065 context
->bw_ctx
.bw
.dcn
.clk
.dispclk_khz
= dc
->debug
.min_disp_clk_khz
;
1067 for (i
= 0, pipe_idx
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
1068 if (!context
->res_ctx
.pipe_ctx
[i
].stream
)
1070 if (context
->res_ctx
.pipe_ctx
[i
].plane_state
)
1071 active_hubp_count
++;
1072 pipes
[pipe_idx
].pipe
.dest
.vstartup_start
= get_vstartup(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
, pipe_idx
);
1073 pipes
[pipe_idx
].pipe
.dest
.vupdate_offset
= get_vupdate_offset(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
, pipe_idx
);
1074 pipes
[pipe_idx
].pipe
.dest
.vupdate_width
= get_vupdate_width(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
, pipe_idx
);
1075 pipes
[pipe_idx
].pipe
.dest
.vready_offset
= get_vready_offset(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
, pipe_idx
);
1077 if (context
->res_ctx
.pipe_ctx
[i
].stream
->mall_stream_config
.type
== SUBVP_PHANTOM
) {
1078 // Phantom pipe requires that DET_SIZE = 0 and no unbounded requests
1079 context
->res_ctx
.pipe_ctx
[i
].det_buffer_size_kb
= 0;
1080 context
->res_ctx
.pipe_ctx
[i
].unbounded_req
= false;
1082 context
->res_ctx
.pipe_ctx
[i
].det_buffer_size_kb
= context
->bw_ctx
.dml
.ip
.det_buffer_size_kbytes
;
1083 context
->res_ctx
.pipe_ctx
[i
].unbounded_req
= pipes
[pipe_idx
].pipe
.src
.unbounded_req_mode
;
1086 if (context
->bw_ctx
.bw
.dcn
.clk
.dppclk_khz
< pipes
[pipe_idx
].clks_cfg
.dppclk_mhz
* 1000)
1087 context
->bw_ctx
.bw
.dcn
.clk
.dppclk_khz
= pipes
[pipe_idx
].clks_cfg
.dppclk_mhz
* 1000;
1088 context
->res_ctx
.pipe_ctx
[i
].plane_res
.bw
.dppclk_khz
=
1089 pipes
[pipe_idx
].clks_cfg
.dppclk_mhz
* 1000;
1090 context
->res_ctx
.pipe_ctx
[i
].pipe_dlg_param
= pipes
[pipe_idx
].pipe
.dest
;
1091 if (dc
->ctx
->dce_version
< DCN_VERSION_3_1
&&
1092 context
->res_ctx
.pipe_ctx
[i
].stream
->adaptive_sync_infopacket
.valid
)
1093 dcn20_adjust_freesync_v_startup(
1094 &context
->res_ctx
.pipe_ctx
[i
].stream
->timing
,
1095 &context
->res_ctx
.pipe_ctx
[i
].pipe_dlg_param
.vstartup_start
);
1099 /* If DCN isn't making memory requests we can allow pstate change */
1100 if (!active_hubp_count
) {
1101 context
->bw_ctx
.bw
.dcn
.clk
.p_state_change_support
= true;
1103 /*save a original dppclock copy*/
1104 context
->bw_ctx
.bw
.dcn
.clk
.bw_dppclk_khz
= context
->bw_ctx
.bw
.dcn
.clk
.dppclk_khz
;
1105 context
->bw_ctx
.bw
.dcn
.clk
.bw_dispclk_khz
= context
->bw_ctx
.bw
.dcn
.clk
.dispclk_khz
;
1106 context
->bw_ctx
.bw
.dcn
.clk
.max_supported_dppclk_khz
= context
->bw_ctx
.dml
.soc
.clock_limits
[vlevel
].dppclk_mhz
* 1000;
1107 context
->bw_ctx
.bw
.dcn
.clk
.max_supported_dispclk_khz
= context
->bw_ctx
.dml
.soc
.clock_limits
[vlevel
].dispclk_mhz
* 1000;
1109 context
->bw_ctx
.bw
.dcn
.compbuf_size_kb
= context
->bw_ctx
.dml
.ip
.config_return_buffer_size_in_kbytes
1110 - context
->bw_ctx
.dml
.ip
.det_buffer_size_kbytes
* pipe_idx
;
1112 for (i
= 0, pipe_idx
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
1113 bool cstate_en
= context
->bw_ctx
.dml
.vba
.PrefetchMode
[vlevel
][context
->bw_ctx
.dml
.vba
.maxMpcComb
] != 2;
1115 if (!context
->res_ctx
.pipe_ctx
[i
].stream
)
1118 /* cstate disabled on 201 */
1119 if (dc
->ctx
->dce_version
== DCN_VERSION_2_01
)
1122 context
->bw_ctx
.dml
.funcs
.rq_dlg_get_dlg_reg(&context
->bw_ctx
.dml
,
1123 &context
->res_ctx
.pipe_ctx
[i
].dlg_regs
,
1124 &context
->res_ctx
.pipe_ctx
[i
].ttu_regs
,
1129 context
->bw_ctx
.bw
.dcn
.clk
.p_state_change_support
,
1130 false, false, true);
1132 context
->bw_ctx
.dml
.funcs
.rq_dlg_get_rq_reg(&context
->bw_ctx
.dml
,
1133 &context
->res_ctx
.pipe_ctx
[i
].rq_regs
,
1134 &pipes
[pipe_idx
].pipe
);
1137 context
->bw_ctx
.bw
.dcn
.clk
.zstate_support
= decide_zstate_support(dc
, context
);
1140 static void swizzle_to_dml_params(
1141 enum swizzle_mode_values swizzle
,
1142 unsigned int *sw_mode
)
1146 *sw_mode
= dm_sw_linear
;
1149 *sw_mode
= dm_sw_4kb_s
;
1152 *sw_mode
= dm_sw_4kb_s_x
;
1155 *sw_mode
= dm_sw_4kb_d
;
1158 *sw_mode
= dm_sw_4kb_d_x
;
1161 *sw_mode
= dm_sw_64kb_s
;
1163 case DC_SW_64KB_S_X
:
1164 *sw_mode
= dm_sw_64kb_s_x
;
1166 case DC_SW_64KB_S_T
:
1167 *sw_mode
= dm_sw_64kb_s_t
;
1170 *sw_mode
= dm_sw_64kb_d
;
1172 case DC_SW_64KB_D_X
:
1173 *sw_mode
= dm_sw_64kb_d_x
;
1175 case DC_SW_64KB_D_T
:
1176 *sw_mode
= dm_sw_64kb_d_t
;
1178 case DC_SW_64KB_R_X
:
1179 *sw_mode
= dm_sw_64kb_r_x
;
1182 *sw_mode
= dm_sw_var_s
;
1185 *sw_mode
= dm_sw_var_s_x
;
1188 *sw_mode
= dm_sw_var_d
;
1191 *sw_mode
= dm_sw_var_d_x
;
1194 *sw_mode
= dm_sw_var_r_x
;
1197 ASSERT(0); /* Not supported */
1202 int dcn20_populate_dml_pipes_from_context(struct dc
*dc
,
1203 struct dc_state
*context
,
1204 display_e2e_pipe_params_st
*pipes
,
1208 bool synchronized_vblank
= true;
1209 struct resource_context
*res_ctx
= &context
->res_ctx
;
1211 dc_assert_fp_enabled();
1213 for (i
= 0, pipe_cnt
= -1; i
< dc
->res_pool
->pipe_count
; i
++) {
1214 if (!res_ctx
->pipe_ctx
[i
].stream
)
1222 if (res_ctx
->pipe_ctx
[pipe_cnt
].stream
== res_ctx
->pipe_ctx
[i
].stream
)
1225 if (dc
->debug
.disable_timing_sync
||
1226 (!resource_are_streams_timing_synchronizable(
1227 res_ctx
->pipe_ctx
[pipe_cnt
].stream
,
1228 res_ctx
->pipe_ctx
[i
].stream
) &&
1229 !resource_are_vblanks_synchronizable(
1230 res_ctx
->pipe_ctx
[pipe_cnt
].stream
,
1231 res_ctx
->pipe_ctx
[i
].stream
))) {
1232 synchronized_vblank
= false;
1237 for (i
= 0, pipe_cnt
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
1238 struct dc_crtc_timing
*timing
= &res_ctx
->pipe_ctx
[i
].stream
->timing
;
1239 unsigned int v_total
;
1240 unsigned int front_porch
;
1242 struct audio_check aud_check
= {0};
1244 if (!res_ctx
->pipe_ctx
[i
].stream
)
1247 v_total
= timing
->v_total
;
1248 front_porch
= timing
->v_front_porch
;
1251 pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = 0;
1252 pipes[pipe_cnt].pipe.src.dcc = 0;
1253 pipes[pipe_cnt].pipe.src.vm = 0;*/
1255 pipes
[pipe_cnt
].clks_cfg
.refclk_mhz
= dc
->res_pool
->ref_clocks
.dchub_ref_clock_inKhz
/ 1000.0;
1257 pipes
[pipe_cnt
].pipe
.dest
.use_maximum_vstartup
= dc
->ctx
->dce_version
== DCN_VERSION_2_01
;
1259 pipes
[pipe_cnt
].dout
.dsc_enable
= res_ctx
->pipe_ctx
[i
].stream
->timing
.flags
.DSC
;
1260 /* todo: rotation?*/
1261 pipes
[pipe_cnt
].dout
.dsc_slices
= res_ctx
->pipe_ctx
[i
].stream
->timing
.dsc_cfg
.num_slices_h
;
1262 if (res_ctx
->pipe_ctx
[i
].stream
->use_dynamic_meta
) {
1263 pipes
[pipe_cnt
].pipe
.src
.dynamic_metadata_enable
= true;
1265 pipes
[pipe_cnt
].pipe
.src
.dynamic_metadata_lines_before_active
=
1266 (v_total
- timing
->v_addressable
1267 - timing
->v_border_top
- timing
->v_border_bottom
) / 2;
1268 /* 36 bytes dp, 32 hdmi */
1269 pipes
[pipe_cnt
].pipe
.src
.dynamic_metadata_xmit_bytes
=
1270 dc_is_dp_signal(res_ctx
->pipe_ctx
[i
].stream
->signal
) ? 36 : 32;
1272 pipes
[pipe_cnt
].pipe
.src
.dcc
= false;
1273 pipes
[pipe_cnt
].pipe
.src
.dcc_rate
= 1;
1274 pipes
[pipe_cnt
].pipe
.dest
.synchronized_vblank_all_planes
= synchronized_vblank
;
1275 pipes
[pipe_cnt
].pipe
.dest
.synchronize_timings
= synchronized_vblank
;
1276 pipes
[pipe_cnt
].pipe
.dest
.hblank_start
= timing
->h_total
- timing
->h_front_porch
;
1277 pipes
[pipe_cnt
].pipe
.dest
.hblank_end
= pipes
[pipe_cnt
].pipe
.dest
.hblank_start
1278 - timing
->h_addressable
1279 - timing
->h_border_left
1280 - timing
->h_border_right
;
1281 pipes
[pipe_cnt
].pipe
.dest
.vblank_start
= v_total
- front_porch
;
1282 pipes
[pipe_cnt
].pipe
.dest
.vblank_end
= pipes
[pipe_cnt
].pipe
.dest
.vblank_start
1283 - timing
->v_addressable
1284 - timing
->v_border_top
1285 - timing
->v_border_bottom
;
1286 pipes
[pipe_cnt
].pipe
.dest
.htotal
= timing
->h_total
;
1287 pipes
[pipe_cnt
].pipe
.dest
.vtotal
= v_total
;
1288 pipes
[pipe_cnt
].pipe
.dest
.hactive
=
1289 timing
->h_addressable
+ timing
->h_border_left
+ timing
->h_border_right
;
1290 pipes
[pipe_cnt
].pipe
.dest
.vactive
=
1291 timing
->v_addressable
+ timing
->v_border_top
+ timing
->v_border_bottom
;
1292 pipes
[pipe_cnt
].pipe
.dest
.interlaced
= timing
->flags
.INTERLACE
;
1293 pipes
[pipe_cnt
].pipe
.dest
.pixel_rate_mhz
= timing
->pix_clk_100hz
/10000.0;
1294 if (timing
->timing_3d_format
== TIMING_3D_FORMAT_HW_FRAME_PACKING
)
1295 pipes
[pipe_cnt
].pipe
.dest
.pixel_rate_mhz
*= 2;
1296 pipes
[pipe_cnt
].pipe
.dest
.otg_inst
= res_ctx
->pipe_ctx
[i
].stream_res
.tg
->inst
;
1297 pipes
[pipe_cnt
].dout
.dp_lanes
= 4;
1298 pipes
[pipe_cnt
].dout
.dp_rate
= dm_dp_rate_na
;
1299 pipes
[pipe_cnt
].dout
.is_virtual
= 0;
1300 pipes
[pipe_cnt
].pipe
.dest
.vtotal_min
= res_ctx
->pipe_ctx
[i
].stream
->adjust
.v_total_min
;
1301 pipes
[pipe_cnt
].pipe
.dest
.vtotal_max
= res_ctx
->pipe_ctx
[i
].stream
->adjust
.v_total_max
;
1302 switch (resource_get_odm_slice_count(&res_ctx
->pipe_ctx
[i
])) {
1304 pipes
[pipe_cnt
].pipe
.dest
.odm_combine
= dm_odm_combine_mode_2to1
;
1307 pipes
[pipe_cnt
].pipe
.dest
.odm_combine
= dm_odm_combine_mode_4to1
;
1310 pipes
[pipe_cnt
].pipe
.dest
.odm_combine
= dm_odm_combine_mode_disabled
;
1312 pipes
[pipe_cnt
].pipe
.src
.hsplit_grp
= res_ctx
->pipe_ctx
[i
].pipe_idx
;
1313 if (res_ctx
->pipe_ctx
[i
].top_pipe
&& res_ctx
->pipe_ctx
[i
].top_pipe
->plane_state
1314 == res_ctx
->pipe_ctx
[i
].plane_state
) {
1315 struct pipe_ctx
*first_pipe
= res_ctx
->pipe_ctx
[i
].top_pipe
;
1318 while (first_pipe
->top_pipe
&& first_pipe
->top_pipe
->plane_state
1319 == res_ctx
->pipe_ctx
[i
].plane_state
) {
1320 first_pipe
= first_pipe
->top_pipe
;
1323 /* Treat 4to1 mpc combine as an mpo of 2 2-to-1 combines */
1325 pipes
[pipe_cnt
].pipe
.src
.hsplit_grp
= first_pipe
->pipe_idx
;
1326 else if (split_idx
== 1)
1327 pipes
[pipe_cnt
].pipe
.src
.hsplit_grp
= res_ctx
->pipe_ctx
[i
].pipe_idx
;
1328 else if (split_idx
== 2)
1329 pipes
[pipe_cnt
].pipe
.src
.hsplit_grp
= res_ctx
->pipe_ctx
[i
].top_pipe
->pipe_idx
;
1330 } else if (res_ctx
->pipe_ctx
[i
].prev_odm_pipe
) {
1331 struct pipe_ctx
*first_pipe
= res_ctx
->pipe_ctx
[i
].prev_odm_pipe
;
1333 while (first_pipe
->prev_odm_pipe
)
1334 first_pipe
= first_pipe
->prev_odm_pipe
;
1335 pipes
[pipe_cnt
].pipe
.src
.hsplit_grp
= first_pipe
->pipe_idx
;
1338 switch (res_ctx
->pipe_ctx
[i
].stream
->signal
) {
1339 case SIGNAL_TYPE_DISPLAY_PORT_MST
:
1340 case SIGNAL_TYPE_DISPLAY_PORT
:
1341 pipes
[pipe_cnt
].dout
.output_type
= dm_dp
;
1342 if (dc
->link_srv
->dp_is_128b_132b_signal(&res_ctx
->pipe_ctx
[i
]))
1343 pipes
[pipe_cnt
].dout
.output_type
= dm_dp2p0
;
1345 case SIGNAL_TYPE_EDP
:
1346 pipes
[pipe_cnt
].dout
.output_type
= dm_edp
;
1348 case SIGNAL_TYPE_HDMI_TYPE_A
:
1349 case SIGNAL_TYPE_DVI_SINGLE_LINK
:
1350 case SIGNAL_TYPE_DVI_DUAL_LINK
:
1351 pipes
[pipe_cnt
].dout
.output_type
= dm_hdmi
;
1354 /* In case there is no signal, set dp with 4 lanes to allow max config */
1355 pipes
[pipe_cnt
].dout
.is_virtual
= 1;
1356 pipes
[pipe_cnt
].dout
.output_type
= dm_dp
;
1357 pipes
[pipe_cnt
].dout
.dp_lanes
= 4;
1360 switch (res_ctx
->pipe_ctx
[i
].stream
->timing
.display_color_depth
) {
1361 case COLOR_DEPTH_666
:
1364 case COLOR_DEPTH_888
:
1367 case COLOR_DEPTH_101010
:
1370 case COLOR_DEPTH_121212
:
1373 case COLOR_DEPTH_141414
:
1376 case COLOR_DEPTH_161616
:
1379 case COLOR_DEPTH_999
:
1382 case COLOR_DEPTH_111111
:
1390 switch (res_ctx
->pipe_ctx
[i
].stream
->timing
.pixel_encoding
) {
1391 case PIXEL_ENCODING_RGB
:
1392 case PIXEL_ENCODING_YCBCR444
:
1393 pipes
[pipe_cnt
].dout
.output_format
= dm_444
;
1394 pipes
[pipe_cnt
].dout
.output_bpp
= output_bpc
* 3;
1396 case PIXEL_ENCODING_YCBCR420
:
1397 pipes
[pipe_cnt
].dout
.output_format
= dm_420
;
1398 pipes
[pipe_cnt
].dout
.output_bpp
= (output_bpc
* 3.0) / 2;
1400 case PIXEL_ENCODING_YCBCR422
:
1401 if (res_ctx
->pipe_ctx
[i
].stream
->timing
.flags
.DSC
&&
1402 !res_ctx
->pipe_ctx
[i
].stream
->timing
.dsc_cfg
.ycbcr422_simple
)
1403 pipes
[pipe_cnt
].dout
.output_format
= dm_n422
;
1405 pipes
[pipe_cnt
].dout
.output_format
= dm_s422
;
1406 pipes
[pipe_cnt
].dout
.output_bpp
= output_bpc
* 2;
1409 pipes
[pipe_cnt
].dout
.output_format
= dm_444
;
1410 pipes
[pipe_cnt
].dout
.output_bpp
= output_bpc
* 3;
1413 if (res_ctx
->pipe_ctx
[i
].stream
->timing
.flags
.DSC
)
1414 pipes
[pipe_cnt
].dout
.output_bpp
= res_ctx
->pipe_ctx
[i
].stream
->timing
.dsc_cfg
.bits_per_pixel
/ 16.0;
1416 /* todo: default max for now, until there is logic reflecting this in dc*/
1417 pipes
[pipe_cnt
].dout
.dsc_input_bpc
= 12;
1418 /*fill up the audio sample rate (unit in kHz)*/
1419 get_audio_check(&res_ctx
->pipe_ctx
[i
].stream
->audio_info
, &aud_check
);
1420 pipes
[pipe_cnt
].dout
.max_audio_sample_rate
= aud_check
.max_audiosample_rate
/ 1000;
1422 * For graphic plane, cursor number is 1, nv12 is 0
1423 * bw calculations due to cursor on/off
1425 if (res_ctx
->pipe_ctx
[i
].plane_state
&&
1426 (res_ctx
->pipe_ctx
[i
].plane_state
->address
.type
== PLN_ADDR_TYPE_VIDEO_PROGRESSIVE
||
1427 res_ctx
->pipe_ctx
[i
].stream
->mall_stream_config
.type
== SUBVP_PHANTOM
))
1428 pipes
[pipe_cnt
].pipe
.src
.num_cursors
= 0;
1430 pipes
[pipe_cnt
].pipe
.src
.num_cursors
= dc
->dml
.ip
.number_of_cursors
;
1432 pipes
[pipe_cnt
].pipe
.src
.cur0_src_width
= 256;
1433 pipes
[pipe_cnt
].pipe
.src
.cur0_bpp
= dm_cur_32bit
;
1435 if (!res_ctx
->pipe_ctx
[i
].plane_state
) {
1436 pipes
[pipe_cnt
].pipe
.src
.is_hsplit
= pipes
[pipe_cnt
].pipe
.dest
.odm_combine
!= dm_odm_combine_mode_disabled
;
1437 pipes
[pipe_cnt
].pipe
.src
.source_scan
= dm_horz
;
1438 pipes
[pipe_cnt
].pipe
.src
.source_rotation
= dm_rotation_0
;
1439 pipes
[pipe_cnt
].pipe
.src
.sw_mode
= dm_sw_4kb_s
;
1440 pipes
[pipe_cnt
].pipe
.src
.macro_tile_size
= dm_64k_tile
;
1441 pipes
[pipe_cnt
].pipe
.src
.viewport_width
= timing
->h_addressable
;
1442 if (pipes
[pipe_cnt
].pipe
.src
.viewport_width
> 1920)
1443 pipes
[pipe_cnt
].pipe
.src
.viewport_width
= 1920;
1444 pipes
[pipe_cnt
].pipe
.src
.viewport_height
= timing
->v_addressable
;
1445 if (pipes
[pipe_cnt
].pipe
.src
.viewport_height
> 1080)
1446 pipes
[pipe_cnt
].pipe
.src
.viewport_height
= 1080;
1447 pipes
[pipe_cnt
].pipe
.src
.surface_height_y
= pipes
[pipe_cnt
].pipe
.src
.viewport_height
;
1448 pipes
[pipe_cnt
].pipe
.src
.surface_width_y
= pipes
[pipe_cnt
].pipe
.src
.viewport_width
;
1449 pipes
[pipe_cnt
].pipe
.src
.surface_height_c
= pipes
[pipe_cnt
].pipe
.src
.viewport_height
;
1450 pipes
[pipe_cnt
].pipe
.src
.surface_width_c
= pipes
[pipe_cnt
].pipe
.src
.viewport_width
;
1451 pipes
[pipe_cnt
].pipe
.src
.data_pitch
= ((pipes
[pipe_cnt
].pipe
.src
.viewport_width
+ 255) / 256) * 256;
1452 pipes
[pipe_cnt
].pipe
.src
.source_format
= dm_444_32
;
1453 pipes
[pipe_cnt
].pipe
.dest
.recout_width
= pipes
[pipe_cnt
].pipe
.src
.viewport_width
; /*vp_width/hratio*/
1454 pipes
[pipe_cnt
].pipe
.dest
.recout_height
= pipes
[pipe_cnt
].pipe
.src
.viewport_height
; /*vp_height/vratio*/
1455 pipes
[pipe_cnt
].pipe
.dest
.full_recout_width
= pipes
[pipe_cnt
].pipe
.dest
.recout_width
; /*when is_hsplit != 1*/
1456 pipes
[pipe_cnt
].pipe
.dest
.full_recout_height
= pipes
[pipe_cnt
].pipe
.dest
.recout_height
; /*when is_hsplit != 1*/
1457 pipes
[pipe_cnt
].pipe
.scale_ratio_depth
.lb_depth
= dm_lb_16
;
1458 pipes
[pipe_cnt
].pipe
.scale_ratio_depth
.hscl_ratio
= 1.0;
1459 pipes
[pipe_cnt
].pipe
.scale_ratio_depth
.vscl_ratio
= 1.0;
1460 pipes
[pipe_cnt
].pipe
.scale_ratio_depth
.scl_enable
= 0; /*Lb only or Full scl*/
1461 pipes
[pipe_cnt
].pipe
.scale_taps
.htaps
= 1;
1462 pipes
[pipe_cnt
].pipe
.scale_taps
.vtaps
= 1;
1463 pipes
[pipe_cnt
].pipe
.dest
.vtotal_min
= v_total
;
1464 pipes
[pipe_cnt
].pipe
.dest
.vtotal_max
= v_total
;
1466 if (pipes
[pipe_cnt
].pipe
.dest
.odm_combine
== dm_odm_combine_mode_2to1
) {
1467 pipes
[pipe_cnt
].pipe
.src
.viewport_width
/= 2;
1468 pipes
[pipe_cnt
].pipe
.dest
.recout_width
/= 2;
1469 } else if (pipes
[pipe_cnt
].pipe
.dest
.odm_combine
== dm_odm_combine_mode_4to1
) {
1470 pipes
[pipe_cnt
].pipe
.src
.viewport_width
/= 4;
1471 pipes
[pipe_cnt
].pipe
.dest
.recout_width
/= 4;
1474 struct dc_plane_state
*pln
= res_ctx
->pipe_ctx
[i
].plane_state
;
1475 struct scaler_data
*scl
= &res_ctx
->pipe_ctx
[i
].plane_res
.scl_data
;
1477 pipes
[pipe_cnt
].pipe
.src
.immediate_flip
= pln
->flip_immediate
;
1478 pipes
[pipe_cnt
].pipe
.src
.is_hsplit
= (res_ctx
->pipe_ctx
[i
].bottom_pipe
&& res_ctx
->pipe_ctx
[i
].bottom_pipe
->plane_state
== pln
)
1479 || (res_ctx
->pipe_ctx
[i
].top_pipe
&& res_ctx
->pipe_ctx
[i
].top_pipe
->plane_state
== pln
)
1480 || pipes
[pipe_cnt
].pipe
.dest
.odm_combine
!= dm_odm_combine_mode_disabled
;
1482 /* stereo is not split */
1483 if (pln
->stereo_format
== PLANE_STEREO_FORMAT_SIDE_BY_SIDE
||
1484 pln
->stereo_format
== PLANE_STEREO_FORMAT_TOP_AND_BOTTOM
) {
1485 pipes
[pipe_cnt
].pipe
.src
.is_hsplit
= false;
1486 pipes
[pipe_cnt
].pipe
.src
.hsplit_grp
= res_ctx
->pipe_ctx
[i
].pipe_idx
;
1489 pipes
[pipe_cnt
].pipe
.src
.source_scan
= pln
->rotation
== ROTATION_ANGLE_90
1490 || pln
->rotation
== ROTATION_ANGLE_270
? dm_vert
: dm_horz
;
1491 switch (pln
->rotation
) {
1492 case ROTATION_ANGLE_0
:
1493 pipes
[pipe_cnt
].pipe
.src
.source_rotation
= dm_rotation_0
;
1495 case ROTATION_ANGLE_90
:
1496 pipes
[pipe_cnt
].pipe
.src
.source_rotation
= dm_rotation_90
;
1498 case ROTATION_ANGLE_180
:
1499 pipes
[pipe_cnt
].pipe
.src
.source_rotation
= dm_rotation_180
;
1501 case ROTATION_ANGLE_270
:
1502 pipes
[pipe_cnt
].pipe
.src
.source_rotation
= dm_rotation_270
;
1508 pipes
[pipe_cnt
].pipe
.src
.viewport_y_y
= scl
->viewport
.y
;
1509 pipes
[pipe_cnt
].pipe
.src
.viewport_y_c
= scl
->viewport_c
.y
;
1510 pipes
[pipe_cnt
].pipe
.src
.viewport_x_y
= scl
->viewport
.x
;
1511 pipes
[pipe_cnt
].pipe
.src
.viewport_x_c
= scl
->viewport_c
.x
;
1512 pipes
[pipe_cnt
].pipe
.src
.viewport_width
= scl
->viewport
.width
;
1513 pipes
[pipe_cnt
].pipe
.src
.viewport_width_c
= scl
->viewport_c
.width
;
1514 pipes
[pipe_cnt
].pipe
.src
.viewport_height
= scl
->viewport
.height
;
1515 pipes
[pipe_cnt
].pipe
.src
.viewport_height_c
= scl
->viewport_c
.height
;
1516 pipes
[pipe_cnt
].pipe
.src
.viewport_width_max
= pln
->src_rect
.width
;
1517 pipes
[pipe_cnt
].pipe
.src
.viewport_height_max
= pln
->src_rect
.height
;
1518 pipes
[pipe_cnt
].pipe
.src
.surface_width_y
= pln
->plane_size
.surface_size
.width
;
1519 pipes
[pipe_cnt
].pipe
.src
.surface_height_y
= pln
->plane_size
.surface_size
.height
;
1520 pipes
[pipe_cnt
].pipe
.src
.surface_width_c
= pln
->plane_size
.chroma_size
.width
;
1521 pipes
[pipe_cnt
].pipe
.src
.surface_height_c
= pln
->plane_size
.chroma_size
.height
;
1522 if (pln
->format
== SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA
1523 || pln
->format
>= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN
) {
1524 pipes
[pipe_cnt
].pipe
.src
.data_pitch
= pln
->plane_size
.surface_pitch
;
1525 pipes
[pipe_cnt
].pipe
.src
.data_pitch_c
= pln
->plane_size
.chroma_pitch
;
1526 pipes
[pipe_cnt
].pipe
.src
.meta_pitch
= pln
->dcc
.meta_pitch
;
1527 pipes
[pipe_cnt
].pipe
.src
.meta_pitch_c
= pln
->dcc
.meta_pitch_c
;
1529 pipes
[pipe_cnt
].pipe
.src
.data_pitch
= pln
->plane_size
.surface_pitch
;
1530 pipes
[pipe_cnt
].pipe
.src
.meta_pitch
= pln
->dcc
.meta_pitch
;
1532 pipes
[pipe_cnt
].pipe
.src
.dcc
= pln
->dcc
.enable
;
1533 pipes
[pipe_cnt
].pipe
.dest
.recout_width
= scl
->recout
.width
;
1534 pipes
[pipe_cnt
].pipe
.dest
.recout_height
= scl
->recout
.height
;
1535 pipes
[pipe_cnt
].pipe
.dest
.full_recout_height
= scl
->recout
.height
;
1536 pipes
[pipe_cnt
].pipe
.dest
.full_recout_width
= scl
->recout
.width
;
1537 if (pipes
[pipe_cnt
].pipe
.dest
.odm_combine
== dm_odm_combine_mode_2to1
)
1538 pipes
[pipe_cnt
].pipe
.dest
.full_recout_width
*= 2;
1539 else if (pipes
[pipe_cnt
].pipe
.dest
.odm_combine
== dm_odm_combine_mode_4to1
)
1540 pipes
[pipe_cnt
].pipe
.dest
.full_recout_width
*= 4;
1542 struct pipe_ctx
*split_pipe
= res_ctx
->pipe_ctx
[i
].bottom_pipe
;
1544 while (split_pipe
&& split_pipe
->plane_state
== pln
) {
1545 pipes
[pipe_cnt
].pipe
.dest
.full_recout_width
+= split_pipe
->plane_res
.scl_data
.recout
.width
;
1546 split_pipe
= split_pipe
->bottom_pipe
;
1548 split_pipe
= res_ctx
->pipe_ctx
[i
].top_pipe
;
1549 while (split_pipe
&& split_pipe
->plane_state
== pln
) {
1550 pipes
[pipe_cnt
].pipe
.dest
.full_recout_width
+= split_pipe
->plane_res
.scl_data
.recout
.width
;
1551 split_pipe
= split_pipe
->top_pipe
;
1555 pipes
[pipe_cnt
].pipe
.scale_ratio_depth
.lb_depth
= dm_lb_16
;
1556 pipes
[pipe_cnt
].pipe
.scale_ratio_depth
.hscl_ratio
= (double) scl
->ratios
.horz
.value
/ (1ULL<<32);
1557 pipes
[pipe_cnt
].pipe
.scale_ratio_depth
.hscl_ratio_c
= (double) scl
->ratios
.horz_c
.value
/ (1ULL<<32);
1558 pipes
[pipe_cnt
].pipe
.scale_ratio_depth
.vscl_ratio
= (double) scl
->ratios
.vert
.value
/ (1ULL<<32);
1559 pipes
[pipe_cnt
].pipe
.scale_ratio_depth
.vscl_ratio_c
= (double) scl
->ratios
.vert_c
.value
/ (1ULL<<32);
1560 pipes
[pipe_cnt
].pipe
.scale_ratio_depth
.scl_enable
=
1561 scl
->ratios
.vert
.value
!= dc_fixpt_one
.value
1562 || scl
->ratios
.horz
.value
!= dc_fixpt_one
.value
1563 || scl
->ratios
.vert_c
.value
!= dc_fixpt_one
.value
1564 || scl
->ratios
.horz_c
.value
!= dc_fixpt_one
.value
/*Lb only or Full scl*/
1565 || dc
->debug
.always_scale
; /*support always scale*/
1566 pipes
[pipe_cnt
].pipe
.scale_taps
.htaps
= scl
->taps
.h_taps
;
1567 pipes
[pipe_cnt
].pipe
.scale_taps
.htaps_c
= scl
->taps
.h_taps_c
;
1568 pipes
[pipe_cnt
].pipe
.scale_taps
.vtaps
= scl
->taps
.v_taps
;
1569 pipes
[pipe_cnt
].pipe
.scale_taps
.vtaps_c
= scl
->taps
.v_taps_c
;
1571 pipes
[pipe_cnt
].pipe
.src
.macro_tile_size
=
1572 swizzle_mode_to_macro_tile_size(pln
->tiling_info
.gfx9
.swizzle
);
1573 swizzle_to_dml_params(pln
->tiling_info
.gfx9
.swizzle
,
1574 &pipes
[pipe_cnt
].pipe
.src
.sw_mode
);
1576 switch (pln
->format
) {
1577 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr
:
1578 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb
:
1579 pipes
[pipe_cnt
].pipe
.src
.source_format
= dm_420_8
;
1581 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr
:
1582 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb
:
1583 pipes
[pipe_cnt
].pipe
.src
.source_format
= dm_420_10
;
1585 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616
:
1586 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616
:
1587 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F
:
1588 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
:
1589 pipes
[pipe_cnt
].pipe
.src
.source_format
= dm_444_64
;
1591 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555
:
1592 case SURFACE_PIXEL_FORMAT_GRPH_RGB565
:
1593 pipes
[pipe_cnt
].pipe
.src
.source_format
= dm_444_16
;
1595 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS
:
1596 pipes
[pipe_cnt
].pipe
.src
.source_format
= dm_444_8
;
1598 case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA
:
1599 pipes
[pipe_cnt
].pipe
.src
.source_format
= dm_rgbe_alpha
;
1602 pipes
[pipe_cnt
].pipe
.src
.source_format
= dm_444_32
;
1610 /* populate writeback information */
1611 dc
->res_pool
->funcs
->populate_dml_writeback_from_context(dc
, res_ctx
, pipes
);
1616 void dcn20_calculate_wm(struct dc
*dc
, struct dc_state
*context
,
1617 display_e2e_pipe_params_st
*pipes
,
1619 int *pipe_split_from
,
1623 int pipe_cnt
, i
, pipe_idx
;
1625 dc_assert_fp_enabled();
1627 for (i
= 0, pipe_idx
= 0, pipe_cnt
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
1628 if (!context
->res_ctx
.pipe_ctx
[i
].stream
)
1631 pipes
[pipe_cnt
].clks_cfg
.refclk_mhz
= dc
->res_pool
->ref_clocks
.dchub_ref_clock_inKhz
/ 1000.0;
1632 pipes
[pipe_cnt
].clks_cfg
.dispclk_mhz
= context
->bw_ctx
.dml
.vba
.RequiredDISPCLK
[vlevel
][context
->bw_ctx
.dml
.vba
.maxMpcComb
];
1634 if (pipe_split_from
[i
] < 0) {
1635 pipes
[pipe_cnt
].clks_cfg
.dppclk_mhz
=
1636 context
->bw_ctx
.dml
.vba
.RequiredDPPCLK
[vlevel
][context
->bw_ctx
.dml
.vba
.maxMpcComb
][pipe_idx
];
1637 if (context
->bw_ctx
.dml
.vba
.BlendingAndTiming
[pipe_idx
] == pipe_idx
)
1638 pipes
[pipe_cnt
].pipe
.dest
.odm_combine
=
1639 context
->bw_ctx
.dml
.vba
.ODMCombineEnabled
[pipe_idx
];
1641 pipes
[pipe_cnt
].pipe
.dest
.odm_combine
= 0;
1644 pipes
[pipe_cnt
].clks_cfg
.dppclk_mhz
=
1645 context
->bw_ctx
.dml
.vba
.RequiredDPPCLK
[vlevel
][context
->bw_ctx
.dml
.vba
.maxMpcComb
][pipe_split_from
[i
]];
1646 if (context
->bw_ctx
.dml
.vba
.BlendingAndTiming
[pipe_split_from
[i
]] == pipe_split_from
[i
])
1647 pipes
[pipe_cnt
].pipe
.dest
.odm_combine
=
1648 context
->bw_ctx
.dml
.vba
.ODMCombineEnabled
[pipe_split_from
[i
]];
1650 pipes
[pipe_cnt
].pipe
.dest
.odm_combine
= 0;
1653 if (dc
->config
.forced_clocks
) {
1654 pipes
[pipe_cnt
].clks_cfg
.dispclk_mhz
= context
->bw_ctx
.dml
.soc
.clock_limits
[0].dispclk_mhz
;
1655 pipes
[pipe_cnt
].clks_cfg
.dppclk_mhz
= context
->bw_ctx
.dml
.soc
.clock_limits
[0].dppclk_mhz
;
1657 if (dc
->debug
.min_disp_clk_khz
> pipes
[pipe_cnt
].clks_cfg
.dispclk_mhz
* 1000)
1658 pipes
[pipe_cnt
].clks_cfg
.dispclk_mhz
= dc
->debug
.min_disp_clk_khz
/ 1000.0;
1659 if (dc
->debug
.min_dpp_clk_khz
> pipes
[pipe_cnt
].clks_cfg
.dppclk_mhz
* 1000)
1660 pipes
[pipe_cnt
].clks_cfg
.dppclk_mhz
= dc
->debug
.min_dpp_clk_khz
/ 1000.0;
1665 if (pipe_cnt
!= pipe_idx
) {
1666 if (dc
->res_pool
->funcs
->populate_dml_pipes
)
1667 pipe_cnt
= dc
->res_pool
->funcs
->populate_dml_pipes(dc
,
1668 context
, pipes
, fast_validate
);
1670 pipe_cnt
= dcn20_populate_dml_pipes_from_context(dc
,
1671 context
, pipes
, fast_validate
);
1674 *out_pipe_cnt
= pipe_cnt
;
1676 pipes
[0].clks_cfg
.voltage
= vlevel
;
1677 pipes
[0].clks_cfg
.dcfclk_mhz
= context
->bw_ctx
.dml
.soc
.clock_limits
[vlevel
].dcfclk_mhz
;
1678 pipes
[0].clks_cfg
.socclk_mhz
= context
->bw_ctx
.dml
.soc
.clock_limits
[vlevel
].socclk_mhz
;
1680 /* only pipe 0 is read for voltage and dcf/soc clocks */
1682 pipes
[0].clks_cfg
.voltage
= 1;
1683 pipes
[0].clks_cfg
.dcfclk_mhz
= context
->bw_ctx
.dml
.soc
.clock_limits
[1].dcfclk_mhz
;
1684 pipes
[0].clks_cfg
.socclk_mhz
= context
->bw_ctx
.dml
.soc
.clock_limits
[1].socclk_mhz
;
1686 context
->bw_ctx
.bw
.dcn
.watermarks
.b
.urgent_ns
= get_wm_urgent(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1687 context
->bw_ctx
.bw
.dcn
.watermarks
.b
.cstate_pstate
.cstate_enter_plus_exit_ns
= get_wm_stutter_enter_exit(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1688 context
->bw_ctx
.bw
.dcn
.watermarks
.b
.cstate_pstate
.cstate_exit_ns
= get_wm_stutter_exit(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1689 context
->bw_ctx
.bw
.dcn
.watermarks
.b
.cstate_pstate
.pstate_change_ns
= get_wm_dram_clock_change(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1690 context
->bw_ctx
.bw
.dcn
.watermarks
.b
.pte_meta_urgent_ns
= get_wm_memory_trip(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1691 context
->bw_ctx
.bw
.dcn
.watermarks
.b
.frac_urg_bw_nom
= get_fraction_of_urgent_bandwidth(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1692 context
->bw_ctx
.bw
.dcn
.watermarks
.b
.frac_urg_bw_flip
= get_fraction_of_urgent_bandwidth_imm_flip(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1693 context
->bw_ctx
.bw
.dcn
.watermarks
.b
.urgent_latency_ns
= get_urgent_latency(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1696 pipes
[0].clks_cfg
.voltage
= 2;
1697 pipes
[0].clks_cfg
.dcfclk_mhz
= context
->bw_ctx
.dml
.soc
.clock_limits
[2].dcfclk_mhz
;
1698 pipes
[0].clks_cfg
.socclk_mhz
= context
->bw_ctx
.dml
.soc
.clock_limits
[2].socclk_mhz
;
1700 context
->bw_ctx
.bw
.dcn
.watermarks
.c
.urgent_ns
= get_wm_urgent(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1701 context
->bw_ctx
.bw
.dcn
.watermarks
.c
.cstate_pstate
.cstate_enter_plus_exit_ns
= get_wm_stutter_enter_exit(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1702 context
->bw_ctx
.bw
.dcn
.watermarks
.c
.cstate_pstate
.cstate_exit_ns
= get_wm_stutter_exit(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1703 context
->bw_ctx
.bw
.dcn
.watermarks
.c
.cstate_pstate
.pstate_change_ns
= get_wm_dram_clock_change(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1704 context
->bw_ctx
.bw
.dcn
.watermarks
.c
.pte_meta_urgent_ns
= get_wm_memory_trip(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1705 context
->bw_ctx
.bw
.dcn
.watermarks
.c
.frac_urg_bw_nom
= get_fraction_of_urgent_bandwidth(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1706 context
->bw_ctx
.bw
.dcn
.watermarks
.c
.frac_urg_bw_flip
= get_fraction_of_urgent_bandwidth_imm_flip(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1709 pipes
[0].clks_cfg
.voltage
= 3;
1710 pipes
[0].clks_cfg
.dcfclk_mhz
= context
->bw_ctx
.dml
.soc
.clock_limits
[2].dcfclk_mhz
;
1711 pipes
[0].clks_cfg
.socclk_mhz
= context
->bw_ctx
.dml
.soc
.clock_limits
[2].socclk_mhz
;
1713 context
->bw_ctx
.bw
.dcn
.watermarks
.d
.urgent_ns
= get_wm_urgent(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1714 context
->bw_ctx
.bw
.dcn
.watermarks
.d
.cstate_pstate
.cstate_enter_plus_exit_ns
= get_wm_stutter_enter_exit(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1715 context
->bw_ctx
.bw
.dcn
.watermarks
.d
.cstate_pstate
.cstate_exit_ns
= get_wm_stutter_exit(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1716 context
->bw_ctx
.bw
.dcn
.watermarks
.d
.cstate_pstate
.pstate_change_ns
= get_wm_dram_clock_change(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1717 context
->bw_ctx
.bw
.dcn
.watermarks
.d
.pte_meta_urgent_ns
= get_wm_memory_trip(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1718 context
->bw_ctx
.bw
.dcn
.watermarks
.d
.frac_urg_bw_nom
= get_fraction_of_urgent_bandwidth(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1719 context
->bw_ctx
.bw
.dcn
.watermarks
.d
.frac_urg_bw_flip
= get_fraction_of_urgent_bandwidth_imm_flip(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1721 pipes
[0].clks_cfg
.voltage
= vlevel
;
1722 pipes
[0].clks_cfg
.dcfclk_mhz
= context
->bw_ctx
.dml
.soc
.clock_limits
[vlevel
].dcfclk_mhz
;
1723 pipes
[0].clks_cfg
.socclk_mhz
= context
->bw_ctx
.dml
.soc
.clock_limits
[vlevel
].socclk_mhz
;
1724 context
->bw_ctx
.bw
.dcn
.watermarks
.a
.urgent_ns
= get_wm_urgent(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1725 context
->bw_ctx
.bw
.dcn
.watermarks
.a
.cstate_pstate
.cstate_enter_plus_exit_ns
= get_wm_stutter_enter_exit(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1726 context
->bw_ctx
.bw
.dcn
.watermarks
.a
.cstate_pstate
.cstate_exit_ns
= get_wm_stutter_exit(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1727 context
->bw_ctx
.bw
.dcn
.watermarks
.a
.cstate_pstate
.pstate_change_ns
= get_wm_dram_clock_change(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1728 context
->bw_ctx
.bw
.dcn
.watermarks
.a
.pte_meta_urgent_ns
= get_wm_memory_trip(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1729 context
->bw_ctx
.bw
.dcn
.watermarks
.a
.frac_urg_bw_nom
= get_fraction_of_urgent_bandwidth(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1730 context
->bw_ctx
.bw
.dcn
.watermarks
.a
.frac_urg_bw_flip
= get_fraction_of_urgent_bandwidth_imm_flip(&context
->bw_ctx
.dml
, pipes
, pipe_cnt
) * 1000;
1733 void dcn20_update_bounding_box(struct dc
*dc
,
1734 struct _vcs_dpi_soc_bounding_box_st
*bb
,
1735 struct pp_smu_nv_clock_table
*max_clocks
,
1736 unsigned int *uclk_states
,
1737 unsigned int num_states
)
1739 int num_calculated_states
= 0;
1743 dc_assert_fp_enabled();
1745 if (num_states
== 0)
1748 memset(bb
->clock_limits
, 0, sizeof(bb
->clock_limits
));
1750 if (dc
->bb_overrides
.min_dcfclk_mhz
> 0) {
1751 min_dcfclk
= dc
->bb_overrides
.min_dcfclk_mhz
;
1753 if (ASICREV_IS_NAVI12_P(dc
->ctx
->asic_id
.hw_internal_rev
))
1756 // Accounting for SOC/DCF relationship, we can go as high as
1761 for (i
= 0; i
< num_states
; i
++) {
1762 int min_fclk_required_by_uclk
;
1763 bb
->clock_limits
[i
].state
= i
;
1764 bb
->clock_limits
[i
].dram_speed_mts
= uclk_states
[i
] * 16 / 1000;
1766 // FCLK:UCLK ratio is 1.08
1767 min_fclk_required_by_uclk
= div_u64(((unsigned long long)uclk_states
[i
]) * 1080,
1770 bb
->clock_limits
[i
].fabricclk_mhz
= (min_fclk_required_by_uclk
< min_dcfclk
) ?
1771 min_dcfclk
: min_fclk_required_by_uclk
;
1773 bb
->clock_limits
[i
].socclk_mhz
= (bb
->clock_limits
[i
].fabricclk_mhz
> max_clocks
->socClockInKhz
/ 1000) ?
1774 max_clocks
->socClockInKhz
/ 1000 : bb
->clock_limits
[i
].fabricclk_mhz
;
1776 bb
->clock_limits
[i
].dcfclk_mhz
= (bb
->clock_limits
[i
].fabricclk_mhz
> max_clocks
->dcfClockInKhz
/ 1000) ?
1777 max_clocks
->dcfClockInKhz
/ 1000 : bb
->clock_limits
[i
].fabricclk_mhz
;
1779 bb
->clock_limits
[i
].dispclk_mhz
= max_clocks
->displayClockInKhz
/ 1000;
1780 bb
->clock_limits
[i
].dppclk_mhz
= max_clocks
->displayClockInKhz
/ 1000;
1781 bb
->clock_limits
[i
].dscclk_mhz
= max_clocks
->displayClockInKhz
/ (1000 * 3);
1783 bb
->clock_limits
[i
].phyclk_mhz
= max_clocks
->phyClockInKhz
/ 1000;
1785 num_calculated_states
++;
1788 bb
->clock_limits
[num_calculated_states
- 1].socclk_mhz
= max_clocks
->socClockInKhz
/ 1000;
1789 bb
->clock_limits
[num_calculated_states
- 1].fabricclk_mhz
= max_clocks
->socClockInKhz
/ 1000;
1790 bb
->clock_limits
[num_calculated_states
- 1].dcfclk_mhz
= max_clocks
->dcfClockInKhz
/ 1000;
1792 bb
->num_states
= num_calculated_states
;
1794 // Duplicate the last state, DML always an extra state identical to max state to work
1795 memcpy(&bb
->clock_limits
[num_calculated_states
], &bb
->clock_limits
[num_calculated_states
- 1], sizeof(struct _vcs_dpi_voltage_scaling_st
));
1796 bb
->clock_limits
[num_calculated_states
].state
= bb
->num_states
;
1799 void dcn20_cap_soc_clocks(struct _vcs_dpi_soc_bounding_box_st
*bb
,
1800 struct pp_smu_nv_clock_table max_clocks
)
1804 dc_assert_fp_enabled();
1806 // First pass - cap all clocks higher than the reported max
1807 for (i
= 0; i
< bb
->num_states
; i
++) {
1808 if ((bb
->clock_limits
[i
].dcfclk_mhz
> (max_clocks
.dcfClockInKhz
/ 1000))
1809 && max_clocks
.dcfClockInKhz
!= 0)
1810 bb
->clock_limits
[i
].dcfclk_mhz
= (max_clocks
.dcfClockInKhz
/ 1000);
1812 if ((bb
->clock_limits
[i
].dram_speed_mts
> (max_clocks
.uClockInKhz
/ 1000) * 16)
1813 && max_clocks
.uClockInKhz
!= 0)
1814 bb
->clock_limits
[i
].dram_speed_mts
= (max_clocks
.uClockInKhz
/ 1000) * 16;
1816 if ((bb
->clock_limits
[i
].fabricclk_mhz
> (max_clocks
.fabricClockInKhz
/ 1000))
1817 && max_clocks
.fabricClockInKhz
!= 0)
1818 bb
->clock_limits
[i
].fabricclk_mhz
= (max_clocks
.fabricClockInKhz
/ 1000);
1820 if ((bb
->clock_limits
[i
].dispclk_mhz
> (max_clocks
.displayClockInKhz
/ 1000))
1821 && max_clocks
.displayClockInKhz
!= 0)
1822 bb
->clock_limits
[i
].dispclk_mhz
= (max_clocks
.displayClockInKhz
/ 1000);
1824 if ((bb
->clock_limits
[i
].dppclk_mhz
> (max_clocks
.dppClockInKhz
/ 1000))
1825 && max_clocks
.dppClockInKhz
!= 0)
1826 bb
->clock_limits
[i
].dppclk_mhz
= (max_clocks
.dppClockInKhz
/ 1000);
1828 if ((bb
->clock_limits
[i
].phyclk_mhz
> (max_clocks
.phyClockInKhz
/ 1000))
1829 && max_clocks
.phyClockInKhz
!= 0)
1830 bb
->clock_limits
[i
].phyclk_mhz
= (max_clocks
.phyClockInKhz
/ 1000);
1832 if ((bb
->clock_limits
[i
].socclk_mhz
> (max_clocks
.socClockInKhz
/ 1000))
1833 && max_clocks
.socClockInKhz
!= 0)
1834 bb
->clock_limits
[i
].socclk_mhz
= (max_clocks
.socClockInKhz
/ 1000);
1836 if ((bb
->clock_limits
[i
].dscclk_mhz
> (max_clocks
.dscClockInKhz
/ 1000))
1837 && max_clocks
.dscClockInKhz
!= 0)
1838 bb
->clock_limits
[i
].dscclk_mhz
= (max_clocks
.dscClockInKhz
/ 1000);
1841 // Second pass - remove all duplicate clock states
1842 for (i
= bb
->num_states
- 1; i
> 1; i
--) {
1843 bool duplicate
= true;
1845 if (bb
->clock_limits
[i
-1].dcfclk_mhz
!= bb
->clock_limits
[i
].dcfclk_mhz
)
1847 if (bb
->clock_limits
[i
-1].dispclk_mhz
!= bb
->clock_limits
[i
].dispclk_mhz
)
1849 if (bb
->clock_limits
[i
-1].dppclk_mhz
!= bb
->clock_limits
[i
].dppclk_mhz
)
1851 if (bb
->clock_limits
[i
-1].dram_speed_mts
!= bb
->clock_limits
[i
].dram_speed_mts
)
1853 if (bb
->clock_limits
[i
-1].dscclk_mhz
!= bb
->clock_limits
[i
].dscclk_mhz
)
1855 if (bb
->clock_limits
[i
-1].fabricclk_mhz
!= bb
->clock_limits
[i
].fabricclk_mhz
)
1857 if (bb
->clock_limits
[i
-1].phyclk_mhz
!= bb
->clock_limits
[i
].phyclk_mhz
)
1859 if (bb
->clock_limits
[i
-1].socclk_mhz
!= bb
->clock_limits
[i
].socclk_mhz
)
1867 void dcn20_patch_bounding_box(struct dc
*dc
, struct _vcs_dpi_soc_bounding_box_st
*bb
)
1869 dc_assert_fp_enabled();
1871 if ((int)(bb
->sr_exit_time_us
* 1000) != dc
->bb_overrides
.sr_exit_time_ns
1872 && dc
->bb_overrides
.sr_exit_time_ns
) {
1873 bb
->sr_exit_time_us
= dc
->bb_overrides
.sr_exit_time_ns
/ 1000.0;
1876 if ((int)(bb
->sr_enter_plus_exit_time_us
* 1000)
1877 != dc
->bb_overrides
.sr_enter_plus_exit_time_ns
1878 && dc
->bb_overrides
.sr_enter_plus_exit_time_ns
) {
1879 bb
->sr_enter_plus_exit_time_us
=
1880 dc
->bb_overrides
.sr_enter_plus_exit_time_ns
/ 1000.0;
1883 if ((int)(bb
->sr_exit_z8_time_us
* 1000)
1884 != dc
->bb_overrides
.sr_exit_z8_time_ns
1885 && dc
->bb_overrides
.sr_exit_z8_time_ns
) {
1886 bb
->sr_exit_z8_time_us
= dc
->bb_overrides
.sr_exit_z8_time_ns
/ 1000.0;
1889 if ((int)(bb
->sr_enter_plus_exit_z8_time_us
* 1000)
1890 != dc
->bb_overrides
.sr_enter_plus_exit_z8_time_ns
1891 && dc
->bb_overrides
.sr_enter_plus_exit_z8_time_ns
) {
1892 bb
->sr_enter_plus_exit_z8_time_us
= dc
->bb_overrides
.sr_enter_plus_exit_z8_time_ns
/ 1000.0;
1894 if ((int)(bb
->urgent_latency_us
* 1000) != dc
->bb_overrides
.urgent_latency_ns
1895 && dc
->bb_overrides
.urgent_latency_ns
) {
1896 bb
->urgent_latency_us
= dc
->bb_overrides
.urgent_latency_ns
/ 1000.0;
1899 if ((int)(bb
->dram_clock_change_latency_us
* 1000)
1900 != dc
->bb_overrides
.dram_clock_change_latency_ns
1901 && dc
->bb_overrides
.dram_clock_change_latency_ns
) {
1902 bb
->dram_clock_change_latency_us
=
1903 dc
->bb_overrides
.dram_clock_change_latency_ns
/ 1000.0;
1906 if ((int)(bb
->dummy_pstate_latency_us
* 1000)
1907 != dc
->bb_overrides
.dummy_clock_change_latency_ns
1908 && dc
->bb_overrides
.dummy_clock_change_latency_ns
) {
1909 bb
->dummy_pstate_latency_us
=
1910 dc
->bb_overrides
.dummy_clock_change_latency_ns
/ 1000.0;
1914 static bool dcn20_validate_bandwidth_internal(struct dc
*dc
, struct dc_state
*context
,
1915 bool fast_validate
, display_e2e_pipe_params_st
*pipes
)
1919 BW_VAL_TRACE_SETUP();
1922 int pipe_split_from
[MAX_PIPES
];
1924 DC_LOGGER_INIT(dc
->ctx
->logger
);
1926 BW_VAL_TRACE_COUNT();
1928 out
= dcn20_fast_validate_bw(dc
, context
, pipes
, &pipe_cnt
, pipe_split_from
, &vlevel
, fast_validate
);
1936 BW_VAL_TRACE_END_VOLTAGE_LEVEL();
1938 if (fast_validate
) {
1939 BW_VAL_TRACE_SKIP(fast
);
1943 dcn20_calculate_wm(dc
, context
, pipes
, &pipe_cnt
, pipe_split_from
, vlevel
, fast_validate
);
1944 dcn20_calculate_dlg_params(dc
, context
, pipes
, pipe_cnt
, vlevel
);
1946 BW_VAL_TRACE_END_WATERMARKS();
1951 DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n",
1952 dml_get_status_message(context
->bw_ctx
.dml
.vba
.ValidationStatus
[context
->bw_ctx
.dml
.vba
.soc
.num_states
]));
1954 BW_VAL_TRACE_SKIP(fail
);
1959 BW_VAL_TRACE_FINISH();
1964 bool dcn20_validate_bandwidth_fp(struct dc
*dc
, struct dc_state
*context
,
1965 bool fast_validate
, display_e2e_pipe_params_st
*pipes
)
1967 bool voltage_supported
= false;
1968 bool full_pstate_supported
= false;
1969 bool dummy_pstate_supported
= false;
1970 double p_state_latency_us
;
1972 dc_assert_fp_enabled();
1974 p_state_latency_us
= context
->bw_ctx
.dml
.soc
.dram_clock_change_latency_us
;
1975 context
->bw_ctx
.dml
.soc
.disable_dram_clock_change_vactive_support
=
1976 dc
->debug
.disable_dram_clock_change_vactive_support
;
1977 context
->bw_ctx
.dml
.soc
.allow_dram_clock_one_display_vactive
=
1978 dc
->debug
.enable_dram_clock_change_one_display_vactive
;
1980 /*Unsafe due to current pipe merge and split logic*/
1981 ASSERT(context
!= dc
->current_state
);
1983 if (fast_validate
) {
1984 return dcn20_validate_bandwidth_internal(dc
, context
, true, pipes
);
1987 // Best case, we support full UCLK switch latency
1988 voltage_supported
= dcn20_validate_bandwidth_internal(dc
, context
, false, pipes
);
1989 full_pstate_supported
= context
->bw_ctx
.bw
.dcn
.clk
.p_state_change_support
;
1991 if (context
->bw_ctx
.dml
.soc
.dummy_pstate_latency_us
== 0 ||
1992 (voltage_supported
&& full_pstate_supported
)) {
1993 context
->bw_ctx
.bw
.dcn
.clk
.p_state_change_support
= full_pstate_supported
;
1994 goto restore_dml_state
;
1997 // Fallback: Try to only support G6 temperature read latency
1998 context
->bw_ctx
.dml
.soc
.dram_clock_change_latency_us
= context
->bw_ctx
.dml
.soc
.dummy_pstate_latency_us
;
2000 memset(pipes
, 0, dc
->res_pool
->pipe_count
* sizeof(display_e2e_pipe_params_st
));
2001 voltage_supported
= dcn20_validate_bandwidth_internal(dc
, context
, false, pipes
);
2002 dummy_pstate_supported
= context
->bw_ctx
.bw
.dcn
.clk
.p_state_change_support
;
2004 if (voltage_supported
&& (dummy_pstate_supported
|| !(context
->stream_count
))) {
2005 context
->bw_ctx
.bw
.dcn
.clk
.p_state_change_support
= false;
2006 goto restore_dml_state
;
2009 // ERROR: fallback is supposed to always work.
2013 context
->bw_ctx
.dml
.soc
.dram_clock_change_latency_us
= p_state_latency_us
;
2014 return voltage_supported
;
2017 void dcn20_fpu_set_wm_ranges(int i
,
2018 struct pp_smu_wm_range_sets
*ranges
,
2019 struct _vcs_dpi_soc_bounding_box_st
*loaded_bb
)
2021 dc_assert_fp_enabled();
2023 ranges
->reader_wm_sets
[i
].min_fill_clk_mhz
= (i
> 0) ? (loaded_bb
->clock_limits
[i
- 1].dram_speed_mts
/ 16) + 1 : 0;
2024 ranges
->reader_wm_sets
[i
].max_fill_clk_mhz
= loaded_bb
->clock_limits
[i
].dram_speed_mts
/ 16;
2027 void dcn20_fpu_adjust_dppclk(struct vba_vars_st
*v
,
2031 bool is_validating_bw
)
2033 dc_assert_fp_enabled();
2035 if (is_validating_bw
)
2036 v
->RequiredDPPCLK
[vlevel
][max_mpc_comb
][pipe_idx
] *= 2;
2038 v
->RequiredDPPCLK
[vlevel
][max_mpc_comb
][pipe_idx
] /= 2;
2041 int dcn21_populate_dml_pipes_from_context(struct dc
*dc
,
2042 struct dc_state
*context
,
2043 display_e2e_pipe_params_st
*pipes
,
2049 dc_assert_fp_enabled();
2051 pipe_cnt
= dcn20_populate_dml_pipes_from_context(dc
, context
, pipes
, fast_validate
);
2053 for (i
= 0; i
< pipe_cnt
; i
++) {
2055 pipes
[i
].pipe
.src
.hostvm
= dc
->res_pool
->hubbub
->riommu_active
;
2056 pipes
[i
].pipe
.src
.gpuvm
= 1;
2062 static void patch_bounding_box(struct dc
*dc
, struct _vcs_dpi_soc_bounding_box_st
*bb
)
2066 if (dc
->bb_overrides
.sr_exit_time_ns
) {
2067 for (i
= 0; i
< WM_SET_COUNT
; i
++) {
2068 dc
->clk_mgr
->bw_params
->wm_table
.entries
[i
].sr_exit_time_us
=
2069 dc
->bb_overrides
.sr_exit_time_ns
/ 1000.0;
2073 if (dc
->bb_overrides
.sr_enter_plus_exit_time_ns
) {
2074 for (i
= 0; i
< WM_SET_COUNT
; i
++) {
2075 dc
->clk_mgr
->bw_params
->wm_table
.entries
[i
].sr_enter_plus_exit_time_us
=
2076 dc
->bb_overrides
.sr_enter_plus_exit_time_ns
/ 1000.0;
2080 if (dc
->bb_overrides
.urgent_latency_ns
) {
2081 bb
->urgent_latency_us
= dc
->bb_overrides
.urgent_latency_ns
/ 1000.0;
2084 if (dc
->bb_overrides
.dram_clock_change_latency_ns
) {
2085 for (i
= 0; i
< WM_SET_COUNT
; i
++) {
2086 dc
->clk_mgr
->bw_params
->wm_table
.entries
[i
].pstate_latency_us
=
2087 dc
->bb_overrides
.dram_clock_change_latency_ns
/ 1000.0;
2092 static void calculate_wm_set_for_vlevel(int vlevel
,
2093 struct wm_range_table_entry
*table_entry
,
2094 struct dcn_watermarks
*wm_set
,
2095 struct display_mode_lib
*dml
,
2096 display_e2e_pipe_params_st
*pipes
,
2099 double dram_clock_change_latency_cached
= dml
->soc
.dram_clock_change_latency_us
;
2101 ASSERT(vlevel
< dml
->soc
.num_states
);
2102 /* only pipe 0 is read for voltage and dcf/soc clocks */
2103 pipes
[0].clks_cfg
.voltage
= vlevel
;
2104 pipes
[0].clks_cfg
.dcfclk_mhz
= dml
->soc
.clock_limits
[vlevel
].dcfclk_mhz
;
2105 pipes
[0].clks_cfg
.socclk_mhz
= dml
->soc
.clock_limits
[vlevel
].socclk_mhz
;
2107 dml
->soc
.dram_clock_change_latency_us
= table_entry
->pstate_latency_us
;
2108 dml
->soc
.sr_exit_time_us
= table_entry
->sr_exit_time_us
;
2109 dml
->soc
.sr_enter_plus_exit_time_us
= table_entry
->sr_enter_plus_exit_time_us
;
2111 wm_set
->urgent_ns
= get_wm_urgent(dml
, pipes
, pipe_cnt
) * 1000;
2112 wm_set
->cstate_pstate
.cstate_enter_plus_exit_ns
= get_wm_stutter_enter_exit(dml
, pipes
, pipe_cnt
) * 1000;
2113 wm_set
->cstate_pstate
.cstate_exit_ns
= get_wm_stutter_exit(dml
, pipes
, pipe_cnt
) * 1000;
2114 wm_set
->cstate_pstate
.pstate_change_ns
= get_wm_dram_clock_change(dml
, pipes
, pipe_cnt
) * 1000;
2115 wm_set
->pte_meta_urgent_ns
= get_wm_memory_trip(dml
, pipes
, pipe_cnt
) * 1000;
2116 wm_set
->frac_urg_bw_nom
= get_fraction_of_urgent_bandwidth(dml
, pipes
, pipe_cnt
) * 1000;
2117 wm_set
->frac_urg_bw_flip
= get_fraction_of_urgent_bandwidth_imm_flip(dml
, pipes
, pipe_cnt
) * 1000;
2118 wm_set
->urgent_latency_ns
= get_urgent_latency(dml
, pipes
, pipe_cnt
) * 1000;
2119 dml
->soc
.dram_clock_change_latency_us
= dram_clock_change_latency_cached
;
2122 static void dcn21_calculate_wm(struct dc
*dc
, struct dc_state
*context
,
2123 display_e2e_pipe_params_st
*pipes
,
2125 int *pipe_split_from
,
2129 int pipe_cnt
, i
, pipe_idx
;
2130 int vlevel
, vlevel_max
;
2131 struct wm_range_table_entry
*table_entry
;
2132 struct clk_bw_params
*bw_params
= dc
->clk_mgr
->bw_params
;
2136 patch_bounding_box(dc
, &context
->bw_ctx
.dml
.soc
);
2138 for (i
= 0, pipe_idx
= 0, pipe_cnt
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
2139 if (!context
->res_ctx
.pipe_ctx
[i
].stream
)
2142 pipes
[pipe_cnt
].clks_cfg
.refclk_mhz
= dc
->res_pool
->ref_clocks
.dchub_ref_clock_inKhz
/ 1000.0;
2143 pipes
[pipe_cnt
].clks_cfg
.dispclk_mhz
= context
->bw_ctx
.dml
.vba
.RequiredDISPCLK
[vlevel_req
][context
->bw_ctx
.dml
.vba
.maxMpcComb
];
2145 if (pipe_split_from
[i
] < 0) {
2146 pipes
[pipe_cnt
].clks_cfg
.dppclk_mhz
=
2147 context
->bw_ctx
.dml
.vba
.RequiredDPPCLK
[vlevel_req
][context
->bw_ctx
.dml
.vba
.maxMpcComb
][pipe_idx
];
2148 if (context
->bw_ctx
.dml
.vba
.BlendingAndTiming
[pipe_idx
] == pipe_idx
)
2149 pipes
[pipe_cnt
].pipe
.dest
.odm_combine
=
2150 context
->bw_ctx
.dml
.vba
.ODMCombineEnablePerState
[vlevel_req
][pipe_idx
];
2152 pipes
[pipe_cnt
].pipe
.dest
.odm_combine
= 0;
2155 pipes
[pipe_cnt
].clks_cfg
.dppclk_mhz
=
2156 context
->bw_ctx
.dml
.vba
.RequiredDPPCLK
[vlevel_req
][context
->bw_ctx
.dml
.vba
.maxMpcComb
][pipe_split_from
[i
]];
2157 if (context
->bw_ctx
.dml
.vba
.BlendingAndTiming
[pipe_split_from
[i
]] == pipe_split_from
[i
])
2158 pipes
[pipe_cnt
].pipe
.dest
.odm_combine
=
2159 context
->bw_ctx
.dml
.vba
.ODMCombineEnablePerState
[vlevel_req
][pipe_split_from
[i
]];
2161 pipes
[pipe_cnt
].pipe
.dest
.odm_combine
= 0;
2166 if (pipe_cnt
!= pipe_idx
) {
2167 if (dc
->res_pool
->funcs
->populate_dml_pipes
)
2168 pipe_cnt
= dc
->res_pool
->funcs
->populate_dml_pipes(dc
,
2169 context
, pipes
, fast_validate
);
2171 pipe_cnt
= dcn21_populate_dml_pipes_from_context(dc
,
2172 context
, pipes
, fast_validate
);
2175 *out_pipe_cnt
= pipe_cnt
;
2177 vlevel_max
= bw_params
->clk_table
.num_entries
- 1;
2181 table_entry
= &bw_params
->wm_table
.entries
[WM_D
];
2182 if (table_entry
->wm_type
== WM_TYPE_RETRAINING
)
2185 vlevel
= vlevel_max
;
2186 calculate_wm_set_for_vlevel(vlevel
, table_entry
, &context
->bw_ctx
.bw
.dcn
.watermarks
.d
,
2187 &context
->bw_ctx
.dml
, pipes
, pipe_cnt
);
2189 table_entry
= &bw_params
->wm_table
.entries
[WM_C
];
2190 vlevel
= MIN(MAX(vlevel_req
, 3), vlevel_max
);
2191 calculate_wm_set_for_vlevel(vlevel
, table_entry
, &context
->bw_ctx
.bw
.dcn
.watermarks
.c
,
2192 &context
->bw_ctx
.dml
, pipes
, pipe_cnt
);
2194 table_entry
= &bw_params
->wm_table
.entries
[WM_B
];
2195 vlevel
= MIN(MAX(vlevel_req
, 2), vlevel_max
);
2196 calculate_wm_set_for_vlevel(vlevel
, table_entry
, &context
->bw_ctx
.bw
.dcn
.watermarks
.b
,
2197 &context
->bw_ctx
.dml
, pipes
, pipe_cnt
);
2200 table_entry
= &bw_params
->wm_table
.entries
[WM_A
];
2201 vlevel
= MIN(vlevel_req
, vlevel_max
);
2202 calculate_wm_set_for_vlevel(vlevel
, table_entry
, &context
->bw_ctx
.bw
.dcn
.watermarks
.a
,
2203 &context
->bw_ctx
.dml
, pipes
, pipe_cnt
);
2206 bool dcn21_validate_bandwidth_fp(struct dc
*dc
, struct dc_state
*context
,
2207 bool fast_validate
, display_e2e_pipe_params_st
*pipes
)
2211 BW_VAL_TRACE_SETUP();
2214 int pipe_split_from
[MAX_PIPES
];
2216 DC_LOGGER_INIT(dc
->ctx
->logger
);
2218 BW_VAL_TRACE_COUNT();
2220 dc_assert_fp_enabled();
2222 /*Unsafe due to current pipe merge and split logic*/
2223 ASSERT(context
!= dc
->current_state
);
2225 out
= dcn21_fast_validate_bw(dc
, context
, pipes
, &pipe_cnt
, pipe_split_from
, &vlevel
, fast_validate
);
2233 BW_VAL_TRACE_END_VOLTAGE_LEVEL();
2235 if (fast_validate
) {
2236 BW_VAL_TRACE_SKIP(fast
);
2240 dcn21_calculate_wm(dc
, context
, pipes
, &pipe_cnt
, pipe_split_from
, vlevel
, fast_validate
);
2241 dcn20_calculate_dlg_params(dc
, context
, pipes
, pipe_cnt
, vlevel
);
2243 BW_VAL_TRACE_END_WATERMARKS();
2248 DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n",
2249 dml_get_status_message(context
->bw_ctx
.dml
.vba
.ValidationStatus
[context
->bw_ctx
.dml
.vba
.soc
.num_states
]));
2251 BW_VAL_TRACE_SKIP(fail
);
2256 BW_VAL_TRACE_FINISH();
2261 static struct _vcs_dpi_voltage_scaling_st
construct_low_pstate_lvl(struct clk_limit_table
*clk_table
, unsigned int high_voltage_lvl
)
2263 struct _vcs_dpi_voltage_scaling_st low_pstate_lvl
;
2266 low_pstate_lvl
.state
= 1;
2267 low_pstate_lvl
.dcfclk_mhz
= clk_table
->entries
[0].dcfclk_mhz
;
2268 low_pstate_lvl
.fabricclk_mhz
= clk_table
->entries
[0].fclk_mhz
;
2269 low_pstate_lvl
.socclk_mhz
= clk_table
->entries
[0].socclk_mhz
;
2270 low_pstate_lvl
.dram_speed_mts
= clk_table
->entries
[0].memclk_mhz
* 2;
2272 low_pstate_lvl
.dispclk_mhz
= dcn2_1_soc
.clock_limits
[high_voltage_lvl
].dispclk_mhz
;
2273 low_pstate_lvl
.dppclk_mhz
= dcn2_1_soc
.clock_limits
[high_voltage_lvl
].dppclk_mhz
;
2274 low_pstate_lvl
.dram_bw_per_chan_gbps
= dcn2_1_soc
.clock_limits
[high_voltage_lvl
].dram_bw_per_chan_gbps
;
2275 low_pstate_lvl
.dscclk_mhz
= dcn2_1_soc
.clock_limits
[high_voltage_lvl
].dscclk_mhz
;
2276 low_pstate_lvl
.dtbclk_mhz
= dcn2_1_soc
.clock_limits
[high_voltage_lvl
].dtbclk_mhz
;
2277 low_pstate_lvl
.phyclk_d18_mhz
= dcn2_1_soc
.clock_limits
[high_voltage_lvl
].phyclk_d18_mhz
;
2278 low_pstate_lvl
.phyclk_mhz
= dcn2_1_soc
.clock_limits
[high_voltage_lvl
].phyclk_mhz
;
2280 for (i
= clk_table
->num_entries
; i
> 1; i
--)
2281 clk_table
->entries
[i
] = clk_table
->entries
[i
-1];
2282 clk_table
->entries
[1] = clk_table
->entries
[0];
2283 clk_table
->num_entries
++;
2285 return low_pstate_lvl
;
2288 void dcn21_update_bw_bounding_box(struct dc
*dc
, struct clk_bw_params
*bw_params
)
2290 struct _vcs_dpi_voltage_scaling_st
*s
= dc
->scratch
.update_bw_bounding_box
.clock_limits
;
2291 struct dcn21_resource_pool
*pool
= TO_DCN21_RES_POOL(dc
->res_pool
);
2292 struct clk_limit_table
*clk_table
= &bw_params
->clk_table
;
2293 unsigned int i
, closest_clk_lvl
= 0, k
= 0;
2296 dc_assert_fp_enabled();
2298 dcn2_1_ip
.max_num_otg
= pool
->base
.res_cap
->num_timing_generator
;
2299 dcn2_1_ip
.max_num_dpp
= pool
->base
.pipe_count
;
2300 dcn2_1_soc
.num_chans
= bw_params
->num_channels
;
2302 ASSERT(clk_table
->num_entries
);
2303 /* Copy dcn2_1_soc.clock_limits to clock_limits to avoid copying over null states later */
2304 memcpy(s
, dcn2_1_soc
.clock_limits
, sizeof(dcn2_1_soc
.clock_limits
));
2306 for (i
= 0; i
< clk_table
->num_entries
; i
++) {
2308 for (closest_clk_lvl
= 0, j
= dcn2_1_soc
.num_states
- 1; j
>= 0; j
--) {
2309 if ((unsigned int) dcn2_1_soc
.clock_limits
[j
].dcfclk_mhz
<= clk_table
->entries
[i
].dcfclk_mhz
) {
2310 closest_clk_lvl
= j
;
2315 /* clk_table[1] is reserved for min DF PState. skip here to fill in later. */
2320 s
[k
].dcfclk_mhz
= clk_table
->entries
[i
].dcfclk_mhz
;
2321 s
[k
].fabricclk_mhz
= clk_table
->entries
[i
].fclk_mhz
;
2322 s
[k
].socclk_mhz
= clk_table
->entries
[i
].socclk_mhz
;
2323 s
[k
].dram_speed_mts
= clk_table
->entries
[i
].memclk_mhz
* 2;
2325 s
[k
].dispclk_mhz
= dcn2_1_soc
.clock_limits
[closest_clk_lvl
].dispclk_mhz
;
2326 s
[k
].dppclk_mhz
= dcn2_1_soc
.clock_limits
[closest_clk_lvl
].dppclk_mhz
;
2327 s
[k
].dram_bw_per_chan_gbps
=
2328 dcn2_1_soc
.clock_limits
[closest_clk_lvl
].dram_bw_per_chan_gbps
;
2329 s
[k
].dscclk_mhz
= dcn2_1_soc
.clock_limits
[closest_clk_lvl
].dscclk_mhz
;
2330 s
[k
].dtbclk_mhz
= dcn2_1_soc
.clock_limits
[closest_clk_lvl
].dtbclk_mhz
;
2331 s
[k
].phyclk_d18_mhz
= dcn2_1_soc
.clock_limits
[closest_clk_lvl
].phyclk_d18_mhz
;
2332 s
[k
].phyclk_mhz
= dcn2_1_soc
.clock_limits
[closest_clk_lvl
].phyclk_mhz
;
2337 memcpy(&dcn2_1_soc
.clock_limits
, s
, sizeof(dcn2_1_soc
.clock_limits
));
2339 if (clk_table
->num_entries
) {
2340 dcn2_1_soc
.num_states
= clk_table
->num_entries
+ 1;
2341 /* fill in min DF PState */
2342 dcn2_1_soc
.clock_limits
[1] = construct_low_pstate_lvl(clk_table
, closest_clk_lvl
);
2343 /* duplicate last level */
2344 dcn2_1_soc
.clock_limits
[dcn2_1_soc
.num_states
] = dcn2_1_soc
.clock_limits
[dcn2_1_soc
.num_states
- 1];
2345 dcn2_1_soc
.clock_limits
[dcn2_1_soc
.num_states
].state
= dcn2_1_soc
.num_states
;
2348 dml_init_instance(&dc
->dml
, &dcn2_1_soc
, &dcn2_1_ip
, DML_PROJECT_DCN21
);
2351 void dcn21_clk_mgr_set_bw_params_wm_table(struct clk_bw_params
*bw_params
)
2353 dc_assert_fp_enabled();
2355 bw_params
->wm_table
.entries
[WM_D
].pstate_latency_us
= LPDDR_MEM_RETRAIN_LATENCY
;
2356 bw_params
->wm_table
.entries
[WM_D
].wm_inst
= WM_D
;
2357 bw_params
->wm_table
.entries
[WM_D
].wm_type
= WM_TYPE_RETRAINING
;
2358 bw_params
->wm_table
.entries
[WM_D
].valid
= true;
2361 void dcn201_populate_dml_writeback_from_context_fpu(struct dc
*dc
,
2362 struct resource_context
*res_ctx
,
2363 display_e2e_pipe_params_st
*pipes
)
2366 double max_calc_writeback_dispclk
;
2367 double writeback_dispclk
;
2368 struct writeback_st dout_wb
;
2370 dc_assert_fp_enabled();
2372 for (i
= 0, pipe_cnt
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
2373 struct dc_stream_state
*stream
= res_ctx
->pipe_ctx
[i
].stream
;
2377 max_calc_writeback_dispclk
= 0;
2379 /* Set writeback information */
2380 pipes
[pipe_cnt
].dout
.wb_enable
= 0;
2381 pipes
[pipe_cnt
].dout
.num_active_wb
= 0;
2382 for (j
= 0; j
< stream
->num_wb_info
; j
++) {
2383 struct dc_writeback_info
*wb_info
= &stream
->writeback_info
[j
];
2385 if (wb_info
->wb_enabled
&& wb_info
->writeback_source_plane
&&
2386 (wb_info
->writeback_source_plane
== res_ctx
->pipe_ctx
[i
].plane_state
)) {
2387 pipes
[pipe_cnt
].dout
.wb_enable
= 1;
2388 pipes
[pipe_cnt
].dout
.num_active_wb
++;
2389 dout_wb
.wb_src_height
= wb_info
->dwb_params
.cnv_params
.crop_en
?
2390 wb_info
->dwb_params
.cnv_params
.crop_height
:
2391 wb_info
->dwb_params
.cnv_params
.src_height
;
2392 dout_wb
.wb_src_width
= wb_info
->dwb_params
.cnv_params
.crop_en
?
2393 wb_info
->dwb_params
.cnv_params
.crop_width
:
2394 wb_info
->dwb_params
.cnv_params
.src_width
;
2395 dout_wb
.wb_dst_width
= wb_info
->dwb_params
.dest_width
;
2396 dout_wb
.wb_dst_height
= wb_info
->dwb_params
.dest_height
;
2397 dout_wb
.wb_htaps_luma
= wb_info
->dwb_params
.scaler_taps
.h_taps
;
2398 dout_wb
.wb_vtaps_luma
= wb_info
->dwb_params
.scaler_taps
.v_taps
;
2399 dout_wb
.wb_htaps_chroma
= wb_info
->dwb_params
.scaler_taps
.h_taps_c
;
2400 dout_wb
.wb_vtaps_chroma
= wb_info
->dwb_params
.scaler_taps
.v_taps_c
;
2401 dout_wb
.wb_hratio
= wb_info
->dwb_params
.cnv_params
.crop_en
?
2402 (double)wb_info
->dwb_params
.cnv_params
.crop_width
/
2403 (double)wb_info
->dwb_params
.dest_width
:
2404 (double)wb_info
->dwb_params
.cnv_params
.src_width
/
2405 (double)wb_info
->dwb_params
.dest_width
;
2406 dout_wb
.wb_vratio
= wb_info
->dwb_params
.cnv_params
.crop_en
?
2407 (double)wb_info
->dwb_params
.cnv_params
.crop_height
/
2408 (double)wb_info
->dwb_params
.dest_height
:
2409 (double)wb_info
->dwb_params
.cnv_params
.src_height
/
2410 (double)wb_info
->dwb_params
.dest_height
;
2411 if (wb_info
->dwb_params
.out_format
== dwb_scaler_mode_yuv420
) {
2412 if (wb_info
->dwb_params
.output_depth
== DWB_OUTPUT_PIXEL_DEPTH_8BPC
)
2413 dout_wb
.wb_pixel_format
= dm_420_8
;
2415 dout_wb
.wb_pixel_format
= dm_420_10
;
2417 dout_wb
.wb_pixel_format
= dm_444_32
;
2419 /* Workaround for cases where multiple writebacks are connected to same plane
2420 * In which case, need to compute worst case and set the associated writeback parameters
2421 * This workaround is necessary due to DML computation assuming only 1 set of writeback
2422 * parameters per pipe */
2423 writeback_dispclk
= CalculateWriteBackDISPCLK(
2424 dout_wb
.wb_pixel_format
,
2425 pipes
[pipe_cnt
].pipe
.dest
.pixel_rate_mhz
,
2428 dout_wb
.wb_htaps_luma
,
2429 dout_wb
.wb_vtaps_luma
,
2430 dout_wb
.wb_htaps_chroma
,
2431 dout_wb
.wb_vtaps_chroma
,
2432 dout_wb
.wb_dst_width
,
2433 pipes
[pipe_cnt
].pipe
.dest
.htotal
,
2436 if (writeback_dispclk
> max_calc_writeback_dispclk
) {
2437 max_calc_writeback_dispclk
= writeback_dispclk
;
2438 pipes
[pipe_cnt
].dout
.wb
= dout_wb
;