]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drm/amd/display: stop doing unnecessary detection when going to D3
[mirror_ubuntu-hirsute-kernel.git] / drivers / gpu / drm / amd / display / dc / dcn20 / dcn20_resource.c
CommitLineData
7ed4e635
HW
1/*
2* Copyright 2016 Advanced Micro Devices, Inc.
6ca3928d 3 * Copyright 2019 Raptor Engineering, LLC
7ed4e635
HW
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
d7929c1e
AD
27#include <linux/slab.h>
28
7ed4e635
HW
29#include "dm_services.h"
30#include "dc.h"
31
78c77382
AK
32#include "dcn20_init.h"
33
7ed4e635
HW
34#include "resource.h"
35#include "include/irq_service_interface.h"
36#include "dcn20/dcn20_resource.h"
37
38#include "dcn10/dcn10_hubp.h"
39#include "dcn10/dcn10_ipp.h"
40#include "dcn20_hubbub.h"
41#include "dcn20_mpc.h"
42#include "dcn20_hubp.h"
43#include "irq/dcn20/irq_service_dcn20.h"
44#include "dcn20_dpp.h"
45#include "dcn20_optc.h"
46#include "dcn20_hwseq.h"
47#include "dce110/dce110_hw_sequencer.h"
278141f5 48#include "dcn10/dcn10_resource.h"
7ed4e635
HW
49#include "dcn20_opp.h"
50
97bda032 51#include "dcn20_dsc.h"
97bda032 52
7ed4e635
HW
53#include "dcn20_link_encoder.h"
54#include "dcn20_stream_encoder.h"
55#include "dce/dce_clock_source.h"
56#include "dce/dce_audio.h"
57#include "dce/dce_hwseq.h"
58#include "virtual/virtual_stream_encoder.h"
59#include "dce110/dce110_resource.h"
60#include "dml/display_mode_vba.h"
61#include "dcn20_dccg.h"
62#include "dcn20_vmid.h"
d9a07577 63#include "dc_link_ddc.h"
7ed4e635
HW
64
65#include "navi10_ip_offset.h"
66
67#include "dcn/dcn_2_0_0_offset.h"
68#include "dcn/dcn_2_0_0_sh_mask.h"
a771ded8
RL
69#include "dpcs/dpcs_2_0_0_offset.h"
70#include "dpcs/dpcs_2_0_0_sh_mask.h"
7ed4e635
HW
71
72#include "nbio/nbio_2_3_offset.h"
73
bb21290f
CL
74#include "dcn20/dcn20_dwb.h"
75#include "dcn20/dcn20_mmhubbub.h"
76
7ed4e635
HW
77#include "mmhub/mmhub_2_0_0_offset.h"
78#include "mmhub/mmhub_2_0_0_sh_mask.h"
79
80#include "reg_helper.h"
81#include "dce/dce_abm.h"
82#include "dce/dce_dmcu.h"
83#include "dce/dce_aux.h"
84#include "dce/dce_i2c.h"
85#include "vm_helper.h"
86
87#include "amdgpu_socbb.h"
88
7ed4e635
HW
89#define DC_LOGGER_INIT(logger)
90
91struct _vcs_dpi_ip_params_st dcn2_0_ip = {
92 .odm_capable = 1,
93 .gpuvm_enable = 0,
94 .hostvm_enable = 0,
95 .gpuvm_max_page_table_levels = 4,
96 .hostvm_max_page_table_levels = 4,
97 .hostvm_cached_page_table_levels = 0,
98 .pte_group_size_bytes = 2048,
97bda032 99 .num_dsc = 6,
7ed4e635
HW
100 .rob_buffer_size_kbytes = 168,
101 .det_buffer_size_kbytes = 164,
102 .dpte_buffer_size_in_pte_reqs_luma = 84,
103 .pde_proc_buffer_size_64k_reqs = 48,
104 .dpp_output_buffer_pixels = 2560,
105 .opp_output_buffer_lines = 1,
106 .pixel_chunk_size_kbytes = 8,
107 .pte_chunk_size_kbytes = 2,
108 .meta_chunk_size_kbytes = 2,
109 .writeback_chunk_size_kbytes = 2,
110 .line_buffer_size_bits = 789504,
111 .is_line_buffer_bpp_fixed = 0,
112 .line_buffer_fixed_bpp = 0,
113 .dcc_supported = true,
114 .max_line_buffer_lines = 12,
115 .writeback_luma_buffer_size_kbytes = 12,
116 .writeback_chroma_buffer_size_kbytes = 8,
117 .writeback_chroma_line_buffer_width_pixels = 4,
118 .writeback_max_hscl_ratio = 1,
119 .writeback_max_vscl_ratio = 1,
120 .writeback_min_hscl_ratio = 1,
121 .writeback_min_vscl_ratio = 1,
122 .writeback_max_hscl_taps = 12,
123 .writeback_max_vscl_taps = 12,
124 .writeback_line_buffer_luma_buffer_size = 0,
125 .writeback_line_buffer_chroma_buffer_size = 14643,
126 .cursor_buffer_size = 8,
127 .cursor_chunk_size = 2,
128 .max_num_otg = 6,
129 .max_num_dpp = 6,
130 .max_num_wb = 1,
131 .max_dchub_pscl_bw_pix_per_clk = 4,
132 .max_pscl_lb_bw_pix_per_clk = 2,
133 .max_lb_vscl_bw_pix_per_clk = 4,
134 .max_vscl_hscl_bw_pix_per_clk = 4,
135 .max_hscl_ratio = 8,
136 .max_vscl_ratio = 8,
137 .hscl_mults = 4,
138 .vscl_mults = 4,
139 .max_hscl_taps = 8,
140 .max_vscl_taps = 8,
141 .dispclk_ramp_margin_percent = 1,
142 .underscan_factor = 1.10,
143 .min_vblank_lines = 32, //
144 .dppclk_delay_subtotal = 77, //
145 .dppclk_delay_scl_lb_only = 16,
146 .dppclk_delay_scl = 50,
147 .dppclk_delay_cnvc_formatter = 8,
148 .dppclk_delay_cnvc_cursor = 6,
149 .dispclk_delay_subtotal = 87, //
150 .dcfclk_cstate_latency = 10, // SRExitTime
151 .max_inter_dcn_tile_repeaters = 8,
152
153 .xfc_supported = true,
154 .xfc_fill_bw_overhead_percent = 10.0,
155 .xfc_fill_constant_bytes = 0,
156};
157
a2c63407
Z
158struct _vcs_dpi_ip_params_st dcn2_0_nv14_ip = {
159 .odm_capable = 1,
160 .gpuvm_enable = 0,
161 .hostvm_enable = 0,
162 .gpuvm_max_page_table_levels = 4,
163 .hostvm_max_page_table_levels = 4,
164 .hostvm_cached_page_table_levels = 0,
165 .num_dsc = 5,
166 .rob_buffer_size_kbytes = 168,
167 .det_buffer_size_kbytes = 164,
168 .dpte_buffer_size_in_pte_reqs_luma = 84,
169 .dpte_buffer_size_in_pte_reqs_chroma = 42,//todo
170 .dpp_output_buffer_pixels = 2560,
171 .opp_output_buffer_lines = 1,
172 .pixel_chunk_size_kbytes = 8,
173 .pte_enable = 1,
174 .max_page_table_levels = 4,
175 .pte_chunk_size_kbytes = 2,
176 .meta_chunk_size_kbytes = 2,
177 .writeback_chunk_size_kbytes = 2,
178 .line_buffer_size_bits = 789504,
179 .is_line_buffer_bpp_fixed = 0,
180 .line_buffer_fixed_bpp = 0,
181 .dcc_supported = true,
182 .max_line_buffer_lines = 12,
183 .writeback_luma_buffer_size_kbytes = 12,
184 .writeback_chroma_buffer_size_kbytes = 8,
185 .writeback_chroma_line_buffer_width_pixels = 4,
186 .writeback_max_hscl_ratio = 1,
187 .writeback_max_vscl_ratio = 1,
188 .writeback_min_hscl_ratio = 1,
189 .writeback_min_vscl_ratio = 1,
190 .writeback_max_hscl_taps = 12,
191 .writeback_max_vscl_taps = 12,
192 .writeback_line_buffer_luma_buffer_size = 0,
193 .writeback_line_buffer_chroma_buffer_size = 14643,
194 .cursor_buffer_size = 8,
195 .cursor_chunk_size = 2,
196 .max_num_otg = 5,
197 .max_num_dpp = 5,
198 .max_num_wb = 1,
199 .max_dchub_pscl_bw_pix_per_clk = 4,
200 .max_pscl_lb_bw_pix_per_clk = 2,
201 .max_lb_vscl_bw_pix_per_clk = 4,
202 .max_vscl_hscl_bw_pix_per_clk = 4,
203 .max_hscl_ratio = 8,
204 .max_vscl_ratio = 8,
205 .hscl_mults = 4,
206 .vscl_mults = 4,
207 .max_hscl_taps = 8,
208 .max_vscl_taps = 8,
209 .dispclk_ramp_margin_percent = 1,
210 .underscan_factor = 1.10,
211 .min_vblank_lines = 32, //
212 .dppclk_delay_subtotal = 77, //
213 .dppclk_delay_scl_lb_only = 16,
214 .dppclk_delay_scl = 50,
215 .dppclk_delay_cnvc_formatter = 8,
216 .dppclk_delay_cnvc_cursor = 6,
217 .dispclk_delay_subtotal = 87, //
218 .dcfclk_cstate_latency = 10, // SRExitTime
219 .max_inter_dcn_tile_repeaters = 8,
220 .xfc_supported = true,
221 .xfc_fill_bw_overhead_percent = 10.0,
222 .xfc_fill_constant_bytes = 0,
223 .ptoi_supported = 0
224};
225
fb6959ae
NK
226struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc = {
227 /* Defaults that get patched on driver load from firmware. */
228 .clock_limits = {
229 {
230 .state = 0,
231 .dcfclk_mhz = 560.0,
232 .fabricclk_mhz = 560.0,
233 .dispclk_mhz = 513.0,
234 .dppclk_mhz = 513.0,
235 .phyclk_mhz = 540.0,
236 .socclk_mhz = 560.0,
237 .dscclk_mhz = 171.0,
238 .dram_speed_mts = 8960.0,
239 },
240 {
241 .state = 1,
242 .dcfclk_mhz = 694.0,
243 .fabricclk_mhz = 694.0,
244 .dispclk_mhz = 642.0,
245 .dppclk_mhz = 642.0,
246 .phyclk_mhz = 600.0,
247 .socclk_mhz = 694.0,
248 .dscclk_mhz = 214.0,
249 .dram_speed_mts = 11104.0,
250 },
251 {
252 .state = 2,
253 .dcfclk_mhz = 875.0,
254 .fabricclk_mhz = 875.0,
255 .dispclk_mhz = 734.0,
256 .dppclk_mhz = 734.0,
257 .phyclk_mhz = 810.0,
258 .socclk_mhz = 875.0,
259 .dscclk_mhz = 245.0,
260 .dram_speed_mts = 14000.0,
261 },
262 {
263 .state = 3,
264 .dcfclk_mhz = 1000.0,
265 .fabricclk_mhz = 1000.0,
266 .dispclk_mhz = 1100.0,
267 .dppclk_mhz = 1100.0,
268 .phyclk_mhz = 810.0,
269 .socclk_mhz = 1000.0,
270 .dscclk_mhz = 367.0,
271 .dram_speed_mts = 16000.0,
272 },
273 {
274 .state = 4,
275 .dcfclk_mhz = 1200.0,
276 .fabricclk_mhz = 1200.0,
277 .dispclk_mhz = 1284.0,
278 .dppclk_mhz = 1284.0,
279 .phyclk_mhz = 810.0,
280 .socclk_mhz = 1200.0,
281 .dscclk_mhz = 428.0,
282 .dram_speed_mts = 16000.0,
283 },
284 /*Extra state, no dispclk ramping*/
285 {
286 .state = 5,
287 .dcfclk_mhz = 1200.0,
288 .fabricclk_mhz = 1200.0,
289 .dispclk_mhz = 1284.0,
290 .dppclk_mhz = 1284.0,
291 .phyclk_mhz = 810.0,
292 .socclk_mhz = 1200.0,
293 .dscclk_mhz = 428.0,
294 .dram_speed_mts = 16000.0,
295 },
296 },
297 .num_states = 5,
298 .sr_exit_time_us = 8.6,
299 .sr_enter_plus_exit_time_us = 10.9,
300 .urgent_latency_us = 4.0,
301 .urgent_latency_pixel_data_only_us = 4.0,
302 .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
303 .urgent_latency_vm_data_only_us = 4.0,
304 .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
305 .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
306 .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
307 .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 40.0,
308 .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0,
309 .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
310 .max_avg_sdp_bw_use_normal_percent = 40.0,
311 .max_avg_dram_bw_use_normal_percent = 40.0,
312 .writeback_latency_us = 12.0,
313 .ideal_dram_bw_after_urgent_percent = 40.0,
314 .max_request_size_bytes = 256,
315 .dram_channel_width_bytes = 2,
316 .fabric_datapath_to_dcn_data_return_bytes = 64,
317 .dcn_downspread_percent = 0.5,
318 .downspread_percent = 0.38,
319 .dram_page_open_time_ns = 50.0,
320 .dram_rw_turnaround_time_ns = 17.5,
321 .dram_return_buffer_per_channel_bytes = 8192,
322 .round_trip_ping_latency_dcfclk_cycles = 131,
323 .urgent_out_of_order_return_per_channel_bytes = 256,
324 .channel_interleave_bytes = 256,
325 .num_banks = 8,
326 .num_chans = 16,
327 .vmm_page_size_bytes = 4096,
328 .dram_clock_change_latency_us = 404.0,
329 .dummy_pstate_latency_us = 5.0,
330 .writeback_dram_clock_change_latency_us = 23.0,
331 .return_bus_width_bytes = 64,
332 .dispclk_dppclk_vco_speed_mhz = 3850,
333 .xfc_bus_transport_time_us = 20,
334 .xfc_xbuf_latency_tolerance_us = 4,
335 .use_urgent_burst_bw = 0
336};
7ed4e635 337
675a9e38 338struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = { 0 };
7ed4e635
HW
339
340#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL
341 #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f
342 #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
343 #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f
344 #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
345 #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f
346 #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
347 #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f
348 #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
349 #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f
350 #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
351 #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f
352 #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
353 #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f
354 #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
355#endif
356
357
358enum dcn20_clk_src_array_id {
359 DCN20_CLK_SRC_PLL0,
360 DCN20_CLK_SRC_PLL1,
361 DCN20_CLK_SRC_PLL2,
362 DCN20_CLK_SRC_PLL3,
363 DCN20_CLK_SRC_PLL4,
364 DCN20_CLK_SRC_PLL5,
365 DCN20_CLK_SRC_TOTAL
366};
367
368/* begin *********************
369 * macros to expend register list macro defined in HW object header file */
370
371/* DCN */
372/* TODO awful hack. fixup dcn20_dwb.h */
373#undef BASE_INNER
374#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
375
376#define BASE(seg) BASE_INNER(seg)
377
378#define SR(reg_name)\
379 .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \
380 mm ## reg_name
381
382#define SRI(reg_name, block, id)\
383 .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
384 mm ## block ## id ## _ ## reg_name
385
386#define SRIR(var_name, reg_name, block, id)\
387 .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
388 mm ## block ## id ## _ ## reg_name
389
390#define SRII(reg_name, block, id)\
391 .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
392 mm ## block ## id ## _ ## reg_name
393
394#define DCCG_SRII(reg_name, block, id)\
395 .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
396 mm ## block ## id ## _ ## reg_name
397
398/* NBIO */
399#define NBIO_BASE_INNER(seg) \
400 NBIO_BASE__INST0_SEG ## seg
401
402#define NBIO_BASE(seg) \
403 NBIO_BASE_INNER(seg)
404
405#define NBIO_SR(reg_name)\
406 .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \
407 mm ## reg_name
408
409/* MMHUB */
410#define MMHUB_BASE_INNER(seg) \
411 MMHUB_BASE__INST0_SEG ## seg
412
413#define MMHUB_BASE(seg) \
414 MMHUB_BASE_INNER(seg)
415
416#define MMHUB_SR(reg_name)\
417 .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \
418 mmMM ## reg_name
419
420static const struct bios_registers bios_regs = {
421 NBIO_SR(BIOS_SCRATCH_3),
422 NBIO_SR(BIOS_SCRATCH_6)
423};
424
425#define clk_src_regs(index, pllid)\
426[index] = {\
427 CS_COMMON_REG_LIST_DCN2_0(index, pllid),\
428}
429
430static const struct dce110_clk_src_regs clk_src_regs[] = {
431 clk_src_regs(0, A),
432 clk_src_regs(1, B),
433 clk_src_regs(2, C),
434 clk_src_regs(3, D),
435 clk_src_regs(4, E),
436 clk_src_regs(5, F)
437};
438
439static const struct dce110_clk_src_shift cs_shift = {
440 CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
441};
442
443static const struct dce110_clk_src_mask cs_mask = {
444 CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
445};
446
447static const struct dce_dmcu_registers dmcu_regs = {
448 DMCU_DCN10_REG_LIST()
449};
450
451static const struct dce_dmcu_shift dmcu_shift = {
452 DMCU_MASK_SH_LIST_DCN10(__SHIFT)
453};
454
455static const struct dce_dmcu_mask dmcu_mask = {
456 DMCU_MASK_SH_LIST_DCN10(_MASK)
457};
d7c29549 458
7ed4e635 459static const struct dce_abm_registers abm_regs = {
d7c29549 460 ABM_DCN20_REG_LIST()
7ed4e635
HW
461};
462
463static const struct dce_abm_shift abm_shift = {
d7c29549 464 ABM_MASK_SH_LIST_DCN20(__SHIFT)
7ed4e635
HW
465};
466
467static const struct dce_abm_mask abm_mask = {
d7c29549 468 ABM_MASK_SH_LIST_DCN20(_MASK)
7ed4e635 469};
d7c29549 470
7ed4e635
HW
471#define audio_regs(id)\
472[id] = {\
473 AUD_COMMON_REG_LIST(id)\
474}
475
476static const struct dce_audio_registers audio_regs[] = {
477 audio_regs(0),
478 audio_regs(1),
479 audio_regs(2),
480 audio_regs(3),
481 audio_regs(4),
482 audio_regs(5),
483 audio_regs(6),
484};
485
486#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\
487 SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\
488 SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\
489 AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)
490
491static const struct dce_audio_shift audio_shift = {
492 DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT)
493};
494
54a9bcb0 495static const struct dce_audio_mask audio_mask = {
7ed4e635
HW
496 DCE120_AUD_COMMON_MASK_SH_LIST(_MASK)
497};
498
499#define stream_enc_regs(id)\
500[id] = {\
501 SE_DCN2_REG_LIST(id)\
502}
503
504static const struct dcn10_stream_enc_registers stream_enc_regs[] = {
505 stream_enc_regs(0),
506 stream_enc_regs(1),
507 stream_enc_regs(2),
508 stream_enc_regs(3),
509 stream_enc_regs(4),
510 stream_enc_regs(5),
511};
512
513static const struct dcn10_stream_encoder_shift se_shift = {
514 SE_COMMON_MASK_SH_LIST_DCN20(__SHIFT)
515};
516
517static const struct dcn10_stream_encoder_mask se_mask = {
518 SE_COMMON_MASK_SH_LIST_DCN20(_MASK)
519};
520
521
522#define aux_regs(id)\
523[id] = {\
524 DCN2_AUX_REG_LIST(id)\
525}
526
527static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = {
528 aux_regs(0),
529 aux_regs(1),
530 aux_regs(2),
531 aux_regs(3),
532 aux_regs(4),
533 aux_regs(5)
534};
535
536#define hpd_regs(id)\
537[id] = {\
538 HPD_REG_LIST(id)\
539}
540
541static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = {
542 hpd_regs(0),
543 hpd_regs(1),
544 hpd_regs(2),
545 hpd_regs(3),
546 hpd_regs(4),
547 hpd_regs(5)
548};
549
550#define link_regs(id, phyid)\
551[id] = {\
552 LE_DCN10_REG_LIST(id), \
553 UNIPHY_DCN2_REG_LIST(phyid), \
a771ded8 554 DPCS_DCN2_REG_LIST(id), \
7ed4e635
HW
555 SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \
556}
557
558static const struct dcn10_link_enc_registers link_enc_regs[] = {
559 link_regs(0, A),
560 link_regs(1, B),
561 link_regs(2, C),
562 link_regs(3, D),
563 link_regs(4, E),
564 link_regs(5, F)
565};
566
567static const struct dcn10_link_enc_shift le_shift = {
a771ded8
RL
568 LINK_ENCODER_MASK_SH_LIST_DCN20(__SHIFT),\
569 DPCS_DCN2_MASK_SH_LIST(__SHIFT)
7ed4e635
HW
570};
571
572static const struct dcn10_link_enc_mask le_mask = {
a771ded8
RL
573 LINK_ENCODER_MASK_SH_LIST_DCN20(_MASK),\
574 DPCS_DCN2_MASK_SH_LIST(_MASK)
7ed4e635
HW
575};
576
577#define ipp_regs(id)\
578[id] = {\
579 IPP_REG_LIST_DCN20(id),\
580}
581
582static const struct dcn10_ipp_registers ipp_regs[] = {
583 ipp_regs(0),
584 ipp_regs(1),
585 ipp_regs(2),
586 ipp_regs(3),
587 ipp_regs(4),
588 ipp_regs(5),
589};
590
591static const struct dcn10_ipp_shift ipp_shift = {
592 IPP_MASK_SH_LIST_DCN20(__SHIFT)
593};
594
595static const struct dcn10_ipp_mask ipp_mask = {
596 IPP_MASK_SH_LIST_DCN20(_MASK),
597};
598
599#define opp_regs(id)\
600[id] = {\
601 OPP_REG_LIST_DCN20(id),\
602}
603
604static const struct dcn20_opp_registers opp_regs[] = {
605 opp_regs(0),
606 opp_regs(1),
607 opp_regs(2),
608 opp_regs(3),
609 opp_regs(4),
610 opp_regs(5),
611};
612
613static const struct dcn20_opp_shift opp_shift = {
614 OPP_MASK_SH_LIST_DCN20(__SHIFT)
615};
616
617static const struct dcn20_opp_mask opp_mask = {
618 OPP_MASK_SH_LIST_DCN20(_MASK)
619};
620
621#define aux_engine_regs(id)\
622[id] = {\
623 AUX_COMMON_REG_LIST0(id), \
624 .AUXN_IMPCAL = 0, \
625 .AUXP_IMPCAL = 0, \
626 .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \
627}
628
629static const struct dce110_aux_registers aux_engine_regs[] = {
630 aux_engine_regs(0),
631 aux_engine_regs(1),
632 aux_engine_regs(2),
633 aux_engine_regs(3),
634 aux_engine_regs(4),
635 aux_engine_regs(5)
636};
637
638#define tf_regs(id)\
639[id] = {\
640 TF_REG_LIST_DCN20(id),\
641}
642
643static const struct dcn2_dpp_registers tf_regs[] = {
644 tf_regs(0),
645 tf_regs(1),
646 tf_regs(2),
647 tf_regs(3),
648 tf_regs(4),
649 tf_regs(5),
650};
651
652static const struct dcn2_dpp_shift tf_shift = {
d56eaa7c
JA
653 TF_REG_LIST_SH_MASK_DCN20(__SHIFT),
654 TF_DEBUG_REG_LIST_SH_DCN10
7ed4e635
HW
655};
656
657static const struct dcn2_dpp_mask tf_mask = {
d56eaa7c
JA
658 TF_REG_LIST_SH_MASK_DCN20(_MASK),
659 TF_DEBUG_REG_LIST_MASK_DCN10
7ed4e635
HW
660};
661
bb21290f
CL
662#define dwbc_regs_dcn2(id)\
663[id] = {\
664 DWBC_COMMON_REG_LIST_DCN2_0(id),\
665 }
666
667static const struct dcn20_dwbc_registers dwbc20_regs[] = {
668 dwbc_regs_dcn2(0),
669};
670
671static const struct dcn20_dwbc_shift dwbc20_shift = {
672 DWBC_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
673};
674
675static const struct dcn20_dwbc_mask dwbc20_mask = {
676 DWBC_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
677};
678
679#define mcif_wb_regs_dcn2(id)\
680[id] = {\
681 MCIF_WB_COMMON_REG_LIST_DCN2_0(id),\
682 }
683
684static const struct dcn20_mmhubbub_registers mcif_wb20_regs[] = {
685 mcif_wb_regs_dcn2(0),
686};
687
688static const struct dcn20_mmhubbub_shift mcif_wb20_shift = {
689 MCIF_WB_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
690};
691
692static const struct dcn20_mmhubbub_mask mcif_wb20_mask = {
693 MCIF_WB_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
694};
695
7ed4e635
HW
696static const struct dcn20_mpc_registers mpc_regs = {
697 MPC_REG_LIST_DCN2_0(0),
698 MPC_REG_LIST_DCN2_0(1),
699 MPC_REG_LIST_DCN2_0(2),
700 MPC_REG_LIST_DCN2_0(3),
701 MPC_REG_LIST_DCN2_0(4),
702 MPC_REG_LIST_DCN2_0(5),
703 MPC_OUT_MUX_REG_LIST_DCN2_0(0),
704 MPC_OUT_MUX_REG_LIST_DCN2_0(1),
705 MPC_OUT_MUX_REG_LIST_DCN2_0(2),
706 MPC_OUT_MUX_REG_LIST_DCN2_0(3),
707 MPC_OUT_MUX_REG_LIST_DCN2_0(4),
708 MPC_OUT_MUX_REG_LIST_DCN2_0(5),
e8027e08 709 MPC_DBG_REG_LIST_DCN2_0()
7ed4e635
HW
710};
711
712static const struct dcn20_mpc_shift mpc_shift = {
713 MPC_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
714};
715
716static const struct dcn20_mpc_mask mpc_mask = {
717 MPC_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
718};
719
720#define tg_regs(id)\
721[id] = {TG_COMMON_REG_LIST_DCN2_0(id)}
722
723
724static const struct dcn_optc_registers tg_regs[] = {
725 tg_regs(0),
726 tg_regs(1),
727 tg_regs(2),
728 tg_regs(3),
729 tg_regs(4),
730 tg_regs(5)
731};
732
733static const struct dcn_optc_shift tg_shift = {
734 TG_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
735};
736
737static const struct dcn_optc_mask tg_mask = {
738 TG_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
739};
740
741#define hubp_regs(id)\
742[id] = {\
743 HUBP_REG_LIST_DCN20(id)\
744}
745
746static const struct dcn_hubp2_registers hubp_regs[] = {
747 hubp_regs(0),
748 hubp_regs(1),
749 hubp_regs(2),
750 hubp_regs(3),
751 hubp_regs(4),
752 hubp_regs(5)
753};
754
755static const struct dcn_hubp2_shift hubp_shift = {
756 HUBP_MASK_SH_LIST_DCN20(__SHIFT)
757};
758
759static const struct dcn_hubp2_mask hubp_mask = {
760 HUBP_MASK_SH_LIST_DCN20(_MASK)
761};
762
763static const struct dcn_hubbub_registers hubbub_reg = {
764 HUBBUB_REG_LIST_DCN20(0)
765};
766
767static const struct dcn_hubbub_shift hubbub_shift = {
768 HUBBUB_MASK_SH_LIST_DCN20(__SHIFT)
769};
770
771static const struct dcn_hubbub_mask hubbub_mask = {
772 HUBBUB_MASK_SH_LIST_DCN20(_MASK)
773};
774
775#define vmid_regs(id)\
776[id] = {\
777 DCN20_VMID_REG_LIST(id)\
778}
779
780static const struct dcn_vmid_registers vmid_regs[] = {
781 vmid_regs(0),
782 vmid_regs(1),
783 vmid_regs(2),
784 vmid_regs(3),
785 vmid_regs(4),
786 vmid_regs(5),
787 vmid_regs(6),
788 vmid_regs(7),
789 vmid_regs(8),
790 vmid_regs(9),
791 vmid_regs(10),
792 vmid_regs(11),
793 vmid_regs(12),
794 vmid_regs(13),
795 vmid_regs(14),
796 vmid_regs(15)
797};
798
799static const struct dcn20_vmid_shift vmid_shifts = {
800 DCN20_VMID_MASK_SH_LIST(__SHIFT)
801};
802
803static const struct dcn20_vmid_mask vmid_masks = {
804 DCN20_VMID_MASK_SH_LIST(_MASK)
805};
806
8276dd87 807static const struct dce110_aux_registers_shift aux_shift = {
808 DCN_AUX_MASK_SH_LIST(__SHIFT)
809};
810
811static const struct dce110_aux_registers_mask aux_mask = {
812 DCN_AUX_MASK_SH_LIST(_MASK)
813};
814
bf7f5ac3
YMM
815static int map_transmitter_id_to_phy_instance(
816 enum transmitter transmitter)
817{
818 switch (transmitter) {
819 case TRANSMITTER_UNIPHY_A:
820 return 0;
821 break;
822 case TRANSMITTER_UNIPHY_B:
823 return 1;
824 break;
825 case TRANSMITTER_UNIPHY_C:
826 return 2;
827 break;
828 case TRANSMITTER_UNIPHY_D:
829 return 3;
830 break;
831 case TRANSMITTER_UNIPHY_E:
832 return 4;
833 break;
834 case TRANSMITTER_UNIPHY_F:
835 return 5;
836 break;
837 default:
838 ASSERT(0);
839 return 0;
840 }
841}
8276dd87 842
97bda032
HW
843#define dsc_regsDCN20(id)\
844[id] = {\
845 DSC_REG_LIST_DCN20(id)\
846}
847
848static const struct dcn20_dsc_registers dsc_regs[] = {
849 dsc_regsDCN20(0),
850 dsc_regsDCN20(1),
851 dsc_regsDCN20(2),
852 dsc_regsDCN20(3),
853 dsc_regsDCN20(4),
854 dsc_regsDCN20(5)
855};
856
857static const struct dcn20_dsc_shift dsc_shift = {
858 DSC_REG_LIST_SH_MASK_DCN20(__SHIFT)
859};
860
861static const struct dcn20_dsc_mask dsc_mask = {
862 DSC_REG_LIST_SH_MASK_DCN20(_MASK)
863};
7ed4e635
HW
864
865static const struct dccg_registers dccg_regs = {
866 DCCG_REG_LIST_DCN2()
867};
868
869static const struct dccg_shift dccg_shift = {
870 DCCG_MASK_SH_LIST_DCN2(__SHIFT)
871};
872
873static const struct dccg_mask dccg_mask = {
874 DCCG_MASK_SH_LIST_DCN2(_MASK)
875};
876
877static const struct resource_caps res_cap_nv10 = {
878 .num_timing_generator = 6,
879 .num_opp = 6,
880 .num_video_plane = 6,
881 .num_audio = 7,
882 .num_stream_encoder = 6,
883 .num_pll = 6,
9cbee6ef 884 .num_dwb = 1,
7ed4e635
HW
885 .num_ddc = 6,
886 .num_vmid = 16,
97bda032 887 .num_dsc = 6,
7ed4e635
HW
888};
889
890static const struct dc_plane_cap plane_cap = {
891 .type = DC_PLANE_TYPE_DCN_UNIVERSAL,
892 .blends_with_above = true,
893 .blends_with_below = true,
7ed4e635 894 .per_pixel_alpha = true,
5b1b2f20
AD
895
896 .pixel_format_support = {
897 .argb8888 = true,
898 .nv12 = true,
899 .fp16 = true
900 },
901
902 .max_upscale_factor = {
903 .argb8888 = 16000,
904 .nv12 = 16000,
905 .fp16 = 1
906 },
907
908 .max_downscale_factor = {
909 .argb8888 = 250,
910 .nv12 = 250,
911 .fp16 = 1
912 }
7ed4e635 913};
2ebe1773
BL
914static const struct resource_caps res_cap_nv14 = {
915 .num_timing_generator = 5,
916 .num_opp = 5,
917 .num_video_plane = 5,
918 .num_audio = 6,
919 .num_stream_encoder = 5,
920 .num_pll = 5,
80df905d 921 .num_dwb = 1,
2ebe1773 922 .num_ddc = 5,
6bb27085
ZL
923 .num_vmid = 16,
924 .num_dsc = 5,
2ebe1773 925};
7ed4e635
HW
926
927static const struct dc_debug_options debug_defaults_drv = {
928 .disable_dmcu = true,
929 .force_abm_enable = false,
930 .timing_trace = false,
931 .clock_trace = true,
932 .disable_pplib_clock_request = true,
933 .pipe_split_policy = MPC_SPLIT_DYNAMIC,
4d25a0d5 934 .force_single_disp_pipe_split = false,
7ed4e635
HW
935 .disable_dcc = DCC_ENABLE,
936 .vsr_support = true,
937 .performance_trace = false,
938 .max_downscale_src_width = 5120,/*upto 5K*/
939 .disable_pplib_wm_range = false,
940 .scl_reset_length10 = true,
9e14d4f1 941 .sanity_checks = false,
7ed4e635 942 .disable_tri_buf = true,
1a7d296d 943 .underflow_assert_delay_us = 0xFFFFFFFF,
7ed4e635
HW
944};
945
946static const struct dc_debug_options debug_defaults_diags = {
947 .disable_dmcu = true,
948 .force_abm_enable = false,
949 .timing_trace = true,
950 .clock_trace = true,
951 .disable_dpp_power_gate = true,
952 .disable_hubp_power_gate = true,
953 .disable_clock_gate = true,
954 .disable_pplib_clock_request = true,
955 .disable_pplib_wm_range = true,
956 .disable_stutter = true,
957 .scl_reset_length10 = true,
1a7d296d 958 .underflow_assert_delay_us = 0xFFFFFFFF,
7ed4e635
HW
959};
960
961void dcn20_dpp_destroy(struct dpp **dpp)
962{
963 kfree(TO_DCN20_DPP(*dpp));
964 *dpp = NULL;
965}
966
967struct dpp *dcn20_dpp_create(
968 struct dc_context *ctx,
969 uint32_t inst)
970{
971 struct dcn20_dpp *dpp =
972 kzalloc(sizeof(struct dcn20_dpp), GFP_KERNEL);
973
974 if (!dpp)
975 return NULL;
976
977 if (dpp2_construct(dpp, ctx, inst,
978 &tf_regs[inst], &tf_shift, &tf_mask))
979 return &dpp->base;
980
981 BREAK_TO_DEBUGGER();
982 kfree(dpp);
983 return NULL;
984}
985
986struct input_pixel_processor *dcn20_ipp_create(
987 struct dc_context *ctx, uint32_t inst)
988{
989 struct dcn10_ipp *ipp =
990 kzalloc(sizeof(struct dcn10_ipp), GFP_KERNEL);
991
992 if (!ipp) {
993 BREAK_TO_DEBUGGER();
994 return NULL;
995 }
996
997 dcn20_ipp_construct(ipp, ctx, inst,
998 &ipp_regs[inst], &ipp_shift, &ipp_mask);
999 return &ipp->base;
1000}
1001
1002
1003struct output_pixel_processor *dcn20_opp_create(
1004 struct dc_context *ctx, uint32_t inst)
1005{
1006 struct dcn20_opp *opp =
1007 kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL);
1008
1009 if (!opp) {
1010 BREAK_TO_DEBUGGER();
1011 return NULL;
1012 }
1013
1014 dcn20_opp_construct(opp, ctx, inst,
1015 &opp_regs[inst], &opp_shift, &opp_mask);
1016 return &opp->base;
1017}
1018
1019struct dce_aux *dcn20_aux_engine_create(
1020 struct dc_context *ctx,
1021 uint32_t inst)
1022{
1023 struct aux_engine_dce110 *aux_engine =
1024 kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL);
1025
1026 if (!aux_engine)
1027 return NULL;
1028
1029 dce110_aux_engine_construct(aux_engine, ctx, inst,
1030 SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
8276dd87 1031 &aux_engine_regs[inst],
1032 &aux_mask,
f6040a43 1033 &aux_shift,
1034 ctx->dc->caps.extended_aux_timeout_support);
7ed4e635
HW
1035
1036 return &aux_engine->base;
1037}
1038#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) }
1039
1040static const struct dce_i2c_registers i2c_hw_regs[] = {
1041 i2c_inst_regs(1),
1042 i2c_inst_regs(2),
1043 i2c_inst_regs(3),
1044 i2c_inst_regs(4),
1045 i2c_inst_regs(5),
1046 i2c_inst_regs(6),
1047};
1048
1049static const struct dce_i2c_shift i2c_shifts = {
1050 I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT)
1051};
1052
1053static const struct dce_i2c_mask i2c_masks = {
1054 I2C_COMMON_MASK_SH_LIST_DCN2(_MASK)
1055};
1056
1057struct dce_i2c_hw *dcn20_i2c_hw_create(
1058 struct dc_context *ctx,
1059 uint32_t inst)
1060{
1061 struct dce_i2c_hw *dce_i2c_hw =
1062 kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL);
1063
1064 if (!dce_i2c_hw)
1065 return NULL;
1066
1067 dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst,
1068 &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks);
1069
1070 return dce_i2c_hw;
1071}
1072struct mpc *dcn20_mpc_create(struct dc_context *ctx)
1073{
1074 struct dcn20_mpc *mpc20 = kzalloc(sizeof(struct dcn20_mpc),
1075 GFP_KERNEL);
1076
1077 if (!mpc20)
1078 return NULL;
1079
1080 dcn20_mpc_construct(mpc20, ctx,
1081 &mpc_regs,
1082 &mpc_shift,
1083 &mpc_mask,
1084 6);
1085
1086 return &mpc20->base;
1087}
1088
1089struct hubbub *dcn20_hubbub_create(struct dc_context *ctx)
1090{
1091 int i;
1092 struct dcn20_hubbub *hubbub = kzalloc(sizeof(struct dcn20_hubbub),
1093 GFP_KERNEL);
1094
1095 if (!hubbub)
1096 return NULL;
1097
1098 hubbub2_construct(hubbub, ctx,
1099 &hubbub_reg,
1100 &hubbub_shift,
1101 &hubbub_mask);
1102
1103 for (i = 0; i < res_cap_nv10.num_vmid; i++) {
1104 struct dcn20_vmid *vmid = &hubbub->vmid[i];
1105
1106 vmid->ctx = ctx;
1107
1108 vmid->regs = &vmid_regs[i];
1109 vmid->shifts = &vmid_shifts;
1110 vmid->masks = &vmid_masks;
1111 }
1112
1113 return &hubbub->base;
1114}
1115
1116struct timing_generator *dcn20_timing_generator_create(
1117 struct dc_context *ctx,
1118 uint32_t instance)
1119{
1120 struct optc *tgn10 =
1121 kzalloc(sizeof(struct optc), GFP_KERNEL);
1122
1123 if (!tgn10)
1124 return NULL;
1125
1126 tgn10->base.inst = instance;
1127 tgn10->base.ctx = ctx;
1128
1129 tgn10->tg_regs = &tg_regs[instance];
1130 tgn10->tg_shift = &tg_shift;
1131 tgn10->tg_mask = &tg_mask;
1132
1133 dcn20_timing_generator_init(tgn10);
1134
1135 return &tgn10->base;
1136}
1137
1138static const struct encoder_feature_support link_enc_feature = {
1139 .max_hdmi_deep_color = COLOR_DEPTH_121212,
1140 .max_hdmi_pixel_clock = 600000,
1141 .hdmi_ycbcr420_supported = true,
1142 .dp_ycbcr420_supported = true,
1143 .flags.bits.IS_HBR2_CAPABLE = true,
1144 .flags.bits.IS_HBR3_CAPABLE = true,
1145 .flags.bits.IS_TPS3_CAPABLE = true,
1146 .flags.bits.IS_TPS4_CAPABLE = true
1147};
1148
1149struct link_encoder *dcn20_link_encoder_create(
1150 const struct encoder_init_data *enc_init_data)
1151{
1152 struct dcn20_link_encoder *enc20 =
1153 kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);
bf7f5ac3 1154 int link_regs_id;
7ed4e635
HW
1155
1156 if (!enc20)
1157 return NULL;
1158
bf7f5ac3
YMM
1159 link_regs_id =
1160 map_transmitter_id_to_phy_instance(enc_init_data->transmitter);
1161
7ed4e635
HW
1162 dcn20_link_encoder_construct(enc20,
1163 enc_init_data,
1164 &link_enc_feature,
bf7f5ac3 1165 &link_enc_regs[link_regs_id],
7ed4e635
HW
1166 &link_enc_aux_regs[enc_init_data->channel - 1],
1167 &link_enc_hpd_regs[enc_init_data->hpd_source],
1168 &le_shift,
1169 &le_mask);
1170
1171 return &enc20->enc10.base;
1172}
1173
1174struct clock_source *dcn20_clock_source_create(
1175 struct dc_context *ctx,
1176 struct dc_bios *bios,
1177 enum clock_source_id id,
1178 const struct dce110_clk_src_regs *regs,
1179 bool dp_clk_src)
1180{
1181 struct dce110_clk_src *clk_src =
1182 kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL);
1183
1184 if (!clk_src)
1185 return NULL;
1186
1187 if (dcn20_clk_src_construct(clk_src, ctx, bios, id,
1188 regs, &cs_shift, &cs_mask)) {
1189 clk_src->base.dp_clk_src = dp_clk_src;
1190 return &clk_src->base;
1191 }
1192
cabe144b 1193 kfree(clk_src);
7ed4e635
HW
1194 BREAK_TO_DEBUGGER();
1195 return NULL;
1196}
1197
1198static void read_dce_straps(
1199 struct dc_context *ctx,
1200 struct resource_straps *straps)
1201{
1202 generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX),
1203 FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio);
1204}
1205
1206static struct audio *dcn20_create_audio(
1207 struct dc_context *ctx, unsigned int inst)
1208{
1209 return dce_audio_create(ctx, inst,
1210 &audio_regs[inst], &audio_shift, &audio_mask);
1211}
1212
1213struct stream_encoder *dcn20_stream_encoder_create(
1214 enum engine_id eng_id,
1215 struct dc_context *ctx)
1216{
1217 struct dcn10_stream_encoder *enc1 =
1218 kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
1219
1220 if (!enc1)
1221 return NULL;
1222
9fd4c2d7
ZL
1223 if (ASICREV_IS_NAVI14_M(ctx->asic_id.hw_internal_rev)) {
1224 if (eng_id >= ENGINE_ID_DIGD)
1225 eng_id++;
1226 }
1227
7ed4e635
HW
1228 dcn20_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id,
1229 &stream_enc_regs[eng_id],
1230 &se_shift, &se_mask);
1231
1232 return &enc1->base;
1233}
1234
1235static const struct dce_hwseq_registers hwseq_reg = {
1236 HWSEQ_DCN2_REG_LIST()
1237};
1238
1239static const struct dce_hwseq_shift hwseq_shift = {
1240 HWSEQ_DCN2_MASK_SH_LIST(__SHIFT)
1241};
1242
1243static const struct dce_hwseq_mask hwseq_mask = {
1244 HWSEQ_DCN2_MASK_SH_LIST(_MASK)
1245};
1246
1247struct dce_hwseq *dcn20_hwseq_create(
1248 struct dc_context *ctx)
1249{
1250 struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);
1251
1252 if (hws) {
1253 hws->ctx = ctx;
1254 hws->regs = &hwseq_reg;
1255 hws->shifts = &hwseq_shift;
1256 hws->masks = &hwseq_mask;
1257 }
1258 return hws;
1259}
1260
1261static const struct resource_create_funcs res_create_funcs = {
1262 .read_dce_straps = read_dce_straps,
1263 .create_audio = dcn20_create_audio,
1264 .create_stream_encoder = dcn20_stream_encoder_create,
1265 .create_hwseq = dcn20_hwseq_create,
1266};
1267
1268static const struct resource_create_funcs res_create_maximus_funcs = {
1269 .read_dce_straps = NULL,
1270 .create_audio = NULL,
1271 .create_stream_encoder = NULL,
1272 .create_hwseq = dcn20_hwseq_create,
1273};
1274
44e149bb
AD
1275static void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu);
1276
7ed4e635
HW
1277void dcn20_clock_source_destroy(struct clock_source **clk_src)
1278{
1279 kfree(TO_DCE110_CLK_SRC(*clk_src));
1280 *clk_src = NULL;
1281}
1282
97bda032
HW
1283
1284struct display_stream_compressor *dcn20_dsc_create(
1285 struct dc_context *ctx, uint32_t inst)
1286{
1287 struct dcn20_dsc *dsc =
1288 kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL);
1289
1290 if (!dsc) {
1291 BREAK_TO_DEBUGGER();
1292 return NULL;
1293 }
1294
1295 dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask);
1296 return &dsc->base;
1297}
1298
1299void dcn20_dsc_destroy(struct display_stream_compressor **dsc)
1300{
1301 kfree(container_of(*dsc, struct dcn20_dsc, base));
1302 *dsc = NULL;
1303}
1304
7ed4e635 1305
d9e32672 1306static void dcn20_resource_destruct(struct dcn20_resource_pool *pool)
7ed4e635
HW
1307{
1308 unsigned int i;
1309
1310 for (i = 0; i < pool->base.stream_enc_count; i++) {
1311 if (pool->base.stream_enc[i] != NULL) {
1312 kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i]));
1313 pool->base.stream_enc[i] = NULL;
1314 }
1315 }
1316
97bda032
HW
1317 for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
1318 if (pool->base.dscs[i] != NULL)
1319 dcn20_dsc_destroy(&pool->base.dscs[i]);
1320 }
7ed4e635
HW
1321
1322 if (pool->base.mpc != NULL) {
1323 kfree(TO_DCN20_MPC(pool->base.mpc));
1324 pool->base.mpc = NULL;
1325 }
1326 if (pool->base.hubbub != NULL) {
1327 kfree(pool->base.hubbub);
1328 pool->base.hubbub = NULL;
1329 }
1330 for (i = 0; i < pool->base.pipe_count; i++) {
1331 if (pool->base.dpps[i] != NULL)
1332 dcn20_dpp_destroy(&pool->base.dpps[i]);
1333
1334 if (pool->base.ipps[i] != NULL)
1335 pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]);
1336
1337 if (pool->base.hubps[i] != NULL) {
1338 kfree(TO_DCN20_HUBP(pool->base.hubps[i]));
1339 pool->base.hubps[i] = NULL;
1340 }
1341
1342 if (pool->base.irqs != NULL) {
1343 dal_irq_service_destroy(&pool->base.irqs);
1344 }
1345 }
1346
1347 for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
1348 if (pool->base.engines[i] != NULL)
1349 dce110_engine_destroy(&pool->base.engines[i]);
1350 if (pool->base.hw_i2cs[i] != NULL) {
1351 kfree(pool->base.hw_i2cs[i]);
1352 pool->base.hw_i2cs[i] = NULL;
1353 }
1354 if (pool->base.sw_i2cs[i] != NULL) {
1355 kfree(pool->base.sw_i2cs[i]);
1356 pool->base.sw_i2cs[i] = NULL;
1357 }
1358 }
1359
1360 for (i = 0; i < pool->base.res_cap->num_opp; i++) {
1361 if (pool->base.opps[i] != NULL)
1362 pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);
1363 }
1364
1365 for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
1366 if (pool->base.timing_generators[i] != NULL) {
1367 kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i]));
1368 pool->base.timing_generators[i] = NULL;
1369 }
1370 }
1371
bb21290f
CL
1372 for (i = 0; i < pool->base.res_cap->num_dwb; i++) {
1373 if (pool->base.dwbc[i] != NULL) {
1374 kfree(TO_DCN20_DWBC(pool->base.dwbc[i]));
1375 pool->base.dwbc[i] = NULL;
1376 }
1377 if (pool->base.mcif_wb[i] != NULL) {
1378 kfree(TO_DCN20_MMHUBBUB(pool->base.mcif_wb[i]));
1379 pool->base.mcif_wb[i] = NULL;
1380 }
1381 }
1382
7ed4e635
HW
1383 for (i = 0; i < pool->base.audio_count; i++) {
1384 if (pool->base.audios[i])
1385 dce_aud_destroy(&pool->base.audios[i]);
1386 }
1387
1388 for (i = 0; i < pool->base.clk_src_count; i++) {
1389 if (pool->base.clock_sources[i] != NULL) {
1390 dcn20_clock_source_destroy(&pool->base.clock_sources[i]);
1391 pool->base.clock_sources[i] = NULL;
1392 }
1393 }
1394
1395 if (pool->base.dp_clock_source != NULL) {
1396 dcn20_clock_source_destroy(&pool->base.dp_clock_source);
1397 pool->base.dp_clock_source = NULL;
1398 }
1399
1400
1401 if (pool->base.abm != NULL)
1402 dce_abm_destroy(&pool->base.abm);
1403
1404 if (pool->base.dmcu != NULL)
1405 dce_dmcu_destroy(&pool->base.dmcu);
1406
1407 if (pool->base.dccg != NULL)
1408 dcn_dccg_destroy(&pool->base.dccg);
1409
1410 if (pool->base.pp_smu != NULL)
1411 dcn20_pp_smu_destroy(&pool->base.pp_smu);
1412
d9a07577
JL
1413 if (pool->base.oem_device != NULL)
1414 dal_ddc_service_destroy(&pool->base.oem_device);
7ed4e635
HW
1415}
1416
1417struct hubp *dcn20_hubp_create(
1418 struct dc_context *ctx,
1419 uint32_t inst)
1420{
1421 struct dcn20_hubp *hubp2 =
1422 kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL);
1423
1424 if (!hubp2)
1425 return NULL;
1426
1427 if (hubp2_construct(hubp2, ctx, inst,
1428 &hubp_regs[inst], &hubp_shift, &hubp_mask))
1429 return &hubp2->base;
1430
1431 BREAK_TO_DEBUGGER();
1432 kfree(hubp2);
1433 return NULL;
1434}
1435
1436static void get_pixel_clock_parameters(
1437 struct pipe_ctx *pipe_ctx,
1438 struct pixel_clk_params *pixel_clk_params)
1439{
1440 const struct dc_stream_state *stream = pipe_ctx->stream;
b1f6d01c
DL
1441 struct pipe_ctx *odm_pipe;
1442 int opp_cnt = 1;
1443
1444 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
1445 opp_cnt++;
7ed4e635
HW
1446
1447 pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz;
1448 pixel_clk_params->encoder_object_id = stream->link->link_enc->id;
1449 pixel_clk_params->signal_type = pipe_ctx->stream->signal;
1450 pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1;
1451 /* TODO: un-hardcode*/
1452 pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
1453 LINK_RATE_REF_FREQ_IN_KHZ;
1454 pixel_clk_params->flags.ENABLE_SS = 0;
1455 pixel_clk_params->color_depth =
1456 stream->timing.display_color_depth;
1457 pixel_clk_params->flags.DISPLAY_BLANKED = 1;
1458 pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding;
1459
1460 if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
1461 pixel_clk_params->color_depth = COLOR_DEPTH_888;
1462
b1f6d01c
DL
1463 if (opp_cnt == 4)
1464 pixel_clk_params->requested_pix_clk_100hz /= 4;
78c77382 1465 else if (optc2_is_two_pixels_per_containter(&stream->timing) || opp_cnt == 2)
7ed4e635
HW
1466 pixel_clk_params->requested_pix_clk_100hz /= 2;
1467
1468 if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
1469 pixel_clk_params->requested_pix_clk_100hz *= 2;
1470
1471}
1472
1473static void build_clamping_params(struct dc_stream_state *stream)
1474{
1475 stream->clamping.clamping_level = CLAMPING_FULL_RANGE;
1476 stream->clamping.c_depth = stream->timing.display_color_depth;
1477 stream->clamping.pixel_encoding = stream->timing.pixel_encoding;
1478}
1479
1480static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx)
1481{
1482
1483 get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params);
1484
1485 pipe_ctx->clock_source->funcs->get_pix_clk_dividers(
1486 pipe_ctx->clock_source,
1487 &pipe_ctx->stream_res.pix_clk_params,
1488 &pipe_ctx->pll_settings);
1489
1490 pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding;
1491
1492 resource_build_bit_depth_reduction_params(pipe_ctx->stream,
1493 &pipe_ctx->stream->bit_depth_params);
1494 build_clamping_params(pipe_ctx->stream);
1495
1496 return DC_OK;
1497}
1498
1499enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream)
1500{
1501 enum dc_status status = DC_OK;
1502 struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream);
1503
1504 /*TODO Seems unneeded anymore */
1505 /* if (old_context && resource_is_stream_unchanged(old_context, stream)) {
1506 if (stream != NULL && old_context->streams[i] != NULL) {
1507 todo: shouldn't have to copy missing parameter here
1508 resource_build_bit_depth_reduction_params(stream,
1509 &stream->bit_depth_params);
1510 stream->clamping.pixel_encoding =
1511 stream->timing.pixel_encoding;
1512
1513 resource_build_bit_depth_reduction_params(stream,
1514 &stream->bit_depth_params);
1515 build_clamping_params(stream);
1516
1517 continue;
1518 }
1519 }
1520 */
1521
1522 if (!pipe_ctx)
1523 return DC_ERROR_UNEXPECTED;
1524
1525
1526 status = build_pipe_hw_param(pipe_ctx);
1527
1528 return status;
1529}
1530
97bda032 1531
c9ae6e16
NC
1532static void acquire_dsc(struct resource_context *res_ctx,
1533 const struct resource_pool *pool,
eab4bb97
NC
1534 struct display_stream_compressor **dsc,
1535 int pipe_idx)
97bda032
HW
1536{
1537 int i;
c9ae6e16
NC
1538
1539 ASSERT(*dsc == NULL);
1540 *dsc = NULL;
97bda032 1541
eab4bb97
NC
1542 if (pool->res_cap->num_dsc == pool->res_cap->num_opp) {
1543 *dsc = pool->dscs[pipe_idx];
1544 res_ctx->is_dsc_acquired[pipe_idx] = true;
1545 return;
1546 }
1547
97bda032
HW
1548 /* Find first free DSC */
1549 for (i = 0; i < pool->res_cap->num_dsc; i++)
1550 if (!res_ctx->is_dsc_acquired[i]) {
c9ae6e16 1551 *dsc = pool->dscs[i];
97bda032
HW
1552 res_ctx->is_dsc_acquired[i] = true;
1553 break;
1554 }
97bda032
HW
1555}
1556
1557static void release_dsc(struct resource_context *res_ctx,
1558 const struct resource_pool *pool,
c9ae6e16 1559 struct display_stream_compressor **dsc)
97bda032
HW
1560{
1561 int i;
1562
1563 for (i = 0; i < pool->res_cap->num_dsc; i++)
c9ae6e16 1564 if (pool->dscs[i] == *dsc) {
97bda032 1565 res_ctx->is_dsc_acquired[i] = false;
c9ae6e16 1566 *dsc = NULL;
97bda032
HW
1567 break;
1568 }
1569}
1570
7ed4e635 1571
7ed4e635 1572
8c20a1ed 1573enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc,
c9ae6e16
NC
1574 struct dc_state *dc_ctx,
1575 struct dc_stream_state *dc_stream)
1576{
1577 enum dc_status result = DC_OK;
1578 int i;
1579 const struct resource_pool *pool = dc->res_pool;
97bda032 1580
c9ae6e16
NC
1581 /* Get a DSC if required and available */
1582 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1583 struct pipe_ctx *pipe_ctx = &dc_ctx->res_ctx.pipe_ctx[i];
97bda032 1584
c9ae6e16
NC
1585 if (pipe_ctx->stream != dc_stream)
1586 continue;
97bda032 1587
8c20a1ed
DF
1588 if (pipe_ctx->stream_res.dsc)
1589 continue;
1590
eab4bb97 1591 acquire_dsc(&dc_ctx->res_ctx, pool, &pipe_ctx->stream_res.dsc, i);
97bda032 1592
c9ae6e16
NC
1593 /* The number of DSCs can be less than the number of pipes */
1594 if (!pipe_ctx->stream_res.dsc) {
c9ae6e16 1595 result = DC_NO_DSC_RESOURCE;
97bda032 1596 }
7ed4e635 1597
c9ae6e16
NC
1598 break;
1599 }
7ed4e635
HW
1600
1601 return result;
1602}
1603
1604
ba32c50f 1605static enum dc_status remove_dsc_from_stream_resource(struct dc *dc,
c9ae6e16
NC
1606 struct dc_state *new_ctx,
1607 struct dc_stream_state *dc_stream)
7ed4e635
HW
1608{
1609 struct pipe_ctx *pipe_ctx = NULL;
1610 int i;
1611
7ed4e635
HW
1612 for (i = 0; i < MAX_PIPES; i++) {
1613 if (new_ctx->res_ctx.pipe_ctx[i].stream == dc_stream && !new_ctx->res_ctx.pipe_ctx[i].top_pipe) {
1614 pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];
b1f6d01c
DL
1615
1616 if (pipe_ctx->stream_res.dsc)
1617 release_dsc(&new_ctx->res_ctx, dc->res_pool, &pipe_ctx->stream_res.dsc);
7ed4e635
HW
1618 }
1619 }
1620
1621 if (!pipe_ctx)
1622 return DC_ERROR_UNEXPECTED;
b1f6d01c
DL
1623 else
1624 return DC_OK;
7ed4e635 1625}
c9ae6e16
NC
1626
1627
1628enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream)
1629{
1630 enum dc_status result = DC_ERROR_UNEXPECTED;
1631
1632 result = resource_map_pool_resources(dc, new_ctx, dc_stream);
1633
1634 if (result == DC_OK)
1635 result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream);
1636
c9ae6e16
NC
1637 /* Get a DSC if required and available */
1638 if (result == DC_OK && dc_stream->timing.flags.DSC)
8c20a1ed 1639 result = dcn20_add_dsc_to_stream_resource(dc, new_ctx, dc_stream);
c9ae6e16
NC
1640
1641 if (result == DC_OK)
1642 result = dcn20_build_mapped_resource(dc, new_ctx, dc_stream);
1643
1644 return result;
1645}
1646
1647
1648enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream)
1649{
1650 enum dc_status result = DC_OK;
1651
ba32c50f 1652 result = remove_dsc_from_stream_resource(dc, new_ctx, dc_stream);
c9ae6e16
NC
1653
1654 return result;
1655}
7ed4e635
HW
1656
1657
1658static void swizzle_to_dml_params(
1659 enum swizzle_mode_values swizzle,
1660 unsigned int *sw_mode)
1661{
1662 switch (swizzle) {
1663 case DC_SW_LINEAR:
1664 *sw_mode = dm_sw_linear;
1665 break;
1666 case DC_SW_4KB_S:
1667 *sw_mode = dm_sw_4kb_s;
1668 break;
1669 case DC_SW_4KB_S_X:
1670 *sw_mode = dm_sw_4kb_s_x;
1671 break;
1672 case DC_SW_4KB_D:
1673 *sw_mode = dm_sw_4kb_d;
1674 break;
1675 case DC_SW_4KB_D_X:
1676 *sw_mode = dm_sw_4kb_d_x;
1677 break;
1678 case DC_SW_64KB_S:
1679 *sw_mode = dm_sw_64kb_s;
1680 break;
1681 case DC_SW_64KB_S_X:
1682 *sw_mode = dm_sw_64kb_s_x;
1683 break;
1684 case DC_SW_64KB_S_T:
1685 *sw_mode = dm_sw_64kb_s_t;
1686 break;
1687 case DC_SW_64KB_D:
1688 *sw_mode = dm_sw_64kb_d;
1689 break;
1690 case DC_SW_64KB_D_X:
1691 *sw_mode = dm_sw_64kb_d_x;
1692 break;
1693 case DC_SW_64KB_D_T:
1694 *sw_mode = dm_sw_64kb_d_t;
1695 break;
1696 case DC_SW_64KB_R_X:
1697 *sw_mode = dm_sw_64kb_r_x;
1698 break;
1699 case DC_SW_VAR_S:
1700 *sw_mode = dm_sw_var_s;
1701 break;
1702 case DC_SW_VAR_S_X:
1703 *sw_mode = dm_sw_var_s_x;
1704 break;
1705 case DC_SW_VAR_D:
1706 *sw_mode = dm_sw_var_d;
1707 break;
1708 case DC_SW_VAR_D_X:
1709 *sw_mode = dm_sw_var_d_x;
1710 break;
1711
1712 default:
1713 ASSERT(0); /* Not supported */
1714 break;
1715 }
1716}
1717
b6bfba6c 1718bool dcn20_split_stream_for_odm(
b1f6d01c
DL
1719 struct resource_context *res_ctx,
1720 const struct resource_pool *pool,
1721 struct pipe_ctx *prev_odm_pipe,
1722 struct pipe_ctx *next_odm_pipe)
1723{
1724 int pipe_idx = next_odm_pipe->pipe_idx;
b1f6d01c
DL
1725
1726 *next_odm_pipe = *prev_odm_pipe;
b1f6d01c
DL
1727
1728 next_odm_pipe->pipe_idx = pipe_idx;
1729 next_odm_pipe->plane_res.mi = pool->mis[next_odm_pipe->pipe_idx];
1730 next_odm_pipe->plane_res.hubp = pool->hubps[next_odm_pipe->pipe_idx];
1731 next_odm_pipe->plane_res.ipp = pool->ipps[next_odm_pipe->pipe_idx];
1732 next_odm_pipe->plane_res.xfm = pool->transforms[next_odm_pipe->pipe_idx];
1733 next_odm_pipe->plane_res.dpp = pool->dpps[next_odm_pipe->pipe_idx];
1734 next_odm_pipe->plane_res.mpcc_inst = pool->dpps[next_odm_pipe->pipe_idx]->inst;
b1f6d01c 1735 next_odm_pipe->stream_res.dsc = NULL;
b1f6d01c 1736 if (prev_odm_pipe->next_odm_pipe && prev_odm_pipe->next_odm_pipe != next_odm_pipe) {
b1f6d01c
DL
1737 next_odm_pipe->next_odm_pipe = prev_odm_pipe->next_odm_pipe;
1738 next_odm_pipe->next_odm_pipe->prev_odm_pipe = next_odm_pipe;
1739 }
1740 prev_odm_pipe->next_odm_pipe = next_odm_pipe;
1741 next_odm_pipe->prev_odm_pipe = prev_odm_pipe;
1742 ASSERT(next_odm_pipe->top_pipe == NULL);
1743
1744 if (prev_odm_pipe->plane_state) {
c0358809
DL
1745 struct scaler_data *sd = &prev_odm_pipe->plane_res.scl_data;
1746 int new_width;
1747
b1f6d01c
DL
1748 /* HACTIVE halved for odm combine */
1749 sd->h_active /= 2;
b1f6d01c
DL
1750 /* Calculate new vp and recout for left pipe */
1751 /* Need at least 16 pixels width per side */
1752 if (sd->recout.x + 16 >= sd->h_active)
1753 return false;
1754 new_width = sd->h_active - sd->recout.x;
1755 sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int(
1756 sd->ratios.horz, sd->recout.width - new_width));
1757 sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int(
1758 sd->ratios.horz_c, sd->recout.width - new_width));
1759 sd->recout.width = new_width;
1760
1761 /* Calculate new vp and recout for right pipe */
1762 sd = &next_odm_pipe->plane_res.scl_data;
c0358809
DL
1763 /* HACTIVE halved for odm combine */
1764 sd->h_active /= 2;
b1f6d01c
DL
1765 /* Need at least 16 pixels width per side */
1766 if (new_width <= 16)
1767 return false;
c0358809 1768 new_width = sd->recout.width + sd->recout.x - sd->h_active;
b1f6d01c
DL
1769 sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int(
1770 sd->ratios.horz, sd->recout.width - new_width));
1771 sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int(
1772 sd->ratios.horz_c, sd->recout.width - new_width));
1773 sd->recout.width = new_width;
1774 sd->viewport.x += dc_fixpt_floor(dc_fixpt_mul_int(
1775 sd->ratios.horz, sd->h_active - sd->recout.x));
1776 sd->viewport_c.x += dc_fixpt_floor(dc_fixpt_mul_int(
1777 sd->ratios.horz_c, sd->h_active - sd->recout.x));
1778 sd->recout.x = 0;
1779 }
1780 next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
b1f6d01c 1781 if (next_odm_pipe->stream->timing.flags.DSC == 1) {
eab4bb97 1782 acquire_dsc(res_ctx, pool, &next_odm_pipe->stream_res.dsc, next_odm_pipe->pipe_idx);
b1f6d01c
DL
1783 ASSERT(next_odm_pipe->stream_res.dsc);
1784 if (next_odm_pipe->stream_res.dsc == NULL)
1785 return false;
1786 }
b1f6d01c
DL
1787
1788 return true;
1789}
1790
b6bfba6c 1791void dcn20_split_stream_for_mpc(
7ed4e635
HW
1792 struct resource_context *res_ctx,
1793 const struct resource_pool *pool,
1794 struct pipe_ctx *primary_pipe,
b1f6d01c 1795 struct pipe_ctx *secondary_pipe)
7ed4e635
HW
1796{
1797 int pipe_idx = secondary_pipe->pipe_idx;
7ed4e635 1798 struct pipe_ctx *sec_bot_pipe = secondary_pipe->bottom_pipe;
7ed4e635
HW
1799
1800 *secondary_pipe = *primary_pipe;
1801 secondary_pipe->bottom_pipe = sec_bot_pipe;
1802
1803 secondary_pipe->pipe_idx = pipe_idx;
1804 secondary_pipe->plane_res.mi = pool->mis[secondary_pipe->pipe_idx];
1805 secondary_pipe->plane_res.hubp = pool->hubps[secondary_pipe->pipe_idx];
1806 secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx];
1807 secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx];
1808 secondary_pipe->plane_res.dpp = pool->dpps[secondary_pipe->pipe_idx];
1809 secondary_pipe->plane_res.mpcc_inst = pool->dpps[secondary_pipe->pipe_idx]->inst;
c92b4c46 1810 secondary_pipe->stream_res.dsc = NULL;
7ed4e635
HW
1811 if (primary_pipe->bottom_pipe && primary_pipe->bottom_pipe != secondary_pipe) {
1812 ASSERT(!secondary_pipe->bottom_pipe);
1813 secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe;
1814 secondary_pipe->bottom_pipe->top_pipe = secondary_pipe;
1815 }
1816 primary_pipe->bottom_pipe = secondary_pipe;
1817 secondary_pipe->top_pipe = primary_pipe;
1818
b1f6d01c
DL
1819 ASSERT(primary_pipe->plane_state);
1820 resource_build_scaling_params(primary_pipe);
1821 resource_build_scaling_params(secondary_pipe);
7ed4e635
HW
1822}
1823
1824void dcn20_populate_dml_writeback_from_context(
1825 struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes)
1826{
1827 int pipe_cnt, i;
1828
1829 for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
1830 struct dc_writeback_info *wb_info = &res_ctx->pipe_ctx[i].stream->writeback_info[0];
1831
1832 if (!res_ctx->pipe_ctx[i].stream)
1833 continue;
1834
1835 /* Set writeback information */
1836 pipes[pipe_cnt].dout.wb_enable = (wb_info->wb_enabled == true) ? 1 : 0;
1837 pipes[pipe_cnt].dout.num_active_wb++;
1838 pipes[pipe_cnt].dout.wb.wb_src_height = wb_info->dwb_params.cnv_params.crop_height;
1839 pipes[pipe_cnt].dout.wb.wb_src_width = wb_info->dwb_params.cnv_params.crop_width;
1840 pipes[pipe_cnt].dout.wb.wb_dst_width = wb_info->dwb_params.dest_width;
1841 pipes[pipe_cnt].dout.wb.wb_dst_height = wb_info->dwb_params.dest_height;
1842 pipes[pipe_cnt].dout.wb.wb_htaps_luma = 1;
1843 pipes[pipe_cnt].dout.wb.wb_vtaps_luma = 1;
1844 pipes[pipe_cnt].dout.wb.wb_htaps_chroma = wb_info->dwb_params.scaler_taps.h_taps_c;
1845 pipes[pipe_cnt].dout.wb.wb_vtaps_chroma = wb_info->dwb_params.scaler_taps.v_taps_c;
1846 pipes[pipe_cnt].dout.wb.wb_hratio = 1.0;
1847 pipes[pipe_cnt].dout.wb.wb_vratio = 1.0;
1848 if (wb_info->dwb_params.out_format == dwb_scaler_mode_yuv420) {
1849 if (wb_info->dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC)
1850 pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_420_8;
1851 else
1852 pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_420_10;
1853 } else
1854 pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_444_32;
1855
1856 pipe_cnt++;
1857 }
1858
1859}
1860
1861int dcn20_populate_dml_pipes_from_context(
2f488884 1862 struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes)
7ed4e635
HW
1863{
1864 int pipe_cnt, i;
1865 bool synchronized_vblank = true;
2f488884 1866 struct resource_context *res_ctx = &context->res_ctx;
7ed4e635
HW
1867
1868 for (i = 0, pipe_cnt = -1; i < dc->res_pool->pipe_count; i++) {
1869 if (!res_ctx->pipe_ctx[i].stream)
1870 continue;
1871
1872 if (pipe_cnt < 0) {
1873 pipe_cnt = i;
1874 continue;
1875 }
785908cf 1876 if (dc->debug.disable_timing_sync || !resource_are_streams_timing_synchronizable(
7ed4e635
HW
1877 res_ctx->pipe_ctx[pipe_cnt].stream,
1878 res_ctx->pipe_ctx[i].stream)) {
1879 synchronized_vblank = false;
1880 break;
1881 }
1882 }
1883
1884 for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
1885 struct dc_crtc_timing *timing = &res_ctx->pipe_ctx[i].stream->timing;
2f488884 1886 unsigned int v_total;
1075735e 1887 unsigned int front_porch;
03fd87db 1888 int output_bpc;
7ed4e635
HW
1889
1890 if (!res_ctx->pipe_ctx[i].stream)
1891 continue;
2f488884
AL
1892
1893 v_total = timing->v_total;
1075735e 1894 front_porch = timing->v_front_porch;
7ed4e635
HW
1895 /* todo:
1896 pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = 0;
1897 pipes[pipe_cnt].pipe.src.dcc = 0;
1898 pipes[pipe_cnt].pipe.src.vm = 0;*/
1899
97bda032
HW
1900 pipes[pipe_cnt].dout.dsc_enable = res_ctx->pipe_ctx[i].stream->timing.flags.DSC;
1901 /* todo: rotation?*/
1902 pipes[pipe_cnt].dout.dsc_slices = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.num_slices_h;
7ed4e635
HW
1903 if (res_ctx->pipe_ctx[i].stream->use_dynamic_meta) {
1904 pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = true;
1905 /* 1/2 vblank */
1906 pipes[pipe_cnt].pipe.src.dynamic_metadata_lines_before_active =
2f488884 1907 (v_total - timing->v_addressable
7ed4e635
HW
1908 - timing->v_border_top - timing->v_border_bottom) / 2;
1909 /* 36 bytes dp, 32 hdmi */
1910 pipes[pipe_cnt].pipe.src.dynamic_metadata_xmit_bytes =
1911 dc_is_dp_signal(res_ctx->pipe_ctx[i].stream->signal) ? 36 : 32;
1912 }
1913 pipes[pipe_cnt].pipe.src.dcc = false;
1914 pipes[pipe_cnt].pipe.src.dcc_rate = 1;
1915 pipes[pipe_cnt].pipe.dest.synchronized_vblank_all_planes = synchronized_vblank;
1916 pipes[pipe_cnt].pipe.dest.hblank_start = timing->h_total - timing->h_front_porch;
1917 pipes[pipe_cnt].pipe.dest.hblank_end = pipes[pipe_cnt].pipe.dest.hblank_start
1918 - timing->h_addressable
1919 - timing->h_border_left
1920 - timing->h_border_right;
1075735e 1921 pipes[pipe_cnt].pipe.dest.vblank_start = v_total - front_porch;
7ed4e635
HW
1922 pipes[pipe_cnt].pipe.dest.vblank_end = pipes[pipe_cnt].pipe.dest.vblank_start
1923 - timing->v_addressable
1924 - timing->v_border_top
1925 - timing->v_border_bottom;
1926 pipes[pipe_cnt].pipe.dest.htotal = timing->h_total;
2f488884 1927 pipes[pipe_cnt].pipe.dest.vtotal = v_total;
7ed4e635
HW
1928 pipes[pipe_cnt].pipe.dest.hactive = timing->h_addressable;
1929 pipes[pipe_cnt].pipe.dest.vactive = timing->v_addressable;
1930 pipes[pipe_cnt].pipe.dest.interlaced = timing->flags.INTERLACE;
1931 pipes[pipe_cnt].pipe.dest.pixel_rate_mhz = timing->pix_clk_100hz/10000.0;
1932 if (timing->timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
1933 pipes[pipe_cnt].pipe.dest.pixel_rate_mhz *= 2;
1934 pipes[pipe_cnt].pipe.dest.otg_inst = res_ctx->pipe_ctx[i].stream_res.tg->inst;
1621f4c4 1935 pipes[pipe_cnt].dout.dp_lanes = 4;
8bb3d7e7
CL
1936 pipes[pipe_cnt].pipe.dest.vtotal_min = res_ctx->pipe_ctx[i].stream->adjust.v_total_min;
1937 pipes[pipe_cnt].pipe.dest.vtotal_max = res_ctx->pipe_ctx[i].stream->adjust.v_total_max;
c0358809
DL
1938 pipes[pipe_cnt].pipe.dest.odm_combine = res_ctx->pipe_ctx[i].prev_odm_pipe
1939 || res_ctx->pipe_ctx[i].next_odm_pipe;
1940 pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].pipe_idx;
1941 if (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state
1942 == res_ctx->pipe_ctx[i].plane_state)
1943 pipes[pipe_cnt].pipe.src.hsplit_grp = res_ctx->pipe_ctx[i].top_pipe->pipe_idx;
1944 else if (res_ctx->pipe_ctx[i].prev_odm_pipe) {
1945 struct pipe_ctx *first_pipe = res_ctx->pipe_ctx[i].prev_odm_pipe;
1946
1947 while (first_pipe->prev_odm_pipe)
1948 first_pipe = first_pipe->prev_odm_pipe;
1949 pipes[pipe_cnt].pipe.src.hsplit_grp = first_pipe->pipe_idx;
1950 }
7ed4e635 1951
7ed4e635
HW
1952 switch (res_ctx->pipe_ctx[i].stream->signal) {
1953 case SIGNAL_TYPE_DISPLAY_PORT_MST:
1954 case SIGNAL_TYPE_DISPLAY_PORT:
1955 pipes[pipe_cnt].dout.output_type = dm_dp;
1956 break;
1957 case SIGNAL_TYPE_EDP:
1958 pipes[pipe_cnt].dout.output_type = dm_edp;
1959 break;
1960 case SIGNAL_TYPE_HDMI_TYPE_A:
1961 case SIGNAL_TYPE_DVI_SINGLE_LINK:
1962 case SIGNAL_TYPE_DVI_DUAL_LINK:
1963 pipes[pipe_cnt].dout.output_type = dm_hdmi;
1964 break;
1965 default:
1966 /* In case there is no signal, set dp with 4 lanes to allow max config */
1967 pipes[pipe_cnt].dout.output_type = dm_dp;
1968 pipes[pipe_cnt].dout.dp_lanes = 4;
1969 }
03fd87db
IB
1970
1971 switch (res_ctx->pipe_ctx[i].stream->timing.display_color_depth) {
1972 case COLOR_DEPTH_666:
1973 output_bpc = 6;
1974 break;
1975 case COLOR_DEPTH_888:
1976 output_bpc = 8;
1977 break;
1978 case COLOR_DEPTH_101010:
1979 output_bpc = 10;
1980 break;
1981 case COLOR_DEPTH_121212:
1982 output_bpc = 12;
1983 break;
1984 case COLOR_DEPTH_141414:
1985 output_bpc = 14;
1986 break;
1987 case COLOR_DEPTH_161616:
1988 output_bpc = 16;
1989 break;
03fd87db
IB
1990 case COLOR_DEPTH_999:
1991 output_bpc = 9;
1992 break;
1993 case COLOR_DEPTH_111111:
1994 output_bpc = 11;
1995 break;
03fd87db
IB
1996 default:
1997 output_bpc = 8;
1998 break;
1999 }
2000
7ed4e635
HW
2001 switch (res_ctx->pipe_ctx[i].stream->timing.pixel_encoding) {
2002 case PIXEL_ENCODING_RGB:
2003 case PIXEL_ENCODING_YCBCR444:
2004 pipes[pipe_cnt].dout.output_format = dm_444;
03fd87db 2005 pipes[pipe_cnt].dout.output_bpp = output_bpc * 3;
7ed4e635
HW
2006 break;
2007 case PIXEL_ENCODING_YCBCR420:
2008 pipes[pipe_cnt].dout.output_format = dm_420;
486cc0ee 2009 pipes[pipe_cnt].dout.output_bpp = (output_bpc * 3.0) / 2;
7ed4e635
HW
2010 break;
2011 case PIXEL_ENCODING_YCBCR422:
2012 if (true) /* todo */
2013 pipes[pipe_cnt].dout.output_format = dm_s422;
2014 else
2015 pipes[pipe_cnt].dout.output_format = dm_n422;
03fd87db 2016 pipes[pipe_cnt].dout.output_bpp = output_bpc * 2;
7ed4e635
HW
2017 break;
2018 default:
2019 pipes[pipe_cnt].dout.output_format = dm_444;
03fd87db 2020 pipes[pipe_cnt].dout.output_bpp = output_bpc * 3;
7ed4e635 2021 }
7ed4e635 2022
486cc0ee
NC
2023 if (res_ctx->pipe_ctx[i].stream->timing.flags.DSC)
2024 pipes[pipe_cnt].dout.output_bpp = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.bits_per_pixel / 16.0;
2025
7ed4e635
HW
2026 /* todo: default max for now, until there is logic reflecting this in dc*/
2027 pipes[pipe_cnt].dout.output_bpc = 12;
2028 /*
2029 * Use max cursor settings for calculations to minimize
2030 * bw calculations due to cursor on/off
2031 */
2032 pipes[pipe_cnt].pipe.src.num_cursors = 2;
ed07237c
IB
2033 pipes[pipe_cnt].pipe.src.cur0_src_width = 256;
2034 pipes[pipe_cnt].pipe.src.cur0_bpp = dm_cur_32bit;
2035 pipes[pipe_cnt].pipe.src.cur1_src_width = 256;
2036 pipes[pipe_cnt].pipe.src.cur1_bpp = dm_cur_32bit;
7ed4e635
HW
2037
2038 if (!res_ctx->pipe_ctx[i].plane_state) {
2039 pipes[pipe_cnt].pipe.src.source_scan = dm_horz;
2040 pipes[pipe_cnt].pipe.src.sw_mode = dm_sw_linear;
2041 pipes[pipe_cnt].pipe.src.macro_tile_size = dm_64k_tile;
2042 pipes[pipe_cnt].pipe.src.viewport_width = timing->h_addressable;
2043 if (pipes[pipe_cnt].pipe.src.viewport_width > 1920)
2044 pipes[pipe_cnt].pipe.src.viewport_width = 1920;
2045 pipes[pipe_cnt].pipe.src.viewport_height = timing->v_addressable;
2046 if (pipes[pipe_cnt].pipe.src.viewport_height > 1080)
2047 pipes[pipe_cnt].pipe.src.viewport_height = 1080;
71e6bd2a 2048 pipes[pipe_cnt].pipe.src.surface_height_y = pipes[pipe_cnt].pipe.src.viewport_height;
7ed4e635
HW
2049 pipes[pipe_cnt].pipe.src.data_pitch = ((pipes[pipe_cnt].pipe.src.viewport_width + 63) / 64) * 64; /* linear sw only */
2050 pipes[pipe_cnt].pipe.src.source_format = dm_444_32;
2051 pipes[pipe_cnt].pipe.dest.recout_width = pipes[pipe_cnt].pipe.src.viewport_width; /*vp_width/hratio*/
2052 pipes[pipe_cnt].pipe.dest.recout_height = pipes[pipe_cnt].pipe.src.viewport_height; /*vp_height/vratio*/
2053 pipes[pipe_cnt].pipe.dest.full_recout_width = pipes[pipe_cnt].pipe.dest.recout_width; /*when is_hsplit != 1*/
2054 pipes[pipe_cnt].pipe.dest.full_recout_height = pipes[pipe_cnt].pipe.dest.recout_height; /*when is_hsplit != 1*/
2055 pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_16;
2056 pipes[pipe_cnt].pipe.scale_ratio_depth.hscl_ratio = 1.0;
2057 pipes[pipe_cnt].pipe.scale_ratio_depth.vscl_ratio = 1.0;
2058 pipes[pipe_cnt].pipe.scale_ratio_depth.scl_enable = 0; /*Lb only or Full scl*/
2059 pipes[pipe_cnt].pipe.scale_taps.htaps = 1;
2060 pipes[pipe_cnt].pipe.scale_taps.vtaps = 1;
2061 pipes[pipe_cnt].pipe.src.is_hsplit = 0;
2062 pipes[pipe_cnt].pipe.dest.odm_combine = 0;
2f488884
AL
2063 pipes[pipe_cnt].pipe.dest.vtotal_min = v_total;
2064 pipes[pipe_cnt].pipe.dest.vtotal_max = v_total;
7ed4e635
HW
2065 } else {
2066 struct dc_plane_state *pln = res_ctx->pipe_ctx[i].plane_state;
2067 struct scaler_data *scl = &res_ctx->pipe_ctx[i].plane_res.scl_data;
2068
7ed4e635
HW
2069 pipes[pipe_cnt].pipe.src.immediate_flip = pln->flip_immediate;
2070 pipes[pipe_cnt].pipe.src.is_hsplit = (res_ctx->pipe_ctx[i].bottom_pipe
2071 && res_ctx->pipe_ctx[i].bottom_pipe->plane_state == pln)
2072 || (res_ctx->pipe_ctx[i].top_pipe
2073 && res_ctx->pipe_ctx[i].top_pipe->plane_state == pln);
7ed4e635
HW
2074 pipes[pipe_cnt].pipe.src.source_scan = pln->rotation == ROTATION_ANGLE_90
2075 || pln->rotation == ROTATION_ANGLE_270 ? dm_vert : dm_horz;
2076 pipes[pipe_cnt].pipe.src.viewport_y_y = scl->viewport.y;
2077 pipes[pipe_cnt].pipe.src.viewport_y_c = scl->viewport_c.y;
2078 pipes[pipe_cnt].pipe.src.viewport_width = scl->viewport.width;
2079 pipes[pipe_cnt].pipe.src.viewport_width_c = scl->viewport_c.width;
2080 pipes[pipe_cnt].pipe.src.viewport_height = scl->viewport.height;
2081 pipes[pipe_cnt].pipe.src.viewport_height_c = scl->viewport_c.height;
71e6bd2a 2082 pipes[pipe_cnt].pipe.src.surface_height_y = pln->plane_size.surface_size.height;
7ed4e635 2083 if (pln->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
12e2b2d4
DL
2084 pipes[pipe_cnt].pipe.src.data_pitch = pln->plane_size.surface_pitch;
2085 pipes[pipe_cnt].pipe.src.data_pitch_c = pln->plane_size.chroma_pitch;
2086 pipes[pipe_cnt].pipe.src.meta_pitch = pln->dcc.meta_pitch;
2087 pipes[pipe_cnt].pipe.src.meta_pitch_c = pln->dcc.meta_pitch_c;
7ed4e635 2088 } else {
12e2b2d4
DL
2089 pipes[pipe_cnt].pipe.src.data_pitch = pln->plane_size.surface_pitch;
2090 pipes[pipe_cnt].pipe.src.meta_pitch = pln->dcc.meta_pitch;
7ed4e635
HW
2091 }
2092 pipes[pipe_cnt].pipe.src.dcc = pln->dcc.enable;
2093 pipes[pipe_cnt].pipe.dest.recout_width = scl->recout.width;
2094 pipes[pipe_cnt].pipe.dest.recout_height = scl->recout.height;
2095 pipes[pipe_cnt].pipe.dest.full_recout_width = scl->recout.width;
2096 pipes[pipe_cnt].pipe.dest.full_recout_height = scl->recout.height;
2097 if (res_ctx->pipe_ctx[i].bottom_pipe && res_ctx->pipe_ctx[i].bottom_pipe->plane_state == pln) {
2098 pipes[pipe_cnt].pipe.dest.full_recout_width +=
2099 res_ctx->pipe_ctx[i].bottom_pipe->plane_res.scl_data.recout.width;
2100 pipes[pipe_cnt].pipe.dest.full_recout_height +=
2101 res_ctx->pipe_ctx[i].bottom_pipe->plane_res.scl_data.recout.height;
2102 } else if (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state == pln) {
2103 pipes[pipe_cnt].pipe.dest.full_recout_width +=
2104 res_ctx->pipe_ctx[i].top_pipe->plane_res.scl_data.recout.width;
2105 pipes[pipe_cnt].pipe.dest.full_recout_height +=
2106 res_ctx->pipe_ctx[i].top_pipe->plane_res.scl_data.recout.height;
2107 }
2108
ed07237c 2109 pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_16;
7ed4e635
HW
2110 pipes[pipe_cnt].pipe.scale_ratio_depth.hscl_ratio = (double) scl->ratios.horz.value / (1ULL<<32);
2111 pipes[pipe_cnt].pipe.scale_ratio_depth.hscl_ratio_c = (double) scl->ratios.horz_c.value / (1ULL<<32);
2112 pipes[pipe_cnt].pipe.scale_ratio_depth.vscl_ratio = (double) scl->ratios.vert.value / (1ULL<<32);
2113 pipes[pipe_cnt].pipe.scale_ratio_depth.vscl_ratio_c = (double) scl->ratios.vert_c.value / (1ULL<<32);
2114 pipes[pipe_cnt].pipe.scale_ratio_depth.scl_enable =
2115 scl->ratios.vert.value != dc_fixpt_one.value
2116 || scl->ratios.horz.value != dc_fixpt_one.value
2117 || scl->ratios.vert_c.value != dc_fixpt_one.value
2118 || scl->ratios.horz_c.value != dc_fixpt_one.value /*Lb only or Full scl*/
2119 || dc->debug.always_scale; /*support always scale*/
2120 pipes[pipe_cnt].pipe.scale_taps.htaps = scl->taps.h_taps;
2121 pipes[pipe_cnt].pipe.scale_taps.htaps_c = scl->taps.h_taps_c;
2122 pipes[pipe_cnt].pipe.scale_taps.vtaps = scl->taps.v_taps;
2123 pipes[pipe_cnt].pipe.scale_taps.vtaps_c = scl->taps.v_taps_c;
2124
b964e790
DL
2125 pipes[pipe_cnt].pipe.src.macro_tile_size =
2126 swizzle_mode_to_macro_tile_size(pln->tiling_info.gfx9.swizzle);
7ed4e635
HW
2127 swizzle_to_dml_params(pln->tiling_info.gfx9.swizzle,
2128 &pipes[pipe_cnt].pipe.src.sw_mode);
2129
2130 switch (pln->format) {
2131 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
2132 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
2133 pipes[pipe_cnt].pipe.src.source_format = dm_420_8;
2134 break;
2135 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
2136 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
2137 pipes[pipe_cnt].pipe.src.source_format = dm_420_10;
2138 break;
2139 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
2140 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
2141 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
2142 pipes[pipe_cnt].pipe.src.source_format = dm_444_64;
2143 break;
2144 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
2145 case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
2146 pipes[pipe_cnt].pipe.src.source_format = dm_444_16;
2147 break;
2148 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
2149 pipes[pipe_cnt].pipe.src.source_format = dm_444_8;
2150 break;
2151 default:
2152 pipes[pipe_cnt].pipe.src.source_format = dm_444_32;
2153 break;
2154 }
2155 }
2156
2157 pipe_cnt++;
2158 }
2159
2160 /* populate writeback information */
2161 dc->res_pool->funcs->populate_dml_writeback_from_context(dc, res_ctx, pipes);
2162
2163 return pipe_cnt;
2164}
2165
2166unsigned int dcn20_calc_max_scaled_time(
2167 unsigned int time_per_pixel,
2168 enum mmhubbub_wbif_mode mode,
2169 unsigned int urgent_watermark)
2170{
2171 unsigned int time_per_byte = 0;
2172 unsigned int total_y_free_entry = 0x200; /* two memory piece for luma */
2173 unsigned int total_c_free_entry = 0x140; /* two memory piece for chroma */
2174 unsigned int small_free_entry, max_free_entry;
2175 unsigned int buf_lh_capability;
2176 unsigned int max_scaled_time;
2177
2178 if (mode == PACKED_444) /* packed mode */
2179 time_per_byte = time_per_pixel/4;
2180 else if (mode == PLANAR_420_8BPC)
2181 time_per_byte = time_per_pixel;
2182 else if (mode == PLANAR_420_10BPC) /* p010 */
2183 time_per_byte = time_per_pixel * 819/1024;
2184
2185 if (time_per_byte == 0)
2186 time_per_byte = 1;
2187
2188 small_free_entry = (total_y_free_entry > total_c_free_entry) ? total_c_free_entry : total_y_free_entry;
2189 max_free_entry = (mode == PACKED_444) ? total_y_free_entry + total_c_free_entry : small_free_entry;
2190 buf_lh_capability = max_free_entry*time_per_byte*32/16; /* there is 4bit fraction */
2191 max_scaled_time = buf_lh_capability - urgent_watermark;
2192 return max_scaled_time;
2193}
2194
2195void dcn20_set_mcif_arb_params(
2196 struct dc *dc,
2197 struct dc_state *context,
2198 display_e2e_pipe_params_st *pipes,
2199 int pipe_cnt)
2200{
2201 enum mmhubbub_wbif_mode wbif_mode;
2202 struct mcif_arb_params *wb_arb_params;
2203 int i, j, k, dwb_pipe;
2204
2205 /* Writeback MCIF_WB arbitration parameters */
2206 dwb_pipe = 0;
2207 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2208
2209 if (!context->res_ctx.pipe_ctx[i].stream)
2210 continue;
2211
2212 for (j = 0; j < MAX_DWB_PIPES; j++) {
2213 if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].wb_enabled == false)
2214 continue;
2215
2216 //wb_arb_params = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j].mcif_arb_params;
2217 wb_arb_params = &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[dwb_pipe];
2218
2219 if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].dwb_params.out_format == dwb_scaler_mode_yuv420) {
2220 if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC)
2221 wbif_mode = PLANAR_420_8BPC;
2222 else
2223 wbif_mode = PLANAR_420_10BPC;
2224 } else
2225 wbif_mode = PACKED_444;
2226
2227 for (k = 0; k < sizeof(wb_arb_params->cli_watermark)/sizeof(wb_arb_params->cli_watermark[0]); k++) {
2228 wb_arb_params->cli_watermark[k] = get_wm_writeback_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2229 wb_arb_params->pstate_watermark[k] = get_wm_writeback_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2230 }
2231 wb_arb_params->time_per_pixel = 16.0 / context->res_ctx.pipe_ctx[i].stream->phy_pix_clk; /* 4 bit fraction, ms */
2232 wb_arb_params->slice_lines = 32;
2233 wb_arb_params->arbitration_slice = 2;
2234 wb_arb_params->max_scaled_time = dcn20_calc_max_scaled_time(wb_arb_params->time_per_pixel,
2235 wbif_mode,
2236 wb_arb_params->cli_watermark[0]); /* assume 4 watermark sets have the same value */
2237
2238 dwb_pipe++;
2239
2240 if (dwb_pipe >= MAX_DWB_PIPES)
2241 return;
2242 }
2243 if (dwb_pipe >= MAX_DWB_PIPES)
2244 return;
2245 }
2246}
2247
b6bfba6c 2248bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx)
0ba37b20
DL
2249{
2250 int i;
2251
2252 /* Validate DSC config, dsc count validation is already done */
2253 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2254 struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];
2255 struct dc_stream_state *stream = pipe_ctx->stream;
2256 struct dsc_config dsc_cfg;
b1f6d01c
DL
2257 struct pipe_ctx *odm_pipe;
2258 int opp_cnt = 1;
2259
2260 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
2261 opp_cnt++;
0ba37b20
DL
2262
2263 /* Only need to validate top pipe */
b1f6d01c 2264 if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe || !stream || !stream->timing.flags.DSC)
0ba37b20
DL
2265 continue;
2266
b1f6d01c
DL
2267 dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left
2268 + stream->timing.h_border_right) / opp_cnt;
0ba37b20
DL
2269 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top
2270 + stream->timing.v_border_bottom;
0ba37b20
DL
2271 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
2272 dsc_cfg.color_depth = stream->timing.display_color_depth;
2273 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
b1f6d01c 2274 dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
0ba37b20
DL
2275
2276 if (!pipe_ctx->stream_res.dsc->funcs->dsc_validate_stream(pipe_ctx->stream_res.dsc, &dsc_cfg))
2277 return false;
2278 }
2279 return true;
2280}
0ba37b20 2281
b6bfba6c 2282struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc,
c681491a
JL
2283 struct resource_context *res_ctx,
2284 const struct resource_pool *pool,
2285 const struct pipe_ctx *primary_pipe)
2286{
2287 struct pipe_ctx *secondary_pipe = NULL;
2288
2289 if (dc && primary_pipe) {
2290 int j;
2291 int preferred_pipe_idx = 0;
2292
2293 /* first check the prev dc state:
2294 * if this primary pipe has a bottom pipe in prev. state
2295 * and if the bottom pipe is still available (which it should be),
2296 * pick that pipe as secondary
b1f6d01c
DL
2297 * Same logic applies for ODM pipes. Since mpo is not allowed with odm
2298 * check in else case.
c681491a
JL
2299 */
2300 if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe) {
2301 preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe->pipe_idx;
2302 if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
2303 secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
2304 secondary_pipe->pipe_idx = preferred_pipe_idx;
2305 }
b1f6d01c
DL
2306 } else if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe) {
2307 preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe->pipe_idx;
2308 if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
2309 secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
2310 secondary_pipe->pipe_idx = preferred_pipe_idx;
2311 }
c681491a
JL
2312 }
2313
2314 /*
2315 * if this primary pipe does not have a bottom pipe in prev. state
2316 * start backward and find a pipe that did not used to be a bottom pipe in
2317 * prev. dc state. This way we make sure we keep the same assignment as
2318 * last state and will not have to reprogram every pipe
2319 */
2320 if (secondary_pipe == NULL) {
2321 for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) {
8b8eda01
DL
2322 if (dc->current_state->res_ctx.pipe_ctx[j].top_pipe == NULL
2323 && dc->current_state->res_ctx.pipe_ctx[j].prev_odm_pipe == NULL) {
c681491a
JL
2324 preferred_pipe_idx = j;
2325
2326 if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
2327 secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
2328 secondary_pipe->pipe_idx = preferred_pipe_idx;
2329 break;
2330 }
2331 }
2332 }
2333 }
2334 /*
2335 * We should never hit this assert unless assignments are shuffled around
2336 * if this happens we will prob. hit a vsync tdr
2337 */
2338 ASSERT(secondary_pipe);
2339 /*
2340 * search backwards for the second pipe to keep pipe
2341 * assignment more consistent
2342 */
2343 if (secondary_pipe == NULL) {
2344 for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) {
2345 preferred_pipe_idx = j;
2346
2347 if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
2348 secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
2349 secondary_pipe->pipe_idx = preferred_pipe_idx;
2350 break;
2351 }
2352 }
2353 }
2354 }
2355
2356 return secondary_pipe;
2357}
2358
b6bfba6c 2359void dcn20_merge_pipes_for_validate(
6de20237 2360 struct dc *dc,
b6bfba6c 2361 struct dc_state *context)
7ed4e635 2362{
b6bfba6c 2363 int i;
7ed4e635 2364
b1f6d01c
DL
2365 /* merge previously split odm pipes since mode support needs to make the decision */
2366 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2367 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
2368 struct pipe_ctx *odm_pipe = pipe->next_odm_pipe;
2369
2370 if (pipe->prev_odm_pipe)
2371 continue;
2372
2373 pipe->next_odm_pipe = NULL;
2374 while (odm_pipe) {
2375 struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe;
2376
2377 odm_pipe->plane_state = NULL;
2378 odm_pipe->stream = NULL;
2379 odm_pipe->top_pipe = NULL;
2380 odm_pipe->bottom_pipe = NULL;
2381 odm_pipe->prev_odm_pipe = NULL;
2382 odm_pipe->next_odm_pipe = NULL;
b1f6d01c
DL
2383 if (odm_pipe->stream_res.dsc)
2384 release_dsc(&context->res_ctx, dc->res_pool, &odm_pipe->stream_res.dsc);
b1f6d01c
DL
2385 /* Clear plane_res and stream_res */
2386 memset(&odm_pipe->plane_res, 0, sizeof(odm_pipe->plane_res));
2387 memset(&odm_pipe->stream_res, 0, sizeof(odm_pipe->stream_res));
2388 odm_pipe = next_odm_pipe;
2389 }
2390 if (pipe->plane_state)
2391 resource_build_scaling_params(pipe);
2392 }
2393
2394 /* merge previously mpc split pipes since mode support needs to make the decision */
7ed4e635
HW
2395 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2396 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
2397 struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe;
2398
2399 if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state)
2400 continue;
2401
7ed4e635
HW
2402 pipe->bottom_pipe = hsplit_pipe->bottom_pipe;
2403 if (hsplit_pipe->bottom_pipe)
2404 hsplit_pipe->bottom_pipe->top_pipe = pipe;
2405 hsplit_pipe->plane_state = NULL;
2406 hsplit_pipe->stream = NULL;
2407 hsplit_pipe->top_pipe = NULL;
2408 hsplit_pipe->bottom_pipe = NULL;
b1f6d01c 2409
7ed4e635
HW
2410 /* Clear plane_res and stream_res */
2411 memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res));
2412 memset(&hsplit_pipe->stream_res, 0, sizeof(hsplit_pipe->stream_res));
2413 if (pipe->plane_state)
2414 resource_build_scaling_params(pipe);
2415 }
b6bfba6c 2416}
7ed4e635 2417
b6bfba6c
DL
2418int dcn20_validate_apply_pipe_split_flags(
2419 struct dc *dc,
2420 struct dc_state *context,
2421 int vlevel,
2422 bool *split)
2423{
b745ecdb 2424 int i, pipe_idx, vlevel_split;
b6bfba6c
DL
2425 bool force_split = false;
2426 bool avoid_split = dc->debug.pipe_split_policy != MPC_SPLIT_DYNAMIC;
7ed4e635 2427
b745ecdb 2428 /* Single display loop, exits if there is more than one display */
7ed4e635
HW
2429 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2430 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
2431 bool exit_loop = false;
2432
2433 if (!pipe->stream || pipe->top_pipe)
2434 continue;
2435
2436 if (dc->debug.force_single_disp_pipe_split) {
2437 if (!force_split)
2438 force_split = true;
2439 else {
2440 force_split = false;
2441 exit_loop = true;
2442 }
2443 }
2444 if (dc->debug.pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP) {
2445 if (avoid_split)
2446 avoid_split = false;
2447 else {
2448 avoid_split = true;
2449 exit_loop = true;
2450 }
2451 }
2452 if (exit_loop)
2453 break;
2454 }
b6bfba6c
DL
2455 /* TODO: fix dc bugs and remove this split threshold thing */
2456 if (context->stream_count > dc->res_pool->pipe_count / 2)
7ed4e635
HW
2457 avoid_split = true;
2458
b745ecdb 2459 /* Avoid split loop looks for lowest voltage level that allows most unsplit pipes possible */
b6bfba6c
DL
2460 if (avoid_split) {
2461 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
2462 if (!context->res_ctx.pipe_ctx[i].stream)
2463 continue;
2464
b745ecdb 2465 for (vlevel_split = vlevel; vlevel <= context->bw_ctx.dml.soc.num_states; vlevel++)
b6bfba6c
DL
2466 if (context->bw_ctx.dml.vba.NoOfDPP[vlevel][0][pipe_idx] == 1)
2467 break;
2468 /* Impossible to not split this pipe */
b745ecdb
DL
2469 if (vlevel > context->bw_ctx.dml.soc.num_states)
2470 vlevel = vlevel_split;
b6bfba6c
DL
2471 pipe_idx++;
2472 }
2473 context->bw_ctx.dml.vba.maxMpcComb = 0;
2474 }
2475
b745ecdb 2476 /* Split loop sets which pipe should be split based on dml outputs and dc flags */
7ed4e635 2477 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
b6bfba6c
DL
2478 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
2479
7ed4e635
HW
2480 if (!context->res_ctx.pipe_ctx[i].stream)
2481 continue;
b6bfba6c
DL
2482
2483 if (force_split || context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] > 1)
2484 split[i] = true;
2485 if ((pipe->stream->view_format ==
2486 VIEW_3D_FORMAT_SIDE_BY_SIDE ||
2487 pipe->stream->view_format ==
2488 VIEW_3D_FORMAT_TOP_AND_BOTTOM) &&
2489 (pipe->stream->timing.timing_3d_format ==
2490 TIMING_3D_FORMAT_TOP_AND_BOTTOM ||
2491 pipe->stream->timing.timing_3d_format ==
2492 TIMING_3D_FORMAT_SIDE_BY_SIDE))
2493 split[i] = true;
2494 if (dc->debug.force_odm_combine & (1 << pipe->stream_res.tg->inst)) {
2495 split[i] = true;
2496 context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel][pipe_idx] = true;
2497 }
78ea008b
DL
2498 context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx] =
2499 context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel][pipe_idx];
b6bfba6c
DL
2500 /* Adjust dppclk when split is forced, do not bother with dispclk */
2501 if (split[i] && context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] == 1)
2502 context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] /= 2;
7ed4e635
HW
2503 pipe_idx++;
2504 }
2505
b6bfba6c
DL
2506 return vlevel;
2507}
2508
2509bool dcn20_fast_validate_bw(
2510 struct dc *dc,
2511 struct dc_state *context,
2512 display_e2e_pipe_params_st *pipes,
2513 int *pipe_cnt_out,
2514 int *pipe_split_from,
2515 int *vlevel_out)
2516{
2517 bool out = false;
2518 bool split[MAX_PIPES] = { false };
2519 int pipe_cnt, i, pipe_idx, vlevel;
2520
2521 ASSERT(pipes);
2522 if (!pipes)
2523 return false;
2524
2525 dcn20_merge_pipes_for_validate(dc, context);
2526
2f488884 2527 pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes);
b6bfba6c
DL
2528
2529 *pipe_cnt_out = pipe_cnt;
2530
2531 if (!pipe_cnt) {
2532 out = true;
2533 goto validate_out;
2534 }
2535
2536 vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
2537
2538 if (vlevel > context->bw_ctx.dml.soc.num_states)
2539 goto validate_fail;
2540
2541 vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split);
2542
2543 /*initialize pipe_just_split_from to invalid idx*/
2544 for (i = 0; i < MAX_PIPES; i++)
2545 pipe_split_from[i] = -1;
2546
7ed4e635
HW
2547 for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) {
2548 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
2549 struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe;
7ed4e635
HW
2550
2551 if (!pipe->stream || pipe_split_from[i] >= 0)
2552 continue;
2553
2554 pipe_idx++;
2555
7ed4e635 2556 if (!pipe->top_pipe && !pipe->plane_state && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) {
c681491a 2557 hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe);
7ed4e635 2558 ASSERT(hsplit_pipe);
b1f6d01c 2559 if (!dcn20_split_stream_for_odm(
7ed4e635 2560 &context->res_ctx, dc->res_pool,
b1f6d01c 2561 pipe, hsplit_pipe))
7ed4e635
HW
2562 goto validate_fail;
2563 pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx;
2564 dcn20_build_mapped_resource(dc, context, pipe->stream);
2565 }
2566
2567 if (!pipe->plane_state)
2568 continue;
2569 /* Skip 2nd half of already split pipe */
2570 if (pipe->top_pipe && pipe->plane_state == pipe->top_pipe->plane_state)
2571 continue;
2572
02ce5a79
DL
2573 /* We do not support mpo + odm at the moment */
2574 if (hsplit_pipe && hsplit_pipe->plane_state != pipe->plane_state
2575 && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx])
2576 goto validate_fail;
2577
b6bfba6c 2578 if (split[i]) {
7ed4e635
HW
2579 if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) {
2580 /* pipe not split previously needs split */
c681491a 2581 hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe);
b6bfba6c 2582 ASSERT(hsplit_pipe);
ff86391e
MS
2583 if (!hsplit_pipe) {
2584 context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] *= 2;
7ed4e635 2585 continue;
ff86391e 2586 }
b1f6d01c
DL
2587 if (context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) {
2588 if (!dcn20_split_stream_for_odm(
2589 &context->res_ctx, dc->res_pool,
2590 pipe, hsplit_pipe))
2591 goto validate_fail;
387596ef 2592 dcn20_build_mapped_resource(dc, context, pipe->stream);
b1f6d01c
DL
2593 } else
2594 dcn20_split_stream_for_mpc(
7ed4e635 2595 &context->res_ctx, dc->res_pool,
b1f6d01c 2596 pipe, hsplit_pipe);
7ed4e635
HW
2597 pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx;
2598 }
02ce5a79 2599 } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) {
7ed4e635
HW
2600 /* merge should already have been done */
2601 ASSERT(0);
2602 }
2603 }
0ba37b20 2604 /* Actual dsc count per stream dsc validation*/
c84ad0d6 2605 if (!dcn20_validate_dsc(dc, context)) {
0ba37b20
DL
2606 context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states] =
2607 DML_FAIL_DSC_VALIDATION_FAILURE;
2608 goto validate_fail;
2609 }
7ed4e635 2610
6de20237 2611 *vlevel_out = vlevel;
42351c66 2612
6de20237
EY
2613 out = true;
2614 goto validate_out;
2615
2616validate_fail:
2617 out = false;
2618
2619validate_out:
2620 return out;
2621}
2622
e2e316d5 2623static void dcn20_calculate_wm(
6de20237
EY
2624 struct dc *dc, struct dc_state *context,
2625 display_e2e_pipe_params_st *pipes,
2626 int *out_pipe_cnt,
2627 int *pipe_split_from,
2628 int vlevel)
2629{
2630 int pipe_cnt, i, pipe_idx;
254eb07c 2631
7ed4e635 2632 for (i = 0, pipe_idx = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
41f03a6d
DL
2633 if (!context->res_ctx.pipe_ctx[i].stream)
2634 continue;
7ed4e635 2635
41f03a6d
DL
2636 pipes[pipe_cnt].clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0;
2637 pipes[pipe_cnt].clks_cfg.dispclk_mhz = context->bw_ctx.dml.vba.RequiredDISPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
7ed4e635 2638
41f03a6d
DL
2639 if (pipe_split_from[i] < 0) {
2640 pipes[pipe_cnt].clks_cfg.dppclk_mhz =
2641 context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx];
2642 if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_idx] == pipe_idx)
2643 pipes[pipe_cnt].pipe.dest.odm_combine =
b6bfba6c 2644 context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx];
41f03a6d
DL
2645 else
2646 pipes[pipe_cnt].pipe.dest.odm_combine = 0;
2647 pipe_idx++;
2648 } else {
2649 pipes[pipe_cnt].clks_cfg.dppclk_mhz =
2650 context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_split_from[i]];
2651 if (context->bw_ctx.dml.vba.BlendingAndTiming[pipe_split_from[i]] == pipe_split_from[i])
2652 pipes[pipe_cnt].pipe.dest.odm_combine =
b6bfba6c 2653 context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_split_from[i]];
41f03a6d
DL
2654 else
2655 pipes[pipe_cnt].pipe.dest.odm_combine = 0;
7ed4e635 2656 }
6de20237 2657
41f03a6d
DL
2658 if (dc->config.forced_clocks) {
2659 pipes[pipe_cnt].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
2660 pipes[pipe_cnt].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
a6465d1f 2661 }
41f03a6d
DL
2662 if (dc->debug.min_disp_clk_khz > pipes[pipe_cnt].clks_cfg.dispclk_mhz * 1000)
2663 pipes[pipe_cnt].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
2664 if (dc->debug.min_dpp_clk_khz > pipes[pipe_cnt].clks_cfg.dppclk_mhz * 1000)
2665 pipes[pipe_cnt].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
2666
2667 pipe_cnt++;
2668 }
7ed4e635 2669
41f03a6d
DL
2670 if (pipe_cnt != pipe_idx) {
2671 if (dc->res_pool->funcs->populate_dml_pipes)
2672 pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc,
2f488884 2673 context, pipes);
41f03a6d
DL
2674 else
2675 pipe_cnt = dcn20_populate_dml_pipes_from_context(dc,
2f488884 2676 context, pipes);
41f03a6d 2677 }
7ed4e635 2678
41f03a6d 2679 *out_pipe_cnt = pipe_cnt;
6de20237 2680
41f03a6d
DL
2681 pipes[0].clks_cfg.voltage = vlevel;
2682 pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].dcfclk_mhz;
2683 pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz;
2684
2685 /* only pipe 0 is read for voltage and dcf/soc clocks */
2686 if (vlevel < 1) {
2687 pipes[0].clks_cfg.voltage = 1;
2688 pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[1].dcfclk_mhz;
2689 pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[1].socclk_mhz;
2690 }
2691 context->bw_ctx.bw.dcn.watermarks.b.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2692 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;
2693 context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2694 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;
2695 context->bw_ctx.bw.dcn.watermarks.b.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
4de094ee
BL
2696 context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2697 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;
b617b265 2698 context->bw_ctx.bw.dcn.watermarks.b.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
41f03a6d
DL
2699
2700 if (vlevel < 2) {
2701 pipes[0].clks_cfg.voltage = 2;
2702 pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].dcfclk_mhz;
2703 pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].socclk_mhz;
2704 }
2705 context->bw_ctx.bw.dcn.watermarks.c.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2706 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;
2707 context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2708 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;
2709 context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
4de094ee
BL
2710 context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2711 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;
41f03a6d
DL
2712
2713 if (vlevel < 3) {
2714 pipes[0].clks_cfg.voltage = 3;
2715 pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].dcfclk_mhz;
2716 pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[2].socclk_mhz;
2717 }
2718 context->bw_ctx.bw.dcn.watermarks.d.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2719 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;
2720 context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2721 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;
2722 context->bw_ctx.bw.dcn.watermarks.d.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
4de094ee
BL
2723 context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2724 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;
41f03a6d
DL
2725
2726 pipes[0].clks_cfg.voltage = vlevel;
2727 pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].dcfclk_mhz;
2728 pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz;
2729 context->bw_ctx.bw.dcn.watermarks.a.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2730 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;
2731 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2732 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;
2733 context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
4de094ee
BL
2734 context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
2735 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;
6de20237
EY
2736}
2737
2738void dcn20_calculate_dlg_params(
2739 struct dc *dc, struct dc_state *context,
2740 display_e2e_pipe_params_st *pipes,
2741 int pipe_cnt,
2742 int vlevel)
2743{
41f03a6d
DL
2744 int i, j, pipe_idx, pipe_idx_unsplit;
2745 bool visited[MAX_PIPES] = { 0 };
8e27a2d4 2746
7ed4e635
HW
2747 /* Writeback MCIF_WB arbitration parameters */
2748 dc->res_pool->funcs->set_mcif_arb_params(dc, context, pipes, pipe_cnt);
2749
2750 context->bw_ctx.bw.dcn.clk.dispclk_khz = context->bw_ctx.dml.vba.DISPCLK * 1000;
2751 context->bw_ctx.bw.dcn.clk.dcfclk_khz = context->bw_ctx.dml.vba.DCFCLK * 1000;
2752 context->bw_ctx.bw.dcn.clk.socclk_khz = context->bw_ctx.dml.vba.SOCCLK * 1000;
173932de 2753 context->bw_ctx.bw.dcn.clk.dramclk_khz = context->bw_ctx.dml.vba.DRAMSpeed * 1000 / 16;
7ed4e635 2754 context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = context->bw_ctx.dml.vba.DCFCLKDeepSleep * 1000;
799c5b9c 2755 context->bw_ctx.bw.dcn.clk.fclk_khz = context->bw_ctx.dml.vba.FabricClock * 1000;
7ed4e635
HW
2756 context->bw_ctx.bw.dcn.clk.p_state_change_support =
2757 context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb]
2758 != dm_dram_clock_change_unsupported;
2759 context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
2760
41f03a6d
DL
2761 /*
2762 * An artifact of dml pipe split/odm is that pipes get merged back together for
2763 * calculation. Therefore we need to only extract for first pipe in ascending index order
2764 * and copy into the other split half.
2765 */
2766 for (i = 0, pipe_idx = 0, pipe_idx_unsplit = 0; i < dc->res_pool->pipe_count; i++) {
2767 if (!context->res_ctx.pipe_ctx[i].stream)
2768 continue;
6de20237 2769
41f03a6d 2770 if (!visited[pipe_idx]) {
74df06dd
DL
2771 display_pipe_source_params_st *src = &pipes[pipe_idx].pipe.src;
2772 display_pipe_dest_params_st *dst = &pipes[pipe_idx].pipe.dest;
41f03a6d
DL
2773
2774 dst->vstartup_start = context->bw_ctx.dml.vba.VStartup[pipe_idx_unsplit];
2775 dst->vupdate_offset = context->bw_ctx.dml.vba.VUpdateOffsetPix[pipe_idx_unsplit];
2776 dst->vupdate_width = context->bw_ctx.dml.vba.VUpdateWidthPix[pipe_idx_unsplit];
2777 dst->vready_offset = context->bw_ctx.dml.vba.VReadyOffsetPix[pipe_idx_unsplit];
2778 /*
2779 * j iterates inside pipes array, unlike i which iterates inside
2780 * pipe_ctx array
2781 */
2782 if (src->is_hsplit)
2783 for (j = pipe_idx + 1; j < pipe_cnt; j++) {
2784 display_pipe_source_params_st *src_j = &pipes[j].pipe.src;
2785 display_pipe_dest_params_st *dst_j = &pipes[j].pipe.dest;
2786
2787 if (src_j->is_hsplit && !visited[j]
2788 && src->hsplit_grp == src_j->hsplit_grp) {
2789 dst_j->vstartup_start = context->bw_ctx.dml.vba.VStartup[pipe_idx_unsplit];
2790 dst_j->vupdate_offset = context->bw_ctx.dml.vba.VUpdateOffsetPix[pipe_idx_unsplit];
2791 dst_j->vupdate_width = context->bw_ctx.dml.vba.VUpdateWidthPix[pipe_idx_unsplit];
2792 dst_j->vready_offset = context->bw_ctx.dml.vba.VReadyOffsetPix[pipe_idx_unsplit];
2793 visited[j] = true;
2794 }
2795 }
2796 visited[pipe_idx] = true;
2797 pipe_idx_unsplit++;
2798 }
2799 pipe_idx++;
2800 }
42351c66 2801
7ed4e635
HW
2802 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
2803 if (!context->res_ctx.pipe_ctx[i].stream)
2804 continue;
7ed4e635
HW
2805 if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
2806 context->bw_ctx.bw.dcn.clk.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
2807 context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz =
2808 pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
41f03a6d 2809 ASSERT(visited[pipe_idx]);
7ed4e635
HW
2810 context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest;
2811 pipe_idx++;
2812 }
925f566c
CL
2813 /*save a original dppclock copy*/
2814 context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
2815 context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
41f03a6d
DL
2816 context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dppclk_mhz * 1000;
2817 context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dispclk_mhz * 1000;
7ed4e635
HW
2818
2819 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
2820 bool cstate_en = context->bw_ctx.dml.vba.PrefetchMode[vlevel][context->bw_ctx.dml.vba.maxMpcComb] != 2;
2821
2822 if (!context->res_ctx.pipe_ctx[i].stream)
2823 continue;
2824
2825 context->bw_ctx.dml.funcs.rq_dlg_get_dlg_reg(&context->bw_ctx.dml,
2826 &context->res_ctx.pipe_ctx[i].dlg_regs,
2827 &context->res_ctx.pipe_ctx[i].ttu_regs,
2828 pipes,
2829 pipe_cnt,
2830 pipe_idx,
2831 cstate_en,
f82c916c
CL
2832 context->bw_ctx.bw.dcn.clk.p_state_change_support,
2833 false, false, false);
254eb07c 2834
7ed4e635
HW
2835 context->bw_ctx.dml.funcs.rq_dlg_get_rq_reg(&context->bw_ctx.dml,
2836 &context->res_ctx.pipe_ctx[i].rq_regs,
2837 pipes[pipe_idx].pipe);
2838 pipe_idx++;
2839 }
6de20237
EY
2840}
2841
057fc695 2842static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *context,
6de20237
EY
2843 bool fast_validate)
2844{
2845 bool out = false;
2846
2847 BW_VAL_TRACE_SETUP();
2848
2849 int vlevel = 0;
2850 int pipe_split_from[MAX_PIPES];
2851 int pipe_cnt = 0;
2852 display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
2853 DC_LOGGER_INIT(dc->ctx->logger);
2854
2855 BW_VAL_TRACE_COUNT();
2856
5e335add
EY
2857 out = dcn20_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel);
2858
2859 if (pipe_cnt == 0)
2860 goto validate_out;
6de20237
EY
2861
2862 if (!out)
2863 goto validate_fail;
2864
2865 BW_VAL_TRACE_END_VOLTAGE_LEVEL();
2866
2867 if (fast_validate) {
2868 BW_VAL_TRACE_SKIP(fast);
2869 goto validate_out;
2870 }
2871
2872 dcn20_calculate_wm(dc, context, pipes, &pipe_cnt, pipe_split_from, vlevel);
2873 dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
2874
2875 BW_VAL_TRACE_END_WATERMARKS();
7ed4e635 2876
254eb07c 2877 goto validate_out;
7ed4e635
HW
2878
2879validate_fail:
00999d99
DL
2880 DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n",
2881 dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states]));
254eb07c 2882
42351c66 2883 BW_VAL_TRACE_SKIP(fail);
254eb07c
JA
2884 out = false;
2885
2886validate_out:
7ed4e635 2887 kfree(pipes);
254eb07c 2888
42351c66
JA
2889 BW_VAL_TRACE_FINISH();
2890
254eb07c 2891 return out;
7ed4e635
HW
2892}
2893
057fc695
JL
2894
2895bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
2896 bool fast_validate)
2897{
2898 bool voltage_supported = false;
2899 bool full_pstate_supported = false;
2900 bool dummy_pstate_supported = false;
7a8a3430 2901 double p_state_latency_us;
057fc695 2902
7a8a3430
TP
2903 DC_FP_START();
2904 p_state_latency_us = context->bw_ctx.dml.soc.dram_clock_change_latency_us;
2905 context->bw_ctx.dml.soc.disable_dram_clock_change_vactive_support =
2906 dc->debug.disable_dram_clock_change_vactive_support;
057fc695 2907
7a8a3430
TP
2908 if (fast_validate) {
2909 voltage_supported = dcn20_validate_bandwidth_internal(dc, context, true);
2910
2911 DC_FP_END();
2912 return voltage_supported;
2913 }
057fc695
JL
2914
2915 // Best case, we support full UCLK switch latency
2916 voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false);
2917 full_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;
2918
2919 if (context->bw_ctx.dml.soc.dummy_pstate_latency_us == 0 ||
2920 (voltage_supported && full_pstate_supported)) {
30c9b7a1 2921 context->bw_ctx.bw.dcn.clk.p_state_change_support = full_pstate_supported;
057fc695
JL
2922 goto restore_dml_state;
2923 }
2924
b9e8d95a 2925 // Fallback: Try to only support G6 temperature read latency
057fc695
JL
2926 context->bw_ctx.dml.soc.dram_clock_change_latency_us = context->bw_ctx.dml.soc.dummy_pstate_latency_us;
2927
2928 voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false);
2929 dummy_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;
2930
2931 if (voltage_supported && dummy_pstate_supported) {
2932 context->bw_ctx.bw.dcn.clk.p_state_change_support = false;
2933 goto restore_dml_state;
2934 }
2935
b9e8d95a 2936 // ERROR: fallback is supposed to always work.
057fc695
JL
2937 ASSERT(false);
2938
2939restore_dml_state:
057fc695
JL
2940 context->bw_ctx.dml.soc.dram_clock_change_latency_us = p_state_latency_us;
2941
7a8a3430 2942 DC_FP_END();
057fc695
JL
2943 return voltage_supported;
2944}
2945
7ed4e635
HW
2946struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer(
2947 struct dc_state *state,
2948 const struct resource_pool *pool,
2949 struct dc_stream_state *stream)
2950{
2951 struct resource_context *res_ctx = &state->res_ctx;
2952 struct pipe_ctx *head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
2953 struct pipe_ctx *idle_pipe = find_idle_secondary_pipe(res_ctx, pool, head_pipe);
2954
2955 if (!head_pipe)
2956 ASSERT(0);
2957
2958 if (!idle_pipe)
7a17c8ce 2959 return NULL;
7ed4e635
HW
2960
2961 idle_pipe->stream = head_pipe->stream;
2962 idle_pipe->stream_res.tg = head_pipe->stream_res.tg;
2963 idle_pipe->stream_res.opp = head_pipe->stream_res.opp;
2964
2965 idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx];
2966 idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx];
2967 idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx];
2968 idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst;
2969
2970 return idle_pipe;
2971}
2972
2973bool dcn20_get_dcc_compression_cap(const struct dc *dc,
2974 const struct dc_dcc_surface_param *input,
2975 struct dc_surface_dcc_cap *output)
2976{
2977 return dc->res_pool->hubbub->funcs->get_dcc_compression_cap(
2978 dc->res_pool->hubbub,
2979 input,
2980 output);
2981}
2982
2983static void dcn20_destroy_resource_pool(struct resource_pool **pool)
2984{
2985 struct dcn20_resource_pool *dcn20_pool = TO_DCN20_RES_POOL(*pool);
2986
d9e32672 2987 dcn20_resource_destruct(dcn20_pool);
7ed4e635
HW
2988 kfree(dcn20_pool);
2989 *pool = NULL;
2990}
2991
2992
2993static struct dc_cap_funcs cap_funcs = {
2994 .get_dcc_compression_cap = dcn20_get_dcc_compression_cap
2995};
2996
2997
2998enum dc_status dcn20_get_default_swizzle_mode(struct dc_plane_state *plane_state)
2999{
3000 enum dc_status result = DC_OK;
3001
3002 enum surface_pixel_format surf_pix_format = plane_state->format;
3003 unsigned int bpp = resource_pixel_format_to_bpp(surf_pix_format);
3004
3005 enum swizzle_mode_values swizzle = DC_SW_LINEAR;
3006
3007 if (bpp == 64)
3008 swizzle = DC_SW_64KB_D;
3009 else
3010 swizzle = DC_SW_64KB_S;
3011
3012 plane_state->tiling_info.gfx9.swizzle = swizzle;
3013 return result;
3014}
3015
3016static struct resource_funcs dcn20_res_pool_funcs = {
3017 .destroy = dcn20_destroy_resource_pool,
3018 .link_enc_create = dcn20_link_encoder_create,
3019 .validate_bandwidth = dcn20_validate_bandwidth,
7ed4e635
HW
3020 .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
3021 .add_stream_to_ctx = dcn20_add_stream_to_ctx,
3022 .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
3023 .populate_dml_writeback_from_context = dcn20_populate_dml_writeback_from_context,
3024 .get_default_swizzle_mode = dcn20_get_default_swizzle_mode,
c9ae6e16 3025 .set_mcif_arb_params = dcn20_set_mcif_arb_params,
b6bfba6c 3026 .populate_dml_pipes = dcn20_populate_dml_pipes_from_context,
278141f5 3027 .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link
7ed4e635
HW
3028};
3029
bb21290f
CL
3030bool dcn20_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)
3031{
3032 int i;
3033 uint32_t pipe_count = pool->res_cap->num_dwb;
3034
bb21290f
CL
3035 for (i = 0; i < pipe_count; i++) {
3036 struct dcn20_dwbc *dwbc20 = kzalloc(sizeof(struct dcn20_dwbc),
3037 GFP_KERNEL);
3038
3039 if (!dwbc20) {
3040 dm_error("DC: failed to create dwbc20!\n");
3041 return false;
3042 }
3043 dcn20_dwbc_construct(dwbc20, ctx,
3044 &dwbc20_regs[i],
3045 &dwbc20_shift,
3046 &dwbc20_mask,
3047 i);
3048 pool->dwbc[i] = &dwbc20->base;
3049 }
3050 return true;
3051}
3052
3053bool dcn20_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool)
3054{
3055 int i;
3056 uint32_t pipe_count = pool->res_cap->num_dwb;
3057
3058 ASSERT(pipe_count > 0);
3059
3060 for (i = 0; i < pipe_count; i++) {
3061 struct dcn20_mmhubbub *mcif_wb20 = kzalloc(sizeof(struct dcn20_mmhubbub),
3062 GFP_KERNEL);
3063
3064 if (!mcif_wb20) {
3065 dm_error("DC: failed to create mcif_wb20!\n");
3066 return false;
3067 }
3068
3069 dcn20_mmhubbub_construct(mcif_wb20, ctx,
3070 &mcif_wb20_regs[i],
3071 &mcif_wb20_shift,
3072 &mcif_wb20_mask,
3073 i);
3074
3075 pool->mcif_wb[i] = &mcif_wb20->base;
3076 }
3077 return true;
3078}
3079
44e149bb 3080static struct pp_smu_funcs *dcn20_pp_smu_create(struct dc_context *ctx)
7ed4e635
HW
3081{
3082 struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL);
3083
3084 if (!pp_smu)
3085 return pp_smu;
3086
3087 dm_pp_get_funcs(ctx, pp_smu);
3088
3089 if (pp_smu->ctx.ver != PP_SMU_VER_NV)
3090 pp_smu = memset(pp_smu, 0, sizeof(struct pp_smu_funcs));
3091
3092 return pp_smu;
3093}
3094
44e149bb 3095static void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu)
7ed4e635
HW
3096{
3097 if (pp_smu && *pp_smu) {
3098 kfree(*pp_smu);
3099 *pp_smu = NULL;
3100 }
3101}
3102
44ce0cd3 3103void dcn20_cap_soc_clocks(
7ed4e635
HW
3104 struct _vcs_dpi_soc_bounding_box_st *bb,
3105 struct pp_smu_nv_clock_table max_clocks)
3106{
3107 int i;
3108
3109 // First pass - cap all clocks higher than the reported max
3110 for (i = 0; i < bb->num_states; i++) {
3111 if ((bb->clock_limits[i].dcfclk_mhz > (max_clocks.dcfClockInKhz / 1000))
3112 && max_clocks.dcfClockInKhz != 0)
3113 bb->clock_limits[i].dcfclk_mhz = (max_clocks.dcfClockInKhz / 1000);
3114
3115 if ((bb->clock_limits[i].dram_speed_mts > (max_clocks.uClockInKhz / 1000) * 16)
3116 && max_clocks.uClockInKhz != 0)
3117 bb->clock_limits[i].dram_speed_mts = (max_clocks.uClockInKhz / 1000) * 16;
3118
3119 if ((bb->clock_limits[i].fabricclk_mhz > (max_clocks.fabricClockInKhz / 1000))
3120 && max_clocks.fabricClockInKhz != 0)
3121 bb->clock_limits[i].fabricclk_mhz = (max_clocks.fabricClockInKhz / 1000);
3122
3123 if ((bb->clock_limits[i].dispclk_mhz > (max_clocks.displayClockInKhz / 1000))
3124 && max_clocks.displayClockInKhz != 0)
3125 bb->clock_limits[i].dispclk_mhz = (max_clocks.displayClockInKhz / 1000);
3126
3127 if ((bb->clock_limits[i].dppclk_mhz > (max_clocks.dppClockInKhz / 1000))
3128 && max_clocks.dppClockInKhz != 0)
3129 bb->clock_limits[i].dppclk_mhz = (max_clocks.dppClockInKhz / 1000);
3130
3131 if ((bb->clock_limits[i].phyclk_mhz > (max_clocks.phyClockInKhz / 1000))
3132 && max_clocks.phyClockInKhz != 0)
3133 bb->clock_limits[i].phyclk_mhz = (max_clocks.phyClockInKhz / 1000);
3134
3135 if ((bb->clock_limits[i].socclk_mhz > (max_clocks.socClockInKhz / 1000))
3136 && max_clocks.socClockInKhz != 0)
3137 bb->clock_limits[i].socclk_mhz = (max_clocks.socClockInKhz / 1000);
3138
3139 if ((bb->clock_limits[i].dscclk_mhz > (max_clocks.dscClockInKhz / 1000))
3140 && max_clocks.dscClockInKhz != 0)
3141 bb->clock_limits[i].dscclk_mhz = (max_clocks.dscClockInKhz / 1000);
3142 }
3143
3144 // Second pass - remove all duplicate clock states
3145 for (i = bb->num_states - 1; i > 1; i--) {
3146 bool duplicate = true;
3147
3148 if (bb->clock_limits[i-1].dcfclk_mhz != bb->clock_limits[i].dcfclk_mhz)
3149 duplicate = false;
3150 if (bb->clock_limits[i-1].dispclk_mhz != bb->clock_limits[i].dispclk_mhz)
3151 duplicate = false;
3152 if (bb->clock_limits[i-1].dppclk_mhz != bb->clock_limits[i].dppclk_mhz)
3153 duplicate = false;
3154 if (bb->clock_limits[i-1].dram_speed_mts != bb->clock_limits[i].dram_speed_mts)
3155 duplicate = false;
3156 if (bb->clock_limits[i-1].dscclk_mhz != bb->clock_limits[i].dscclk_mhz)
3157 duplicate = false;
3158 if (bb->clock_limits[i-1].fabricclk_mhz != bb->clock_limits[i].fabricclk_mhz)
3159 duplicate = false;
3160 if (bb->clock_limits[i-1].phyclk_mhz != bb->clock_limits[i].phyclk_mhz)
3161 duplicate = false;
3162 if (bb->clock_limits[i-1].socclk_mhz != bb->clock_limits[i].socclk_mhz)
3163 duplicate = false;
3164
3165 if (duplicate)
3166 bb->num_states--;
3167 }
3168}
3169
44ce0cd3 3170void dcn20_update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb,
7ed4e635
HW
3171 struct pp_smu_nv_clock_table *max_clocks, unsigned int *uclk_states, unsigned int num_states)
3172{
960b6f4f 3173 struct _vcs_dpi_voltage_scaling_st calculated_states[MAX_CLOCK_LIMIT_STATES];
f18bc4e5 3174 int i;
7ed4e635 3175 int num_calculated_states = 0;
f18bc4e5 3176 int min_dcfclk = 0;
7ed4e635
HW
3177
3178 if (num_states == 0)
3179 return;
3180
960b6f4f
RR
3181 memset(calculated_states, 0, sizeof(calculated_states));
3182
f18bc4e5
JL
3183 if (dc->bb_overrides.min_dcfclk_mhz > 0)
3184 min_dcfclk = dc->bb_overrides.min_dcfclk_mhz;
6ce2427d
AL
3185 else {
3186 if (ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev))
3187 min_dcfclk = 310;
3188 else
3189 // Accounting for SOC/DCF relationship, we can go as high as
3190 // 506Mhz in Vmin.
3191 min_dcfclk = 506;
3192 }
f18bc4e5 3193
7ed4e635 3194 for (i = 0; i < num_states; i++) {
f18bc4e5
JL
3195 int min_fclk_required_by_uclk;
3196 calculated_states[i].state = i;
3197 calculated_states[i].dram_speed_mts = uclk_states[i] * 16 / 1000;
7ed4e635 3198
5d36f783 3199 // FCLK:UCLK ratio is 1.08
5f65ae34 3200 min_fclk_required_by_uclk = mul_u64_u32_shr(BIT_ULL(32) * 1080 / 1000000, uclk_states[i], 32);
7ed4e635 3201
f18bc4e5
JL
3202 calculated_states[i].fabricclk_mhz = (min_fclk_required_by_uclk < min_dcfclk) ?
3203 min_dcfclk : min_fclk_required_by_uclk;
7ed4e635 3204
f18bc4e5
JL
3205 calculated_states[i].socclk_mhz = (calculated_states[i].fabricclk_mhz > max_clocks->socClockInKhz / 1000) ?
3206 max_clocks->socClockInKhz / 1000 : calculated_states[i].fabricclk_mhz;
7ed4e635 3207
f18bc4e5
JL
3208 calculated_states[i].dcfclk_mhz = (calculated_states[i].fabricclk_mhz > max_clocks->dcfClockInKhz / 1000) ?
3209 max_clocks->dcfClockInKhz / 1000 : calculated_states[i].fabricclk_mhz;
7ed4e635 3210
f18bc4e5
JL
3211 calculated_states[i].dispclk_mhz = max_clocks->displayClockInKhz / 1000;
3212 calculated_states[i].dppclk_mhz = max_clocks->displayClockInKhz / 1000;
3213 calculated_states[i].dscclk_mhz = max_clocks->displayClockInKhz / (1000 * 3);
7ed4e635 3214
f18bc4e5 3215 calculated_states[i].phyclk_mhz = max_clocks->phyClockInKhz / 1000;
7ed4e635 3216
f18bc4e5 3217 num_calculated_states++;
7ed4e635
HW
3218 }
3219
6da16270
JL
3220 calculated_states[num_calculated_states - 1].socclk_mhz = max_clocks->socClockInKhz / 1000;
3221 calculated_states[num_calculated_states - 1].fabricclk_mhz = max_clocks->socClockInKhz / 1000;
3222 calculated_states[num_calculated_states - 1].dcfclk_mhz = max_clocks->dcfClockInKhz / 1000;
3223
7ed4e635
HW
3224 memcpy(bb->clock_limits, calculated_states, sizeof(bb->clock_limits));
3225 bb->num_states = num_calculated_states;
f18bc4e5
JL
3226
3227 // Duplicate the last state, DML always an extra state identical to max state to work
3228 memcpy(&bb->clock_limits[num_calculated_states], &bb->clock_limits[num_calculated_states - 1], sizeof(struct _vcs_dpi_voltage_scaling_st));
3229 bb->clock_limits[num_calculated_states].state = bb->num_states;
7ed4e635
HW
3230}
3231
44ce0cd3 3232void dcn20_patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb)
7ed4e635 3233{
7ed4e635
HW
3234 if ((int)(bb->sr_exit_time_us * 1000) != dc->bb_overrides.sr_exit_time_ns
3235 && dc->bb_overrides.sr_exit_time_ns) {
3236 bb->sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
3237 }
3238
3239 if ((int)(bb->sr_enter_plus_exit_time_us * 1000)
3240 != dc->bb_overrides.sr_enter_plus_exit_time_ns
3241 && dc->bb_overrides.sr_enter_plus_exit_time_ns) {
3242 bb->sr_enter_plus_exit_time_us =
3243 dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
3244 }
3245
3246 if ((int)(bb->urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns
3247 && dc->bb_overrides.urgent_latency_ns) {
3248 bb->urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
3249 }
3250
3251 if ((int)(bb->dram_clock_change_latency_us * 1000)
3252 != dc->bb_overrides.dram_clock_change_latency_ns
3253 && dc->bb_overrides.dram_clock_change_latency_ns) {
3254 bb->dram_clock_change_latency_us =
3255 dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
3256 }
7ed4e635
HW
3257}
3258
675a9e38
LL
3259static struct _vcs_dpi_soc_bounding_box_st *get_asic_rev_soc_bb(
3260 uint32_t hw_internal_rev)
3261{
3262 if (ASICREV_IS_NAVI12_P(hw_internal_rev))
3263 return &dcn2_0_nv12_soc;
3264
3265 return &dcn2_0_soc;
3266}
3267
3268static struct _vcs_dpi_ip_params_st *get_asic_rev_ip_params(
3269 uint32_t hw_internal_rev)
3270{
72b741af
Z
3271 /* NV14 */
3272 if (ASICREV_IS_NAVI14_M(hw_internal_rev))
3273 return &dcn2_0_nv14_ip;
3274
675a9e38
LL
3275 /* NV12 and NV10 */
3276 return &dcn2_0_ip;
3277}
3278
3279static enum dml_project get_dml_project_version(uint32_t hw_internal_rev)
3280{
3281 return DML_PROJECT_NAVI10v2;
3282}
3283
7ed4e635
HW
3284#define fixed16_to_double(x) (((double) x) / ((double) (1 << 16)))
3285#define fixed16_to_double_to_cpu(x) fixed16_to_double(le32_to_cpu(x))
3286
3287static bool init_soc_bounding_box(struct dc *dc,
3288 struct dcn20_resource_pool *pool)
3289{
3290 const struct gpu_info_soc_bounding_box_v1_0 *bb = dc->soc_bounding_box;
675a9e38
LL
3291 struct _vcs_dpi_soc_bounding_box_st *loaded_bb =
3292 get_asic_rev_soc_bb(dc->ctx->asic_id.hw_internal_rev);
3293 struct _vcs_dpi_ip_params_st *loaded_ip =
3294 get_asic_rev_ip_params(dc->ctx->asic_id.hw_internal_rev);
3295
7ed4e635
HW
3296 DC_LOGGER_INIT(dc->ctx->logger);
3297
3e0c55f3
ZL
3298 /* TODO: upstream NV12 bounding box when its launched */
3299 if (!bb && ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev)) {
7ed4e635
HW
3300 DC_LOG_ERROR("%s: not valid soc bounding box/n", __func__);
3301 return false;
3302 }
3303
3e0c55f3 3304 if (bb && ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev)) {
7ed4e635
HW
3305 int i;
3306
675a9e38 3307 dcn2_0_nv12_soc.sr_exit_time_us =
7ed4e635 3308 fixed16_to_double_to_cpu(bb->sr_exit_time_us);
675a9e38 3309 dcn2_0_nv12_soc.sr_enter_plus_exit_time_us =
7ed4e635 3310 fixed16_to_double_to_cpu(bb->sr_enter_plus_exit_time_us);
675a9e38 3311 dcn2_0_nv12_soc.urgent_latency_us =
7ed4e635 3312 fixed16_to_double_to_cpu(bb->urgent_latency_us);
675a9e38 3313 dcn2_0_nv12_soc.urgent_latency_pixel_data_only_us =
7ed4e635 3314 fixed16_to_double_to_cpu(bb->urgent_latency_pixel_data_only_us);
675a9e38 3315 dcn2_0_nv12_soc.urgent_latency_pixel_mixed_with_vm_data_us =
7ed4e635 3316 fixed16_to_double_to_cpu(bb->urgent_latency_pixel_mixed_with_vm_data_us);
675a9e38 3317 dcn2_0_nv12_soc.urgent_latency_vm_data_only_us =
7ed4e635 3318 fixed16_to_double_to_cpu(bb->urgent_latency_vm_data_only_us);
675a9e38 3319 dcn2_0_nv12_soc.urgent_out_of_order_return_per_channel_pixel_only_bytes =
7ed4e635 3320 le32_to_cpu(bb->urgent_out_of_order_return_per_channel_pixel_only_bytes);
675a9e38 3321 dcn2_0_nv12_soc.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes =
7ed4e635 3322 le32_to_cpu(bb->urgent_out_of_order_return_per_channel_pixel_and_vm_bytes);
675a9e38 3323 dcn2_0_nv12_soc.urgent_out_of_order_return_per_channel_vm_only_bytes =
7ed4e635 3324 le32_to_cpu(bb->urgent_out_of_order_return_per_channel_vm_only_bytes);
675a9e38 3325 dcn2_0_nv12_soc.pct_ideal_dram_sdp_bw_after_urgent_pixel_only =
7ed4e635 3326 fixed16_to_double_to_cpu(bb->pct_ideal_dram_sdp_bw_after_urgent_pixel_only);
675a9e38 3327 dcn2_0_nv12_soc.pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm =
7ed4e635 3328 fixed16_to_double_to_cpu(bb->pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm);
675a9e38 3329 dcn2_0_nv12_soc.pct_ideal_dram_sdp_bw_after_urgent_vm_only =
7ed4e635 3330 fixed16_to_double_to_cpu(bb->pct_ideal_dram_sdp_bw_after_urgent_vm_only);
675a9e38 3331 dcn2_0_nv12_soc.max_avg_sdp_bw_use_normal_percent =
7ed4e635 3332 fixed16_to_double_to_cpu(bb->max_avg_sdp_bw_use_normal_percent);
675a9e38 3333 dcn2_0_nv12_soc.max_avg_dram_bw_use_normal_percent =
7ed4e635 3334 fixed16_to_double_to_cpu(bb->max_avg_dram_bw_use_normal_percent);
675a9e38 3335 dcn2_0_nv12_soc.writeback_latency_us =
7ed4e635 3336 fixed16_to_double_to_cpu(bb->writeback_latency_us);
675a9e38 3337 dcn2_0_nv12_soc.ideal_dram_bw_after_urgent_percent =
7ed4e635 3338 fixed16_to_double_to_cpu(bb->ideal_dram_bw_after_urgent_percent);
675a9e38 3339 dcn2_0_nv12_soc.max_request_size_bytes =
7ed4e635 3340 le32_to_cpu(bb->max_request_size_bytes);
675a9e38 3341 dcn2_0_nv12_soc.dram_channel_width_bytes =
7ed4e635 3342 le32_to_cpu(bb->dram_channel_width_bytes);
675a9e38 3343 dcn2_0_nv12_soc.fabric_datapath_to_dcn_data_return_bytes =
7ed4e635 3344 le32_to_cpu(bb->fabric_datapath_to_dcn_data_return_bytes);
675a9e38 3345 dcn2_0_nv12_soc.dcn_downspread_percent =
7ed4e635 3346 fixed16_to_double_to_cpu(bb->dcn_downspread_percent);
675a9e38 3347 dcn2_0_nv12_soc.downspread_percent =
7ed4e635 3348 fixed16_to_double_to_cpu(bb->downspread_percent);
675a9e38 3349 dcn2_0_nv12_soc.dram_page_open_time_ns =
7ed4e635 3350 fixed16_to_double_to_cpu(bb->dram_page_open_time_ns);
675a9e38 3351 dcn2_0_nv12_soc.dram_rw_turnaround_time_ns =
7ed4e635 3352 fixed16_to_double_to_cpu(bb->dram_rw_turnaround_time_ns);
675a9e38 3353 dcn2_0_nv12_soc.dram_return_buffer_per_channel_bytes =
7ed4e635 3354 le32_to_cpu(bb->dram_return_buffer_per_channel_bytes);
675a9e38 3355 dcn2_0_nv12_soc.round_trip_ping_latency_dcfclk_cycles =
7ed4e635 3356 le32_to_cpu(bb->round_trip_ping_latency_dcfclk_cycles);
675a9e38 3357 dcn2_0_nv12_soc.urgent_out_of_order_return_per_channel_bytes =
7ed4e635 3358 le32_to_cpu(bb->urgent_out_of_order_return_per_channel_bytes);
675a9e38 3359 dcn2_0_nv12_soc.channel_interleave_bytes =
7ed4e635 3360 le32_to_cpu(bb->channel_interleave_bytes);
675a9e38 3361 dcn2_0_nv12_soc.num_banks =
7ed4e635 3362 le32_to_cpu(bb->num_banks);
675a9e38 3363 dcn2_0_nv12_soc.num_chans =
7ed4e635 3364 le32_to_cpu(bb->num_chans);
675a9e38 3365 dcn2_0_nv12_soc.vmm_page_size_bytes =
7ed4e635 3366 le32_to_cpu(bb->vmm_page_size_bytes);
675a9e38 3367 dcn2_0_nv12_soc.dram_clock_change_latency_us =
7ed4e635 3368 fixed16_to_double_to_cpu(bb->dram_clock_change_latency_us);
675a9e38
LL
3369 // HACK!! Lower uclock latency switch time so we don't switch
3370 dcn2_0_nv12_soc.dram_clock_change_latency_us = 10;
3371 dcn2_0_nv12_soc.writeback_dram_clock_change_latency_us =
7ed4e635 3372 fixed16_to_double_to_cpu(bb->writeback_dram_clock_change_latency_us);
675a9e38 3373 dcn2_0_nv12_soc.return_bus_width_bytes =
7ed4e635 3374 le32_to_cpu(bb->return_bus_width_bytes);
675a9e38 3375 dcn2_0_nv12_soc.dispclk_dppclk_vco_speed_mhz =
7ed4e635 3376 le32_to_cpu(bb->dispclk_dppclk_vco_speed_mhz);
675a9e38 3377 dcn2_0_nv12_soc.xfc_bus_transport_time_us =
7ed4e635 3378 le32_to_cpu(bb->xfc_bus_transport_time_us);
675a9e38 3379 dcn2_0_nv12_soc.xfc_xbuf_latency_tolerance_us =
7ed4e635 3380 le32_to_cpu(bb->xfc_xbuf_latency_tolerance_us);
675a9e38 3381 dcn2_0_nv12_soc.use_urgent_burst_bw =
7ed4e635 3382 le32_to_cpu(bb->use_urgent_burst_bw);
675a9e38 3383 dcn2_0_nv12_soc.num_states =
7ed4e635
HW
3384 le32_to_cpu(bb->num_states);
3385
675a9e38
LL
3386 for (i = 0; i < dcn2_0_nv12_soc.num_states; i++) {
3387 dcn2_0_nv12_soc.clock_limits[i].state =
7ed4e635 3388 le32_to_cpu(bb->clock_limits[i].state);
675a9e38 3389 dcn2_0_nv12_soc.clock_limits[i].dcfclk_mhz =
7ed4e635 3390 fixed16_to_double_to_cpu(bb->clock_limits[i].dcfclk_mhz);
675a9e38 3391 dcn2_0_nv12_soc.clock_limits[i].fabricclk_mhz =
7ed4e635 3392 fixed16_to_double_to_cpu(bb->clock_limits[i].fabricclk_mhz);
675a9e38 3393 dcn2_0_nv12_soc.clock_limits[i].dispclk_mhz =
7ed4e635 3394 fixed16_to_double_to_cpu(bb->clock_limits[i].dispclk_mhz);
675a9e38 3395 dcn2_0_nv12_soc.clock_limits[i].dppclk_mhz =
7ed4e635 3396 fixed16_to_double_to_cpu(bb->clock_limits[i].dppclk_mhz);
675a9e38 3397 dcn2_0_nv12_soc.clock_limits[i].phyclk_mhz =
7ed4e635 3398 fixed16_to_double_to_cpu(bb->clock_limits[i].phyclk_mhz);
675a9e38 3399 dcn2_0_nv12_soc.clock_limits[i].socclk_mhz =
7ed4e635 3400 fixed16_to_double_to_cpu(bb->clock_limits[i].socclk_mhz);
675a9e38 3401 dcn2_0_nv12_soc.clock_limits[i].dscclk_mhz =
7ed4e635 3402 fixed16_to_double_to_cpu(bb->clock_limits[i].dscclk_mhz);
675a9e38 3403 dcn2_0_nv12_soc.clock_limits[i].dram_speed_mts =
7ed4e635
HW
3404 fixed16_to_double_to_cpu(bb->clock_limits[i].dram_speed_mts);
3405 }
3406 }
3407
3408 if (pool->base.pp_smu) {
3409 struct pp_smu_nv_clock_table max_clocks = {0};
3410 unsigned int uclk_states[8] = {0};
3411 unsigned int num_states = 0;
3412 enum pp_smu_status status;
3413 bool clock_limits_available = false;
3414 bool uclk_states_available = false;
3415
3416 if (pool->base.pp_smu->nv_funcs.get_uclk_dpm_states) {
3417 status = (pool->base.pp_smu->nv_funcs.get_uclk_dpm_states)
3418 (&pool->base.pp_smu->nv_funcs.pp_smu, uclk_states, &num_states);
3419
3420 uclk_states_available = (status == PP_SMU_RESULT_OK);
3421 }
3422
3423 if (pool->base.pp_smu->nv_funcs.get_maximum_sustainable_clocks) {
3424 status = (*pool->base.pp_smu->nv_funcs.get_maximum_sustainable_clocks)
3425 (&pool->base.pp_smu->nv_funcs.pp_smu, &max_clocks);
c2ad17c3
AW
3426 /* SMU cannot set DCF clock to anything equal to or higher than SOC clock
3427 */
3428 if (max_clocks.dcfClockInKhz >= max_clocks.socClockInKhz)
3429 max_clocks.dcfClockInKhz = max_clocks.socClockInKhz - 1000;
7ed4e635
HW
3430 clock_limits_available = (status == PP_SMU_RESULT_OK);
3431 }
3432
c2ad17c3 3433 if (clock_limits_available && uclk_states_available && num_states)
44ce0cd3 3434 dcn20_update_bounding_box(dc, loaded_bb, &max_clocks, uclk_states, num_states);
7ed4e635 3435 else if (clock_limits_available)
44ce0cd3 3436 dcn20_cap_soc_clocks(loaded_bb, max_clocks);
7ed4e635
HW
3437 }
3438
675a9e38
LL
3439 loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator;
3440 loaded_ip->max_num_dpp = pool->base.pipe_count;
44ce0cd3 3441 dcn20_patch_bounding_box(dc, loaded_bb);
7ed4e635
HW
3442
3443 return true;
3444}
3445
d9e32672 3446static bool dcn20_resource_construct(
7ed4e635
HW
3447 uint8_t num_virtual_links,
3448 struct dc *dc,
3449 struct dcn20_resource_pool *pool)
3450{
3451 int i;
3452 struct dc_context *ctx = dc->ctx;
3453 struct irq_service_init_data init_data;
d9a07577 3454 struct ddc_service_init_data ddc_init_data;
675a9e38
LL
3455 struct _vcs_dpi_soc_bounding_box_st *loaded_bb =
3456 get_asic_rev_soc_bb(ctx->asic_id.hw_internal_rev);
3457 struct _vcs_dpi_ip_params_st *loaded_ip =
3458 get_asic_rev_ip_params(ctx->asic_id.hw_internal_rev);
3459 enum dml_project dml_project_version =
3460 get_dml_project_version(ctx->asic_id.hw_internal_rev);
7ed4e635 3461
7a8a3430
TP
3462 DC_FP_START();
3463
7ed4e635 3464 ctx->dc_bios->regs = &bios_regs;
7ed4e635
HW
3465 pool->base.funcs = &dcn20_res_pool_funcs;
3466
2ebe1773
BL
3467 if (ASICREV_IS_NAVI14_M(ctx->asic_id.hw_internal_rev)) {
3468 pool->base.res_cap = &res_cap_nv14;
3469 pool->base.pipe_count = 5;
3470 pool->base.mpcc_count = 5;
3471 } else {
3472 pool->base.res_cap = &res_cap_nv10;
3473 pool->base.pipe_count = 6;
3474 pool->base.mpcc_count = 6;
3475 }
7ed4e635
HW
3476 /*************************************************
3477 * Resource + asic cap harcoding *
3478 *************************************************/
3479 pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
3480
7ed4e635
HW
3481 dc->caps.max_downscale_ratio = 200;
3482 dc->caps.i2c_speed_in_khz = 100;
3483 dc->caps.max_cursor_size = 256;
3484 dc->caps.dmdata_alloc_size = 2048;
3485
3486 dc->caps.max_slave_planes = 1;
3487 dc->caps.post_blend_color_processing = true;
3488 dc->caps.force_dp_tps4_for_cp2520 = true;
3489 dc->caps.hw_3d_lut = true;
ca4f844e 3490 dc->caps.extended_aux_timeout_support = true;
7ed4e635 3491
803a1412 3492 if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) {
7ed4e635 3493 dc->debug = debug_defaults_drv;
803a1412
ES
3494 } else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
3495 pool->base.pipe_count = 4;
7ed4e635
HW
3496 pool->base.mpcc_count = pool->base.pipe_count;
3497 dc->debug = debug_defaults_diags;
803a1412 3498 } else {
7ed4e635 3499 dc->debug = debug_defaults_diags;
803a1412 3500 }
7ed4e635
HW
3501 //dcn2.0x
3502 dc->work_arounds.dedcn20_305_wa = true;
3503
3504 // Init the vm_helper
3505 if (dc->vm_helper)
bda9afda 3506 vm_helper_init(dc->vm_helper, 16);
7ed4e635
HW
3507
3508 /*************************************************
3509 * Create resources *
3510 *************************************************/
3511
3512 pool->base.clock_sources[DCN20_CLK_SRC_PLL0] =
3513 dcn20_clock_source_create(ctx, ctx->dc_bios,
3514 CLOCK_SOURCE_COMBO_PHY_PLL0,
3515 &clk_src_regs[0], false);
3516 pool->base.clock_sources[DCN20_CLK_SRC_PLL1] =
3517 dcn20_clock_source_create(ctx, ctx->dc_bios,
3518 CLOCK_SOURCE_COMBO_PHY_PLL1,
3519 &clk_src_regs[1], false);
3520 pool->base.clock_sources[DCN20_CLK_SRC_PLL2] =
3521 dcn20_clock_source_create(ctx, ctx->dc_bios,
3522 CLOCK_SOURCE_COMBO_PHY_PLL2,
3523 &clk_src_regs[2], false);
3524 pool->base.clock_sources[DCN20_CLK_SRC_PLL3] =
3525 dcn20_clock_source_create(ctx, ctx->dc_bios,
3526 CLOCK_SOURCE_COMBO_PHY_PLL3,
3527 &clk_src_regs[3], false);
3528 pool->base.clock_sources[DCN20_CLK_SRC_PLL4] =
3529 dcn20_clock_source_create(ctx, ctx->dc_bios,
3530 CLOCK_SOURCE_COMBO_PHY_PLL4,
3531 &clk_src_regs[4], false);
3532 pool->base.clock_sources[DCN20_CLK_SRC_PLL5] =
3533 dcn20_clock_source_create(ctx, ctx->dc_bios,
3534 CLOCK_SOURCE_COMBO_PHY_PLL5,
3535 &clk_src_regs[5], false);
3536 pool->base.clk_src_count = DCN20_CLK_SRC_TOTAL;
3537 /* todo: not reuse phy_pll registers */
3538 pool->base.dp_clock_source =
3539 dcn20_clock_source_create(ctx, ctx->dc_bios,
3540 CLOCK_SOURCE_ID_DP_DTO,
3541 &clk_src_regs[0], true);
3542
3543 for (i = 0; i < pool->base.clk_src_count; i++) {
3544 if (pool->base.clock_sources[i] == NULL) {
3545 dm_error("DC: failed to create clock sources!\n");
3546 BREAK_TO_DEBUGGER();
3547 goto create_fail;
3548 }
3549 }
3550
3551 pool->base.dccg = dccg2_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask);
3552 if (pool->base.dccg == NULL) {
3553 dm_error("DC: failed to create dccg!\n");
3554 BREAK_TO_DEBUGGER();
3555 goto create_fail;
3556 }
3557
3558 pool->base.dmcu = dcn20_dmcu_create(ctx,
3559 &dmcu_regs,
3560 &dmcu_shift,
3561 &dmcu_mask);
3562 if (pool->base.dmcu == NULL) {
3563 dm_error("DC: failed to create dmcu!\n");
3564 BREAK_TO_DEBUGGER();
3565 goto create_fail;
3566 }
3567
d7c29549 3568 pool->base.abm = dce_abm_create(ctx,
7ed4e635
HW
3569 &abm_regs,
3570 &abm_shift,
3571 &abm_mask);
3572 if (pool->base.abm == NULL) {
3573 dm_error("DC: failed to create abm!\n");
3574 BREAK_TO_DEBUGGER();
3575 goto create_fail;
d7c29549 3576 }
7ed4e635
HW
3577
3578 pool->base.pp_smu = dcn20_pp_smu_create(ctx);
3579
3580
3581 if (!init_soc_bounding_box(dc, pool)) {
3582 dm_error("DC: failed to initialize soc bounding box!\n");
3583 BREAK_TO_DEBUGGER();
3584 goto create_fail;
3585 }
3586
675a9e38 3587 dml_init_instance(&dc->dml, loaded_bb, loaded_ip, dml_project_version);
7ed4e635
HW
3588
3589 if (!dc->debug.disable_pplib_wm_range) {
3590 struct pp_smu_wm_range_sets ranges = {0};
3591 int i = 0;
3592
3593 ranges.num_reader_wm_sets = 0;
3594
675a9e38 3595 if (loaded_bb->num_states == 1) {
7ed4e635
HW
3596 ranges.reader_wm_sets[0].wm_inst = i;
3597 ranges.reader_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
3598 ranges.reader_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
3599 ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
3600 ranges.reader_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
3601
3602 ranges.num_reader_wm_sets = 1;
675a9e38
LL
3603 } else if (loaded_bb->num_states > 1) {
3604 for (i = 0; i < 4 && i < loaded_bb->num_states; i++) {
7ed4e635
HW
3605 ranges.reader_wm_sets[i].wm_inst = i;
3606 ranges.reader_wm_sets[i].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
3607 ranges.reader_wm_sets[i].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
675a9e38
LL
3608 ranges.reader_wm_sets[i].min_fill_clk_mhz = (i > 0) ? (loaded_bb->clock_limits[i - 1].dram_speed_mts / 16) + 1 : 0;
3609 ranges.reader_wm_sets[i].max_fill_clk_mhz = loaded_bb->clock_limits[i].dram_speed_mts / 16;
7ed4e635
HW
3610
3611 ranges.num_reader_wm_sets = i + 1;
3612 }
7ed4e635 3613
5d36f783
JL
3614 ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
3615 ranges.reader_wm_sets[ranges.num_reader_wm_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
3616 }
7ed4e635
HW
3617
3618 ranges.num_writer_wm_sets = 1;
3619
3620 ranges.writer_wm_sets[0].wm_inst = 0;
3621 ranges.writer_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
3622 ranges.writer_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
3623 ranges.writer_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
3624 ranges.writer_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
3625
3626 /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */
3627 if (pool->base.pp_smu->nv_funcs.set_wm_ranges)
3628 pool->base.pp_smu->nv_funcs.set_wm_ranges(&pool->base.pp_smu->nv_funcs.pp_smu, &ranges);
3629 }
3630
3631 init_data.ctx = dc->ctx;
3632 pool->base.irqs = dal_irq_service_dcn20_create(&init_data);
3633 if (!pool->base.irqs)
3634 goto create_fail;
3635
3636 /* mem input -> ipp -> dpp -> opp -> TG */
3637 for (i = 0; i < pool->base.pipe_count; i++) {
3638 pool->base.hubps[i] = dcn20_hubp_create(ctx, i);
3639 if (pool->base.hubps[i] == NULL) {
3640 BREAK_TO_DEBUGGER();
3641 dm_error(
3642 "DC: failed to create memory input!\n");
3643 goto create_fail;
3644 }
3645
3646 pool->base.ipps[i] = dcn20_ipp_create(ctx, i);
3647 if (pool->base.ipps[i] == NULL) {
3648 BREAK_TO_DEBUGGER();
3649 dm_error(
3650 "DC: failed to create input pixel processor!\n");
3651 goto create_fail;
3652 }
3653
3654 pool->base.dpps[i] = dcn20_dpp_create(ctx, i);
3655 if (pool->base.dpps[i] == NULL) {
3656 BREAK_TO_DEBUGGER();
3657 dm_error(
3658 "DC: failed to create dpps!\n");
3659 goto create_fail;
3660 }
3661 }
3662 for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
3663 pool->base.engines[i] = dcn20_aux_engine_create(ctx, i);
3664 if (pool->base.engines[i] == NULL) {
3665 BREAK_TO_DEBUGGER();
3666 dm_error(
3667 "DC:failed to create aux engine!!\n");
3668 goto create_fail;
3669 }
3670 pool->base.hw_i2cs[i] = dcn20_i2c_hw_create(ctx, i);
3671 if (pool->base.hw_i2cs[i] == NULL) {
3672 BREAK_TO_DEBUGGER();
3673 dm_error(
3674 "DC:failed to create hw i2c!!\n");
3675 goto create_fail;
3676 }
3677 pool->base.sw_i2cs[i] = NULL;
3678 }
3679
3680 for (i = 0; i < pool->base.res_cap->num_opp; i++) {
3681 pool->base.opps[i] = dcn20_opp_create(ctx, i);
3682 if (pool->base.opps[i] == NULL) {
3683 BREAK_TO_DEBUGGER();
3684 dm_error(
3685 "DC: failed to create output pixel processor!\n");
3686 goto create_fail;
3687 }
3688 }
3689
3690 for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
3691 pool->base.timing_generators[i] = dcn20_timing_generator_create(
3692 ctx, i);
3693 if (pool->base.timing_generators[i] == NULL) {
3694 BREAK_TO_DEBUGGER();
3695 dm_error("DC: failed to create tg!\n");
3696 goto create_fail;
3697 }
3698 }
3699
3700 pool->base.timing_generator_count = i;
3701
3702 pool->base.mpc = dcn20_mpc_create(ctx);
3703 if (pool->base.mpc == NULL) {
3704 BREAK_TO_DEBUGGER();
3705 dm_error("DC: failed to create mpc!\n");
3706 goto create_fail;
3707 }
3708
3709 pool->base.hubbub = dcn20_hubbub_create(ctx);
3710 if (pool->base.hubbub == NULL) {
3711 BREAK_TO_DEBUGGER();
3712 dm_error("DC: failed to create hubbub!\n");
3713 goto create_fail;
3714 }
3715
97bda032
HW
3716 for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
3717 pool->base.dscs[i] = dcn20_dsc_create(ctx, i);
3718 if (pool->base.dscs[i] == NULL) {
3719 BREAK_TO_DEBUGGER();
3720 dm_error("DC: failed to create display stream compressor %d!\n", i);
3721 goto create_fail;
3722 }
3723 }
7ed4e635 3724
bb21290f
CL
3725 if (!dcn20_dwbc_create(ctx, &pool->base)) {
3726 BREAK_TO_DEBUGGER();
3727 dm_error("DC: failed to create dwbc!\n");
3728 goto create_fail;
3729 }
3730 if (!dcn20_mmhubbub_create(ctx, &pool->base)) {
3731 BREAK_TO_DEBUGGER();
3732 dm_error("DC: failed to create mcif_wb!\n");
3733 goto create_fail;
3734 }
3735
7ed4e635
HW
3736 if (!resource_construct(num_virtual_links, dc, &pool->base,
3737 (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
3738 &res_create_funcs : &res_create_maximus_funcs)))
3739 goto create_fail;
3740
3741 dcn20_hw_sequencer_construct(dc);
3742
3743 dc->caps.max_planes = pool->base.pipe_count;
3744
3745 for (i = 0; i < dc->caps.max_planes; ++i)
3746 dc->caps.planes[i] = plane_cap;
3747
3748 dc->cap_funcs = cap_funcs;
3749
d9a07577
JL
3750 if (dc->ctx->dc_bios->fw_info.oem_i2c_present) {
3751 ddc_init_data.ctx = dc->ctx;
3752 ddc_init_data.link = NULL;
3753 ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id;
3754 ddc_init_data.id.enum_id = 0;
3755 ddc_init_data.id.type = OBJECT_TYPE_GENERIC;
3756 pool->base.oem_device = dal_ddc_service_create(&ddc_init_data);
3757 } else {
3758 pool->base.oem_device = NULL;
3759 }
3760
7a8a3430 3761 DC_FP_END();
7ed4e635
HW
3762 return true;
3763
3764create_fail:
3765
7a8a3430 3766 DC_FP_END();
d9e32672 3767 dcn20_resource_destruct(pool);
7ed4e635
HW
3768
3769 return false;
3770}
3771
3772struct resource_pool *dcn20_create_resource_pool(
3773 const struct dc_init_data *init_data,
3774 struct dc *dc)
3775{
3776 struct dcn20_resource_pool *pool =
3777 kzalloc(sizeof(struct dcn20_resource_pool), GFP_KERNEL);
3778
3779 if (!pool)
3780 return NULL;
3781
d9e32672 3782 if (dcn20_resource_construct(init_data->num_virtual_links, dc, pool))
7ed4e635
HW
3783 return &pool->base;
3784
3785 BREAK_TO_DEBUGGER();
3786 kfree(pool);
3787 return NULL;
3788}