File Index
Files and directories
Sign in
FILE

dcn20_fpu.c

File preview with syntax highlighting.

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