brintos

brintos / linux-shallow public Read only

0
0
Text · 82.0 KiB · a124ad9 Raw
2873 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright 2022 Advanced Micro Devices, Inc.4 *5 * Permission is hereby granted, free of charge, to any person obtaining a6 * copy of this software and associated documentation files (the "Software"),7 * to deal in the Software without restriction, including without limitation8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,9 * and/or sell copies of the Software, and to permit persons to whom the10 * Software is furnished to do so, subject to the following conditions:11 *12 * The above copyright notice and this permission notice shall be included in13 * all copies or substantial portions of the Software.14 *15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR19 * 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 OR21 * OTHER DEALINGS IN THE SOFTWARE.22 *23 * Authors: AMD24 *25 */26 27#include "dm_services.h"28#include "dc.h"29 30#include "dcn32/dcn32_init.h"31 32#include "resource.h"33#include "include/irq_service_interface.h"34#include "dcn32_resource.h"35 36#include "dcn20/dcn20_resource.h"37#include "dcn30/dcn30_resource.h"38 39#include "dcn10/dcn10_ipp.h"40#include "dcn30/dcn30_hubbub.h"41#include "dcn31/dcn31_hubbub.h"42#include "dcn32/dcn32_hubbub.h"43#include "dcn32/dcn32_mpc.h"44#include "dcn32/dcn32_hubp.h"45#include "irq/dcn32/irq_service_dcn32.h"46#include "dcn32/dcn32_dpp.h"47#include "dcn32/dcn32_optc.h"48#include "dcn20/dcn20_hwseq.h"49#include "dcn30/dcn30_hwseq.h"50#include "dce110/dce110_hwseq.h"51#include "dcn30/dcn30_opp.h"52#include "dcn20/dcn20_dsc.h"53#include "dcn30/dcn30_vpg.h"54#include "dcn30/dcn30_afmt.h"55#include "dcn30/dcn30_dio_stream_encoder.h"56#include "dcn32/dcn32_dio_stream_encoder.h"57#include "dcn31/dcn31_hpo_dp_stream_encoder.h"58#include "dcn31/dcn31_hpo_dp_link_encoder.h"59#include "dcn32/dcn32_hpo_dp_link_encoder.h"60#include "dcn31/dcn31_apg.h"61#include "dcn31/dcn31_dio_link_encoder.h"62#include "dcn32/dcn32_dio_link_encoder.h"63#include "dce/dce_clock_source.h"64#include "dce/dce_audio.h"65#include "dce/dce_hwseq.h"66#include "clk_mgr.h"67#include "virtual/virtual_stream_encoder.h"68#include "dml/display_mode_vba.h"69#include "dcn32/dcn32_dccg.h"70#include "dcn10/dcn10_resource.h"71#include "link.h"72#include "dcn31/dcn31_panel_cntl.h"73 74#include "dcn30/dcn30_dwb.h"75#include "dcn32/dcn32_mmhubbub.h"76 77#include "dcn/dcn_3_2_0_offset.h"78#include "dcn/dcn_3_2_0_sh_mask.h"79#include "nbio/nbio_4_3_0_offset.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/display_mode_vba_30.h"88#include "vm_helper.h"89#include "dcn20/dcn20_vmid.h"90#include "dml/dcn32/dcn32_fpu.h"91 92#include "dc_state_priv.h"93 94#include "dml2/dml2_wrapper.h"95 96#define DC_LOGGER_INIT(logger)97 98enum dcn32_clk_src_array_id {99	DCN32_CLK_SRC_PLL0,100	DCN32_CLK_SRC_PLL1,101	DCN32_CLK_SRC_PLL2,102	DCN32_CLK_SRC_PLL3,103	DCN32_CLK_SRC_PLL4,104	DCN32_CLK_SRC_TOTAL105};106 107/* begin *********************108 * macros to expend register list macro defined in HW object header file109 */110 111/* DCN */112#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg]113 114#define BASE(seg) BASE_INNER(seg)115 116#define SR(reg_name)\117		REG_STRUCT.reg_name = BASE(reg ## reg_name ## _BASE_IDX) +  \118					reg ## reg_name119#define SR_ARR(reg_name, id) \120	REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name121 122#define SR_ARR_INIT(reg_name, id, value) \123	REG_STRUCT[id].reg_name = value124 125#define SRI(reg_name, block, id)\126	REG_STRUCT.reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \127		reg ## block ## id ## _ ## reg_name128 129#define SRI_ARR(reg_name, block, id)\130	REG_STRUCT[id].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \131		reg ## block ## id ## _ ## reg_name132 133#define SR_ARR_I2C(reg_name, id) \134	REG_STRUCT[id-1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name135 136#define SRI_ARR_I2C(reg_name, block, id)\137	REG_STRUCT[id-1].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \138		reg ## block ## id ## _ ## reg_name139 140#define SRI_ARR_ALPHABET(reg_name, block, index, id)\141	REG_STRUCT[index].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \142		reg ## block ## id ## _ ## reg_name143 144#define SRI2(reg_name, block, id)\145	.reg_name = BASE(reg ## reg_name ## _BASE_IDX) +	\146		reg ## reg_name147#define SRI2_ARR(reg_name, block, id)\148	REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) +	\149		reg ## reg_name150 151#define SRIR(var_name, reg_name, block, id)\152	.var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \153		reg ## block ## id ## _ ## reg_name154 155#define SRII(reg_name, block, id)\156	REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \157					reg ## block ## id ## _ ## reg_name158 159#define SRII_ARR_2(reg_name, block, id, inst)\160	REG_STRUCT[inst].reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \161		reg ## block ## id ## _ ## reg_name162 163#define SRII_MPC_RMU(reg_name, block, id)\164	.RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \165		reg ## block ## id ## _ ## reg_name166 167#define SRII_DWB(reg_name, temp_name, block, id)\168	REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \169		reg ## block ## id ## _ ## temp_name170 171#define SF_DWB2(reg_name, block, id, field_name, post_fix)	\172	.field_name = reg_name ## __ ## field_name ## post_fix173 174#define DCCG_SRII(reg_name, block, id)\175	REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \176		reg ## block ## id ## _ ## reg_name177 178#define VUPDATE_SRII(reg_name, block, id)\179	REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \180		reg ## reg_name ## _ ## block ## id181 182/* NBIO */183#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg]184 185#define NBIO_BASE(seg) \186	NBIO_BASE_INNER(seg)187 188#define NBIO_SR(reg_name)\189	REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \190			regBIF_BX0_ ## reg_name191#define NBIO_SR_ARR(reg_name, id)\192	REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \193		regBIF_BX0_ ## reg_name194 195#undef CTX196#define CTX ctx197#define REG(reg_name) \198	(ctx->dcn_reg_offsets[reg ## reg_name ## _BASE_IDX] + reg ## reg_name)199 200static struct bios_registers bios_regs;201 202#define bios_regs_init() \203		( \204		NBIO_SR(BIOS_SCRATCH_3),\205		NBIO_SR(BIOS_SCRATCH_6)\206		)207 208#define clk_src_regs_init(index, pllid)\209	CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid)210 211static struct dce110_clk_src_regs clk_src_regs[5];212 213static const struct dce110_clk_src_shift cs_shift = {214		CS_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT)215};216 217static const struct dce110_clk_src_mask cs_mask = {218		CS_COMMON_MASK_SH_LIST_DCN3_2(_MASK)219};220 221#define abm_regs_init(id)\222		ABM_DCN32_REG_LIST_RI(id)223 224static struct dce_abm_registers abm_regs[4];225 226static const struct dce_abm_shift abm_shift = {227		ABM_MASK_SH_LIST_DCN32(__SHIFT)228};229 230static const struct dce_abm_mask abm_mask = {231		ABM_MASK_SH_LIST_DCN32(_MASK)232};233 234#define audio_regs_init(id)\235		AUD_COMMON_REG_LIST_RI(id)236 237static struct dce_audio_registers audio_regs[5];238 239#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\240		SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\241		SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\242		AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)243 244static const struct dce_audio_shift audio_shift = {245		DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT)246};247 248static const struct dce_audio_mask audio_mask = {249		DCE120_AUD_COMMON_MASK_SH_LIST(_MASK)250};251 252#define vpg_regs_init(id)\253	VPG_DCN3_REG_LIST_RI(id)254 255static struct dcn30_vpg_registers vpg_regs[10];256 257static const struct dcn30_vpg_shift vpg_shift = {258	DCN3_VPG_MASK_SH_LIST(__SHIFT)259};260 261static const struct dcn30_vpg_mask vpg_mask = {262	DCN3_VPG_MASK_SH_LIST(_MASK)263};264 265#define afmt_regs_init(id)\266	AFMT_DCN3_REG_LIST_RI(id)267 268static struct dcn30_afmt_registers afmt_regs[6];269 270static const struct dcn30_afmt_shift afmt_shift = {271	DCN3_AFMT_MASK_SH_LIST(__SHIFT)272};273 274static const struct dcn30_afmt_mask afmt_mask = {275	DCN3_AFMT_MASK_SH_LIST(_MASK)276};277 278#define apg_regs_init(id)\279	APG_DCN31_REG_LIST_RI(id)280 281static struct dcn31_apg_registers apg_regs[4];282 283static const struct dcn31_apg_shift apg_shift = {284	DCN31_APG_MASK_SH_LIST(__SHIFT)285};286 287static const struct dcn31_apg_mask apg_mask = {288		DCN31_APG_MASK_SH_LIST(_MASK)289};290 291#define stream_enc_regs_init(id)\292	SE_DCN32_REG_LIST_RI(id)293 294static struct dcn10_stream_enc_registers stream_enc_regs[5];295 296static const struct dcn10_stream_encoder_shift se_shift = {297		SE_COMMON_MASK_SH_LIST_DCN32(__SHIFT)298};299 300static const struct dcn10_stream_encoder_mask se_mask = {301		SE_COMMON_MASK_SH_LIST_DCN32(_MASK)302};303 304 305#define aux_regs_init(id)\306	DCN2_AUX_REG_LIST_RI(id)307 308static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5];309 310#define hpd_regs_init(id)\311	HPD_REG_LIST_RI(id)312 313static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5];314 315#define link_regs_init(id, phyid)\316	( \317	LE_DCN31_REG_LIST_RI(id), \318	UNIPHY_DCN2_REG_LIST_RI(id, phyid)\319	)320	/*DPCS_DCN31_REG_LIST(id),*/ \321 322static struct dcn10_link_enc_registers link_enc_regs[5];323 324static const struct dcn10_link_enc_shift le_shift = {325	LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \326	//DPCS_DCN31_MASK_SH_LIST(__SHIFT)327};328 329static const struct dcn10_link_enc_mask le_mask = {330	LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \331	//DPCS_DCN31_MASK_SH_LIST(_MASK)332};333 334#define hpo_dp_stream_encoder_reg_init(id)\335	DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id)336 337static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4];338 339static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = {340	DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT)341};342 343static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = {344	DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK)345};346 347 348#define hpo_dp_link_encoder_reg_init(id)\349	DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id)350	/*DCN3_1_RDPCSTX_REG_LIST(0),*/351	/*DCN3_1_RDPCSTX_REG_LIST(1),*/352	/*DCN3_1_RDPCSTX_REG_LIST(2),*/353	/*DCN3_1_RDPCSTX_REG_LIST(3),*/354 355static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[2];356 357static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = {358	DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT)359};360 361static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = {362	DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK)363};364 365#define dpp_regs_init(id)\366	DPP_REG_LIST_DCN30_COMMON_RI(id)367 368static struct dcn3_dpp_registers dpp_regs[4];369 370static const struct dcn3_dpp_shift tf_shift = {371		DPP_REG_LIST_SH_MASK_DCN30_COMMON(__SHIFT)372};373 374static const struct dcn3_dpp_mask tf_mask = {375		DPP_REG_LIST_SH_MASK_DCN30_COMMON(_MASK)376};377 378 379#define opp_regs_init(id)\380	OPP_REG_LIST_DCN30_RI(id)381 382static struct dcn20_opp_registers opp_regs[4];383 384static const struct dcn20_opp_shift opp_shift = {385	OPP_MASK_SH_LIST_DCN20(__SHIFT)386};387 388static const struct dcn20_opp_mask opp_mask = {389	OPP_MASK_SH_LIST_DCN20(_MASK)390};391 392#define aux_engine_regs_init(id)\393	( \394	AUX_COMMON_REG_LIST0_RI(id), \395	SR_ARR_INIT(AUXN_IMPCAL, id, 0), \396	SR_ARR_INIT(AUXP_IMPCAL, id, 0), \397	SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK), \398	SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK)\399	)400 401static struct dce110_aux_registers aux_engine_regs[5];402 403static const struct dce110_aux_registers_shift aux_shift = {404	DCN_AUX_MASK_SH_LIST(__SHIFT)405};406 407static const struct dce110_aux_registers_mask aux_mask = {408	DCN_AUX_MASK_SH_LIST(_MASK)409};410 411#define dwbc_regs_dcn3_init(id)\412	DWBC_COMMON_REG_LIST_DCN30_RI(id)413 414static struct dcn30_dwbc_registers dwbc30_regs[1];415 416static const struct dcn30_dwbc_shift dwbc30_shift = {417	DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT)418};419 420static const struct dcn30_dwbc_mask dwbc30_mask = {421	DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK)422};423 424#define mcif_wb_regs_dcn3_init(id)\425	MCIF_WB_COMMON_REG_LIST_DCN32_RI(id)426 427static struct dcn30_mmhubbub_registers mcif_wb30_regs[1];428 429static const struct dcn30_mmhubbub_shift mcif_wb30_shift = {430	MCIF_WB_COMMON_MASK_SH_LIST_DCN32(__SHIFT)431};432 433static const struct dcn30_mmhubbub_mask mcif_wb30_mask = {434	MCIF_WB_COMMON_MASK_SH_LIST_DCN32(_MASK)435};436 437#define dsc_regsDCN20_init(id)\438	DSC_REG_LIST_DCN20_RI(id)439 440static struct dcn20_dsc_registers dsc_regs[4];441 442static const struct dcn20_dsc_shift dsc_shift = {443	DSC_REG_LIST_SH_MASK_DCN20(__SHIFT)444};445 446static const struct dcn20_dsc_mask dsc_mask = {447	DSC_REG_LIST_SH_MASK_DCN20(_MASK)448};449 450static struct dcn30_mpc_registers mpc_regs;451 452#define dcn_mpc_regs_init() \453	MPC_REG_LIST_DCN3_2_RI(0),\454	MPC_REG_LIST_DCN3_2_RI(1),\455	MPC_REG_LIST_DCN3_2_RI(2),\456	MPC_REG_LIST_DCN3_2_RI(3),\457	MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0),\458	MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1),\459	MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2),\460	MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3),\461	MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0)462 463static const struct dcn30_mpc_shift mpc_shift = {464	MPC_COMMON_MASK_SH_LIST_DCN32(__SHIFT)465};466 467static const struct dcn30_mpc_mask mpc_mask = {468	MPC_COMMON_MASK_SH_LIST_DCN32(_MASK)469};470 471#define optc_regs_init(id)\472	OPTC_COMMON_REG_LIST_DCN3_2_RI(id)473 474static struct dcn_optc_registers optc_regs[4];475 476static const struct dcn_optc_shift optc_shift = {477	OPTC_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT)478};479 480static const struct dcn_optc_mask optc_mask = {481	OPTC_COMMON_MASK_SH_LIST_DCN3_2(_MASK)482};483 484#define hubp_regs_init(id)\485	HUBP_REG_LIST_DCN32_RI(id)486 487static struct dcn_hubp2_registers hubp_regs[4];488 489 490static const struct dcn_hubp2_shift hubp_shift = {491		HUBP_MASK_SH_LIST_DCN32(__SHIFT)492};493 494static const struct dcn_hubp2_mask hubp_mask = {495		HUBP_MASK_SH_LIST_DCN32(_MASK)496};497 498static struct dcn_hubbub_registers hubbub_reg;499#define hubbub_reg_init()\500		HUBBUB_REG_LIST_DCN32_RI(0)501 502static const struct dcn_hubbub_shift hubbub_shift = {503		HUBBUB_MASK_SH_LIST_DCN32(__SHIFT)504};505 506static const struct dcn_hubbub_mask hubbub_mask = {507		HUBBUB_MASK_SH_LIST_DCN32(_MASK)508};509 510static struct dccg_registers dccg_regs;511 512#define dccg_regs_init()\513	DCCG_REG_LIST_DCN32_RI()514 515static const struct dccg_shift dccg_shift = {516		DCCG_MASK_SH_LIST_DCN32(__SHIFT)517};518 519static const struct dccg_mask dccg_mask = {520		DCCG_MASK_SH_LIST_DCN32(_MASK)521};522 523 524#define SRII2(reg_name_pre, reg_name_post, id)\525	.reg_name_pre ## _ ##  reg_name_post[id] = BASE(reg ## reg_name_pre \526			## id ## _ ## reg_name_post ## _BASE_IDX) + \527			reg ## reg_name_pre ## id ## _ ## reg_name_post528 529 530#define HWSEQ_DCN32_REG_LIST()\531	SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \532	SR(DIO_MEM_PWR_CTRL), \533	SR(ODM_MEM_PWR_CTRL3), \534	SR(MMHUBBUB_MEM_PWR_CNTL), \535	SR(DCCG_GATE_DISABLE_CNTL), \536	SR(DCCG_GATE_DISABLE_CNTL2), \537	SR(DCFCLK_CNTL),\538	SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \539	SRII(PIXEL_RATE_CNTL, OTG, 0), \540	SRII(PIXEL_RATE_CNTL, OTG, 1),\541	SRII(PIXEL_RATE_CNTL, OTG, 2),\542	SRII(PIXEL_RATE_CNTL, OTG, 3),\543	SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\544	SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\545	SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\546	SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\547	SR(MICROSECOND_TIME_BASE_DIV), \548	SR(MILLISECOND_TIME_BASE_DIV), \549	SR(DISPCLK_FREQ_CHANGE_CNTL), \550	SR(RBBMIF_TIMEOUT_DIS), \551	SR(RBBMIF_TIMEOUT_DIS_2), \552	SR(DCHUBBUB_CRC_CTRL), \553	SR(DPP_TOP0_DPP_CRC_CTRL), \554	SR(DPP_TOP0_DPP_CRC_VAL_B_A), \555	SR(DPP_TOP0_DPP_CRC_VAL_R_G), \556	SR(MPC_CRC_CTRL), \557	SR(MPC_CRC_RESULT_GB), \558	SR(MPC_CRC_RESULT_C), \559	SR(MPC_CRC_RESULT_AR), \560	SR(DOMAIN0_PG_CONFIG), \561	SR(DOMAIN1_PG_CONFIG), \562	SR(DOMAIN2_PG_CONFIG), \563	SR(DOMAIN3_PG_CONFIG), \564	SR(DOMAIN16_PG_CONFIG), \565	SR(DOMAIN17_PG_CONFIG), \566	SR(DOMAIN18_PG_CONFIG), \567	SR(DOMAIN19_PG_CONFIG), \568	SR(DOMAIN0_PG_STATUS), \569	SR(DOMAIN1_PG_STATUS), \570	SR(DOMAIN2_PG_STATUS), \571	SR(DOMAIN3_PG_STATUS), \572	SR(DOMAIN16_PG_STATUS), \573	SR(DOMAIN17_PG_STATUS), \574	SR(DOMAIN18_PG_STATUS), \575	SR(DOMAIN19_PG_STATUS), \576	SR(D1VGA_CONTROL), \577	SR(D2VGA_CONTROL), \578	SR(D3VGA_CONTROL), \579	SR(D4VGA_CONTROL), \580	SR(D5VGA_CONTROL), \581	SR(D6VGA_CONTROL), \582	SR(DC_IP_REQUEST_CNTL), \583	SR(AZALIA_AUDIO_DTO), \584	SR(AZALIA_CONTROLLER_CLOCK_GATING)585 586static struct dce_hwseq_registers hwseq_reg;587 588#define hwseq_reg_init()\589	HWSEQ_DCN32_REG_LIST()590 591#define HWSEQ_DCN32_MASK_SH_LIST(mask_sh)\592	HWSEQ_DCN_MASK_SH_LIST(mask_sh), \593	HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \594	HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \595	HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \596	HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \597	HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \598	HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \599	HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \600	HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \601	HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \602	HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \603	HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \604	HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \605	HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \606	HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \607	HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \608	HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \609	HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \610	HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \611	HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \612	HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \613	HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \614	HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \615	HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \616	HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \617	HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \618	HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \619	HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \620	HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \621	HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \622	HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \623	HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh)624 625static const struct dce_hwseq_shift hwseq_shift = {626		HWSEQ_DCN32_MASK_SH_LIST(__SHIFT)627};628 629static const struct dce_hwseq_mask hwseq_mask = {630		HWSEQ_DCN32_MASK_SH_LIST(_MASK)631};632#define vmid_regs_init(id)\633		DCN20_VMID_REG_LIST_RI(id)634 635static struct dcn_vmid_registers vmid_regs[16];636 637static const struct dcn20_vmid_shift vmid_shifts = {638		DCN20_VMID_MASK_SH_LIST(__SHIFT)639};640 641static const struct dcn20_vmid_mask vmid_masks = {642		DCN20_VMID_MASK_SH_LIST(_MASK)643};644 645static const struct resource_caps res_cap_dcn32 = {646	.num_timing_generator = 4,647	.num_opp = 4,648	.num_video_plane = 4,649	.num_audio = 5,650	.num_stream_encoder = 5,651	.num_hpo_dp_stream_encoder = 4,652	.num_hpo_dp_link_encoder = 2,653	.num_pll = 5,654	.num_dwb = 1,655	.num_ddc = 5,656	.num_vmid = 16,657	.num_mpc_3dlut = 4,658	.num_dsc = 4,659};660 661static const struct dc_plane_cap plane_cap = {662	.type = DC_PLANE_TYPE_DCN_UNIVERSAL,663	.per_pixel_alpha = true,664 665	.pixel_format_support = {666			.argb8888 = true,667			.nv12 = true,668			.fp16 = true,669			.p010 = true,670			.ayuv = false,671	},672 673	.max_upscale_factor = {674			.argb8888 = 16000,675			.nv12 = 16000,676			.fp16 = 16000677	},678 679	// 6:1 downscaling ratio: 1000/6 = 166.666680	.max_downscale_factor = {681			.argb8888 = 167,682			.nv12 = 167,683			.fp16 = 167684	},685	64,686	64687};688 689static const struct dc_debug_options debug_defaults_drv = {690	.disable_dmcu = true,691	.force_abm_enable = false,692	.timing_trace = false,693	.clock_trace = true,694	.disable_pplib_clock_request = false,695	.pipe_split_policy = MPC_SPLIT_AVOID, // Due to CRB, no need to MPC split anymore696	.force_single_disp_pipe_split = false,697	.disable_dcc = DCC_ENABLE,698	.vsr_support = true,699	.performance_trace = false,700	.max_downscale_src_width = 7680,/*upto 8K*/701	.disable_pplib_wm_range = false,702	.scl_reset_length10 = true,703	.sanity_checks = false,704	.underflow_assert_delay_us = 0xFFFFFFFF,705	.dwb_fi_phase = -1, // -1 = disable,706	.dmub_command_table = true,707	.enable_mem_low_power = {708		.bits = {709			.vga = false,710			.i2c = false,711			.dmcu = false, // This is previously known to cause hang on S3 cycles if enabled712			.dscl = false,713			.cm = false,714			.mpc = false,715			.optc = true,716		}717	},718	.use_max_lb = true,719	.force_disable_subvp = false,720	.exit_idle_opt_for_cursor_updates = true,721	.using_dml2 = false,722	.using_dml21 = false, // TODO : Temporary for N-1 validation. Remove after N-1 is done.723	.enable_single_display_2to1_odm_policy = true,724 725	/* Must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/726	.enable_double_buffered_dsc_pg_support = true,727	.enable_dp_dig_pixel_rate_div_policy = 1,728	.allow_sw_cursor_fallback = false, // Linux can't do SW cursor "fallback"729	.alloc_extra_way_for_cursor = true,730	.min_prefetch_in_strobe_ns = 60000, // 60us731	.disable_unbounded_requesting = false,732	.override_dispclk_programming = true,733	.disable_fpo_optimizations = false,734	.fpo_vactive_margin_us = 2000, // 2000us735	.disable_fpo_vactive = false,736	.disable_boot_optimizations = false,737	.disable_subvp_high_refresh = false,738	.disable_dp_plus_plus_wa = true,739	.fpo_vactive_min_active_margin_us = 200,740	.fpo_vactive_max_blank_us = 1000,741	.enable_legacy_fast_update = false,742};743 744static struct dce_aux *dcn32_aux_engine_create(745	struct dc_context *ctx,746	uint32_t inst)747{748	struct aux_engine_dce110 *aux_engine =749		kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL);750 751	if (!aux_engine)752		return NULL;753 754#undef REG_STRUCT755#define REG_STRUCT aux_engine_regs756	aux_engine_regs_init(0),757	aux_engine_regs_init(1),758	aux_engine_regs_init(2),759	aux_engine_regs_init(3),760	aux_engine_regs_init(4);761 762	dce110_aux_engine_construct(aux_engine, ctx, inst,763				    SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,764				    &aux_engine_regs[inst],765					&aux_mask,766					&aux_shift,767					ctx->dc->caps.extended_aux_timeout_support);768 769	return &aux_engine->base;770}771#define i2c_inst_regs_init(id)\772	I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id)773 774static struct dce_i2c_registers i2c_hw_regs[5];775 776static const struct dce_i2c_shift i2c_shifts = {777		I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT)778};779 780static const struct dce_i2c_mask i2c_masks = {781		I2C_COMMON_MASK_SH_LIST_DCN30(_MASK)782};783 784static struct dce_i2c_hw *dcn32_i2c_hw_create(785	struct dc_context *ctx,786	uint32_t inst)787{788	struct dce_i2c_hw *dce_i2c_hw =789		kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL);790 791	if (!dce_i2c_hw)792		return NULL;793 794#undef REG_STRUCT795#define REG_STRUCT i2c_hw_regs796	i2c_inst_regs_init(1),797	i2c_inst_regs_init(2),798	i2c_inst_regs_init(3),799	i2c_inst_regs_init(4),800	i2c_inst_regs_init(5);801 802	dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst,803				    &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks);804 805	return dce_i2c_hw;806}807 808static struct clock_source *dcn32_clock_source_create(809		struct dc_context *ctx,810		struct dc_bios *bios,811		enum clock_source_id id,812		const struct dce110_clk_src_regs *regs,813		bool dp_clk_src)814{815	struct dce110_clk_src *clk_src =816		kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL);817 818	if (!clk_src)819		return NULL;820 821	if (dcn31_clk_src_construct(clk_src, ctx, bios, id,822			regs, &cs_shift, &cs_mask)) {823		clk_src->base.dp_clk_src = dp_clk_src;824		return &clk_src->base;825	}826 827	kfree(clk_src);828	BREAK_TO_DEBUGGER();829	return NULL;830}831 832static struct hubbub *dcn32_hubbub_create(struct dc_context *ctx)833{834	int i;835 836	struct dcn20_hubbub *hubbub2 = kzalloc(sizeof(struct dcn20_hubbub),837					  GFP_KERNEL);838 839	if (!hubbub2)840		return NULL;841 842#undef REG_STRUCT843#define REG_STRUCT hubbub_reg844	hubbub_reg_init();845 846#undef REG_STRUCT847#define REG_STRUCT vmid_regs848	vmid_regs_init(0),849	vmid_regs_init(1),850	vmid_regs_init(2),851	vmid_regs_init(3),852	vmid_regs_init(4),853	vmid_regs_init(5),854	vmid_regs_init(6),855	vmid_regs_init(7),856	vmid_regs_init(8),857	vmid_regs_init(9),858	vmid_regs_init(10),859	vmid_regs_init(11),860	vmid_regs_init(12),861	vmid_regs_init(13),862	vmid_regs_init(14),863	vmid_regs_init(15);864 865	hubbub32_construct(hubbub2, ctx,866			&hubbub_reg,867			&hubbub_shift,868			&hubbub_mask,869			ctx->dc->dml.ip.det_buffer_size_kbytes,870			ctx->dc->dml.ip.pixel_chunk_size_kbytes,871			ctx->dc->dml.ip.config_return_buffer_size_in_kbytes);872 873 874	for (i = 0; i < res_cap_dcn32.num_vmid; i++) {875		struct dcn20_vmid *vmid = &hubbub2->vmid[i];876 877		vmid->ctx = ctx;878 879		vmid->regs = &vmid_regs[i];880		vmid->shifts = &vmid_shifts;881		vmid->masks = &vmid_masks;882	}883 884	return &hubbub2->base;885}886 887static struct hubp *dcn32_hubp_create(888	struct dc_context *ctx,889	uint32_t inst)890{891	struct dcn20_hubp *hubp2 =892		kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL);893 894	if (!hubp2)895		return NULL;896 897#undef REG_STRUCT898#define REG_STRUCT hubp_regs899	hubp_regs_init(0),900	hubp_regs_init(1),901	hubp_regs_init(2),902	hubp_regs_init(3);903 904	if (hubp32_construct(hubp2, ctx, inst,905			&hubp_regs[inst], &hubp_shift, &hubp_mask))906		return &hubp2->base;907 908	BREAK_TO_DEBUGGER();909	kfree(hubp2);910	return NULL;911}912 913static void dcn32_dpp_destroy(struct dpp **dpp)914{915	kfree(TO_DCN30_DPP(*dpp));916	*dpp = NULL;917}918 919static struct dpp *dcn32_dpp_create(920	struct dc_context *ctx,921	uint32_t inst)922{923	struct dcn3_dpp *dpp3 =924		kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL);925 926	if (!dpp3)927		return NULL;928 929#undef REG_STRUCT930#define REG_STRUCT dpp_regs931	dpp_regs_init(0),932	dpp_regs_init(1),933	dpp_regs_init(2),934	dpp_regs_init(3);935 936	if (dpp32_construct(dpp3, ctx, inst,937			&dpp_regs[inst], &tf_shift, &tf_mask))938		return &dpp3->base;939 940	BREAK_TO_DEBUGGER();941	kfree(dpp3);942	return NULL;943}944 945static struct mpc *dcn32_mpc_create(946		struct dc_context *ctx,947		int num_mpcc,948		int num_rmu)949{950	struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc),951					  GFP_KERNEL);952 953	if (!mpc30)954		return NULL;955 956#undef REG_STRUCT957#define REG_STRUCT mpc_regs958	dcn_mpc_regs_init();959 960	dcn32_mpc_construct(mpc30, ctx,961			&mpc_regs,962			&mpc_shift,963			&mpc_mask,964			num_mpcc,965			num_rmu);966 967	return &mpc30->base;968}969 970static struct output_pixel_processor *dcn32_opp_create(971	struct dc_context *ctx, uint32_t inst)972{973	struct dcn20_opp *opp2 =974		kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL);975 976	if (!opp2) {977		BREAK_TO_DEBUGGER();978		return NULL;979	}980 981#undef REG_STRUCT982#define REG_STRUCT opp_regs983	opp_regs_init(0),984	opp_regs_init(1),985	opp_regs_init(2),986	opp_regs_init(3);987 988	dcn20_opp_construct(opp2, ctx, inst,989			&opp_regs[inst], &opp_shift, &opp_mask);990	return &opp2->base;991}992 993 994static struct timing_generator *dcn32_timing_generator_create(995		struct dc_context *ctx,996		uint32_t instance)997{998	struct optc *tgn10 =999		kzalloc(sizeof(struct optc), GFP_KERNEL);1000 1001	if (!tgn10)1002		return NULL;1003 1004#undef REG_STRUCT1005#define REG_STRUCT optc_regs1006	optc_regs_init(0),1007	optc_regs_init(1),1008	optc_regs_init(2),1009	optc_regs_init(3);1010 1011	tgn10->base.inst = instance;1012	tgn10->base.ctx = ctx;1013 1014	tgn10->tg_regs = &optc_regs[instance];1015	tgn10->tg_shift = &optc_shift;1016	tgn10->tg_mask = &optc_mask;1017 1018	dcn32_timing_generator_init(tgn10);1019 1020	return &tgn10->base;1021}1022 1023static const struct encoder_feature_support link_enc_feature = {1024		.max_hdmi_deep_color = COLOR_DEPTH_121212,1025		.max_hdmi_pixel_clock = 600000,1026		.hdmi_ycbcr420_supported = true,1027		.dp_ycbcr420_supported = true,1028		.fec_supported = true,1029		.flags.bits.IS_HBR2_CAPABLE = true,1030		.flags.bits.IS_HBR3_CAPABLE = true,1031		.flags.bits.IS_TPS3_CAPABLE = true,1032		.flags.bits.IS_TPS4_CAPABLE = true1033};1034 1035static struct link_encoder *dcn32_link_encoder_create(1036	struct dc_context *ctx,1037	const struct encoder_init_data *enc_init_data)1038{1039	struct dcn20_link_encoder *enc20 =1040		kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);1041 1042	if (!enc20)1043		return NULL;1044 1045#undef REG_STRUCT1046#define REG_STRUCT link_enc_aux_regs1047	aux_regs_init(0),1048	aux_regs_init(1),1049	aux_regs_init(2),1050	aux_regs_init(3),1051	aux_regs_init(4);1052 1053#undef REG_STRUCT1054#define REG_STRUCT link_enc_hpd_regs1055	hpd_regs_init(0),1056	hpd_regs_init(1),1057	hpd_regs_init(2),1058	hpd_regs_init(3),1059	hpd_regs_init(4);1060 1061#undef REG_STRUCT1062#define REG_STRUCT link_enc_regs1063	link_regs_init(0, A),1064	link_regs_init(1, B),1065	link_regs_init(2, C),1066	link_regs_init(3, D),1067	link_regs_init(4, E);1068 1069	dcn32_link_encoder_construct(enc20,1070			enc_init_data,1071			&link_enc_feature,1072			&link_enc_regs[enc_init_data->transmitter],1073			&link_enc_aux_regs[enc_init_data->channel - 1],1074			&link_enc_hpd_regs[enc_init_data->hpd_source],1075			&le_shift,1076			&le_mask);1077 1078	return &enc20->enc10.base;1079}1080 1081struct panel_cntl *dcn32_panel_cntl_create(const struct panel_cntl_init_data *init_data)1082{1083	struct dcn31_panel_cntl *panel_cntl =1084		kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL);1085 1086	if (!panel_cntl)1087		return NULL;1088 1089	dcn31_panel_cntl_construct(panel_cntl, init_data);1090 1091	return &panel_cntl->base;1092}1093 1094static void read_dce_straps(1095	struct dc_context *ctx,1096	struct resource_straps *straps)1097{1098	generic_reg_get(ctx, ctx->dcn_reg_offsets[regDC_PINSTRAPS_BASE_IDX] + regDC_PINSTRAPS,1099		FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio);1100 1101}1102 1103static struct audio *dcn32_create_audio(1104		struct dc_context *ctx, unsigned int inst)1105{1106 1107#undef REG_STRUCT1108#define REG_STRUCT audio_regs1109	audio_regs_init(0),1110	audio_regs_init(1),1111	audio_regs_init(2),1112	audio_regs_init(3),1113	audio_regs_init(4);1114 1115	return dce_audio_create(ctx, inst,1116			&audio_regs[inst], &audio_shift, &audio_mask);1117}1118 1119static struct vpg *dcn32_vpg_create(1120	struct dc_context *ctx,1121	uint32_t inst)1122{1123	struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL);1124 1125	if (!vpg3)1126		return NULL;1127 1128#undef REG_STRUCT1129#define REG_STRUCT vpg_regs1130	vpg_regs_init(0),1131	vpg_regs_init(1),1132	vpg_regs_init(2),1133	vpg_regs_init(3),1134	vpg_regs_init(4),1135	vpg_regs_init(5),1136	vpg_regs_init(6),1137	vpg_regs_init(7),1138	vpg_regs_init(8),1139	vpg_regs_init(9);1140 1141	vpg3_construct(vpg3, ctx, inst,1142			&vpg_regs[inst],1143			&vpg_shift,1144			&vpg_mask);1145 1146	return &vpg3->base;1147}1148 1149static struct afmt *dcn32_afmt_create(1150	struct dc_context *ctx,1151	uint32_t inst)1152{1153	struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL);1154 1155	if (!afmt3)1156		return NULL;1157 1158#undef REG_STRUCT1159#define REG_STRUCT afmt_regs1160	afmt_regs_init(0),1161	afmt_regs_init(1),1162	afmt_regs_init(2),1163	afmt_regs_init(3),1164	afmt_regs_init(4),1165	afmt_regs_init(5);1166 1167	afmt3_construct(afmt3, ctx, inst,1168			&afmt_regs[inst],1169			&afmt_shift,1170			&afmt_mask);1171 1172	return &afmt3->base;1173}1174 1175static struct apg *dcn31_apg_create(1176	struct dc_context *ctx,1177	uint32_t inst)1178{1179	struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL);1180 1181	if (!apg31)1182		return NULL;1183 1184#undef REG_STRUCT1185#define REG_STRUCT apg_regs1186	apg_regs_init(0),1187	apg_regs_init(1),1188	apg_regs_init(2),1189	apg_regs_init(3);1190 1191	apg31_construct(apg31, ctx, inst,1192			&apg_regs[inst],1193			&apg_shift,1194			&apg_mask);1195 1196	return &apg31->base;1197}1198 1199static struct stream_encoder *dcn32_stream_encoder_create(1200	enum engine_id eng_id,1201	struct dc_context *ctx)1202{1203	struct dcn10_stream_encoder *enc1;1204	struct vpg *vpg;1205	struct afmt *afmt;1206	int vpg_inst;1207	int afmt_inst;1208 1209	/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */1210	if (eng_id <= ENGINE_ID_DIGF) {1211		vpg_inst = eng_id;1212		afmt_inst = eng_id;1213	} else1214		return NULL;1215 1216	enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);1217	vpg = dcn32_vpg_create(ctx, vpg_inst);1218	afmt = dcn32_afmt_create(ctx, afmt_inst);1219 1220	if (!enc1 || !vpg || !afmt) {1221		kfree(enc1);1222		kfree(vpg);1223		kfree(afmt);1224		return NULL;1225	}1226 1227#undef REG_STRUCT1228#define REG_STRUCT stream_enc_regs1229	stream_enc_regs_init(0),1230	stream_enc_regs_init(1),1231	stream_enc_regs_init(2),1232	stream_enc_regs_init(3),1233	stream_enc_regs_init(4);1234 1235	dcn32_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios,1236					eng_id, vpg, afmt,1237					&stream_enc_regs[eng_id],1238					&se_shift, &se_mask);1239 1240	return &enc1->base;1241}1242 1243static struct hpo_dp_stream_encoder *dcn32_hpo_dp_stream_encoder_create(1244	enum engine_id eng_id,1245	struct dc_context *ctx)1246{1247	struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31;1248	struct vpg *vpg;1249	struct apg *apg;1250	uint32_t hpo_dp_inst;1251	uint32_t vpg_inst;1252	uint32_t apg_inst;1253 1254	ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3));1255	hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0;1256 1257	/* Mapping of VPG register blocks to HPO DP block instance:1258	 * VPG[6] -> HPO_DP[0]1259	 * VPG[7] -> HPO_DP[1]1260	 * VPG[8] -> HPO_DP[2]1261	 * VPG[9] -> HPO_DP[3]1262	 */1263	vpg_inst = hpo_dp_inst + 6;1264 1265	/* Mapping of APG register blocks to HPO DP block instance:1266	 * APG[0] -> HPO_DP[0]1267	 * APG[1] -> HPO_DP[1]1268	 * APG[2] -> HPO_DP[2]1269	 * APG[3] -> HPO_DP[3]1270	 */1271	apg_inst = hpo_dp_inst;1272 1273	/* allocate HPO stream encoder and create VPG sub-block */1274	hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL);1275	vpg = dcn32_vpg_create(ctx, vpg_inst);1276	apg = dcn31_apg_create(ctx, apg_inst);1277 1278	if (!hpo_dp_enc31 || !vpg || !apg) {1279		kfree(hpo_dp_enc31);1280		kfree(vpg);1281		kfree(apg);1282		return NULL;1283	}1284 1285#undef REG_STRUCT1286#define REG_STRUCT hpo_dp_stream_enc_regs1287	hpo_dp_stream_encoder_reg_init(0),1288	hpo_dp_stream_encoder_reg_init(1),1289	hpo_dp_stream_encoder_reg_init(2),1290	hpo_dp_stream_encoder_reg_init(3);1291 1292	dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios,1293					hpo_dp_inst, eng_id, vpg, apg,1294					&hpo_dp_stream_enc_regs[hpo_dp_inst],1295					&hpo_dp_se_shift, &hpo_dp_se_mask);1296 1297	return &hpo_dp_enc31->base;1298}1299 1300static struct hpo_dp_link_encoder *dcn32_hpo_dp_link_encoder_create(1301	uint8_t inst,1302	struct dc_context *ctx)1303{1304	struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31;1305 1306	/* allocate HPO link encoder */1307	hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL);1308	if (!hpo_dp_enc31)1309		return NULL; /* out of memory */1310 1311#undef REG_STRUCT1312#define REG_STRUCT hpo_dp_link_enc_regs1313	hpo_dp_link_encoder_reg_init(0),1314	hpo_dp_link_encoder_reg_init(1);1315 1316	hpo_dp_link_encoder32_construct(hpo_dp_enc31, ctx, inst,1317					&hpo_dp_link_enc_regs[inst],1318					&hpo_dp_le_shift, &hpo_dp_le_mask);1319 1320	return &hpo_dp_enc31->base;1321}1322 1323static struct dce_hwseq *dcn32_hwseq_create(1324	struct dc_context *ctx)1325{1326	struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);1327 1328#undef REG_STRUCT1329#define REG_STRUCT hwseq_reg1330	hwseq_reg_init();1331 1332	if (hws) {1333		hws->ctx = ctx;1334		hws->regs = &hwseq_reg;1335		hws->shifts = &hwseq_shift;1336		hws->masks = &hwseq_mask;1337	}1338	return hws;1339}1340static const struct resource_create_funcs res_create_funcs = {1341	.read_dce_straps = read_dce_straps,1342	.create_audio = dcn32_create_audio,1343	.create_stream_encoder = dcn32_stream_encoder_create,1344	.create_hpo_dp_stream_encoder = dcn32_hpo_dp_stream_encoder_create,1345	.create_hpo_dp_link_encoder = dcn32_hpo_dp_link_encoder_create,1346	.create_hwseq = dcn32_hwseq_create,1347};1348 1349static void dcn32_resource_destruct(struct dcn32_resource_pool *pool)1350{1351	unsigned int i;1352 1353	for (i = 0; i < pool->base.stream_enc_count; i++) {1354		if (pool->base.stream_enc[i] != NULL) {1355			if (pool->base.stream_enc[i]->vpg != NULL) {1356				kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg));1357				pool->base.stream_enc[i]->vpg = NULL;1358			}1359			if (pool->base.stream_enc[i]->afmt != NULL) {1360				kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt));1361				pool->base.stream_enc[i]->afmt = NULL;1362			}1363			kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i]));1364			pool->base.stream_enc[i] = NULL;1365		}1366	}1367 1368	for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) {1369		if (pool->base.hpo_dp_stream_enc[i] != NULL) {1370			if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) {1371				kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg));1372				pool->base.hpo_dp_stream_enc[i]->vpg = NULL;1373			}1374			if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) {1375				kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg));1376				pool->base.hpo_dp_stream_enc[i]->apg = NULL;1377			}1378			kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i]));1379			pool->base.hpo_dp_stream_enc[i] = NULL;1380		}1381	}1382 1383	for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) {1384		if (pool->base.hpo_dp_link_enc[i] != NULL) {1385			kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i]));1386			pool->base.hpo_dp_link_enc[i] = NULL;1387		}1388	}1389 1390	for (i = 0; i < pool->base.res_cap->num_dsc; i++) {1391		if (pool->base.dscs[i] != NULL)1392			dcn20_dsc_destroy(&pool->base.dscs[i]);1393	}1394 1395	if (pool->base.mpc != NULL) {1396		kfree(TO_DCN20_MPC(pool->base.mpc));1397		pool->base.mpc = NULL;1398	}1399	if (pool->base.hubbub != NULL) {1400		kfree(TO_DCN20_HUBBUB(pool->base.hubbub));1401		pool->base.hubbub = NULL;1402	}1403	for (i = 0; i < pool->base.pipe_count; i++) {1404		if (pool->base.dpps[i] != NULL)1405			dcn32_dpp_destroy(&pool->base.dpps[i]);1406 1407		if (pool->base.ipps[i] != NULL)1408			pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]);1409 1410		if (pool->base.hubps[i] != NULL) {1411			kfree(TO_DCN20_HUBP(pool->base.hubps[i]));1412			pool->base.hubps[i] = NULL;1413		}1414 1415		if (pool->base.irqs != NULL) {1416			dal_irq_service_destroy(&pool->base.irqs);1417		}1418	}1419 1420	for (i = 0; i < pool->base.res_cap->num_ddc; i++) {1421		if (pool->base.engines[i] != NULL)1422			dce110_engine_destroy(&pool->base.engines[i]);1423		if (pool->base.hw_i2cs[i] != NULL) {1424			kfree(pool->base.hw_i2cs[i]);1425			pool->base.hw_i2cs[i] = NULL;1426		}1427		if (pool->base.sw_i2cs[i] != NULL) {1428			kfree(pool->base.sw_i2cs[i]);1429			pool->base.sw_i2cs[i] = NULL;1430		}1431	}1432 1433	for (i = 0; i < pool->base.res_cap->num_opp; i++) {1434		if (pool->base.opps[i] != NULL)1435			pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);1436	}1437 1438	for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {1439		if (pool->base.timing_generators[i] != NULL)	{1440			kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i]));1441			pool->base.timing_generators[i] = NULL;1442		}1443	}1444 1445	for (i = 0; i < pool->base.res_cap->num_dwb; i++) {1446		if (pool->base.dwbc[i] != NULL) {1447			kfree(TO_DCN30_DWBC(pool->base.dwbc[i]));1448			pool->base.dwbc[i] = NULL;1449		}1450		if (pool->base.mcif_wb[i] != NULL) {1451			kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i]));1452			pool->base.mcif_wb[i] = NULL;1453		}1454	}1455 1456	for (i = 0; i < pool->base.audio_count; i++) {1457		if (pool->base.audios[i])1458			dce_aud_destroy(&pool->base.audios[i]);1459	}1460 1461	for (i = 0; i < pool->base.clk_src_count; i++) {1462		if (pool->base.clock_sources[i] != NULL) {1463			dcn20_clock_source_destroy(&pool->base.clock_sources[i]);1464			pool->base.clock_sources[i] = NULL;1465		}1466	}1467 1468	for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) {1469		if (pool->base.mpc_lut[i] != NULL) {1470			dc_3dlut_func_release(pool->base.mpc_lut[i]);1471			pool->base.mpc_lut[i] = NULL;1472		}1473		if (pool->base.mpc_shaper[i] != NULL) {1474			dc_transfer_func_release(pool->base.mpc_shaper[i]);1475			pool->base.mpc_shaper[i] = NULL;1476		}1477	}1478 1479	if (pool->base.dp_clock_source != NULL) {1480		dcn20_clock_source_destroy(&pool->base.dp_clock_source);1481		pool->base.dp_clock_source = NULL;1482	}1483 1484	for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {1485		if (pool->base.multiple_abms[i] != NULL)1486			dce_abm_destroy(&pool->base.multiple_abms[i]);1487	}1488 1489	if (pool->base.psr != NULL)1490		dmub_psr_destroy(&pool->base.psr);1491 1492	if (pool->base.dccg != NULL)1493		dcn_dccg_destroy(&pool->base.dccg);1494 1495	if (pool->base.oem_device != NULL) {1496		struct dc *dc = pool->base.oem_device->ctx->dc;1497 1498		dc->link_srv->destroy_ddc_service(&pool->base.oem_device);1499	}1500}1501 1502 1503static bool dcn32_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)1504{1505	int i;1506	uint32_t dwb_count = pool->res_cap->num_dwb;1507 1508	for (i = 0; i < dwb_count; i++) {1509		struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc),1510						    GFP_KERNEL);1511 1512		if (!dwbc30) {1513			dm_error("DC: failed to create dwbc30!\n");1514			return false;1515		}1516 1517#undef REG_STRUCT1518#define REG_STRUCT dwbc30_regs1519		dwbc_regs_dcn3_init(0);1520 1521		dcn30_dwbc_construct(dwbc30, ctx,1522				&dwbc30_regs[i],1523				&dwbc30_shift,1524				&dwbc30_mask,1525				i);1526 1527		pool->dwbc[i] = &dwbc30->base;1528	}1529	return true;1530}1531 1532static bool dcn32_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool)1533{1534	int i;1535	uint32_t dwb_count = pool->res_cap->num_dwb;1536 1537	for (i = 0; i < dwb_count; i++) {1538		struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub),1539						    GFP_KERNEL);1540 1541		if (!mcif_wb30) {1542			dm_error("DC: failed to create mcif_wb30!\n");1543			return false;1544		}1545 1546#undef REG_STRUCT1547#define REG_STRUCT mcif_wb30_regs1548		mcif_wb_regs_dcn3_init(0);1549 1550		dcn32_mmhubbub_construct(mcif_wb30, ctx,1551				&mcif_wb30_regs[i],1552				&mcif_wb30_shift,1553				&mcif_wb30_mask,1554				i);1555 1556		pool->mcif_wb[i] = &mcif_wb30->base;1557	}1558	return true;1559}1560 1561static struct display_stream_compressor *dcn32_dsc_create(1562	struct dc_context *ctx, uint32_t inst)1563{1564	struct dcn20_dsc *dsc =1565		kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL);1566 1567	if (!dsc) {1568		BREAK_TO_DEBUGGER();1569		return NULL;1570	}1571 1572#undef REG_STRUCT1573#define REG_STRUCT dsc_regs1574	dsc_regsDCN20_init(0),1575	dsc_regsDCN20_init(1),1576	dsc_regsDCN20_init(2),1577	dsc_regsDCN20_init(3);1578 1579	dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask);1580 1581	dsc->max_image_width = 6016;1582 1583	return &dsc->base;1584}1585 1586static void dcn32_destroy_resource_pool(struct resource_pool **pool)1587{1588	struct dcn32_resource_pool *dcn32_pool = TO_DCN32_RES_POOL(*pool);1589 1590	dcn32_resource_destruct(dcn32_pool);1591	kfree(dcn32_pool);1592	*pool = NULL;1593}1594 1595bool dcn32_acquire_post_bldn_3dlut(1596		struct resource_context *res_ctx,1597		const struct resource_pool *pool,1598		int mpcc_id,1599		struct dc_3dlut **lut,1600		struct dc_transfer_func **shaper)1601{1602	bool ret = false;1603 1604	ASSERT(*lut == NULL && *shaper == NULL);1605	*lut = NULL;1606	*shaper = NULL;1607 1608	if (!res_ctx->is_mpc_3dlut_acquired[mpcc_id]) {1609		*lut = pool->mpc_lut[mpcc_id];1610		*shaper = pool->mpc_shaper[mpcc_id];1611		res_ctx->is_mpc_3dlut_acquired[mpcc_id] = true;1612		ret = true;1613	}1614	return ret;1615}1616 1617bool dcn32_release_post_bldn_3dlut(1618		struct resource_context *res_ctx,1619		const struct resource_pool *pool,1620		struct dc_3dlut **lut,1621		struct dc_transfer_func **shaper)1622{1623	int i;1624	bool ret = false;1625 1626	for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) {1627		if (pool->mpc_lut[i] == *lut && pool->mpc_shaper[i] == *shaper) {1628			res_ctx->is_mpc_3dlut_acquired[i] = false;1629			pool->mpc_lut[i]->state.raw = 0;1630			*lut = NULL;1631			*shaper = NULL;1632			ret = true;1633			break;1634		}1635	}1636	return ret;1637}1638 1639static void dcn32_enable_phantom_plane(struct dc *dc,1640		struct dc_state *context,1641		struct dc_stream_state *phantom_stream,1642		unsigned int dc_pipe_idx)1643{1644	struct dc_plane_state *phantom_plane = NULL;1645	struct dc_plane_state *prev_phantom_plane = NULL;1646	struct pipe_ctx *curr_pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx];1647 1648	while (curr_pipe) {1649		if (curr_pipe->top_pipe && curr_pipe->top_pipe->plane_state == curr_pipe->plane_state)1650			phantom_plane = prev_phantom_plane;1651		else1652			phantom_plane = dc_state_create_phantom_plane(dc, context, curr_pipe->plane_state);1653 1654		if (!phantom_plane)1655			continue;1656 1657		memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address));1658		memcpy(&phantom_plane->scaling_quality, &curr_pipe->plane_state->scaling_quality,1659				sizeof(phantom_plane->scaling_quality));1660		memcpy(&phantom_plane->src_rect, &curr_pipe->plane_state->src_rect, sizeof(phantom_plane->src_rect));1661		memcpy(&phantom_plane->dst_rect, &curr_pipe->plane_state->dst_rect, sizeof(phantom_plane->dst_rect));1662		memcpy(&phantom_plane->clip_rect, &curr_pipe->plane_state->clip_rect, sizeof(phantom_plane->clip_rect));1663		memcpy(&phantom_plane->plane_size, &curr_pipe->plane_state->plane_size,1664				sizeof(phantom_plane->plane_size));1665		memcpy(&phantom_plane->tiling_info, &curr_pipe->plane_state->tiling_info,1666				sizeof(phantom_plane->tiling_info));1667		memcpy(&phantom_plane->dcc, &curr_pipe->plane_state->dcc, sizeof(phantom_plane->dcc));1668		phantom_plane->format = curr_pipe->plane_state->format;1669		phantom_plane->rotation = curr_pipe->plane_state->rotation;1670		phantom_plane->visible = curr_pipe->plane_state->visible;1671 1672		/* Shadow pipe has small viewport. */1673		phantom_plane->clip_rect.y = 0;1674		phantom_plane->clip_rect.height = phantom_stream->src.height;1675 1676		dc_state_add_phantom_plane(dc, phantom_stream, phantom_plane, context);1677 1678		curr_pipe = curr_pipe->bottom_pipe;1679		prev_phantom_plane = phantom_plane;1680	}1681}1682 1683static struct dc_stream_state *dcn32_enable_phantom_stream(struct dc *dc,1684		struct dc_state *context,1685		display_e2e_pipe_params_st *pipes,1686		unsigned int pipe_cnt,1687		unsigned int dc_pipe_idx)1688{1689	struct dc_stream_state *phantom_stream = NULL;1690	struct pipe_ctx *ref_pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx];1691 1692	phantom_stream = dc_state_create_phantom_stream(dc, context, ref_pipe->stream);1693	if (!phantom_stream)1694		return phantom_stream;1695 1696	/* stream has limited viewport and small timing */1697	memcpy(&phantom_stream->timing, &ref_pipe->stream->timing, sizeof(phantom_stream->timing));1698	memcpy(&phantom_stream->src, &ref_pipe->stream->src, sizeof(phantom_stream->src));1699	memcpy(&phantom_stream->dst, &ref_pipe->stream->dst, sizeof(phantom_stream->dst));1700	DC_FP_START();1701	dcn32_set_phantom_stream_timing(dc, context, ref_pipe, phantom_stream, pipes, pipe_cnt, dc_pipe_idx);1702	DC_FP_END();1703 1704	dc_state_add_phantom_stream(dc, context, phantom_stream, ref_pipe->stream);1705	return phantom_stream;1706}1707 1708/* TODO: Input to this function should indicate which pipe indexes (or streams)1709 * require a phantom pipe / stream1710 */1711void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context,1712		display_e2e_pipe_params_st *pipes,1713		unsigned int pipe_cnt,1714		unsigned int index)1715{1716	struct dc_stream_state *phantom_stream = NULL;1717	unsigned int i;1718 1719	// The index of the DC pipe passed into this function is guarenteed to1720	// be a valid candidate for SubVP (i.e. has a plane, stream, doesn't1721	// already have phantom pipe assigned, etc.) by previous checks.1722	phantom_stream = dcn32_enable_phantom_stream(dc, context, pipes, pipe_cnt, index);1723	if (!phantom_stream)1724		return;1725 1726	dcn32_enable_phantom_plane(dc, context, phantom_stream, index);1727 1728	for (i = 0; i < dc->res_pool->pipe_count; i++) {1729		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];1730 1731		// Build scaling params for phantom pipes which were newly added.1732		// We determine which phantom pipes were added by comparing with1733		// the phantom stream.1734		if (pipe->plane_state && pipe->stream && pipe->stream == phantom_stream &&1735				dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) {1736			pipe->stream->use_dynamic_meta = false;1737			pipe->plane_state->flip_immediate = false;1738			if (!resource_build_scaling_params(pipe)) {1739				// Log / remove phantom pipes since failed to build scaling params1740			}1741		}1742	}1743}1744 1745static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_validate)1746{1747	bool out = false;1748 1749	BW_VAL_TRACE_SETUP();1750 1751	int vlevel = 0;1752	int pipe_cnt = 0;1753	display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL);1754 1755	/* To handle Freesync properly, setting FreeSync DML parameters1756	 * to its default state for the first stage of validation1757	 */1758	context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false;1759	context->bw_ctx.dml.soc.dram_clock_change_requirement_final = true;1760 1761	DC_LOGGER_INIT(dc->ctx->logger);1762 1763	BW_VAL_TRACE_COUNT();1764 1765	if (!pipes)1766		goto validate_fail;1767 1768	DC_FP_START();1769	out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate);1770	DC_FP_END();1771 1772	if (pipe_cnt == 0)1773		goto validate_out;1774 1775	if (!out)1776		goto validate_fail;1777 1778	BW_VAL_TRACE_END_VOLTAGE_LEVEL();1779 1780	if (fast_validate) {1781		BW_VAL_TRACE_SKIP(fast);1782		goto validate_out;1783	}1784 1785	dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);1786 1787	dcn32_override_min_req_memclk(dc, context);1788	dcn32_override_min_req_dcfclk(dc, context);1789 1790	BW_VAL_TRACE_END_WATERMARKS();1791 1792	goto validate_out;1793 1794validate_fail:1795	DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n",1796		dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states]));1797 1798	BW_VAL_TRACE_SKIP(fail);1799	out = false;1800 1801validate_out:1802	kfree(pipes);1803 1804	BW_VAL_TRACE_FINISH();1805 1806	return out;1807}1808 1809bool dcn32_validate_bandwidth(struct dc *dc,1810		struct dc_state *context,1811		bool fast_validate)1812{1813	bool out = false;1814 1815	if (dc->debug.using_dml2)1816		out = dml2_validate(dc, context,1817				context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,1818				fast_validate);1819	else1820		out = dml1_validate(dc, context, fast_validate);1821	return out;1822}1823 1824int dcn32_populate_dml_pipes_from_context(1825	struct dc *dc, struct dc_state *context,1826	display_e2e_pipe_params_st *pipes,1827	bool fast_validate)1828{1829	int i, pipe_cnt;1830	struct resource_context *res_ctx = &context->res_ctx;1831	struct pipe_ctx *pipe = NULL;1832	bool subvp_in_use = false;1833	struct dc_crtc_timing *timing;1834	int subvp_main_pipe_index = -1;1835	enum mall_stream_type mall_type;1836	bool single_display_subvp = false;1837	struct dc_stream_state *stream = NULL;1838	int num_subvp_main = 0;1839	int num_subvp_phantom = 0;1840	int num_subvp_none = 0;1841	int odm_slice_count;1842 1843	dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);1844 1845	/* For single display subvp, look for subvp main so if we have phantom1846	 *  pipe, we can set odm policy to match main pipe1847	 */1848	for (i = 0; i < context->stream_count; i++) {1849		stream = context->streams[i];1850		mall_type = dc_state_get_stream_subvp_type(context, stream);1851		if (mall_type == SUBVP_MAIN)1852			num_subvp_main++;1853		else if (mall_type == SUBVP_PHANTOM)1854			num_subvp_phantom++;1855		else1856			num_subvp_none++;1857	}1858	if (num_subvp_main == 1 && num_subvp_phantom == 1 && num_subvp_none == 0)1859		single_display_subvp = true;1860 1861	if (single_display_subvp) {1862		for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {1863			pipe = &res_ctx->pipe_ctx[i];1864			if (!res_ctx->pipe_ctx[i].stream)1865				continue;1866 1867			mall_type = dc_state_get_pipe_subvp_type(context, pipe);1868			if (mall_type == SUBVP_MAIN) {1869				if (resource_is_pipe_type(pipe, OTG_MASTER))1870					subvp_main_pipe_index = i;1871			}1872			pipe_cnt++;1873		}1874	}1875 1876	for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {1877 1878		if (!res_ctx->pipe_ctx[i].stream)1879			continue;1880		pipe = &res_ctx->pipe_ctx[i];1881		timing = &pipe->stream->timing;1882 1883		pipes[pipe_cnt].pipe.src.gpuvm = true;1884		DC_FP_START();1885		dcn32_zero_pipe_dcc_fraction(pipes, pipe_cnt);1886		DC_FP_END();1887		pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch;1888		if (dc->config.enable_windowed_mpo_odm &&1889				dc->debug.enable_single_display_2to1_odm_policy) {1890			/* For single display subvp, if pipe is phantom pipe,1891			 *  then copy odm policy from subvp main pipe1892			 */1893			mall_type = dc_state_get_pipe_subvp_type(context, pipe);1894			if (single_display_subvp && (mall_type == SUBVP_PHANTOM)) {1895				if (subvp_main_pipe_index < 0) {1896					odm_slice_count = -1;1897					ASSERT(0);1898				} else {1899					odm_slice_count = resource_get_odm_slice_count(&res_ctx->pipe_ctx[subvp_main_pipe_index]);1900				}1901			} else {1902				odm_slice_count = resource_get_odm_slice_count(pipe);1903			}1904			switch (odm_slice_count) {1905			case 2:1906				pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;1907				break;1908			case 4:1909				pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_4to1;1910				break;1911			default:1912				pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;1913			}1914		} else {1915			pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;1916		}1917 1918		pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet1919		pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;1920		pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_19;1921 1922		/* Only populate DML input with subvp info for full updates.1923		 * This is just a workaround -- needs a proper fix.1924		 */1925		if (!fast_validate) {1926			switch (dc_state_get_pipe_subvp_type(context, pipe)) {1927			case SUBVP_MAIN:1928				pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_sub_viewport;1929				subvp_in_use = true;1930				break;1931			case SUBVP_PHANTOM:1932				pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_phantom_pipe;1933				pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable;1934				// Disallow unbounded req for SubVP according to DCHUB programming guide1935				pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;1936				break;1937			case SUBVP_NONE:1938				pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_disable;1939				pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable;1940				break;1941			default:1942				break;1943			}1944		}1945 1946		pipes[pipe_cnt].dout.dsc_input_bpc = 0;1947		if (pipes[pipe_cnt].dout.dsc_enable) {1948			switch (timing->display_color_depth) {1949			case COLOR_DEPTH_888:1950				pipes[pipe_cnt].dout.dsc_input_bpc = 8;1951				break;1952			case COLOR_DEPTH_101010:1953				pipes[pipe_cnt].dout.dsc_input_bpc = 10;1954				break;1955			case COLOR_DEPTH_121212:1956				pipes[pipe_cnt].dout.dsc_input_bpc = 12;1957				break;1958			default:1959				ASSERT(0);1960				break;1961			}1962		}1963 1964 1965		pipe_cnt++;1966	}1967 1968	/* For DET allocation, we don't want to use DML policy (not optimal for utilizing all1969	 * the DET available for each pipe). Use the DET override input to maintain our driver1970	 * policy.1971	 */1972	dcn32_set_det_allocations(dc, context, pipes);1973 1974	// In general cases we want to keep the dram clock change requirement1975	// (prefer configs that support MCLK switch). Only override to false1976	// for SubVP1977	if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || subvp_in_use)1978		context->bw_ctx.dml.soc.dram_clock_change_requirement_final = false;1979	else1980		context->bw_ctx.dml.soc.dram_clock_change_requirement_final = true;1981 1982	return pipe_cnt;1983}1984 1985unsigned int dcn32_calculate_mall_ways_from_bytes(const struct dc *dc, unsigned int total_size_in_mall_bytes)1986{1987	uint32_t cache_lines_used, lines_per_way, total_cache_lines, num_ways;1988 1989	if (total_size_in_mall_bytes == 0) {1990		return 0;1991	}1992 1993	/* add 2 lines for worst case alignment */1994	cache_lines_used = total_size_in_mall_bytes / dc->caps.cache_line_size + 2;1995 1996	total_cache_lines = dc->caps.max_cab_allocation_bytes / dc->caps.cache_line_size;1997	lines_per_way = total_cache_lines / dc->caps.cache_num_ways;1998	num_ways = cache_lines_used / lines_per_way;1999	if (cache_lines_used % lines_per_way > 0)2000		num_ways++;2001 2002	return num_ways;2003}2004 2005static struct dc_cap_funcs cap_funcs = {2006	.get_dcc_compression_cap = dcn20_get_dcc_compression_cap,2007	.get_subvp_en = dcn32_subvp_in_use,2008};2009 2010void dcn32_calculate_wm_and_dlg(struct dc *dc, struct dc_state *context,2011				display_e2e_pipe_params_st *pipes,2012				int pipe_cnt,2013				int vlevel)2014{2015    DC_FP_START();2016    dcn32_calculate_wm_and_dlg_fpu(dc, context, pipes, pipe_cnt, vlevel);2017    DC_FP_END();2018}2019 2020static void dcn32_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)2021{2022	struct dml2_configuration_options *dml2_opt = &dc->dml2_tmp;2023 2024	memcpy(dml2_opt, &dc->dml2_options, sizeof(dc->dml2_options));2025 2026	DC_FP_START();2027 2028	dcn32_update_bw_bounding_box_fpu(dc, bw_params);2029 2030	dml2_opt->use_clock_dc_limits = false;2031	if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2)2032		dml2_reinit(dc, dml2_opt, &dc->current_state->bw_ctx.dml2);2033 2034	dml2_opt->use_clock_dc_limits = true;2035	if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2_dc_power_source)2036		dml2_reinit(dc, dml2_opt, &dc->current_state->bw_ctx.dml2_dc_power_source);2037 2038	DC_FP_END();2039}2040 2041static struct resource_funcs dcn32_res_pool_funcs = {2042	.destroy = dcn32_destroy_resource_pool,2043	.link_enc_create = dcn32_link_encoder_create,2044	.link_enc_create_minimal = NULL,2045	.panel_cntl_create = dcn32_panel_cntl_create,2046	.validate_bandwidth = dcn32_validate_bandwidth,2047	.calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg,2048	.populate_dml_pipes = dcn32_populate_dml_pipes_from_context,2049	.acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe,2050	.acquire_free_pipe_as_secondary_opp_head = dcn32_acquire_free_pipe_as_secondary_opp_head,2051	.release_pipe = dcn20_release_pipe,2052	.add_stream_to_ctx = dcn30_add_stream_to_ctx,2053	.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,2054	.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,2055	.populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context,2056	.set_mcif_arb_params = dcn30_set_mcif_arb_params,2057	.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,2058	.acquire_post_bldn_3dlut = dcn32_acquire_post_bldn_3dlut,2059	.release_post_bldn_3dlut = dcn32_release_post_bldn_3dlut,2060	.update_bw_bounding_box = dcn32_update_bw_bounding_box,2061	.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,2062	.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,2063	.add_phantom_pipes = dcn32_add_phantom_pipes,2064	.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,2065	.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,2066};2067 2068static uint32_t read_pipe_fuses(struct dc_context *ctx)2069{2070	uint32_t value = REG_READ(CC_DC_PIPE_DIS);2071	/* DCN32 support max 4 pipes */2072	value = value & 0xf;2073	return value;2074}2075 2076 2077static bool dcn32_resource_construct(2078	uint8_t num_virtual_links,2079	struct dc *dc,2080	struct dcn32_resource_pool *pool)2081{2082	int i, j;2083	struct dc_context *ctx = dc->ctx;2084	struct irq_service_init_data init_data;2085	struct ddc_service_init_data ddc_init_data = {0};2086	uint32_t pipe_fuses = 0;2087	uint32_t num_pipes  = 4;2088 2089#undef REG_STRUCT2090#define REG_STRUCT bios_regs2091	bios_regs_init();2092 2093#undef REG_STRUCT2094#define REG_STRUCT clk_src_regs2095	clk_src_regs_init(0, A),2096	clk_src_regs_init(1, B),2097	clk_src_regs_init(2, C),2098	clk_src_regs_init(3, D),2099	clk_src_regs_init(4, E);2100 2101#undef REG_STRUCT2102#define REG_STRUCT abm_regs2103	abm_regs_init(0),2104	abm_regs_init(1),2105	abm_regs_init(2),2106	abm_regs_init(3);2107 2108#undef REG_STRUCT2109#define REG_STRUCT dccg_regs2110	dccg_regs_init();2111 2112	DC_FP_START();2113 2114	ctx->dc_bios->regs = &bios_regs;2115 2116	pool->base.res_cap = &res_cap_dcn32;2117	/* max number of pipes for ASIC before checking for pipe fuses */2118	num_pipes  = pool->base.res_cap->num_timing_generator;2119	pipe_fuses = read_pipe_fuses(ctx);2120 2121	for (i = 0; i < pool->base.res_cap->num_timing_generator; i++)2122		if (pipe_fuses & 1 << i)2123			num_pipes--;2124 2125	if (pipe_fuses & 1)2126		ASSERT(0); //Unexpected - Pipe 0 should always be fully functional!2127 2128	if (pipe_fuses & CC_DC_PIPE_DIS__DC_FULL_DIS_MASK)2129		ASSERT(0); //Entire DCN is harvested!2130 2131	/* within dml lib, initial value is hard coded, if ASIC pipe is fused, the2132	 * value will be changed, update max_num_dpp and max_num_otg for dml.2133	 */2134	dcn3_2_ip.max_num_dpp = num_pipes;2135	dcn3_2_ip.max_num_otg = num_pipes;2136 2137	pool->base.funcs = &dcn32_res_pool_funcs;2138 2139	/*************************************************2140	 *  Resource + asic cap harcoding                *2141	 *************************************************/2142	pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;2143	pool->base.timing_generator_count = num_pipes;2144	pool->base.pipe_count = num_pipes;2145	pool->base.mpcc_count = num_pipes;2146	dc->caps.max_downscale_ratio = 600;2147	dc->caps.i2c_speed_in_khz = 100;2148	dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/2149	/* TODO: Bring max_cursor_size back to 256 after subvp cursor corruption is fixed*/2150	dc->caps.max_cursor_size = 64;2151	dc->caps.min_horizontal_blanking_period = 80;2152	dc->caps.dmdata_alloc_size = 2048;2153	dc->caps.mall_size_per_mem_channel = 4;2154	/* total size = mall per channel * num channels * 1024 * 1024 */2155	dc->caps.mall_size_total = dc->caps.mall_size_per_mem_channel * dc->ctx->dc_bios->vram_info.num_chans * 1048576;2156	dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8;2157 2158	dc->caps.cache_line_size = 64;2159	dc->caps.cache_num_ways = 16;2160 2161	/* Calculate the available MALL space */2162	dc->caps.max_cab_allocation_bytes = dcn32_calc_num_avail_chans_for_mall(2163		dc, dc->ctx->dc_bios->vram_info.num_chans) *2164		dc->caps.mall_size_per_mem_channel * 1024 * 1024;2165	dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes;2166 2167	dc->caps.subvp_fw_processing_delay_us = 15;2168	dc->caps.subvp_drr_max_vblank_margin_us = 40;2169	dc->caps.subvp_prefetch_end_to_mall_start_us = 15;2170	dc->caps.subvp_swath_height_margin_lines = 16;2171	dc->caps.subvp_pstate_allow_width_us = 20;2172	dc->caps.subvp_vertical_int_margin_us = 30;2173	dc->caps.subvp_drr_vblank_start_margin_us = 100; // 100us margin2174 2175	dc->caps.max_slave_planes = 2;2176	dc->caps.max_slave_yuv_planes = 2;2177	dc->caps.max_slave_rgb_planes = 2;2178	dc->caps.post_blend_color_processing = true;2179	dc->caps.force_dp_tps4_for_cp2520 = true;2180	if (dc->config.forceHBR2CP2520)2181		dc->caps.force_dp_tps4_for_cp2520 = false;2182	dc->caps.dp_hpo = true;2183	dc->caps.dp_hdmi21_pcon_support = true;2184	dc->caps.edp_dsc_support = true;2185	dc->caps.extended_aux_timeout_support = true;2186	dc->caps.dmcub_support = true;2187	dc->caps.seamless_odm = true;2188	dc->caps.max_v_total = (1 << 15) - 1;2189 2190	/* Color pipeline capabilities */2191	dc->caps.color.dpp.dcn_arch = 1;2192	dc->caps.color.dpp.input_lut_shared = 0;2193	dc->caps.color.dpp.icsc = 1;2194	dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr2195	dc->caps.color.dpp.dgam_rom_caps.srgb = 1;2196	dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1;2197	dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1;2198	dc->caps.color.dpp.dgam_rom_caps.pq = 1;2199	dc->caps.color.dpp.dgam_rom_caps.hlg = 1;2200	dc->caps.color.dpp.post_csc = 1;2201	dc->caps.color.dpp.gamma_corr = 1;2202	dc->caps.color.dpp.dgam_rom_for_yuv = 0;2203 2204	dc->caps.color.dpp.hw_3d_lut = 1;2205	dc->caps.color.dpp.ogam_ram = 0;  // no OGAM in DPP since DCN12206	// no OGAM ROM on DCN2 and later ASICs2207	dc->caps.color.dpp.ogam_rom_caps.srgb = 0;2208	dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0;2209	dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0;2210	dc->caps.color.dpp.ogam_rom_caps.pq = 0;2211	dc->caps.color.dpp.ogam_rom_caps.hlg = 0;2212	dc->caps.color.dpp.ocsc = 0;2213 2214	dc->caps.color.mpc.gamut_remap = 1;2215	dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //4, configurable to be before or after BLND in MPCC2216	dc->caps.color.mpc.ogam_ram = 1;2217	dc->caps.color.mpc.ogam_rom_caps.srgb = 0;2218	dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0;2219	dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0;2220	dc->caps.color.mpc.ogam_rom_caps.pq = 0;2221	dc->caps.color.mpc.ogam_rom_caps.hlg = 0;2222	dc->caps.color.mpc.ocsc = 1;2223 2224	/* Use pipe context based otg sync logic */2225	dc->config.use_pipe_ctx_sync_logic = true;2226 2227	dc->config.dc_mode_clk_limit_support = true;2228	dc->config.enable_windowed_mpo_odm = true;2229	dc->config.disable_hbr_audio_dp2 = true;2230	/* read VBIOS LTTPR caps */2231	{2232		if (ctx->dc_bios->funcs->get_lttpr_caps) {2233			enum bp_result bp_query_result;2234			uint8_t is_vbios_lttpr_enable = 0;2235 2236			bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable);2237			dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;2238		}2239 2240		/* interop bit is implicit */2241		{2242			dc->caps.vbios_lttpr_aware = true;2243		}2244	}2245 2246	if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)2247		dc->debug = debug_defaults_drv;2248 2249	// Init the vm_helper2250	if (dc->vm_helper)2251		vm_helper_init(dc->vm_helper, 16);2252 2253	/*************************************************2254	 *  Create resources                             *2255	 *************************************************/2256 2257	/* Clock Sources for Pixel Clock*/2258	pool->base.clock_sources[DCN32_CLK_SRC_PLL0] =2259			dcn32_clock_source_create(ctx, ctx->dc_bios,2260				CLOCK_SOURCE_COMBO_PHY_PLL0,2261				&clk_src_regs[0], false);2262	pool->base.clock_sources[DCN32_CLK_SRC_PLL1] =2263			dcn32_clock_source_create(ctx, ctx->dc_bios,2264				CLOCK_SOURCE_COMBO_PHY_PLL1,2265				&clk_src_regs[1], false);2266	pool->base.clock_sources[DCN32_CLK_SRC_PLL2] =2267			dcn32_clock_source_create(ctx, ctx->dc_bios,2268				CLOCK_SOURCE_COMBO_PHY_PLL2,2269				&clk_src_regs[2], false);2270	pool->base.clock_sources[DCN32_CLK_SRC_PLL3] =2271			dcn32_clock_source_create(ctx, ctx->dc_bios,2272				CLOCK_SOURCE_COMBO_PHY_PLL3,2273				&clk_src_regs[3], false);2274	pool->base.clock_sources[DCN32_CLK_SRC_PLL4] =2275			dcn32_clock_source_create(ctx, ctx->dc_bios,2276				CLOCK_SOURCE_COMBO_PHY_PLL4,2277				&clk_src_regs[4], false);2278 2279	pool->base.clk_src_count = DCN32_CLK_SRC_TOTAL;2280 2281	/* todo: not reuse phy_pll registers */2282	pool->base.dp_clock_source =2283			dcn32_clock_source_create(ctx, ctx->dc_bios,2284				CLOCK_SOURCE_ID_DP_DTO,2285				&clk_src_regs[0], true);2286 2287	for (i = 0; i < pool->base.clk_src_count; i++) {2288		if (pool->base.clock_sources[i] == NULL) {2289			dm_error("DC: failed to create clock sources!\n");2290			BREAK_TO_DEBUGGER();2291			goto create_fail;2292		}2293	}2294 2295	/* DCCG */2296	pool->base.dccg = dccg32_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask);2297	if (pool->base.dccg == NULL) {2298		dm_error("DC: failed to create dccg!\n");2299		BREAK_TO_DEBUGGER();2300		goto create_fail;2301	}2302 2303	/* DML */2304	dml_init_instance(&dc->dml, &dcn3_2_soc, &dcn3_2_ip, DML_PROJECT_DCN32);2305 2306	/* IRQ Service */2307	init_data.ctx = dc->ctx;2308	pool->base.irqs = dal_irq_service_dcn32_create(&init_data);2309	if (!pool->base.irqs)2310		goto create_fail;2311 2312	/* HUBBUB */2313	pool->base.hubbub = dcn32_hubbub_create(ctx);2314	if (pool->base.hubbub == NULL) {2315		BREAK_TO_DEBUGGER();2316		dm_error("DC: failed to create hubbub!\n");2317		goto create_fail;2318	}2319 2320	/* HUBPs, DPPs, OPPs, TGs, ABMs */2321	for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) {2322 2323		/* if pipe is disabled, skip instance of HW pipe,2324		 * i.e, skip ASIC register instance2325		 */2326		if (pipe_fuses & 1 << i)2327			continue;2328 2329		/* HUBPs */2330		pool->base.hubps[j] = dcn32_hubp_create(ctx, i);2331		if (pool->base.hubps[j] == NULL) {2332			BREAK_TO_DEBUGGER();2333			dm_error(2334				"DC: failed to create hubps!\n");2335			goto create_fail;2336		}2337 2338		/* DPPs */2339		pool->base.dpps[j] = dcn32_dpp_create(ctx, i);2340		if (pool->base.dpps[j] == NULL) {2341			BREAK_TO_DEBUGGER();2342			dm_error(2343				"DC: failed to create dpps!\n");2344			goto create_fail;2345		}2346 2347		/* OPPs */2348		pool->base.opps[j] = dcn32_opp_create(ctx, i);2349		if (pool->base.opps[j] == NULL) {2350			BREAK_TO_DEBUGGER();2351			dm_error(2352				"DC: failed to create output pixel processor!\n");2353			goto create_fail;2354		}2355 2356		/* TGs */2357		pool->base.timing_generators[j] = dcn32_timing_generator_create(2358				ctx, i);2359		if (pool->base.timing_generators[j] == NULL) {2360			BREAK_TO_DEBUGGER();2361			dm_error("DC: failed to create tg!\n");2362			goto create_fail;2363		}2364 2365		/* ABMs */2366		pool->base.multiple_abms[j] = dmub_abm_create(ctx,2367				&abm_regs[i],2368				&abm_shift,2369				&abm_mask);2370		if (pool->base.multiple_abms[j] == NULL) {2371			dm_error("DC: failed to create abm for pipe %d!\n", i);2372			BREAK_TO_DEBUGGER();2373			goto create_fail;2374		}2375 2376		/* index for resource pool arrays for next valid pipe */2377		j++;2378	}2379 2380	/* PSR */2381	pool->base.psr = dmub_psr_create(ctx);2382	if (pool->base.psr == NULL) {2383		dm_error("DC: failed to create psr obj!\n");2384		BREAK_TO_DEBUGGER();2385		goto create_fail;2386	}2387 2388	/* MPCCs */2389	pool->base.mpc = dcn32_mpc_create(ctx, pool->base.res_cap->num_timing_generator, pool->base.res_cap->num_mpc_3dlut);2390	if (pool->base.mpc == NULL) {2391		BREAK_TO_DEBUGGER();2392		dm_error("DC: failed to create mpc!\n");2393		goto create_fail;2394	}2395 2396	/* DSCs */2397	for (i = 0; i < pool->base.res_cap->num_dsc; i++) {2398		pool->base.dscs[i] = dcn32_dsc_create(ctx, i);2399		if (pool->base.dscs[i] == NULL) {2400			BREAK_TO_DEBUGGER();2401			dm_error("DC: failed to create display stream compressor %d!\n", i);2402			goto create_fail;2403		}2404	}2405 2406	/* DWB */2407	if (!dcn32_dwbc_create(ctx, &pool->base)) {2408		BREAK_TO_DEBUGGER();2409		dm_error("DC: failed to create dwbc!\n");2410		goto create_fail;2411	}2412 2413	/* MMHUBBUB */2414	if (!dcn32_mmhubbub_create(ctx, &pool->base)) {2415		BREAK_TO_DEBUGGER();2416		dm_error("DC: failed to create mcif_wb!\n");2417		goto create_fail;2418	}2419 2420	/* AUX and I2C */2421	for (i = 0; i < pool->base.res_cap->num_ddc; i++) {2422		pool->base.engines[i] = dcn32_aux_engine_create(ctx, i);2423		if (pool->base.engines[i] == NULL) {2424			BREAK_TO_DEBUGGER();2425			dm_error(2426				"DC:failed to create aux engine!!\n");2427			goto create_fail;2428		}2429		pool->base.hw_i2cs[i] = dcn32_i2c_hw_create(ctx, i);2430		if (pool->base.hw_i2cs[i] == NULL) {2431			BREAK_TO_DEBUGGER();2432			dm_error(2433				"DC:failed to create hw i2c!!\n");2434			goto create_fail;2435		}2436		pool->base.sw_i2cs[i] = NULL;2437	}2438 2439	/* Audio, HWSeq, Stream Encoders including HPO and virtual, MPC 3D LUTs */2440	if (!resource_construct(num_virtual_links, dc, &pool->base,2441			&res_create_funcs))2442		goto create_fail;2443 2444	/* HW Sequencer init functions and Plane caps */2445	dcn32_hw_sequencer_init_functions(dc);2446 2447	dc->caps.max_planes =  pool->base.pipe_count;2448 2449	for (i = 0; i < dc->caps.max_planes; ++i)2450		dc->caps.planes[i] = plane_cap;2451 2452	dc->cap_funcs = cap_funcs;2453 2454	if (dc->ctx->dc_bios->fw_info.oem_i2c_present) {2455		ddc_init_data.ctx = dc->ctx;2456		ddc_init_data.link = NULL;2457		ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id;2458		ddc_init_data.id.enum_id = 0;2459		ddc_init_data.id.type = OBJECT_TYPE_GENERIC;2460		pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data);2461	} else {2462		pool->base.oem_device = NULL;2463	}2464 2465	dc->dml2_options.dcn_pipe_count = pool->base.pipe_count;2466	dc->dml2_options.use_native_pstate_optimization = false;2467	dc->dml2_options.use_native_soc_bb_construction = true;2468	dc->dml2_options.minimize_dispclk_using_odm = true;2469 2470	resource_init_common_dml2_callbacks(dc, &dc->dml2_options);2471	dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch;2472	dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc;2473	dc->dml2_options.svp_pstate.callbacks.calculate_mall_ways_from_bytes = pool->base.funcs->calculate_mall_ways_from_bytes;2474 2475	dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us;2476	dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us;2477	dc->dml2_options.svp_pstate.subvp_pstate_allow_width_us = dc->caps.subvp_pstate_allow_width_us;2478	dc->dml2_options.svp_pstate.subvp_swath_height_margin_lines = dc->caps.subvp_swath_height_margin_lines;2479 2480	dc->dml2_options.svp_pstate.force_disable_subvp = dc->debug.force_disable_subvp;2481	dc->dml2_options.svp_pstate.force_enable_subvp = dc->debug.force_subvp_mclk_switch;2482 2483	dc->dml2_options.mall_cfg.cache_line_size_bytes = dc->caps.cache_line_size;2484	dc->dml2_options.mall_cfg.cache_num_ways = dc->caps.cache_num_ways;2485	dc->dml2_options.mall_cfg.max_cab_allocation_bytes = dc->caps.max_cab_allocation_bytes;2486	dc->dml2_options.mall_cfg.mblk_height_4bpe_pixels = DCN3_2_MBLK_HEIGHT_4BPE;2487	dc->dml2_options.mall_cfg.mblk_height_8bpe_pixels = DCN3_2_MBLK_HEIGHT_8BPE;2488	dc->dml2_options.mall_cfg.mblk_size_bytes = DCN3_2_MALL_MBLK_SIZE_BYTES;2489	dc->dml2_options.mall_cfg.mblk_width_pixels = DCN3_2_MBLK_WIDTH;2490 2491	dc->dml2_options.max_segments_per_hubp = 18;2492	dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;2493	dc->dml2_options.map_dc_pipes_with_callbacks = true;2494 2495	if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev) && (dc->config.sdpif_request_limit_words_per_umc == 0))2496		dc->config.sdpif_request_limit_words_per_umc = 16;2497 2498	DC_FP_END();2499 2500	return true;2501 2502create_fail:2503 2504	DC_FP_END();2505 2506	dcn32_resource_destruct(pool);2507 2508	return false;2509}2510 2511struct resource_pool *dcn32_create_resource_pool(2512		const struct dc_init_data *init_data,2513		struct dc *dc)2514{2515	struct dcn32_resource_pool *pool =2516		kzalloc(sizeof(struct dcn32_resource_pool), GFP_KERNEL);2517 2518	if (!pool)2519		return NULL;2520 2521	if (dcn32_resource_construct(init_data->num_virtual_links, dc, pool))2522		return &pool->base;2523 2524	BREAK_TO_DEBUGGER();2525	kfree(pool);2526	return NULL;2527}2528 2529/*2530 * Find the most optimal free pipe from res_ctx, which could be used as a2531 * secondary dpp pipe for input opp head pipe.2532 *2533 * a free pipe - a pipe in input res_ctx not yet used for any streams or2534 * planes.2535 * secondary dpp pipe - a pipe gets inserted to a head OPP pipe's MPC blending2536 * tree. This is typical used for rendering MPO planes or additional offset2537 * areas in MPCC combine.2538 *2539 * Hardware Transition Minimization Algorithm for Finding a Secondary DPP Pipe2540 * -------------------------------------------------------------------------2541 *2542 * PROBLEM:2543 *2544 * 1. There is a hardware limitation that a secondary DPP pipe cannot be2545 * transferred from one MPC blending tree to the other in a single frame.2546 * Otherwise it could cause glitches on the screen.2547 *2548 * For instance, we cannot transition from state 1 to state 2 in one frame. This2549 * is because PIPE1 is transferred from PIPE0's MPC blending tree over to2550 * PIPE2's MPC blending tree, which is not supported by hardware.2551 * To support this transition we need to first remove PIPE1 from PIPE0's MPC2552 * blending tree in one frame and then insert PIPE1 to PIPE2's MPC blending tree2553 * in the next frame. This is not optimal as it will delay the flip for two2554 * frames.2555 *2556 *	State 1:2557 *	PIPE0 -- secondary DPP pipe --> (PIPE1)2558 *	PIPE2 -- secondary DPP pipe --> NONE2559 *2560 *	State 2:2561 *	PIPE0 -- secondary DPP pipe --> NONE2562 *	PIPE2 -- secondary DPP pipe --> (PIPE1)2563 *2564 * 2. We want to in general minimize the unnecessary changes in pipe topology.2565 * If a pipe is already added in current blending tree and there are no changes2566 * to plane topology, we don't want to swap it with another free pipe2567 * unnecessarily in every update. Powering up and down a pipe would require a2568 * full update which delays the flip for 1 frame. If we use the original pipe2569 * we don't have to toggle its power. So we can flip faster.2570 */2571int dcn32_find_optimal_free_pipe_as_secondary_dpp_pipe(2572		const struct resource_context *cur_res_ctx,2573		struct resource_context *new_res_ctx,2574		const struct resource_pool *pool,2575		const struct pipe_ctx *new_opp_head)2576{2577	const struct pipe_ctx *cur_opp_head;2578	int free_pipe_idx;2579 2580	cur_opp_head = &cur_res_ctx->pipe_ctx[new_opp_head->pipe_idx];2581	free_pipe_idx = resource_find_free_pipe_used_in_cur_mpc_blending_tree(2582			cur_res_ctx, new_res_ctx, cur_opp_head);2583 2584	/* Up until here if we have not found a free secondary pipe, we will2585	 * need to wait for at least one frame to complete the transition2586	 * sequence.2587	 */2588	if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)2589		free_pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx(2590				cur_res_ctx, new_res_ctx, pool);2591 2592	/* Up until here if we have not found a free secondary pipe, we will2593	 * need to wait for at least two frames to complete the transition2594	 * sequence. It really doesn't matter which pipe we decide take from2595	 * current enabled pipes. It won't save our frame time when we swap only2596	 * one pipe or more pipes.2597	 */2598	if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)2599		free_pipe_idx = resource_find_free_pipe_used_as_cur_sec_dpp_in_mpcc_combine(2600				cur_res_ctx, new_res_ctx, pool);2601 2602	if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)2603		free_pipe_idx = resource_find_any_free_pipe(new_res_ctx, pool);2604 2605	return free_pipe_idx;2606}2607 2608static struct pipe_ctx *find_idle_secondary_pipe_check_mpo(2609		struct resource_context *res_ctx,2610		const struct resource_pool *pool,2611		const struct pipe_ctx *primary_pipe)2612{2613	int i;2614	struct pipe_ctx *secondary_pipe = NULL;2615	struct pipe_ctx *next_odm_mpo_pipe = NULL;2616	int primary_index, preferred_pipe_idx;2617	struct pipe_ctx *old_primary_pipe = NULL;2618 2619	/*2620	 * Modified from find_idle_secondary_pipe2621	 * With windowed MPO and ODM, we want to avoid the case where we want a2622	 *  free pipe for the left side but the free pipe is being used on the2623	 *  right side.2624	 * Add check on current_state if the primary_pipe is the left side,2625	 *  to check the right side ( primary_pipe->next_odm_pipe ) to see if2626	 *  it is using a pipe for MPO ( primary_pipe->next_odm_pipe->bottom_pipe )2627	 * - If so, then don't use this pipe2628	 * EXCEPTION - 3 plane ( 2 MPO plane ) case2629	 * - in this case, the primary pipe has already gotten a free pipe for the2630	 *  MPO window in the left2631	 * - when it tries to get a free pipe for the MPO window on the right,2632	 *  it will see that it is already assigned to the right side2633	 *  ( primary_pipe->next_odm_pipe ).  But in this case, we want this2634	 *  free pipe, since it will be for the right side.  So add an2635	 *  additional condition, that skipping the free pipe on the right only2636	 *  applies if the primary pipe has no bottom pipe currently assigned2637	 */2638	if (primary_pipe) {2639		primary_index = primary_pipe->pipe_idx;2640		old_primary_pipe = &primary_pipe->stream->ctx->dc->current_state->res_ctx.pipe_ctx[primary_index];2641		if ((old_primary_pipe->next_odm_pipe) && (old_primary_pipe->next_odm_pipe->bottom_pipe)2642			&& (!primary_pipe->bottom_pipe))2643			next_odm_mpo_pipe = old_primary_pipe->next_odm_pipe->bottom_pipe;2644 2645		preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx;2646		if ((res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) &&2647			!(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == preferred_pipe_idx)) {2648			secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];2649			secondary_pipe->pipe_idx = preferred_pipe_idx;2650		}2651	}2652 2653	/*2654	 * search backwards for the second pipe to keep pipe2655	 * assignment more consistent2656	 */2657	if (!secondary_pipe)2658		for (i = pool->pipe_count - 1; i >= 0; i--) {2659			if ((res_ctx->pipe_ctx[i].stream == NULL) &&2660				!(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == i)) {2661				secondary_pipe = &res_ctx->pipe_ctx[i];2662				secondary_pipe->pipe_idx = i;2663				break;2664			}2665		}2666 2667	return secondary_pipe;2668}2669 2670static struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(2671		struct dc_state *state,2672		const struct resource_pool *pool,2673		struct dc_stream_state *stream,2674		const struct pipe_ctx *head_pipe)2675{2676	struct resource_context *res_ctx = &state->res_ctx;2677	struct pipe_ctx *idle_pipe, *pipe;2678	struct resource_context *old_ctx = &stream->ctx->dc->current_state->res_ctx;2679	int head_index;2680 2681	if (!head_pipe) {2682		ASSERT(0);2683		return NULL;2684	}2685 2686	/*2687	 * Modified from dcn20_acquire_idle_pipe_for_layer2688	 * Check if head_pipe in old_context already has bottom_pipe allocated.2689	 * - If so, check if that pipe is available in the current context.2690	 * --  If so, reuse pipe from old_context2691	 */2692	head_index = head_pipe->pipe_idx;2693	pipe = &old_ctx->pipe_ctx[head_index];2694	if (pipe->bottom_pipe && res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx].stream == NULL) {2695		idle_pipe = &res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx];2696		idle_pipe->pipe_idx = pipe->bottom_pipe->pipe_idx;2697	} else {2698		idle_pipe = find_idle_secondary_pipe_check_mpo(res_ctx, pool, head_pipe);2699		if (!idle_pipe)2700			return NULL;2701	}2702 2703	idle_pipe->stream = head_pipe->stream;2704	idle_pipe->stream_res.tg = head_pipe->stream_res.tg;2705	idle_pipe->stream_res.opp = head_pipe->stream_res.opp;2706 2707	idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx];2708	idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx];2709	idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx];2710	idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst;2711 2712	return idle_pipe;2713}2714 2715static int find_optimal_free_pipe_as_secondary_opp_head(2716		const struct resource_context *cur_res_ctx,2717		struct resource_context *new_res_ctx,2718		const struct resource_pool *pool,2719		const struct pipe_ctx *new_otg_master)2720{2721	const struct pipe_ctx *cur_otg_master;2722	int free_pipe_idx;2723 2724	cur_otg_master =  &cur_res_ctx->pipe_ctx[new_otg_master->pipe_idx];2725	free_pipe_idx = resource_find_free_pipe_used_as_sec_opp_head_by_cur_otg_master(2726			cur_res_ctx, new_res_ctx, cur_otg_master);2727 2728	/* Up until here if we have not found a free secondary pipe, we will2729	 * need to wait for at least one frame to complete the transition2730	 * sequence.2731	 */2732	if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)2733		free_pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx(2734				cur_res_ctx, new_res_ctx, pool);2735 2736	if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)2737		free_pipe_idx = resource_find_any_free_pipe(new_res_ctx, pool);2738 2739	return free_pipe_idx;2740}2741 2742struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe(2743		const struct dc_state *cur_ctx,2744		struct dc_state *new_ctx,2745		const struct resource_pool *pool,2746		const struct pipe_ctx *opp_head_pipe)2747{2748 2749	int free_pipe_idx;2750	struct pipe_ctx *free_pipe;2751 2752	if (!opp_head_pipe->stream->ctx->dc->config.enable_windowed_mpo_odm)2753		return dcn32_acquire_idle_pipe_for_head_pipe_in_layer(2754				new_ctx, pool, opp_head_pipe->stream, opp_head_pipe);2755 2756	free_pipe_idx = dcn32_find_optimal_free_pipe_as_secondary_dpp_pipe(2757					&cur_ctx->res_ctx, &new_ctx->res_ctx,2758					pool, opp_head_pipe);2759	if (free_pipe_idx >= 0) {2760		free_pipe = &new_ctx->res_ctx.pipe_ctx[free_pipe_idx];2761		free_pipe->pipe_idx = free_pipe_idx;2762		free_pipe->stream = opp_head_pipe->stream;2763		free_pipe->stream_res.tg = opp_head_pipe->stream_res.tg;2764		free_pipe->stream_res.opp = opp_head_pipe->stream_res.opp;2765 2766		free_pipe->plane_res.hubp = pool->hubps[free_pipe->pipe_idx];2767		free_pipe->plane_res.ipp = pool->ipps[free_pipe->pipe_idx];2768		free_pipe->plane_res.dpp = pool->dpps[free_pipe->pipe_idx];2769		free_pipe->plane_res.mpcc_inst =2770				pool->dpps[free_pipe->pipe_idx]->inst;2771	} else {2772		ASSERT(opp_head_pipe);2773		free_pipe = NULL;2774	}2775 2776	return free_pipe;2777}2778 2779struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_opp_head(2780		const struct dc_state *cur_ctx,2781		struct dc_state *new_ctx,2782		const struct resource_pool *pool,2783		const struct pipe_ctx *otg_master)2784{2785	int free_pipe_idx = find_optimal_free_pipe_as_secondary_opp_head(2786			&cur_ctx->res_ctx, &new_ctx->res_ctx,2787			pool, otg_master);2788	struct pipe_ctx *free_pipe;2789 2790	if (free_pipe_idx >= 0) {2791		free_pipe = &new_ctx->res_ctx.pipe_ctx[free_pipe_idx];2792		free_pipe->pipe_idx = free_pipe_idx;2793		free_pipe->stream = otg_master->stream;2794		free_pipe->stream_res.tg = otg_master->stream_res.tg;2795		free_pipe->stream_res.dsc = NULL;2796		free_pipe->stream_res.opp = pool->opps[free_pipe_idx];2797		free_pipe->plane_res.mi = pool->mis[free_pipe_idx];2798		free_pipe->plane_res.hubp = pool->hubps[free_pipe_idx];2799		free_pipe->plane_res.ipp = pool->ipps[free_pipe_idx];2800		free_pipe->plane_res.xfm = pool->transforms[free_pipe_idx];2801		free_pipe->plane_res.dpp = pool->dpps[free_pipe_idx];2802		free_pipe->plane_res.mpcc_inst = pool->dpps[free_pipe_idx]->inst;2803		if (free_pipe->stream->timing.flags.DSC == 1) {2804			dcn20_acquire_dsc(free_pipe->stream->ctx->dc,2805					&new_ctx->res_ctx,2806					&free_pipe->stream_res.dsc,2807					free_pipe_idx);2808			ASSERT(free_pipe->stream_res.dsc);2809			if (free_pipe->stream_res.dsc == NULL) {2810				memset(free_pipe, 0, sizeof(*free_pipe));2811				free_pipe = NULL;2812			}2813		}2814	} else {2815		ASSERT(otg_master);2816		free_pipe = NULL;2817	}2818 2819	return free_pipe;2820}2821 2822unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans)2823{2824	/*2825	 * DCN32 and DCN321 SKUs may have different sizes for MALL2826	 *  but we may not be able to access all the MALL space.2827	 *  If the num_chans is power of 2, then we can access all2828	 *  of the available MALL space.  Otherwise, we can only2829	 *  access:2830	 *2831	 *  max_cab_size_in_bytes = total_cache_size_in_bytes *2832	 *    ((2^floor(log2(num_chans)))/num_chans)2833	 *2834	 * Calculating the MALL sizes for all available SKUs, we2835	 *  have come up with the follow simplified check.2836	 * - we have max_chans which provides the max MALL size.2837	 *  Each chans supports 4MB of MALL so:2838	 *2839	 *  total_cache_size_in_bytes = max_chans * 4 MB2840	 *2841	 * - we have avail_chans which shows the number of channels2842	 *  we can use if we can't access the entire MALL space.2843	 *  It is generally half of max_chans2844	 * - so we use the following checks:2845	 *2846	 *   if (num_chans == max_chans), return max_chans2847	 *   if (num_chans < max_chans), return avail_chans2848	 *2849	 * - exception is GC_11_0_0 where we can't access max_chans,2850	 *  so we define max_avail_chans as the maximum available2851	 *  MALL space2852	 *2853	 */2854	int gc_11_0_0_max_chans = 48;2855	int gc_11_0_0_max_avail_chans = 32;2856	int gc_11_0_0_avail_chans = 16;2857	int gc_11_0_3_max_chans = 16;2858	int gc_11_0_3_avail_chans = 8;2859	int gc_11_0_2_max_chans = 8;2860	int gc_11_0_2_avail_chans = 4;2861 2862	if (ASICREV_IS_GC_11_0_0(dc->ctx->asic_id.hw_internal_rev)) {2863		return (num_chans == gc_11_0_0_max_chans) ?2864			gc_11_0_0_max_avail_chans : gc_11_0_0_avail_chans;2865	} else if (ASICREV_IS_GC_11_0_2(dc->ctx->asic_id.hw_internal_rev)) {2866		return (num_chans == gc_11_0_2_max_chans) ?2867			gc_11_0_2_max_chans : gc_11_0_2_avail_chans;2868	} else { // if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev)) {2869		return (num_chans == gc_11_0_3_max_chans) ?2870			gc_11_0_3_max_chans : gc_11_0_3_avail_chans;2871	}2872}2873