2631 lines · c
1/*2 * Copyright 2020 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26 27#include "dm_services.h"28#include "dc.h"29 30#include "dcn30/dcn30_init.h"31 32#include "resource.h"33#include "include/irq_service_interface.h"34#include "dcn20/dcn20_resource.h"35 36#include "dcn30_resource.h"37 38#include "dcn10/dcn10_ipp.h"39#include "dcn30/dcn30_hubbub.h"40#include "dcn30/dcn30_mpc.h"41#include "dcn30/dcn30_hubp.h"42#include "irq/dcn30/irq_service_dcn30.h"43#include "dcn30/dcn30_dpp.h"44#include "dcn30/dcn30_optc.h"45#include "dcn20/dcn20_hwseq.h"46#include "dcn30/dcn30_hwseq.h"47#include "dce110/dce110_hwseq.h"48#include "dcn30/dcn30_opp.h"49#include "dcn20/dcn20_dsc.h"50#include "dcn30/dcn30_vpg.h"51#include "dcn30/dcn30_afmt.h"52#include "dcn30/dcn30_dio_stream_encoder.h"53#include "dcn30/dcn30_dio_link_encoder.h"54#include "dce/dce_clock_source.h"55#include "dce/dce_audio.h"56#include "dce/dce_hwseq.h"57#include "clk_mgr.h"58#include "virtual/virtual_stream_encoder.h"59#include "dce110/dce110_resource.h"60#include "dml/display_mode_vba.h"61#include "dcn30/dcn30_dccg.h"62#include "dcn10/dcn10_resource.h"63#include "link.h"64#include "dce/dce_panel_cntl.h"65 66#include "dcn30/dcn30_dwb.h"67#include "dcn30/dcn30_mmhubbub.h"68 69#include "sienna_cichlid_ip_offset.h"70#include "dcn/dcn_3_0_0_offset.h"71#include "dcn/dcn_3_0_0_sh_mask.h"72 73#include "nbio/nbio_7_4_offset.h"74 75#include "dpcs/dpcs_3_0_0_offset.h"76#include "dpcs/dpcs_3_0_0_sh_mask.h"77 78#include "mmhub/mmhub_2_0_0_offset.h"79#include "mmhub/mmhub_2_0_0_sh_mask.h"80 81#include "reg_helper.h"82#include "dce/dmub_abm.h"83#include "dce/dmub_psr.h"84#include "dce/dce_aux.h"85#include "dce/dce_i2c.h"86 87#include "dml/dcn30/dcn30_fpu.h"88#include "dml/dcn30/display_mode_vba_30.h"89#include "vm_helper.h"90#include "dcn20/dcn20_vmid.h"91#include "amdgpu_socbb.h"92#include "dc_dmub_srv.h"93 94#define DC_LOGGER \95 dc->ctx->logger96#define DC_LOGGER_INIT(logger)97 98enum dcn30_clk_src_array_id {99 DCN30_CLK_SRC_PLL0,100 DCN30_CLK_SRC_PLL1,101 DCN30_CLK_SRC_PLL2,102 DCN30_CLK_SRC_PLL3,103 DCN30_CLK_SRC_PLL4,104 DCN30_CLK_SRC_PLL5,105 DCN30_CLK_SRC_TOTAL106};107 108/* begin *********************109 * macros to expend register list macro defined in HW object header file110 */111 112/* DCN */113#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg114 115#define BASE(seg) BASE_INNER(seg)116 117#define SR(reg_name)\118 .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \119 mm ## reg_name120 121#define SRI(reg_name, block, id)\122 .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \123 mm ## block ## id ## _ ## reg_name124 125#define SRI2(reg_name, block, id)\126 .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \127 mm ## reg_name128 129#define SRIR(var_name, reg_name, block, id)\130 .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \131 mm ## block ## id ## _ ## reg_name132 133#define SRII(reg_name, block, id)\134 .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \135 mm ## block ## id ## _ ## reg_name136 137#define SRII_MPC_RMU(reg_name, block, id)\138 .RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \139 mm ## block ## id ## _ ## reg_name140 141#define SRII_DWB(reg_name, temp_name, block, id)\142 .reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \143 mm ## block ## id ## _ ## temp_name144 145#define SF_DWB2(reg_name, block, id, field_name, post_fix) \146 .field_name = reg_name ## __ ## field_name ## post_fix147 148#define DCCG_SRII(reg_name, block, id)\149 .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \150 mm ## block ## id ## _ ## reg_name151 152#define VUPDATE_SRII(reg_name, block, id)\153 .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \154 mm ## reg_name ## _ ## block ## id155 156/* NBIO */157#define NBIO_BASE_INNER(seg) \158 NBIO_BASE__INST0_SEG ## seg159 160#define NBIO_BASE(seg) \161 NBIO_BASE_INNER(seg)162 163#define NBIO_SR(reg_name)\164 .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \165 mm ## reg_name166 167/* MMHUB */168#define MMHUB_BASE_INNER(seg) \169 MMHUB_BASE__INST0_SEG ## seg170 171#define MMHUB_BASE(seg) \172 MMHUB_BASE_INNER(seg)173 174#define MMHUB_SR(reg_name)\175 .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \176 mmMM ## reg_name177 178/* CLOCK */179#define CLK_BASE_INNER(seg) \180 CLK_BASE__INST0_SEG ## seg181 182#define CLK_BASE(seg) \183 CLK_BASE_INNER(seg)184 185#define CLK_SRI(reg_name, block, inst)\186 .reg_name = CLK_BASE(mm ## block ## _ ## inst ## _ ## reg_name ## _BASE_IDX) + \187 mm ## block ## _ ## inst ## _ ## reg_name188 189 190static const struct bios_registers bios_regs = {191 NBIO_SR(BIOS_SCRATCH_3),192 NBIO_SR(BIOS_SCRATCH_6)193};194 195#define clk_src_regs(index, pllid)\196[index] = {\197 CS_COMMON_REG_LIST_DCN2_0(index, pllid),\198}199 200static const struct dce110_clk_src_regs clk_src_regs[] = {201 clk_src_regs(0, A),202 clk_src_regs(1, B),203 clk_src_regs(2, C),204 clk_src_regs(3, D),205 clk_src_regs(4, E),206 clk_src_regs(5, F)207};208 209static const struct dce110_clk_src_shift cs_shift = {210 CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)211};212 213static const struct dce110_clk_src_mask cs_mask = {214 CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK)215};216 217#define abm_regs(id)\218[id] = {\219 ABM_DCN30_REG_LIST(id)\220}221 222static const struct dce_abm_registers abm_regs[] = {223 abm_regs(0),224 abm_regs(1),225 abm_regs(2),226 abm_regs(3),227 abm_regs(4),228 abm_regs(5),229};230 231static const struct dce_abm_shift abm_shift = {232 ABM_MASK_SH_LIST_DCN30(__SHIFT)233};234 235static const struct dce_abm_mask abm_mask = {236 ABM_MASK_SH_LIST_DCN30(_MASK)237};238 239 240 241#define audio_regs(id)\242[id] = {\243 AUD_COMMON_REG_LIST(id)\244}245 246static const struct dce_audio_registers audio_regs[] = {247 audio_regs(0),248 audio_regs(1),249 audio_regs(2),250 audio_regs(3),251 audio_regs(4),252 audio_regs(5),253 audio_regs(6)254};255 256#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\257 SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\258 SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\259 AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)260 261static const struct dce_audio_shift audio_shift = {262 DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT)263};264 265static const struct dce_audio_mask audio_mask = {266 DCE120_AUD_COMMON_MASK_SH_LIST(_MASK)267};268 269#define vpg_regs(id)\270[id] = {\271 VPG_DCN3_REG_LIST(id)\272}273 274static const struct dcn30_vpg_registers vpg_regs[] = {275 vpg_regs(0),276 vpg_regs(1),277 vpg_regs(2),278 vpg_regs(3),279 vpg_regs(4),280 vpg_regs(5),281 vpg_regs(6),282};283 284static const struct dcn30_vpg_shift vpg_shift = {285 DCN3_VPG_MASK_SH_LIST(__SHIFT)286};287 288static const struct dcn30_vpg_mask vpg_mask = {289 DCN3_VPG_MASK_SH_LIST(_MASK)290};291 292#define afmt_regs(id)\293[id] = {\294 AFMT_DCN3_REG_LIST(id)\295}296 297static const struct dcn30_afmt_registers afmt_regs[] = {298 afmt_regs(0),299 afmt_regs(1),300 afmt_regs(2),301 afmt_regs(3),302 afmt_regs(4),303 afmt_regs(5),304 afmt_regs(6),305};306 307static const struct dcn30_afmt_shift afmt_shift = {308 DCN3_AFMT_MASK_SH_LIST(__SHIFT)309};310 311static const struct dcn30_afmt_mask afmt_mask = {312 DCN3_AFMT_MASK_SH_LIST(_MASK)313};314 315#define stream_enc_regs(id)\316[id] = {\317 SE_DCN3_REG_LIST(id)\318}319 320static const struct dcn10_stream_enc_registers stream_enc_regs[] = {321 stream_enc_regs(0),322 stream_enc_regs(1),323 stream_enc_regs(2),324 stream_enc_regs(3),325 stream_enc_regs(4),326 stream_enc_regs(5)327};328 329static const struct dcn10_stream_encoder_shift se_shift = {330 SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT)331};332 333static const struct dcn10_stream_encoder_mask se_mask = {334 SE_COMMON_MASK_SH_LIST_DCN30(_MASK)335};336 337 338#define aux_regs(id)\339[id] = {\340 DCN2_AUX_REG_LIST(id)\341}342 343static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = {344 aux_regs(0),345 aux_regs(1),346 aux_regs(2),347 aux_regs(3),348 aux_regs(4),349 aux_regs(5)350};351 352#define hpd_regs(id)\353[id] = {\354 HPD_REG_LIST(id)\355}356 357static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = {358 hpd_regs(0),359 hpd_regs(1),360 hpd_regs(2),361 hpd_regs(3),362 hpd_regs(4),363 hpd_regs(5)364};365 366#define link_regs(id, phyid)\367[id] = {\368 LE_DCN3_REG_LIST(id), \369 UNIPHY_DCN2_REG_LIST(phyid), \370 DPCS_DCN2_REG_LIST(id), \371 SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \372}373 374static const struct dce110_aux_registers_shift aux_shift = {375 DCN_AUX_MASK_SH_LIST(__SHIFT)376};377 378static const struct dce110_aux_registers_mask aux_mask = {379 DCN_AUX_MASK_SH_LIST(_MASK)380};381 382static const struct dcn10_link_enc_registers link_enc_regs[] = {383 link_regs(0, A),384 link_regs(1, B),385 link_regs(2, C),386 link_regs(3, D),387 link_regs(4, E),388 link_regs(5, F)389};390 391static const struct dcn10_link_enc_shift le_shift = {392 LINK_ENCODER_MASK_SH_LIST_DCN30(__SHIFT),\393 DPCS_DCN2_MASK_SH_LIST(__SHIFT)394};395 396static const struct dcn10_link_enc_mask le_mask = {397 LINK_ENCODER_MASK_SH_LIST_DCN30(_MASK),\398 DPCS_DCN2_MASK_SH_LIST(_MASK)399};400 401 402static const struct dce_panel_cntl_registers panel_cntl_regs[] = {403 { DCN_PANEL_CNTL_REG_LIST() }404};405 406static const struct dce_panel_cntl_shift panel_cntl_shift = {407 DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT)408};409 410static const struct dce_panel_cntl_mask panel_cntl_mask = {411 DCE_PANEL_CNTL_MASK_SH_LIST(_MASK)412};413 414#define dpp_regs(id)\415[id] = {\416 DPP_REG_LIST_DCN30(id),\417}418 419static const struct dcn3_dpp_registers dpp_regs[] = {420 dpp_regs(0),421 dpp_regs(1),422 dpp_regs(2),423 dpp_regs(3),424 dpp_regs(4),425 dpp_regs(5),426};427 428static const struct dcn3_dpp_shift tf_shift = {429 DPP_REG_LIST_SH_MASK_DCN30(__SHIFT)430};431 432static const struct dcn3_dpp_mask tf_mask = {433 DPP_REG_LIST_SH_MASK_DCN30(_MASK)434};435 436#define opp_regs(id)\437[id] = {\438 OPP_REG_LIST_DCN30(id),\439}440 441static const struct dcn20_opp_registers opp_regs[] = {442 opp_regs(0),443 opp_regs(1),444 opp_regs(2),445 opp_regs(3),446 opp_regs(4),447 opp_regs(5)448};449 450static const struct dcn20_opp_shift opp_shift = {451 OPP_MASK_SH_LIST_DCN20(__SHIFT)452};453 454static const struct dcn20_opp_mask opp_mask = {455 OPP_MASK_SH_LIST_DCN20(_MASK)456};457 458#define aux_engine_regs(id)\459[id] = {\460 AUX_COMMON_REG_LIST0(id), \461 .AUXN_IMPCAL = 0, \462 .AUXP_IMPCAL = 0, \463 .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \464}465 466static const struct dce110_aux_registers aux_engine_regs[] = {467 aux_engine_regs(0),468 aux_engine_regs(1),469 aux_engine_regs(2),470 aux_engine_regs(3),471 aux_engine_regs(4),472 aux_engine_regs(5)473};474 475#define dwbc_regs_dcn3(id)\476[id] = {\477 DWBC_COMMON_REG_LIST_DCN30(id),\478}479 480static const struct dcn30_dwbc_registers dwbc30_regs[] = {481 dwbc_regs_dcn3(0),482};483 484static const struct dcn30_dwbc_shift dwbc30_shift = {485 DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT)486};487 488static const struct dcn30_dwbc_mask dwbc30_mask = {489 DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK)490};491 492#define mcif_wb_regs_dcn3(id)\493[id] = {\494 MCIF_WB_COMMON_REG_LIST_DCN30(id),\495}496 497static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = {498 mcif_wb_regs_dcn3(0)499};500 501static const struct dcn30_mmhubbub_shift mcif_wb30_shift = {502 MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT)503};504 505static const struct dcn30_mmhubbub_mask mcif_wb30_mask = {506 MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK)507};508 509#define dsc_regsDCN20(id)\510[id] = {\511 DSC_REG_LIST_DCN20(id)\512}513 514static const struct dcn20_dsc_registers dsc_regs[] = {515 dsc_regsDCN20(0),516 dsc_regsDCN20(1),517 dsc_regsDCN20(2),518 dsc_regsDCN20(3),519 dsc_regsDCN20(4),520 dsc_regsDCN20(5)521};522 523static const struct dcn20_dsc_shift dsc_shift = {524 DSC_REG_LIST_SH_MASK_DCN20(__SHIFT)525};526 527static const struct dcn20_dsc_mask dsc_mask = {528 DSC_REG_LIST_SH_MASK_DCN20(_MASK)529};530 531static const struct dcn30_mpc_registers mpc_regs = {532 MPC_REG_LIST_DCN3_0(0),533 MPC_REG_LIST_DCN3_0(1),534 MPC_REG_LIST_DCN3_0(2),535 MPC_REG_LIST_DCN3_0(3),536 MPC_REG_LIST_DCN3_0(4),537 MPC_REG_LIST_DCN3_0(5),538 MPC_OUT_MUX_REG_LIST_DCN3_0(0),539 MPC_OUT_MUX_REG_LIST_DCN3_0(1),540 MPC_OUT_MUX_REG_LIST_DCN3_0(2),541 MPC_OUT_MUX_REG_LIST_DCN3_0(3),542 MPC_OUT_MUX_REG_LIST_DCN3_0(4),543 MPC_OUT_MUX_REG_LIST_DCN3_0(5),544 MPC_RMU_GLOBAL_REG_LIST_DCN3AG,545 MPC_RMU_REG_LIST_DCN3AG(0),546 MPC_RMU_REG_LIST_DCN3AG(1),547 MPC_RMU_REG_LIST_DCN3AG(2),548 MPC_DWB_MUX_REG_LIST_DCN3_0(0),549};550 551static const struct dcn30_mpc_shift mpc_shift = {552 MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT)553};554 555static const struct dcn30_mpc_mask mpc_mask = {556 MPC_COMMON_MASK_SH_LIST_DCN30(_MASK)557};558 559#define optc_regs(id)\560[id] = {OPTC_COMMON_REG_LIST_DCN3_0(id)}561 562 563static const struct dcn_optc_registers optc_regs[] = {564 optc_regs(0),565 optc_regs(1),566 optc_regs(2),567 optc_regs(3),568 optc_regs(4),569 optc_regs(5)570};571 572static const struct dcn_optc_shift optc_shift = {573 OPTC_COMMON_MASK_SH_LIST_DCN30(__SHIFT)574};575 576static const struct dcn_optc_mask optc_mask = {577 OPTC_COMMON_MASK_SH_LIST_DCN30(_MASK)578};579 580#define hubp_regs(id)\581[id] = {\582 HUBP_REG_LIST_DCN30(id)\583}584 585static const struct dcn_hubp2_registers hubp_regs[] = {586 hubp_regs(0),587 hubp_regs(1),588 hubp_regs(2),589 hubp_regs(3),590 hubp_regs(4),591 hubp_regs(5)592};593 594static const struct dcn_hubp2_shift hubp_shift = {595 HUBP_MASK_SH_LIST_DCN30(__SHIFT)596};597 598static const struct dcn_hubp2_mask hubp_mask = {599 HUBP_MASK_SH_LIST_DCN30(_MASK)600};601 602static const struct dcn_hubbub_registers hubbub_reg = {603 HUBBUB_REG_LIST_DCN30(0)604};605 606static const struct dcn_hubbub_shift hubbub_shift = {607 HUBBUB_MASK_SH_LIST_DCN30(__SHIFT)608};609 610static const struct dcn_hubbub_mask hubbub_mask = {611 HUBBUB_MASK_SH_LIST_DCN30(_MASK)612};613 614static const struct dccg_registers dccg_regs = {615 DCCG_REG_LIST_DCN30()616};617 618static const struct dccg_shift dccg_shift = {619 DCCG_MASK_SH_LIST_DCN3(__SHIFT)620};621 622static const struct dccg_mask dccg_mask = {623 DCCG_MASK_SH_LIST_DCN3(_MASK)624};625 626static const struct dce_hwseq_registers hwseq_reg = {627 HWSEQ_DCN30_REG_LIST()628};629 630static const struct dce_hwseq_shift hwseq_shift = {631 HWSEQ_DCN30_MASK_SH_LIST(__SHIFT)632};633 634static const struct dce_hwseq_mask hwseq_mask = {635 HWSEQ_DCN30_MASK_SH_LIST(_MASK)636};637#define vmid_regs(id)\638[id] = {\639 DCN20_VMID_REG_LIST(id)\640}641 642static const struct dcn_vmid_registers vmid_regs[] = {643 vmid_regs(0),644 vmid_regs(1),645 vmid_regs(2),646 vmid_regs(3),647 vmid_regs(4),648 vmid_regs(5),649 vmid_regs(6),650 vmid_regs(7),651 vmid_regs(8),652 vmid_regs(9),653 vmid_regs(10),654 vmid_regs(11),655 vmid_regs(12),656 vmid_regs(13),657 vmid_regs(14),658 vmid_regs(15)659};660 661static const struct dcn20_vmid_shift vmid_shifts = {662 DCN20_VMID_MASK_SH_LIST(__SHIFT)663};664 665static const struct dcn20_vmid_mask vmid_masks = {666 DCN20_VMID_MASK_SH_LIST(_MASK)667};668 669static const struct resource_caps res_cap_dcn3 = {670 .num_timing_generator = 6,671 .num_opp = 6,672 .num_video_plane = 6,673 .num_audio = 6,674 .num_stream_encoder = 6,675 .num_pll = 6,676 .num_dwb = 1,677 .num_ddc = 6,678 .num_vmid = 16,679 .num_mpc_3dlut = 3,680 .num_dsc = 6,681};682 683static const struct dc_plane_cap plane_cap = {684 .type = DC_PLANE_TYPE_DCN_UNIVERSAL,685 .per_pixel_alpha = true,686 687 .pixel_format_support = {688 .argb8888 = true,689 .nv12 = true,690 .fp16 = true,691 .p010 = true,692 .ayuv = false,693 },694 695 .max_upscale_factor = {696 .argb8888 = 16000,697 .nv12 = 16000,698 .fp16 = 16000699 },700 701 /* 6:1 downscaling ratio: 1000/6 = 166.666 */702 .max_downscale_factor = {703 .argb8888 = 167,704 .nv12 = 167,705 .fp16 = 167706 },707 16,708 16709};710 711static const struct dc_debug_options debug_defaults_drv = {712 .disable_dmcu = true, //No DMCU on DCN30713 .force_abm_enable = false,714 .timing_trace = false,715 .clock_trace = true,716 .disable_pplib_clock_request = true,717 .pipe_split_policy = MPC_SPLIT_DYNAMIC,718 .force_single_disp_pipe_split = false,719 .disable_dcc = DCC_ENABLE,720 .vsr_support = true,721 .performance_trace = false,722 .max_downscale_src_width = 7680,/*upto 8K*/723 .disable_pplib_wm_range = false,724 .scl_reset_length10 = true,725 .sanity_checks = false,726 .underflow_assert_delay_us = 0xFFFFFFFF,727 .dwb_fi_phase = -1, // -1 = disable,728 .dmub_command_table = true,729 .use_max_lb = true,730 .exit_idle_opt_for_cursor_updates = true,731 .enable_legacy_fast_update = false,732 .using_dml2 = false,733};734 735static const struct dc_panel_config panel_config_defaults = {736 .psr = {737 .disable_psr = false,738 .disallow_psrsu = false,739 .disallow_replay = false,740 },741};742 743static void dcn30_dpp_destroy(struct dpp **dpp)744{745 kfree(TO_DCN20_DPP(*dpp));746 *dpp = NULL;747}748 749static struct dpp *dcn30_dpp_create(750 struct dc_context *ctx,751 uint32_t inst)752{753 struct dcn3_dpp *dpp =754 kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL);755 756 if (!dpp)757 return NULL;758 759 if (dpp3_construct(dpp, ctx, inst,760 &dpp_regs[inst], &tf_shift, &tf_mask))761 return &dpp->base;762 763 BREAK_TO_DEBUGGER();764 kfree(dpp);765 return NULL;766}767 768static struct output_pixel_processor *dcn30_opp_create(769 struct dc_context *ctx, uint32_t inst)770{771 struct dcn20_opp *opp =772 kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL);773 774 if (!opp) {775 BREAK_TO_DEBUGGER();776 return NULL;777 }778 779 dcn20_opp_construct(opp, ctx, inst,780 &opp_regs[inst], &opp_shift, &opp_mask);781 return &opp->base;782}783 784static struct dce_aux *dcn30_aux_engine_create(785 struct dc_context *ctx,786 uint32_t inst)787{788 struct aux_engine_dce110 *aux_engine =789 kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL);790 791 if (!aux_engine)792 return NULL;793 794 dce110_aux_engine_construct(aux_engine, ctx, inst,795 SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,796 &aux_engine_regs[inst],797 &aux_mask,798 &aux_shift,799 ctx->dc->caps.extended_aux_timeout_support);800 801 return &aux_engine->base;802}803 804#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) }805 806static const struct dce_i2c_registers i2c_hw_regs[] = {807 i2c_inst_regs(1),808 i2c_inst_regs(2),809 i2c_inst_regs(3),810 i2c_inst_regs(4),811 i2c_inst_regs(5),812 i2c_inst_regs(6),813};814 815static const struct dce_i2c_shift i2c_shifts = {816 I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT)817};818 819static const struct dce_i2c_mask i2c_masks = {820 I2C_COMMON_MASK_SH_LIST_DCN30(_MASK)821};822 823static struct dce_i2c_hw *dcn30_i2c_hw_create(824 struct dc_context *ctx,825 uint32_t inst)826{827 struct dce_i2c_hw *dce_i2c_hw =828 kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL);829 830 if (!dce_i2c_hw)831 return NULL;832 833 dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst,834 &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks);835 836 return dce_i2c_hw;837}838 839static struct mpc *dcn30_mpc_create(840 struct dc_context *ctx,841 int num_mpcc,842 int num_rmu)843{844 struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc),845 GFP_KERNEL);846 847 if (!mpc30)848 return NULL;849 850 dcn30_mpc_construct(mpc30, ctx,851 &mpc_regs,852 &mpc_shift,853 &mpc_mask,854 num_mpcc,855 num_rmu);856 857 return &mpc30->base;858}859 860static struct hubbub *dcn30_hubbub_create(struct dc_context *ctx)861{862 int i;863 864 struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub),865 GFP_KERNEL);866 867 if (!hubbub3)868 return NULL;869 870 hubbub3_construct(hubbub3, ctx,871 &hubbub_reg,872 &hubbub_shift,873 &hubbub_mask);874 875 876 for (i = 0; i < res_cap_dcn3.num_vmid; i++) {877 struct dcn20_vmid *vmid = &hubbub3->vmid[i];878 879 vmid->ctx = ctx;880 881 vmid->regs = &vmid_regs[i];882 vmid->shifts = &vmid_shifts;883 vmid->masks = &vmid_masks;884 }885 886 return &hubbub3->base;887}888 889static struct timing_generator *dcn30_timing_generator_create(890 struct dc_context *ctx,891 uint32_t instance)892{893 struct optc *tgn10 =894 kzalloc(sizeof(struct optc), GFP_KERNEL);895 896 if (!tgn10)897 return NULL;898 899 tgn10->base.inst = instance;900 tgn10->base.ctx = ctx;901 902 tgn10->tg_regs = &optc_regs[instance];903 tgn10->tg_shift = &optc_shift;904 tgn10->tg_mask = &optc_mask;905 906 dcn30_timing_generator_init(tgn10);907 908 return &tgn10->base;909}910 911static const struct encoder_feature_support link_enc_feature = {912 .max_hdmi_deep_color = COLOR_DEPTH_121212,913 .max_hdmi_pixel_clock = 600000,914 .hdmi_ycbcr420_supported = true,915 .dp_ycbcr420_supported = true,916 .fec_supported = true,917 .flags.bits.IS_HBR2_CAPABLE = true,918 .flags.bits.IS_HBR3_CAPABLE = true,919 .flags.bits.IS_TPS3_CAPABLE = true,920 .flags.bits.IS_TPS4_CAPABLE = true921};922 923static struct link_encoder *dcn30_link_encoder_create(924 struct dc_context *ctx,925 const struct encoder_init_data *enc_init_data)926{927 struct dcn20_link_encoder *enc20 =928 kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);929 930 if (!enc20)931 return NULL;932 933 dcn30_link_encoder_construct(enc20,934 enc_init_data,935 &link_enc_feature,936 &link_enc_regs[enc_init_data->transmitter],937 &link_enc_aux_regs[enc_init_data->channel - 1],938 &link_enc_hpd_regs[enc_init_data->hpd_source],939 &le_shift,940 &le_mask);941 942 return &enc20->enc10.base;943}944 945static struct panel_cntl *dcn30_panel_cntl_create(const struct panel_cntl_init_data *init_data)946{947 struct dce_panel_cntl *panel_cntl =948 kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL);949 950 if (!panel_cntl)951 return NULL;952 953 dce_panel_cntl_construct(panel_cntl,954 init_data,955 &panel_cntl_regs[init_data->inst],956 &panel_cntl_shift,957 &panel_cntl_mask);958 959 return &panel_cntl->base;960}961 962static void read_dce_straps(963 struct dc_context *ctx,964 struct resource_straps *straps)965{966 generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX),967 FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio);968 969}970 971static struct audio *dcn30_create_audio(972 struct dc_context *ctx, unsigned int inst)973{974 return dce_audio_create(ctx, inst,975 &audio_regs[inst], &audio_shift, &audio_mask);976}977 978static struct vpg *dcn30_vpg_create(979 struct dc_context *ctx,980 uint32_t inst)981{982 struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL);983 984 if (!vpg3)985 return NULL;986 987 vpg3_construct(vpg3, ctx, inst,988 &vpg_regs[inst],989 &vpg_shift,990 &vpg_mask);991 992 return &vpg3->base;993}994 995static struct afmt *dcn30_afmt_create(996 struct dc_context *ctx,997 uint32_t inst)998{999 struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL);1000 1001 if (!afmt3)1002 return NULL;1003 1004 afmt3_construct(afmt3, ctx, inst,1005 &afmt_regs[inst],1006 &afmt_shift,1007 &afmt_mask);1008 1009 return &afmt3->base;1010}1011 1012static struct stream_encoder *dcn30_stream_encoder_create(enum engine_id eng_id,1013 struct dc_context *ctx)1014{1015 struct dcn10_stream_encoder *enc1;1016 struct vpg *vpg;1017 struct afmt *afmt;1018 int vpg_inst;1019 int afmt_inst;1020 1021 /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */1022 if (eng_id <= ENGINE_ID_DIGF) {1023 vpg_inst = eng_id;1024 afmt_inst = eng_id;1025 } else1026 return NULL;1027 1028 enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);1029 vpg = dcn30_vpg_create(ctx, vpg_inst);1030 afmt = dcn30_afmt_create(ctx, afmt_inst);1031 1032 if (!enc1 || !vpg || !afmt) {1033 kfree(enc1);1034 kfree(vpg);1035 kfree(afmt);1036 return NULL;1037 }1038 1039 dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios,1040 eng_id, vpg, afmt,1041 &stream_enc_regs[eng_id],1042 &se_shift, &se_mask);1043 1044 return &enc1->base;1045}1046 1047static struct dce_hwseq *dcn30_hwseq_create(struct dc_context *ctx)1048{1049 struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);1050 1051 if (hws) {1052 hws->ctx = ctx;1053 hws->regs = &hwseq_reg;1054 hws->shifts = &hwseq_shift;1055 hws->masks = &hwseq_mask;1056 }1057 return hws;1058}1059static const struct resource_create_funcs res_create_funcs = {1060 .read_dce_straps = read_dce_straps,1061 .create_audio = dcn30_create_audio,1062 .create_stream_encoder = dcn30_stream_encoder_create,1063 .create_hwseq = dcn30_hwseq_create,1064};1065 1066static void dcn30_resource_destruct(struct dcn30_resource_pool *pool)1067{1068 unsigned int i;1069 1070 for (i = 0; i < pool->base.stream_enc_count; i++) {1071 if (pool->base.stream_enc[i] != NULL) {1072 if (pool->base.stream_enc[i]->vpg != NULL) {1073 kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg));1074 pool->base.stream_enc[i]->vpg = NULL;1075 }1076 if (pool->base.stream_enc[i]->afmt != NULL) {1077 kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt));1078 pool->base.stream_enc[i]->afmt = NULL;1079 }1080 kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i]));1081 pool->base.stream_enc[i] = NULL;1082 }1083 }1084 1085 for (i = 0; i < pool->base.res_cap->num_dsc; i++) {1086 if (pool->base.dscs[i] != NULL)1087 dcn20_dsc_destroy(&pool->base.dscs[i]);1088 }1089 1090 if (pool->base.mpc != NULL) {1091 kfree(TO_DCN20_MPC(pool->base.mpc));1092 pool->base.mpc = NULL;1093 }1094 if (pool->base.hubbub != NULL) {1095 kfree(pool->base.hubbub);1096 pool->base.hubbub = NULL;1097 }1098 for (i = 0; i < pool->base.pipe_count; i++) {1099 if (pool->base.dpps[i] != NULL)1100 dcn30_dpp_destroy(&pool->base.dpps[i]);1101 1102 if (pool->base.ipps[i] != NULL)1103 pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]);1104 1105 if (pool->base.hubps[i] != NULL) {1106 kfree(TO_DCN20_HUBP(pool->base.hubps[i]));1107 pool->base.hubps[i] = NULL;1108 }1109 1110 if (pool->base.irqs != NULL) {1111 dal_irq_service_destroy(&pool->base.irqs);1112 }1113 }1114 1115 for (i = 0; i < pool->base.res_cap->num_ddc; i++) {1116 if (pool->base.engines[i] != NULL)1117 dce110_engine_destroy(&pool->base.engines[i]);1118 if (pool->base.hw_i2cs[i] != NULL) {1119 kfree(pool->base.hw_i2cs[i]);1120 pool->base.hw_i2cs[i] = NULL;1121 }1122 if (pool->base.sw_i2cs[i] != NULL) {1123 kfree(pool->base.sw_i2cs[i]);1124 pool->base.sw_i2cs[i] = NULL;1125 }1126 }1127 1128 for (i = 0; i < pool->base.res_cap->num_opp; i++) {1129 if (pool->base.opps[i] != NULL)1130 pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);1131 }1132 1133 for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {1134 if (pool->base.timing_generators[i] != NULL) {1135 kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i]));1136 pool->base.timing_generators[i] = NULL;1137 }1138 }1139 1140 for (i = 0; i < pool->base.res_cap->num_dwb; i++) {1141 if (pool->base.dwbc[i] != NULL) {1142 kfree(TO_DCN30_DWBC(pool->base.dwbc[i]));1143 pool->base.dwbc[i] = NULL;1144 }1145 if (pool->base.mcif_wb[i] != NULL) {1146 kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i]));1147 pool->base.mcif_wb[i] = NULL;1148 }1149 }1150 1151 for (i = 0; i < pool->base.audio_count; i++) {1152 if (pool->base.audios[i])1153 dce_aud_destroy(&pool->base.audios[i]);1154 }1155 1156 for (i = 0; i < pool->base.clk_src_count; i++) {1157 if (pool->base.clock_sources[i] != NULL) {1158 dcn20_clock_source_destroy(&pool->base.clock_sources[i]);1159 pool->base.clock_sources[i] = NULL;1160 }1161 }1162 1163 for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) {1164 if (pool->base.mpc_lut[i] != NULL) {1165 dc_3dlut_func_release(pool->base.mpc_lut[i]);1166 pool->base.mpc_lut[i] = NULL;1167 }1168 if (pool->base.mpc_shaper[i] != NULL) {1169 dc_transfer_func_release(pool->base.mpc_shaper[i]);1170 pool->base.mpc_shaper[i] = NULL;1171 }1172 }1173 1174 if (pool->base.dp_clock_source != NULL) {1175 dcn20_clock_source_destroy(&pool->base.dp_clock_source);1176 pool->base.dp_clock_source = NULL;1177 }1178 1179 for (i = 0; i < pool->base.pipe_count; i++) {1180 if (pool->base.multiple_abms[i] != NULL)1181 dce_abm_destroy(&pool->base.multiple_abms[i]);1182 }1183 1184 if (pool->base.psr != NULL)1185 dmub_psr_destroy(&pool->base.psr);1186 1187 if (pool->base.dccg != NULL)1188 dcn_dccg_destroy(&pool->base.dccg);1189 1190 if (pool->base.oem_device != NULL) {1191 struct dc *dc = pool->base.oem_device->ctx->dc;1192 1193 dc->link_srv->destroy_ddc_service(&pool->base.oem_device);1194 }1195}1196 1197static struct hubp *dcn30_hubp_create(1198 struct dc_context *ctx,1199 uint32_t inst)1200{1201 struct dcn20_hubp *hubp2 =1202 kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL);1203 1204 if (!hubp2)1205 return NULL;1206 1207 if (hubp3_construct(hubp2, ctx, inst,1208 &hubp_regs[inst], &hubp_shift, &hubp_mask))1209 return &hubp2->base;1210 1211 BREAK_TO_DEBUGGER();1212 kfree(hubp2);1213 return NULL;1214}1215 1216static bool dcn30_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)1217{1218 int i;1219 uint32_t pipe_count = pool->res_cap->num_dwb;1220 1221 for (i = 0; i < pipe_count; i++) {1222 struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc),1223 GFP_KERNEL);1224 1225 if (!dwbc30) {1226 dm_error("DC: failed to create dwbc30!\n");1227 return false;1228 }1229 1230 dcn30_dwbc_construct(dwbc30, ctx,1231 &dwbc30_regs[i],1232 &dwbc30_shift,1233 &dwbc30_mask,1234 i);1235 1236 pool->dwbc[i] = &dwbc30->base;1237 }1238 return true;1239}1240 1241static bool dcn30_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool)1242{1243 int i;1244 uint32_t pipe_count = pool->res_cap->num_dwb;1245 1246 for (i = 0; i < pipe_count; i++) {1247 struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub),1248 GFP_KERNEL);1249 1250 if (!mcif_wb30) {1251 dm_error("DC: failed to create mcif_wb30!\n");1252 return false;1253 }1254 1255 dcn30_mmhubbub_construct(mcif_wb30, ctx,1256 &mcif_wb30_regs[i],1257 &mcif_wb30_shift,1258 &mcif_wb30_mask,1259 i);1260 1261 pool->mcif_wb[i] = &mcif_wb30->base;1262 }1263 return true;1264}1265 1266static struct display_stream_compressor *dcn30_dsc_create(1267 struct dc_context *ctx, uint32_t inst)1268{1269 struct dcn20_dsc *dsc =1270 kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL);1271 1272 if (!dsc) {1273 BREAK_TO_DEBUGGER();1274 return NULL;1275 }1276 1277 dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask);1278 return &dsc->base;1279}1280 1281enum dc_status dcn30_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream)1282{1283 1284 return dcn20_add_stream_to_ctx(dc, new_ctx, dc_stream);1285}1286 1287static void dcn30_destroy_resource_pool(struct resource_pool **pool)1288{1289 struct dcn30_resource_pool *dcn30_pool = TO_DCN30_RES_POOL(*pool);1290 1291 dcn30_resource_destruct(dcn30_pool);1292 kfree(dcn30_pool);1293 *pool = NULL;1294}1295 1296static struct clock_source *dcn30_clock_source_create(1297 struct dc_context *ctx,1298 struct dc_bios *bios,1299 enum clock_source_id id,1300 const struct dce110_clk_src_regs *regs,1301 bool dp_clk_src)1302{1303 struct dce110_clk_src *clk_src =1304 kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL);1305 1306 if (!clk_src)1307 return NULL;1308 1309 if (dcn3_clk_src_construct(clk_src, ctx, bios, id,1310 regs, &cs_shift, &cs_mask)) {1311 clk_src->base.dp_clk_src = dp_clk_src;1312 return &clk_src->base;1313 }1314 1315 kfree(clk_src);1316 BREAK_TO_DEBUGGER();1317 return NULL;1318}1319 1320int dcn30_populate_dml_pipes_from_context(1321 struct dc *dc, struct dc_state *context,1322 display_e2e_pipe_params_st *pipes,1323 bool fast_validate)1324{1325 int i, pipe_cnt;1326 struct resource_context *res_ctx = &context->res_ctx;1327 1328 DC_FP_START();1329 dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);1330 DC_FP_END();1331 1332 for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {1333 if (!res_ctx->pipe_ctx[i].stream)1334 continue;1335 1336 pipes[pipe_cnt++].pipe.scale_ratio_depth.lb_depth =1337 dm_lb_16;1338 }1339 1340 return pipe_cnt;1341}1342 1343void dcn30_populate_dml_writeback_from_context(1344 struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes)1345{1346 DC_FP_START();1347 dcn30_fpu_populate_dml_writeback_from_context(dc, res_ctx, pipes);1348 DC_FP_END();1349}1350 1351unsigned int dcn30_calc_max_scaled_time(1352 unsigned int time_per_pixel,1353 enum mmhubbub_wbif_mode mode,1354 unsigned int urgent_watermark)1355{1356 unsigned int time_per_byte = 0;1357 unsigned int total_free_entry = 0xb40;1358 unsigned int buf_lh_capability;1359 unsigned int max_scaled_time;1360 1361 if (mode == PACKED_444) /* packed mode 32 bpp */1362 time_per_byte = time_per_pixel/4;1363 else if (mode == PACKED_444_FP16) /* packed mode 64 bpp */1364 time_per_byte = time_per_pixel/8;1365 1366 if (time_per_byte == 0)1367 time_per_byte = 1;1368 1369 buf_lh_capability = (total_free_entry*time_per_byte*32) >> 6; /* time_per_byte is in u6.6*/1370 max_scaled_time = buf_lh_capability - urgent_watermark;1371 return max_scaled_time;1372}1373 1374void dcn30_set_mcif_arb_params(1375 struct dc *dc,1376 struct dc_state *context,1377 display_e2e_pipe_params_st *pipes,1378 int pipe_cnt)1379{1380 enum mmhubbub_wbif_mode wbif_mode;1381 struct display_mode_lib *dml = &context->bw_ctx.dml;1382 struct mcif_arb_params *wb_arb_params;1383 int i, j, dwb_pipe;1384 1385 /* Writeback MCIF_WB arbitration parameters */1386 dwb_pipe = 0;1387 for (i = 0; i < dc->res_pool->pipe_count; i++) {1388 1389 if (!context->res_ctx.pipe_ctx[i].stream)1390 continue;1391 1392 for (j = 0; j < MAX_DWB_PIPES; j++) {1393 struct dc_writeback_info *writeback_info = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j];1394 1395 if (writeback_info->wb_enabled == false)1396 continue;1397 1398 //wb_arb_params = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j].mcif_arb_params;1399 wb_arb_params = &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[dwb_pipe];1400 1401 if (writeback_info->dwb_params.cnv_params.fc_out_format == DWB_OUT_FORMAT_64BPP_ARGB ||1402 writeback_info->dwb_params.cnv_params.fc_out_format == DWB_OUT_FORMAT_64BPP_RGBA)1403 wbif_mode = PACKED_444_FP16;1404 else1405 wbif_mode = PACKED_444;1406 1407 DC_FP_START();1408 dcn30_fpu_set_mcif_arb_params(wb_arb_params, dml, pipes, pipe_cnt, j);1409 DC_FP_END();1410 wb_arb_params->time_per_pixel = (1000000 << 6) / context->res_ctx.pipe_ctx[i].stream->phy_pix_clk; /* time_per_pixel should be in u6.6 format */1411 wb_arb_params->slice_lines = 32;1412 wb_arb_params->arbitration_slice = 2; /* irrelevant since there is no YUV output */1413 wb_arb_params->max_scaled_time = dcn30_calc_max_scaled_time(wb_arb_params->time_per_pixel,1414 wbif_mode,1415 wb_arb_params->cli_watermark[0]); /* assume 4 watermark sets have the same value */1416 1417 dwb_pipe++;1418 1419 if (dwb_pipe >= MAX_DWB_PIPES)1420 return;1421 }1422 }1423}1424 1425static struct dc_cap_funcs cap_funcs = {1426 .get_dcc_compression_cap = dcn20_get_dcc_compression_cap1427};1428 1429bool dcn30_acquire_post_bldn_3dlut(1430 struct resource_context *res_ctx,1431 const struct resource_pool *pool,1432 int mpcc_id,1433 struct dc_3dlut **lut,1434 struct dc_transfer_func **shaper)1435{1436 int i;1437 bool ret = false;1438 union dc_3dlut_state *state;1439 1440 ASSERT(*lut == NULL && *shaper == NULL);1441 *lut = NULL;1442 *shaper = NULL;1443 1444 for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) {1445 if (!res_ctx->is_mpc_3dlut_acquired[i]) {1446 *lut = pool->mpc_lut[i];1447 *shaper = pool->mpc_shaper[i];1448 state = &pool->mpc_lut[i]->state;1449 res_ctx->is_mpc_3dlut_acquired[i] = true;1450 state->bits.rmu_idx_valid = 1;1451 state->bits.rmu_mux_num = i;1452 if (state->bits.rmu_mux_num == 0)1453 state->bits.mpc_rmu0_mux = mpcc_id;1454 else if (state->bits.rmu_mux_num == 1)1455 state->bits.mpc_rmu1_mux = mpcc_id;1456 else if (state->bits.rmu_mux_num == 2)1457 state->bits.mpc_rmu2_mux = mpcc_id;1458 ret = true;1459 break;1460 }1461 }1462 return ret;1463}1464 1465bool dcn30_release_post_bldn_3dlut(1466 struct resource_context *res_ctx,1467 const struct resource_pool *pool,1468 struct dc_3dlut **lut,1469 struct dc_transfer_func **shaper)1470{1471 int i;1472 bool ret = false;1473 1474 for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) {1475 if (pool->mpc_lut[i] == *lut && pool->mpc_shaper[i] == *shaper) {1476 res_ctx->is_mpc_3dlut_acquired[i] = false;1477 pool->mpc_lut[i]->state.raw = 0;1478 *lut = NULL;1479 *shaper = NULL;1480 ret = true;1481 break;1482 }1483 }1484 return ret;1485}1486 1487static bool is_soc_bounding_box_valid(struct dc *dc)1488{1489 uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev;1490 1491 if (ASICREV_IS_SIENNA_CICHLID_P(hw_internal_rev))1492 return true;1493 1494 return false;1495}1496 1497static bool init_soc_bounding_box(struct dc *dc,1498 struct dcn30_resource_pool *pool)1499{1500 struct _vcs_dpi_soc_bounding_box_st *loaded_bb = &dcn3_0_soc;1501 struct _vcs_dpi_ip_params_st *loaded_ip = &dcn3_0_ip;1502 1503 DC_LOGGER_INIT(dc->ctx->logger);1504 1505 if (!is_soc_bounding_box_valid(dc)) {1506 DC_LOG_ERROR("%s: not valid soc bounding box\n", __func__);1507 return false;1508 }1509 1510 loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator;1511 loaded_ip->max_num_dpp = pool->base.pipe_count;1512 loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk;1513 dcn20_patch_bounding_box(dc, loaded_bb);1514 DC_FP_START();1515 patch_dcn30_soc_bounding_box(dc, &dcn3_0_soc);1516 DC_FP_END();1517 1518 return true;1519}1520 1521static bool dcn30_split_stream_for_mpc_or_odm(1522 const struct dc *dc,1523 struct resource_context *res_ctx,1524 struct pipe_ctx *pri_pipe,1525 struct pipe_ctx *sec_pipe,1526 bool odm)1527{1528 int pipe_idx = sec_pipe->pipe_idx;1529 const struct resource_pool *pool = dc->res_pool;1530 1531 *sec_pipe = *pri_pipe;1532 1533 sec_pipe->pipe_idx = pipe_idx;1534 sec_pipe->plane_res.mi = pool->mis[pipe_idx];1535 sec_pipe->plane_res.hubp = pool->hubps[pipe_idx];1536 sec_pipe->plane_res.ipp = pool->ipps[pipe_idx];1537 sec_pipe->plane_res.xfm = pool->transforms[pipe_idx];1538 sec_pipe->plane_res.dpp = pool->dpps[pipe_idx];1539 sec_pipe->plane_res.mpcc_inst = pool->dpps[pipe_idx]->inst;1540 sec_pipe->stream_res.dsc = NULL;1541 if (odm) {1542 if (pri_pipe->next_odm_pipe) {1543 ASSERT(pri_pipe->next_odm_pipe != sec_pipe);1544 sec_pipe->next_odm_pipe = pri_pipe->next_odm_pipe;1545 sec_pipe->next_odm_pipe->prev_odm_pipe = sec_pipe;1546 }1547 if (pri_pipe->top_pipe && pri_pipe->top_pipe->next_odm_pipe) {1548 pri_pipe->top_pipe->next_odm_pipe->bottom_pipe = sec_pipe;1549 sec_pipe->top_pipe = pri_pipe->top_pipe->next_odm_pipe;1550 }1551 if (pri_pipe->bottom_pipe && pri_pipe->bottom_pipe->next_odm_pipe) {1552 pri_pipe->bottom_pipe->next_odm_pipe->top_pipe = sec_pipe;1553 sec_pipe->bottom_pipe = pri_pipe->bottom_pipe->next_odm_pipe;1554 }1555 pri_pipe->next_odm_pipe = sec_pipe;1556 sec_pipe->prev_odm_pipe = pri_pipe;1557 1558 if (!sec_pipe->top_pipe)1559 sec_pipe->stream_res.opp = pool->opps[pipe_idx];1560 else1561 sec_pipe->stream_res.opp = sec_pipe->top_pipe->stream_res.opp;1562 if (sec_pipe->stream->timing.flags.DSC == 1) {1563 dcn20_acquire_dsc(dc, res_ctx, &sec_pipe->stream_res.dsc, pipe_idx);1564 ASSERT(sec_pipe->stream_res.dsc);1565 if (sec_pipe->stream_res.dsc == NULL)1566 return false;1567 }1568 } else {1569 if (pri_pipe->bottom_pipe) {1570 ASSERT(pri_pipe->bottom_pipe != sec_pipe);1571 sec_pipe->bottom_pipe = pri_pipe->bottom_pipe;1572 sec_pipe->bottom_pipe->top_pipe = sec_pipe;1573 }1574 pri_pipe->bottom_pipe = sec_pipe;1575 sec_pipe->top_pipe = pri_pipe;1576 1577 ASSERT(pri_pipe->plane_state);1578 }1579 1580 return true;1581}1582 1583static struct pipe_ctx *dcn30_find_split_pipe(1584 struct dc *dc,1585 struct dc_state *context,1586 int old_index)1587{1588 struct pipe_ctx *pipe = NULL;1589 int i;1590 1591 if (old_index >= 0 && context->res_ctx.pipe_ctx[old_index].stream == NULL) {1592 pipe = &context->res_ctx.pipe_ctx[old_index];1593 pipe->pipe_idx = old_index;1594 }1595 1596 if (!pipe)1597 for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {1598 if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL1599 && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) {1600 if (context->res_ctx.pipe_ctx[i].stream == NULL) {1601 pipe = &context->res_ctx.pipe_ctx[i];1602 pipe->pipe_idx = i;1603 break;1604 }1605 }1606 }1607 1608 /*1609 * May need to fix pipes getting tossed from 1 opp to another on flip1610 * Add for debugging transient underflow during topology updates:1611 * ASSERT(pipe);1612 */1613 if (!pipe)1614 for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {1615 if (context->res_ctx.pipe_ctx[i].stream == NULL) {1616 pipe = &context->res_ctx.pipe_ctx[i];1617 pipe->pipe_idx = i;1618 break;1619 }1620 }1621 1622 return pipe;1623}1624 1625noinline bool dcn30_internal_validate_bw(1626 struct dc *dc,1627 struct dc_state *context,1628 display_e2e_pipe_params_st *pipes,1629 int *pipe_cnt_out,1630 int *vlevel_out,1631 bool fast_validate,1632 bool allow_self_refresh_only)1633{1634 bool out = false;1635 bool repopulate_pipes = false;1636 int split[MAX_PIPES] = { 0 };1637 bool merge[MAX_PIPES] = { false };1638 bool newly_split[MAX_PIPES] = { false };1639 int pipe_cnt, i, pipe_idx, vlevel = 0;1640 struct vba_vars_st *vba = &context->bw_ctx.dml.vba;1641 1642 ASSERT(pipes);1643 if (!pipes)1644 return false;1645 1646 context->bw_ctx.dml.vba.maxMpcComb = 0;1647 context->bw_ctx.dml.vba.VoltageLevel = 0;1648 context->bw_ctx.dml.vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive;1649 dc->res_pool->funcs->update_soc_for_wm_a(dc, context);1650 pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);1651 1652 if (!pipe_cnt) {1653 out = true;1654 goto validate_out;1655 }1656 1657 dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt);1658 1659 if (!fast_validate || !allow_self_refresh_only) {1660 /*1661 * DML favors voltage over p-state, but we're more interested in1662 * supporting p-state over voltage. We can't support p-state in1663 * prefetch mode > 0 so try capping the prefetch mode to start.1664 */1665 context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank =1666 dm_allow_self_refresh_and_mclk_switch;1667 vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);1668 /* This may adjust vlevel and maxMpcComb */1669 if (vlevel < context->bw_ctx.dml.soc.num_states)1670 vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge);1671 }1672 if (allow_self_refresh_only &&1673 (fast_validate || vlevel == context->bw_ctx.dml.soc.num_states ||1674 vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported)) {1675 /*1676 * If mode is unsupported or there's still no p-state support1677 * then fall back to favoring voltage.1678 *1679 * We don't actually support prefetch mode 2, so require that we1680 * at least support prefetch mode 1.1681 */1682 context->bw_ctx.dml.validate_max_state = fast_validate;1683 context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank =1684 dm_allow_self_refresh;1685 1686 vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);1687 if (vlevel < context->bw_ctx.dml.soc.num_states) {1688 memset(split, 0, sizeof(split));1689 memset(merge, 0, sizeof(merge));1690 vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge);1691 }1692 context->bw_ctx.dml.validate_max_state = false;1693 }1694 1695 dml_log_mode_support_params(&context->bw_ctx.dml);1696 1697 if (vlevel == context->bw_ctx.dml.soc.num_states)1698 goto validate_fail;1699 1700 if (!dc->config.enable_windowed_mpo_odm) {1701 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {1702 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];1703 struct pipe_ctx *mpo_pipe = pipe->bottom_pipe;1704 1705 if (!pipe->stream)1706 continue;1707 1708 /* We only support full screen mpo with ODM */1709 if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled1710 && pipe->plane_state && mpo_pipe1711 && memcmp(&mpo_pipe->plane_state->clip_rect,1712 &pipe->stream->src,1713 sizeof(struct rect)) != 0) {1714 ASSERT(mpo_pipe->plane_state != pipe->plane_state);1715 goto validate_fail;1716 }1717 pipe_idx++;1718 }1719 }1720 1721 /* merge pipes if necessary */1722 for (i = 0; i < dc->res_pool->pipe_count; i++) {1723 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];1724 1725 /*skip pipes that don't need merging*/1726 if (!merge[i])1727 continue;1728 1729 /* if ODM merge we ignore mpc tree, mpo pipes will have their own flags */1730 if (pipe->prev_odm_pipe) {1731 /*split off odm pipe*/1732 pipe->prev_odm_pipe->next_odm_pipe = pipe->next_odm_pipe;1733 if (pipe->next_odm_pipe)1734 pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe;1735 1736 pipe->bottom_pipe = NULL;1737 pipe->next_odm_pipe = NULL;1738 pipe->plane_state = NULL;1739 pipe->stream = NULL;1740 pipe->top_pipe = NULL;1741 pipe->prev_odm_pipe = NULL;1742 if (pipe->stream_res.dsc)1743 dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc);1744 memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));1745 memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));1746 repopulate_pipes = true;1747 } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) {1748 struct pipe_ctx *top_pipe = pipe->top_pipe;1749 struct pipe_ctx *bottom_pipe = pipe->bottom_pipe;1750 1751 top_pipe->bottom_pipe = bottom_pipe;1752 if (bottom_pipe)1753 bottom_pipe->top_pipe = top_pipe;1754 1755 pipe->top_pipe = NULL;1756 pipe->bottom_pipe = NULL;1757 pipe->plane_state = NULL;1758 pipe->stream = NULL;1759 memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));1760 memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));1761 repopulate_pipes = true;1762 } else1763 ASSERT(0); /* Should never try to merge master pipe */1764 1765 }1766 1767 for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) {1768 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];1769 struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];1770 struct pipe_ctx *hsplit_pipe = NULL;1771 bool odm;1772 int old_index = -1;1773 1774 if (!pipe->stream || newly_split[i])1775 continue;1776 1777 pipe_idx++;1778 odm = vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled;1779 1780 if (!pipe->plane_state && !odm)1781 continue;1782 1783 if (split[i]) {1784 if (odm) {1785 if (split[i] == 4 && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe)1786 old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;1787 else if (old_pipe->next_odm_pipe)1788 old_index = old_pipe->next_odm_pipe->pipe_idx;1789 } else {1790 if (split[i] == 4 && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&1791 old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)1792 old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx;1793 else if (old_pipe->bottom_pipe &&1794 old_pipe->bottom_pipe->plane_state == old_pipe->plane_state)1795 old_index = old_pipe->bottom_pipe->pipe_idx;1796 }1797 hsplit_pipe = dcn30_find_split_pipe(dc, context, old_index);1798 ASSERT(hsplit_pipe);1799 if (!hsplit_pipe)1800 goto validate_fail;1801 1802 if (!dcn30_split_stream_for_mpc_or_odm(1803 dc, &context->res_ctx,1804 pipe, hsplit_pipe, odm))1805 goto validate_fail;1806 1807 newly_split[hsplit_pipe->pipe_idx] = true;1808 repopulate_pipes = true;1809 }1810 if (split[i] == 4) {1811 struct pipe_ctx *pipe_4to1;1812 1813 if (odm && old_pipe->next_odm_pipe)1814 old_index = old_pipe->next_odm_pipe->pipe_idx;1815 else if (!odm && old_pipe->bottom_pipe &&1816 old_pipe->bottom_pipe->plane_state == old_pipe->plane_state)1817 old_index = old_pipe->bottom_pipe->pipe_idx;1818 else1819 old_index = -1;1820 pipe_4to1 = dcn30_find_split_pipe(dc, context, old_index);1821 ASSERT(pipe_4to1);1822 if (!pipe_4to1)1823 goto validate_fail;1824 if (!dcn30_split_stream_for_mpc_or_odm(1825 dc, &context->res_ctx,1826 pipe, pipe_4to1, odm))1827 goto validate_fail;1828 newly_split[pipe_4to1->pipe_idx] = true;1829 1830 if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe1831 && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe)1832 old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;1833 else if (!odm && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&1834 old_pipe->bottom_pipe->bottom_pipe->bottom_pipe &&1835 old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)1836 old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx;1837 else1838 old_index = -1;1839 pipe_4to1 = dcn30_find_split_pipe(dc, context, old_index);1840 ASSERT(pipe_4to1);1841 if (!pipe_4to1)1842 goto validate_fail;1843 if (!dcn30_split_stream_for_mpc_or_odm(1844 dc, &context->res_ctx,1845 hsplit_pipe, pipe_4to1, odm))1846 goto validate_fail;1847 newly_split[pipe_4to1->pipe_idx] = true;1848 }1849 if (odm)1850 dcn20_build_mapped_resource(dc, context, pipe->stream);1851 }1852 1853 for (i = 0; i < dc->res_pool->pipe_count; i++) {1854 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];1855 1856 if (pipe->plane_state) {1857 if (!resource_build_scaling_params(pipe))1858 goto validate_fail;1859 }1860 }1861 1862 /* Actual dsc count per stream dsc validation*/1863 if (!dcn20_validate_dsc(dc, context)) {1864 vba->ValidationStatus[vba->soc.num_states] = DML_FAIL_DSC_VALIDATION_FAILURE;1865 goto validate_fail;1866 }1867 1868 if (repopulate_pipes)1869 pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);1870 context->bw_ctx.dml.vba.VoltageLevel = vlevel;1871 *vlevel_out = vlevel;1872 *pipe_cnt_out = pipe_cnt;1873 1874 out = true;1875 goto validate_out;1876 1877validate_fail:1878 out = false;1879 1880validate_out:1881 return out;1882}1883 1884static int get_refresh_rate(struct dc_state *context)1885{1886 int refresh_rate = 0;1887 int h_v_total = 0;1888 struct dc_crtc_timing *timing = NULL;1889 1890 if (context == NULL || context->streams[0] == NULL)1891 return 0;1892 1893 /* check if refresh rate at least 120hz */1894 timing = &context->streams[0]->timing;1895 if (timing == NULL)1896 return 0;1897 1898 h_v_total = timing->h_total * timing->v_total;1899 if (h_v_total == 0)1900 return 0;1901 1902 refresh_rate = ((timing->pix_clk_100hz * 100) / (h_v_total)) + 1;1903 return refresh_rate;1904}1905 1906#define MAX_STRETCHED_V_BLANK 500 // in micro-seconds1907/*1908 * Scaling factor for v_blank stretch calculations considering timing in1909 * micro-seconds and pixel clock in 100hz.1910 * Note: the parenthesis are necessary to ensure the correct order of1911 * operation where V_SCALE is used.1912 */1913#define V_SCALE (10000 / MAX_STRETCHED_V_BLANK)1914 1915static int get_frame_rate_at_max_stretch_100hz(struct dc_state *context)1916{1917 struct dc_crtc_timing *timing = NULL;1918 uint32_t sec_per_100_lines;1919 uint32_t max_v_blank;1920 uint32_t curr_v_blank;1921 uint32_t v_stretch_max;1922 uint32_t stretched_frame_pix_cnt;1923 uint32_t scaled_stretched_frame_pix_cnt;1924 uint32_t scaled_refresh_rate;1925 1926 if (context == NULL || context->streams[0] == NULL)1927 return 0;1928 1929 /* check if refresh rate at least 120hz */1930 timing = &context->streams[0]->timing;1931 if (timing == NULL)1932 return 0;1933 1934 sec_per_100_lines = timing->pix_clk_100hz / timing->h_total + 1;1935 max_v_blank = sec_per_100_lines / V_SCALE + 1;1936 curr_v_blank = timing->v_total - timing->v_addressable;1937 v_stretch_max = (max_v_blank > curr_v_blank) ? (max_v_blank - curr_v_blank) : (0);1938 stretched_frame_pix_cnt = (v_stretch_max + timing->v_total) * timing->h_total;1939 scaled_stretched_frame_pix_cnt = stretched_frame_pix_cnt / 10000;1940 scaled_refresh_rate = (timing->pix_clk_100hz) / scaled_stretched_frame_pix_cnt + 1;1941 1942 return scaled_refresh_rate;1943}1944 1945static bool is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(struct dc_state *context)1946{1947 int refresh_rate_max_stretch_100hz;1948 int min_refresh_100hz;1949 1950 if (context == NULL || context->streams[0] == NULL)1951 return false;1952 1953 refresh_rate_max_stretch_100hz = get_frame_rate_at_max_stretch_100hz(context);1954 min_refresh_100hz = context->streams[0]->timing.min_refresh_in_uhz / 10000;1955 1956 if (refresh_rate_max_stretch_100hz < min_refresh_100hz)1957 return false;1958 1959 return true;1960}1961 1962bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context)1963{1964 int refresh_rate = 0;1965 const int minimum_refreshrate_supported = 120;1966 struct dc_stream_status *stream_status = NULL;1967 1968 if (context == NULL || context->streams[0] == NULL)1969 return false;1970 1971 if (context->streams[0]->sink->edid_caps.panel_patch.disable_fams)1972 return false;1973 1974 if (dc->debug.disable_fams)1975 return false;1976 1977 if (!dc->caps.dmub_caps.mclk_sw)1978 return false;1979 1980 if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching_shut_down)1981 return false;1982 1983 /* more then 1 monitor connected */1984 if (context->stream_count != 1)1985 return false;1986 1987 refresh_rate = get_refresh_rate(context);1988 if (refresh_rate < minimum_refreshrate_supported)1989 return false;1990 1991 if (!is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(context))1992 return false;1993 1994 if (!context->streams[0]->allow_freesync)1995 return false;1996 1997 if (context->streams[0]->vrr_active_variable && (dc->debug.disable_fams_gaming == INGAME_FAMS_DISABLE))1998 return false;1999 2000 stream_status = dc_state_get_stream_status(context, context->streams[0]);2001 2002 if (!stream_status)2003 return false;2004 2005 stream_status->fpo_in_use = true;2006 2007 return true;2008}2009 2010/*2011 * set up FPO watermarks, pstate, dram latency2012 */2013void dcn30_setup_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context)2014{2015 ASSERT(dc != NULL && context != NULL);2016 if (dc == NULL || context == NULL)2017 return;2018 2019 /* Set wm_a.pstate so high natural MCLK switches are impossible: 4 seconds */2020 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 4U * 1000U * 1000U * 1000U;2021}2022 2023void dcn30_update_soc_for_wm_a(struct dc *dc, struct dc_state *context)2024{2025 DC_FP_START();2026 dcn30_fpu_update_soc_for_wm_a(dc, context);2027 DC_FP_END();2028}2029 2030void dcn30_calculate_wm_and_dlg(2031 struct dc *dc, struct dc_state *context,2032 display_e2e_pipe_params_st *pipes,2033 int pipe_cnt,2034 int vlevel)2035{2036 DC_FP_START();2037 dcn30_fpu_calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);2038 DC_FP_END();2039}2040 2041bool dcn30_validate_bandwidth(struct dc *dc,2042 struct dc_state *context,2043 bool fast_validate)2044{2045 bool out = false;2046 2047 BW_VAL_TRACE_SETUP();2048 2049 int vlevel = 0;2050 int pipe_cnt = 0;2051 display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL);2052 DC_LOGGER_INIT(dc->ctx->logger);2053 2054 BW_VAL_TRACE_COUNT();2055 2056 if (!pipes)2057 goto validate_fail;2058 2059 DC_FP_START();2060 out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, true);2061 DC_FP_END();2062 2063 if (pipe_cnt == 0)2064 goto validate_out;2065 2066 if (!out)2067 goto validate_fail;2068 2069 BW_VAL_TRACE_END_VOLTAGE_LEVEL();2070 2071 if (fast_validate) {2072 BW_VAL_TRACE_SKIP(fast);2073 goto validate_out;2074 }2075 2076 DC_FP_START();2077 if (dc->res_pool->funcs->calculate_wm_and_dlg)2078 dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);2079 DC_FP_END();2080 2081 BW_VAL_TRACE_END_WATERMARKS();2082 2083 goto validate_out;2084 2085validate_fail:2086 DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n",2087 dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states]));2088 2089 BW_VAL_TRACE_SKIP(fail);2090 out = false;2091 2092validate_out:2093 kfree(pipes);2094 2095 BW_VAL_TRACE_FINISH();2096 2097 return out;2098}2099 2100void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)2101{2102 unsigned int i, j;2103 unsigned int num_states = 0;2104 2105 unsigned int dcfclk_mhz[DC__VOLTAGE_STATES] = {0};2106 unsigned int dram_speed_mts[DC__VOLTAGE_STATES] = {0};2107 unsigned int optimal_uclk_for_dcfclk_sta_targets[DC__VOLTAGE_STATES] = {0};2108 unsigned int optimal_dcfclk_for_uclk[DC__VOLTAGE_STATES] = {0};2109 2110 unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {694, 875, 1000, 1200};2111 unsigned int num_dcfclk_sta_targets = 4;2112 unsigned int num_uclk_states;2113 2114 struct dc_bounding_box_max_clk dcn30_bb_max_clk;2115 2116 memset(&dcn30_bb_max_clk, 0, sizeof(dcn30_bb_max_clk));2117 2118 if (dc->ctx->dc_bios->vram_info.num_chans)2119 dcn3_0_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans;2120 2121 DC_FP_START();2122 dcn30_fpu_update_dram_channel_width_bytes(dc);2123 DC_FP_END();2124 2125 if (bw_params->clk_table.entries[0].memclk_mhz) {2126 2127 for (i = 0; i < MAX_NUM_DPM_LVL; i++) {2128 if (bw_params->clk_table.entries[i].dcfclk_mhz > dcn30_bb_max_clk.max_dcfclk_mhz)2129 dcn30_bb_max_clk.max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;2130 if (bw_params->clk_table.entries[i].dispclk_mhz > dcn30_bb_max_clk.max_dispclk_mhz)2131 dcn30_bb_max_clk.max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;2132 if (bw_params->clk_table.entries[i].dppclk_mhz > dcn30_bb_max_clk.max_dppclk_mhz)2133 dcn30_bb_max_clk.max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;2134 if (bw_params->clk_table.entries[i].phyclk_mhz > dcn30_bb_max_clk.max_phyclk_mhz)2135 dcn30_bb_max_clk.max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;2136 }2137 2138 DC_FP_START();2139 dcn30_fpu_update_max_clk(&dcn30_bb_max_clk);2140 DC_FP_END();2141 2142 if (dcn30_bb_max_clk.max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {2143 // If max DCFCLK is greater than the max DCFCLK STA target, insert into the DCFCLK STA target array2144 dcfclk_sta_targets[num_dcfclk_sta_targets] = dcn30_bb_max_clk.max_dcfclk_mhz;2145 num_dcfclk_sta_targets++;2146 } else if (dcn30_bb_max_clk.max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {2147 // If max DCFCLK is less than the max DCFCLK STA target, cap values and remove duplicates2148 for (i = 0; i < num_dcfclk_sta_targets; i++) {2149 if (dcfclk_sta_targets[i] > dcn30_bb_max_clk.max_dcfclk_mhz) {2150 dcfclk_sta_targets[i] = dcn30_bb_max_clk.max_dcfclk_mhz;2151 break;2152 }2153 }2154 // Update size of array since we "removed" duplicates2155 num_dcfclk_sta_targets = i + 1;2156 }2157 2158 num_uclk_states = bw_params->clk_table.num_entries;2159 2160 // Calculate optimal dcfclk for each uclk2161 for (i = 0; i < num_uclk_states; i++) {2162 DC_FP_START();2163 dcn30_fpu_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16,2164 &optimal_dcfclk_for_uclk[i], NULL);2165 DC_FP_END();2166 if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz) {2167 optimal_dcfclk_for_uclk[i] = bw_params->clk_table.entries[0].dcfclk_mhz;2168 }2169 }2170 2171 // Calculate optimal uclk for each dcfclk sta target2172 for (i = 0; i < num_dcfclk_sta_targets; i++) {2173 for (j = 0; j < num_uclk_states; j++) {2174 if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) {2175 optimal_uclk_for_dcfclk_sta_targets[i] =2176 bw_params->clk_table.entries[j].memclk_mhz * 16;2177 break;2178 } else {2179 /* condition where (dcfclk_sta_targets[i] >= optimal_dcfclk_for_uclk[j]):2180 * If it just so happens that the memory bandwidth is low enough such that2181 * all the optimal DCFCLK for each UCLK is lower than the smallest DCFCLK STA2182 * target, we need to populate the optimal UCLK for each DCFCLK STA target to2183 * be the max UCLK.2184 */2185 if (j == num_uclk_states - 1) {2186 optimal_uclk_for_dcfclk_sta_targets[i] =2187 bw_params->clk_table.entries[j].memclk_mhz * 16;2188 }2189 }2190 }2191 }2192 2193 i = 0;2194 j = 0;2195 // create the final dcfclk and uclk table2196 while (i < num_dcfclk_sta_targets && j < num_uclk_states && num_states < DC__VOLTAGE_STATES) {2197 if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j] && i < num_dcfclk_sta_targets) {2198 dcfclk_mhz[num_states] = dcfclk_sta_targets[i];2199 dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];2200 } else {2201 if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= dcn30_bb_max_clk.max_dcfclk_mhz) {2202 dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];2203 dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;2204 } else {2205 j = num_uclk_states;2206 }2207 }2208 }2209 2210 while (i < num_dcfclk_sta_targets && num_states < DC__VOLTAGE_STATES) {2211 dcfclk_mhz[num_states] = dcfclk_sta_targets[i];2212 dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];2213 }2214 2215 while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES &&2216 optimal_dcfclk_for_uclk[j] <= dcn30_bb_max_clk.max_dcfclk_mhz) {2217 dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];2218 dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;2219 }2220 2221 dcn3_0_soc.num_states = num_states;2222 DC_FP_START();2223 dcn30_fpu_update_bw_bounding_box(dc, bw_params, &dcn30_bb_max_clk, dcfclk_mhz, dram_speed_mts);2224 DC_FP_END();2225 }2226}2227 2228static void dcn30_get_panel_config_defaults(struct dc_panel_config *panel_config)2229{2230 *panel_config = panel_config_defaults;2231}2232 2233static const struct resource_funcs dcn30_res_pool_funcs = {2234 .destroy = dcn30_destroy_resource_pool,2235 .link_enc_create = dcn30_link_encoder_create,2236 .panel_cntl_create = dcn30_panel_cntl_create,2237 .validate_bandwidth = dcn30_validate_bandwidth,2238 .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg,2239 .update_soc_for_wm_a = dcn30_update_soc_for_wm_a,2240 .populate_dml_pipes = dcn30_populate_dml_pipes_from_context,2241 .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer,2242 .release_pipe = dcn20_release_pipe,2243 .add_stream_to_ctx = dcn30_add_stream_to_ctx,2244 .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,2245 .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,2246 .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context,2247 .set_mcif_arb_params = dcn30_set_mcif_arb_params,2248 .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,2249 .acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut,2250 .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,2251 .update_bw_bounding_box = dcn30_update_bw_bounding_box,2252 .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,2253 .get_panel_config_defaults = dcn30_get_panel_config_defaults,2254};2255 2256#define CTX ctx2257 2258#define REG(reg_name) \2259 (DCN_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name)2260 2261static uint32_t read_pipe_fuses(struct dc_context *ctx)2262{2263 uint32_t value = REG_READ(CC_DC_PIPE_DIS);2264 /* Support for max 6 pipes */2265 value = value & 0x3f;2266 return value;2267}2268 2269static bool dcn30_resource_construct(2270 uint8_t num_virtual_links,2271 struct dc *dc,2272 struct dcn30_resource_pool *pool)2273{2274 int i;2275 struct dc_context *ctx = dc->ctx;2276 struct irq_service_init_data init_data;2277 struct ddc_service_init_data ddc_init_data = {0};2278 uint32_t pipe_fuses = read_pipe_fuses(ctx);2279 uint32_t num_pipes = 0;2280 2281 if (!(pipe_fuses == 0 || pipe_fuses == 0x3e)) {2282 BREAK_TO_DEBUGGER();2283 dm_error("DC: Unexpected fuse recipe for navi2x !\n");2284 /* fault to single pipe */2285 pipe_fuses = 0x3e;2286 }2287 2288 DC_FP_START();2289 2290 ctx->dc_bios->regs = &bios_regs;2291 2292 pool->base.res_cap = &res_cap_dcn3;2293 2294 pool->base.funcs = &dcn30_res_pool_funcs;2295 2296 /*************************************************2297 * Resource + asic cap harcoding *2298 *************************************************/2299 pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;2300 pool->base.pipe_count = pool->base.res_cap->num_timing_generator;2301 pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;2302 dc->caps.max_downscale_ratio = 600;2303 dc->caps.i2c_speed_in_khz = 100;2304 dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/2305 dc->caps.max_cursor_size = 256;2306 dc->caps.min_horizontal_blanking_period = 80;2307 dc->caps.dmdata_alloc_size = 2048;2308 dc->caps.mall_size_per_mem_channel = 8;2309 /* total size = mall per channel * num channels * 1024 * 1024 */2310 dc->caps.mall_size_total = dc->caps.mall_size_per_mem_channel * dc->ctx->dc_bios->vram_info.num_chans * 1048576;2311 dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8;2312 2313 dc->caps.max_slave_planes = 2;2314 dc->caps.max_slave_yuv_planes = 2;2315 dc->caps.max_slave_rgb_planes = 2;2316 dc->caps.post_blend_color_processing = true;2317 dc->caps.force_dp_tps4_for_cp2520 = true;2318 dc->caps.extended_aux_timeout_support = true;2319 dc->caps.dmcub_support = true;2320 2321 /* Color pipeline capabilities */2322 dc->caps.color.dpp.dcn_arch = 1;2323 dc->caps.color.dpp.input_lut_shared = 0;2324 dc->caps.color.dpp.icsc = 1;2325 dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr2326 dc->caps.color.dpp.dgam_rom_caps.srgb = 1;2327 dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1;2328 dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1;2329 dc->caps.color.dpp.dgam_rom_caps.pq = 1;2330 dc->caps.color.dpp.dgam_rom_caps.hlg = 1;2331 dc->caps.color.dpp.post_csc = 1;2332 dc->caps.color.dpp.gamma_corr = 1;2333 dc->caps.color.dpp.dgam_rom_for_yuv = 0;2334 2335 dc->caps.color.dpp.hw_3d_lut = 1;2336 dc->caps.color.dpp.ogam_ram = 1;2337 // no OGAM ROM on DCN32338 dc->caps.color.dpp.ogam_rom_caps.srgb = 0;2339 dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0;2340 dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0;2341 dc->caps.color.dpp.ogam_rom_caps.pq = 0;2342 dc->caps.color.dpp.ogam_rom_caps.hlg = 0;2343 dc->caps.color.dpp.ocsc = 0;2344 2345 dc->caps.color.mpc.gamut_remap = 1;2346 dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //32347 dc->caps.color.mpc.ogam_ram = 1;2348 dc->caps.color.mpc.ogam_rom_caps.srgb = 0;2349 dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0;2350 dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0;2351 dc->caps.color.mpc.ogam_rom_caps.pq = 0;2352 dc->caps.color.mpc.ogam_rom_caps.hlg = 0;2353 dc->caps.color.mpc.ocsc = 1;2354 2355 dc->caps.dp_hdmi21_pcon_support = true;2356 dc->caps.max_v_total = (1 << 15) - 1;2357 2358 /* read VBIOS LTTPR caps */2359 {2360 if (ctx->dc_bios->funcs->get_lttpr_caps) {2361 enum bp_result bp_query_result;2362 uint8_t is_vbios_lttpr_enable = 0;2363 2364 bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable);2365 dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;2366 }2367 2368 if (ctx->dc_bios->funcs->get_lttpr_interop) {2369 enum bp_result bp_query_result;2370 uint8_t is_vbios_interop_enabled = 0;2371 2372 bp_query_result = ctx->dc_bios->funcs->get_lttpr_interop(ctx->dc_bios,2373 &is_vbios_interop_enabled);2374 dc->caps.vbios_lttpr_aware = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled;2375 }2376 }2377 2378 if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)2379 dc->debug = debug_defaults_drv;2380 2381 // Init the vm_helper2382 if (dc->vm_helper)2383 vm_helper_init(dc->vm_helper, 16);2384 2385 /*************************************************2386 * Create resources *2387 *************************************************/2388 2389 /* Clock Sources for Pixel Clock*/2390 pool->base.clock_sources[DCN30_CLK_SRC_PLL0] =2391 dcn30_clock_source_create(ctx, ctx->dc_bios,2392 CLOCK_SOURCE_COMBO_PHY_PLL0,2393 &clk_src_regs[0], false);2394 pool->base.clock_sources[DCN30_CLK_SRC_PLL1] =2395 dcn30_clock_source_create(ctx, ctx->dc_bios,2396 CLOCK_SOURCE_COMBO_PHY_PLL1,2397 &clk_src_regs[1], false);2398 pool->base.clock_sources[DCN30_CLK_SRC_PLL2] =2399 dcn30_clock_source_create(ctx, ctx->dc_bios,2400 CLOCK_SOURCE_COMBO_PHY_PLL2,2401 &clk_src_regs[2], false);2402 pool->base.clock_sources[DCN30_CLK_SRC_PLL3] =2403 dcn30_clock_source_create(ctx, ctx->dc_bios,2404 CLOCK_SOURCE_COMBO_PHY_PLL3,2405 &clk_src_regs[3], false);2406 pool->base.clock_sources[DCN30_CLK_SRC_PLL4] =2407 dcn30_clock_source_create(ctx, ctx->dc_bios,2408 CLOCK_SOURCE_COMBO_PHY_PLL4,2409 &clk_src_regs[4], false);2410 pool->base.clock_sources[DCN30_CLK_SRC_PLL5] =2411 dcn30_clock_source_create(ctx, ctx->dc_bios,2412 CLOCK_SOURCE_COMBO_PHY_PLL5,2413 &clk_src_regs[5], false);2414 2415 pool->base.clk_src_count = DCN30_CLK_SRC_TOTAL;2416 2417 /* todo: not reuse phy_pll registers */2418 pool->base.dp_clock_source =2419 dcn30_clock_source_create(ctx, ctx->dc_bios,2420 CLOCK_SOURCE_ID_DP_DTO,2421 &clk_src_regs[0], true);2422 2423 for (i = 0; i < pool->base.clk_src_count; i++) {2424 if (pool->base.clock_sources[i] == NULL) {2425 dm_error("DC: failed to create clock sources!\n");2426 BREAK_TO_DEBUGGER();2427 goto create_fail;2428 }2429 }2430 2431 /* DCCG */2432 pool->base.dccg = dccg30_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask);2433 if (pool->base.dccg == NULL) {2434 dm_error("DC: failed to create dccg!\n");2435 BREAK_TO_DEBUGGER();2436 goto create_fail;2437 }2438 2439 /* PP Lib and SMU interfaces */2440 init_soc_bounding_box(dc, pool);2441 2442 num_pipes = dcn3_0_ip.max_num_dpp;2443 2444 for (i = 0; i < dcn3_0_ip.max_num_dpp; i++)2445 if (pipe_fuses & 1 << i)2446 num_pipes--;2447 2448 dcn3_0_ip.max_num_dpp = num_pipes;2449 dcn3_0_ip.max_num_otg = num_pipes;2450 2451 dml_init_instance(&dc->dml, &dcn3_0_soc, &dcn3_0_ip, DML_PROJECT_DCN30);2452 2453 /* IRQ */2454 init_data.ctx = dc->ctx;2455 pool->base.irqs = dal_irq_service_dcn30_create(&init_data);2456 if (!pool->base.irqs)2457 goto create_fail;2458 2459 /* HUBBUB */2460 pool->base.hubbub = dcn30_hubbub_create(ctx);2461 if (pool->base.hubbub == NULL) {2462 BREAK_TO_DEBUGGER();2463 dm_error("DC: failed to create hubbub!\n");2464 goto create_fail;2465 }2466 2467 /* HUBPs, DPPs, OPPs and TGs */2468 for (i = 0; i < pool->base.pipe_count; i++) {2469 pool->base.hubps[i] = dcn30_hubp_create(ctx, i);2470 if (pool->base.hubps[i] == NULL) {2471 BREAK_TO_DEBUGGER();2472 dm_error(2473 "DC: failed to create hubps!\n");2474 goto create_fail;2475 }2476 2477 pool->base.dpps[i] = dcn30_dpp_create(ctx, i);2478 if (pool->base.dpps[i] == NULL) {2479 BREAK_TO_DEBUGGER();2480 dm_error(2481 "DC: failed to create dpps!\n");2482 goto create_fail;2483 }2484 }2485 2486 for (i = 0; i < pool->base.res_cap->num_opp; i++) {2487 pool->base.opps[i] = dcn30_opp_create(ctx, i);2488 if (pool->base.opps[i] == NULL) {2489 BREAK_TO_DEBUGGER();2490 dm_error(2491 "DC: failed to create output pixel processor!\n");2492 goto create_fail;2493 }2494 }2495 2496 for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {2497 pool->base.timing_generators[i] = dcn30_timing_generator_create(2498 ctx, i);2499 if (pool->base.timing_generators[i] == NULL) {2500 BREAK_TO_DEBUGGER();2501 dm_error("DC: failed to create tg!\n");2502 goto create_fail;2503 }2504 }2505 pool->base.timing_generator_count = i;2506 /* PSR */2507 pool->base.psr = dmub_psr_create(ctx);2508 2509 if (pool->base.psr == NULL) {2510 dm_error("DC: failed to create PSR obj!\n");2511 BREAK_TO_DEBUGGER();2512 goto create_fail;2513 }2514 2515 /* ABM */2516 for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {2517 pool->base.multiple_abms[i] = dmub_abm_create(ctx,2518 &abm_regs[i],2519 &abm_shift,2520 &abm_mask);2521 if (pool->base.multiple_abms[i] == NULL) {2522 dm_error("DC: failed to create abm for pipe %d!\n", i);2523 BREAK_TO_DEBUGGER();2524 goto create_fail;2525 }2526 }2527 /* MPC and DSC */2528 pool->base.mpc = dcn30_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut);2529 if (pool->base.mpc == NULL) {2530 BREAK_TO_DEBUGGER();2531 dm_error("DC: failed to create mpc!\n");2532 goto create_fail;2533 }2534 2535 for (i = 0; i < pool->base.res_cap->num_dsc; i++) {2536 pool->base.dscs[i] = dcn30_dsc_create(ctx, i);2537 if (pool->base.dscs[i] == NULL) {2538 BREAK_TO_DEBUGGER();2539 dm_error("DC: failed to create display stream compressor %d!\n", i);2540 goto create_fail;2541 }2542 }2543 2544 /* DWB and MMHUBBUB */2545 if (!dcn30_dwbc_create(ctx, &pool->base)) {2546 BREAK_TO_DEBUGGER();2547 dm_error("DC: failed to create dwbc!\n");2548 goto create_fail;2549 }2550 2551 if (!dcn30_mmhubbub_create(ctx, &pool->base)) {2552 BREAK_TO_DEBUGGER();2553 dm_error("DC: failed to create mcif_wb!\n");2554 goto create_fail;2555 }2556 2557 /* AUX and I2C */2558 for (i = 0; i < pool->base.res_cap->num_ddc; i++) {2559 pool->base.engines[i] = dcn30_aux_engine_create(ctx, i);2560 if (pool->base.engines[i] == NULL) {2561 BREAK_TO_DEBUGGER();2562 dm_error(2563 "DC:failed to create aux engine!!\n");2564 goto create_fail;2565 }2566 pool->base.hw_i2cs[i] = dcn30_i2c_hw_create(ctx, i);2567 if (pool->base.hw_i2cs[i] == NULL) {2568 BREAK_TO_DEBUGGER();2569 dm_error(2570 "DC:failed to create hw i2c!!\n");2571 goto create_fail;2572 }2573 pool->base.sw_i2cs[i] = NULL;2574 }2575 2576 /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */2577 if (!resource_construct(num_virtual_links, dc, &pool->base,2578 &res_create_funcs))2579 goto create_fail;2580 2581 /* HW Sequencer and Plane caps */2582 dcn30_hw_sequencer_construct(dc);2583 2584 dc->caps.max_planes = pool->base.pipe_count;2585 2586 for (i = 0; i < dc->caps.max_planes; ++i)2587 dc->caps.planes[i] = plane_cap;2588 2589 dc->cap_funcs = cap_funcs;2590 2591 if (dc->ctx->dc_bios->fw_info.oem_i2c_present) {2592 ddc_init_data.ctx = dc->ctx;2593 ddc_init_data.link = NULL;2594 ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id;2595 ddc_init_data.id.enum_id = 0;2596 ddc_init_data.id.type = OBJECT_TYPE_GENERIC;2597 pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data);2598 } else {2599 pool->base.oem_device = NULL;2600 }2601 2602 DC_FP_END();2603 2604 return true;2605 2606create_fail:2607 2608 DC_FP_END();2609 dcn30_resource_destruct(pool);2610 2611 return false;2612}2613 2614struct resource_pool *dcn30_create_resource_pool(2615 const struct dc_init_data *init_data,2616 struct dc *dc)2617{2618 struct dcn30_resource_pool *pool =2619 kzalloc(sizeof(struct dcn30_resource_pool), GFP_KERNEL);2620 2621 if (!pool)2622 return NULL;2623 2624 if (dcn30_resource_construct(init_data->num_virtual_links, dc, pool))2625 return &pool->base;2626 2627 BREAK_TO_DEBUGGER();2628 kfree(pool);2629 return NULL;2630}2631