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